Reputation: 579
I am trying to make a heatmap of values in polar coordinates using gnuplot
. I found this SO question, which seems to indicate that I need to use splot
and pm3d
, and feed it the points in rectangular form. Ideally, I would like to pipe the data into gnuplot
from another program without converting to ASCII or use a temporary file, so I have been trying to get it to read from a binary format.
To generate some test data:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
FILE *out = fopen("test.bin", "wb");
for(int i=0; i<100; i++) {
float output[3];
float r = (float)rand()/RAND_MAX;
float theta = (float)rand()/RAND_MAX * 2*M_PI;
output[0] = r*cos(theta);
output[1] = r*sin(theta);
output[2] = r*r;
fwrite(output, sizeof(float), 3, out);
}
fclose(out);
}
This makes data in the format
X1 Y1 Z1 X2 Y2 Z2 X3 Y3 Z3 ...
Reading the gnuplot
docs, it seems to prefer data in a matrix format with column and row headers, which is incompatible with conversion from polar (since no x and y coordinates are the same), and I can't decipher what it's saying past that. After messing around for a while the best I have gotten is this:
splot 'test.bin' binary record=(100):(100):(100)
How can I convert this into a 2D heatmap plot, where the outside is "brighter" than the middle like this?
Attempting to use pm3d
just results in the following error:
gnuplot> splot 'test.bin' binary record=(100):(100):(100) w pm3d
Warning: Single isoline (scan) is not enough for a pm3d plot.
Hint: Missing blank lines in the data file? See 'help pm3d' and FAQ.
Upvotes: 1
Views: 262
Reputation: 15093
It would help to know a bit more about your data and your requirements for the plot.
(1) If you have sparse data (as in your test with only 100 points) then it may be best simply to show the points, colored as appropriate. For this you can use polar mode directly to generate a 2D plot. I use ascii data rather than binary for the purpose of showing a self-contained example, but you already know how to use binary data instead for an external stream.
set print $DATA
do for [i=1:100] {
theta = rand(0) * 2.*pi
r = rand(0)
print theta, r, r*r
}
unset print
unset xtics; unset ytics; set rtics; set ttics;
unset border; set border polar;
set grid polar front
unset key
set rrange [0:1]
set polar
set palette cubehelix negative
set size ratio -1 # "set isotropic in version 5.5"
set pointsize 5.0
plot $DATA using 1:2:3 with points lc palette pt 7
(2) If you have much denser data points, the answer could be the same except that it looks more like what you might have had in mind. Here is the same plot except that it contains 10000 smaller points.
(3) If you have samples from a known distribution, or otherwise have an a priori model for the data, then you may want to first use the data to fit model parameters and then plot the model surface. That's an entirely different set of requirements. I won't try to show this here but if might be appropriate to your data then you could revise the question and ask again.
(3) Using your binary data in cartesian coordinates, the closest I know how to get is via use of the dgrid3
option to fit splines to your sparse points. Issues with this approach include the uneven sampling due to polar->cartesian conversion and the difficulty of cutting out only the portion of the plot with R < limit (however see below).
set palette cubehelix negative
set dgrid3d 50,50 spline
set view map
splot 'polar.bin' binary record=100:100:100 using 1:2:3 with pm3d
(4) A possible approach to masking out the unwanted portions of the rectangular grid: How to display non-rectangular and ungridded data as a map with gnuplot?
Upvotes: 1