Search code examples
gnuplot

How to plot heatmap in gnuplot with polar coordinate


I would like to plot this in gnuplot :

enter image description here

my data :

#x, y, cm[], r, theta, theta*180./M_PI
0.125 0.125 0.1309 0.125 0.1309 7.5
0.125 0.375 0.1309 0.125 0.392699 22.5
0.375 0.125 0.392699 0.375 0.1309 7.5
0.3125 0.3125 0.327249 0.3125 0.327249 18.75
0.3125 0.4375 0.327249 0.3125 0.458149 26.25
0.4375 0.3125 0.458149 0.4375 0.327249 18.75
0.4375 0.4375 0.458149 0.4375 0.458149 26.25
0.125 0.625 0.1309 0.125 0.654498 37.5
0.125 0.875 0.1309 0.125 0.916298 52.5
0.3125 0.5625 0.327249 0.3125 0.589049 33.75
0.3125 0.6875 0.327249 0.3125 0.719948 41.25
0.4375 0.5625 0.458149 0.4375 0.589049 33.75
0.4375 0.6875 0.458149 0.4375 0.719948 41.25
0.375 0.875 0.392699 0.375 0.916298 52.5
0.625 0.125 0.654498 0.625 0.1309 7.5
0.5625 0.3125 0.589049 0.5625 0.327249 18.75
0.5625 0.4375 0.589049 0.5625 0.458149 26.25
0.6875 0.3125 0.719948 0.6875 0.327249 18.75
0.6875 0.4375 0.719948 0.6875 0.458149 26.25
0.875 0.125 0.916298 0.875 0.1309 7.5
0.875 0.375 0.916298 0.875 0.392699 22.5
0.5625 0.5625 0.589049 0.5625 0.589049 33.75
0.5625 0.6875 0.589049 0.5625 0.719948 41.25
0.6875 0.5625 0.719948 0.6875 0.589049 33.75
0.6875 0.6875 0.719948 0.6875 0.719948 41.25
0.625 0.875 0.654498 0.625 0.916298 52.5
0.875 0.625 0.916298 0.875 0.654498 37.5
0.875 0.875 0.916298 0.875 0.916298 52.5

where cm[] is the value I'd like to plot in polar coordinates. I think I need to use dgrid3d but I don't know how and if it's possible to obtain the same image but with gnuplot?

my piece of code :

set pm3d map
unset key

set multiplot

# plot the heatmap

unset border
unset xtics
unset ytics

set angles degrees
r = 1
set xrange[-r:r]
set yrange[-r:r]
set colorbox user origin 0.9,0.1 size 0.03,0.8
#set dgrid3d 20,20
sp 'log' u 1:2:3

# now plot the polar grid only
set style line 11 lc rgb 'white' lw 2
set grid polar ls 11
set polar
set rrange[0:r]
unset raxis
set rtics format '' scale 0
set for [i=0:330:30] label at first (r+0.35)*cos(i), first (r+0.35)*sin(i)\
center sprintf('%d', i)
plot NaN w l
unset multiplot

I have tried the code here :`

set mapping cylindrical
set view equal xy
set view map
set angle degrees
set dgrid3d 200,200
sp 'log' u 6:3:4 w pm3d

enter image description here

but this ins't what I wanted. In a polar mode I can't use splot and pm3d.

I tried also this code :

set polar
set angles degrees
set grid polar 15. lt -1 dt 0 lw 0.5
unset border
unset xtics
unset ytics
unset raxis
p 'log' u 6:3 

enter image description here

but I would like to fill the mesh with a color set by column 3

I've simplified my data for a regular grid :

#x, y, cm[], r, theta, theta*180./M_PI
0.125 0.125 0.1309 0.125 0.1309 7.5
0.125 0.375 0.1309 0.125 0.392699 22.5
0.375 0.125 0.392699 0.375 0.1309 7.5
0.375 0.375 0.392699 0.375 0.392699 22.5
0.125 0.625 0.1309 0.125 0.654498 37.5
0.125 0.875 0.1309 0.125 0.916298 52.5
0.375 0.625 0.392699 0.375 0.654498 37.5
0.375 0.875 0.392699 0.375 0.916298 52.5
0.625 0.125 0.654498 0.625 0.1309 7.5
0.625 0.375 0.654498 0.625 0.392699 22.5
0.875 0.125 0.916298 0.875 0.1309 7.5
0.875 0.375 0.916298 0.875 0.392699 22.5
0.625 0.625 0.654498 0.625 0.654498 37.5
0.625 0.875 0.654498 0.625 0.916298 52.5
0.875 0.625 0.916298 0.875 0.654498 37.5
0.875 0.875 0.916298 0.875 0.916298 52.5

using the "simplified" data with this code :

### workaround for polar heatmap
reset session

set table $Data
   plot "log" using 6:4:3 with table
unset table

set size square
set angle degrees
unset border
unset tics
set cbtics
set polar
set border polar
unset raxis
set grid polar 15.

astep = 180./4
rstep = 0.25

# create the segments for each datapoint
set print $PolarHeatmap
    do for [i=1:|$Data|] {
        a = real(word($Data[i],1))
        r = real(word($Data[i],2))
        c = real(word($Data[i],3))
        do for [j=0:5] {
            print sprintf("%g %g %g",a+j*astep/10., r-0.5*rstep, c)
        }
        do for [j=5:0:-1] {
            print sprintf("%g %g %g",a+j*astep/10., r+0.5*rstep, c)
        }
        print ""
        print ""
    }
set print

set style fill noborder

plot $PolarHeatmap u 1:2:3 w filledcurves palette notitle
### end of code

I get : enter image description here

I almost what I want but my data are [0:Pi/3] and It's not the case. I don't understand : [j=0:5] and [j=5:0:-1] and why do we need to print again.


Solution

  • Here is a surprisingly compact solution, not straightforward though. This works in your case because you have a strict grid in your data. If you don't have a regular grid you might need to use dgrid3d with interpolation (what you already tried) or Delaunay-triangulation or a Voronoi-diagram.

    With gnuplot you can easily plot segments of a circle. If you do it in the right order you can get your desired output. The basic idea is that you have a minimal regular step in radius and angle (here: dr=0.125 and da=7.5) which are defining the minimal cell. If your datapoint is on the grid you take 4 minimal cells together to one bigger cell.

    Some comments:

    • first sort your data by decreasing radius via "seriously misusing" smooth zsort and write it into the datablock $Sorted.

    • check if your datapoints are on the grid ($1/dr==int($1/dr) or not. Write this into column3 of datablock $Grid

    • when plotting $Grid if the datapoint is on the grid take the current radius + dr and current angle +/-da to plot a circle segment. If the datapoint is not on the grid instead take +dr/2 and +/-da/2, respectively.

    • in order to activate the palette (apparently) you first need to plot (NaN):(NaN):3 with the z-range of the data (I don't know yet why). It doesn't seem to work right away when plotting the circle segments.

    You could certainly do the same thing also in polar coordinates.

    Data: SO77873892.dat

    #x,      y,       cm[],      r,       theta,     theta*180./M_PI
    0.1250   0.1250   0.130900   0.1250   0.130900    7.50
    0.1250   0.3750   0.130900   0.1250   0.392699   22.50
    0.3750   0.1250   0.392699   0.3750   0.130900    7.50
    0.3125   0.3125   0.327249   0.3125   0.327249   18.75
    0.3125   0.4375   0.327249   0.3125   0.458149   26.25
    0.4375   0.3125   0.458149   0.4375   0.327249   18.75
    0.4375   0.4375   0.458149   0.4375   0.458149   26.25
    0.1250   0.6250   0.130900   0.1250   0.654498   37.50
    0.1250   0.8750   0.130900   0.1250   0.916298   52.50
    0.3125   0.5625   0.327249   0.3125   0.589049   33.75
    0.3125   0.6875   0.327249   0.3125   0.719948   41.25
    0.4375   0.5625   0.458149   0.4375   0.589049   33.75
    0.4375   0.6875   0.458149   0.4375   0.719948   41.25
    0.3750   0.8750   0.392699   0.3750   0.916298   52.50
    0.6250   0.1250   0.654498   0.6250   0.130900    7.50
    0.5625   0.3125   0.589049   0.5625   0.327249   18.75
    0.5625   0.4375   0.589049   0.5625   0.458149   26.25
    0.6875   0.3125   0.719948   0.6875   0.327249   18.75
    0.6875   0.4375   0.719948   0.6875   0.458149   26.25
    0.8750   0.1250   0.916298   0.8750   0.130900    7.50
    0.8750   0.3750   0.916298   0.8750   0.392699   22.50
    0.5625   0.5625   0.589049   0.5625   0.589049   33.75
    0.5625   0.6875   0.589049   0.5625   0.719948   41.25
    0.6875   0.5625   0.719948   0.6875   0.589049   33.75
    0.6875   0.6875   0.719948   0.6875   0.719948   41.25
    0.6250   0.8750   0.654498   0.6250   0.916298   52.50
    0.8750   0.6250   0.916298   0.8750   0.654498   37.50
    0.8750   0.8750   0.916298   0.8750   0.916298   52.50
    

    Script: (requires gnuplot>=5.4.0, because of smooth zsort)

    ### plot circle segments to mimic polar heatmap
    reset session
    
    FILE = "SO77873892.dat"
    
    da = 7.5        # grid angle step
    dr = 0.125      # grid radius step
    
    set table $Sorted
        plot FILE u 4:6:(-$4):3 smooth zsort lc var       # sort by decreasing radius
    set table $Grid
        plot $Sorted u 1:2:3:($1/dr==int($1/dr)) w table  # check if on the grid
    unset table
    
    set size ratio -1
    set xrange[0:1]
    set yrange[0:1]
    set style fill transparent solid 1.0 border lc "black"
    set key noautotitle
    set palette defined (0 "#00d0ff", 1 "#40fffc", 2 "#b7ffc4", 3 "#f3ff65", 4 "#ffff00")
    
    plot FILE  u (NaN):(NaN):3 w p palette z, \
         $Grid u (0):(0):(g=($4==1?1:0.5), $1+dr*g):($2-da*g):($2+da*g):3 w circles lc palette z
    ### end of script
    

    Result:

    enter image description here