Gnuplot: how to write the z values in a heatmap plot - gnuplot

I am using Gnuplot 4.6.5
I want to write the z value in a heatmap plot.
Here is the code for producing the heatmap:
#
# Two ways of generating a 2D heat map from ascii data
#
set title "Heat Map generated from a file containing Z values only"
unset key
set tic scale 0
# Color runs from white to green
set palette rgbformula -7,2,-7
set cbrange [0:5]
set cblabel "Score"
unset cbtics
set xrange [-0.5:1.5]
set yrange [-0.5:1.5]
set view map
plot '-' using 1:2:3 with image
0 0 5
0 1 4
1 0 2
1 1 2
e
This gives:
I want to write the z values in the figure:
My actually data is much larger than the demonstration data used here. So it is almost impractical to write each point manually.
Any help would be appreciated.

You can use the labels plotting style for this. See also gnuplot matrix or plot : display both color and point value for a very similar question:
unset key
set palette rgbformula -7,2,-7
set cbrange [0:5]
set cblabel "Score"
unset cbtics
set autoscale fix
plot '-' using 1:2:3 with image, \
'-' using 1:2:(strcol(3)) with labels
0 0 5
0 1 4
1 0 2
1 1 2
e
0 0 5
0 1 4
1 0 2
1 1 2
e

Related

Filledcurves between different scaled y-axis

I have to "reinvent" a diagram like the following:
My problem is, the "filledcurves" option does not work correctly, if I use the different scaled y-axis.
set y2tics textcolor rgb "black"
set ytics nomirror
set yrange [0:80]
set y2range [0:180]
set key off
set grid dashtype 5 # auch dt ".-." möglich
plot "klima_flach.txt" using 1:3:4 with filledcurves x1,\
"" using 1:4 with lines axis x1y2,\
"" using 1:3:xtic(2) with lines axis x1y1
The used data is the following:
0 0 11 50
1 J 10 70
2 F 11 42
3 M 12 50
4 A 15 50
5 M 18 20
6 J 22 10
7 J 25 1
8 A 25 20
9 S 23 40
10 O 20 80
11 N 25 70
12 D 11 60
Any ideas, how I can get this problem solved?
By the way: A pattern as in the original diagram... possible or not?
#Wolfgang Höfer, the scaling between the axes in such type of Walter/Lieth-climate diagrams is 2. Hence, your y-range should be [0:90] and hence scaling factor 90./180.
Nevertheless, I assume #Christoph's answer solved your problem.
To your last question: a pattern as in your picture, i.e. a vertical hatch pattern? That's what I asked here (Hatch patterns in gnuplot) recently. Apparently, it's seems not possible in gnuplot.
Some time ago, I also "struggled" with climate diagrams, i.e. with filledcurves and even nonlinear axes. I would like to provide the code which I ended up. Maybe it will be useful to you or to others to draw such climate diagrams with gnuplot. If you are reading from a file, replace $DataIn with your filename. Suggestions and improvements are welcome.
# Walter/Lieth climate diagram with nonlinear axis
reset session
set encoding "utf8"
$DataIn <<EOD
# Mumbai/India, 18°54'N/72°49'E, 11 m
# No. Month Temperature Precipitation
1 January 23.9 3
2 February 23.9 3
3 March 26.1 3
4 April 28.1 2
5 May 29.7 18
6 June 28.9 485
7 July 27.2 617
8 August 27.0 340
9 September 27.0 264
10 October 28.1 64
11 November 27.2 13
12 December 25.6 3
EOD
# in order to be flexible for different input files
ColTemp = 3 # col# temperature
ColPrec = 4 # col# precipitation
# get location label from first commented row starting after '# '
set datafile commentschar "" # set the comment char to none
set datafile separator "\n" # data will be a full line
set table $Dummy # plot following data to a dummy table
# plots only first line 'every ::0::0' as string to the dummy table
# and assigns this line starting after the 3rd character to variable 'Location'
plot $DataIn u (Location = stringcolumn(1)[3:]) every ::0::0 with table
unset table # stop plotting to table
set datafile commentschar "#" # restore default commentschar
set datafile separator whitespace # restore default separator
set label 1 at graph 0.02,0.96 Location font ",10" # put label on graph
# set periodic boundaries, i.e. add lines of Dec and Jan again
# independent of the input format $DataIn, column1 of $Data will be the number of month
set datafile separator "\n"
set table $Data
plot $DataIn u (0):(stringcolumn(1)) every ::11::11 with table
plot $DataIn u ($0+1):(stringcolumn(1)) with table
plot $DataIn u (13):(stringcolumn(1)) every ::0::0 with table
unset table
set datafile separator whitespace
# print $Data
# settings for nonlinear scale
ScaleChangeAt = 100.
ScaleChangeFactor = 5.
f1(y) = (y<=ScaleChangeAt) ? y : ((y - ScaleChangeAt)/ScaleChangeFactor + ScaleChangeAt)
f2(y) = (y<=ScaleChangeAt) ? y : ((y - ScaleChangeAt)*ScaleChangeFactor + ScaleChangeAt)
f3(y) = f1(y)/2. # relation between axes y and y2; standard for Walter/Lieth climate diagrams
set nonlinear y2 via f1(y) inverse f2(y)
# settings for x-axis
set xrange[0.5:12.5]
set xtics 1 scale 0,1
set mxtics 2
set grid mxtics
# create months labels from local settings
do for [i=1:12] {
set xtics add (strftime("%b",strptime("%m",sprintf("%g",i))) i)
}
# settings for y- and y2-axes
stats [*:*] $DataIn u ColTemp:ColPrec nooutput
Round(m,n) = int(m/n)*n + sgn(m)*n
Ymin = STATS_min_x > 0 ? 0 : Round(STATS_min_x,10)
Ymax = 50
Y2min = Ymin < 0 ? f1(Ymin)*2 : 0
Y2max = Round(STATS_max_y,10**int(log(STATS_max_y)/log(10))) # round to next 10 or 100
# print Ymin, Ymax, Y2min, Y2max
# y-axis
set ylabel "Temperature / °C" tc rgb "red"
set yrange [Ymin:f3(Y2max)] # h(Y2max)]
set ytics 10 nomirror tc rgb "red"
# "manual" setting of ytics, up to 50°C
set ytics ("0" 0)
do for [i=Ymin:50:10] {
set ytics add (sprintf("%g",i) i)
}
# settings for y2-axis
set y2label "Precipitation / mm" tc rgb "blue"
set y2range [Y2min:Y2max]
# "manual" setting of y2tics
set y2tics nomirror tc rgb "blue"
set y2tics ("0" 0)
set grid y2tics
do for [i=20:ScaleChangeAt:20] {
set y2tics add (sprintf("%g",i) i)
}
do for [i=ScaleChangeAt:Y2max:20*ScaleChangeFactor] {
set y2tics add (sprintf("%g",i) i)
}
plot \
$Data u 1:ColTemp+1:(f3(column(ColPrec+1))) axis x1y1 w filledcurves above lc rgb "yellow" not,\
'' u 1:ColTemp+1:(f3(column(ColPrec+1))) axis x1y1 w filledcurves below fs pattern 4 fc rgb "blue" not,\
'' u 1:(f3(ScaleChangeAt)):(f3(column(ColPrec+1))) axis x1y1 w filledcurves below fs solid 1.0 fc rgb "blue" not,\
'' u 1:ColTemp+1 w l lw 2 lc rgb "red" not,\
'' u 1:ColPrec+1 axes x1y2 w l lw 2 lc rgb "blue" not
### end of code
which results in:
The filledcurves doesn't have an option for choosing different axes for the y-values in column two and three. But you are in the lucky situation, that you have fixed y-ranges. So you can define a scaling function for one of the columns:
set y2tics textcolor rgb "black"
set ytics nomirror
set yrange [0:80]
set y2range [0:180]
scale = 80.0/180.0
set key off
set grid dashtype 5 # auch dt ".-." möglich
plot "klima_flach.txt" using 1:3:(scale*$4) with filledcurves,\
"" using 1:4 with lines axis x1y2,\
"" using 1:3:xtic(2) with lines axis x1y1

Why my commands do not work for gnuplot?

I have input file test.dat that contains
1 1
2 2
3 3
4 4
I wrote the script for gnuplot:
gnuplot <<EOF
set term png size 1000,1000;
set output "out.png";
set arrow from graph 0,1 to graph 0,1.1 filled
set arrow from graph 1,0 to graph 1.1,0 filled
set tmargin 5
set rmargin 20
set border 3
set tics nomirror
set grid
set xtics font "Verdana,14"
set ytics font "Verdana,14"
set nokey
set style line 1 lt 1 lw 3 pt 3 linecolor rgb "black"
set ylabel "Efficiency, %" offset 2,0,0 font "Verdana,14"
set xlabel "Cores, N" offset 0,0,0 font "Verdana,14"
func1(x) = x / 2
func2(x) = x * 2
plot "test.dat" u (func1($1)):(func2($2)) ls 1 smooth csplines;
EOF
But the error occurs when you try to start it:
gnuplot> plot "test.dat" u (func1()):(func2()) ls 1 smooth csplines;
line 0: invalid expression
The dollar signs are interpreted as starting a shell variable. Use column instead:
gnuplot <<EOF
set term png size 1000,1000;
set output "out.png";
func1(x) = x / 2
func2(x) = x * 2
plot "test.dat" u (func1(column(1))):(func2(column(2))) ls 1 smooth csplines;
EOF

How to highlight regions of plot with gnuplot

I'd appreciate if somebody can help with this question.
I am working with a radar (or spiderweb) plot with gnuplot 5.0.0:
The scale and range in all axes is the same. The numbers at and beyond 1 have a special meaning and I would like to highlight that.
I am thinking of three things that would increase visibility:
Simply make the tick mark at 1 (labelled "Limit") boldfaced. How could I highlight just a specific tick and label?
I could also highlight the circular dashed line at level 1
On the plot itself I'd like to have the background colored differently for radius > 1.
How can I achieve either of the three options above? All three would be ideal of course, but just a a minimum differentiation from the rest of that value would help.
This is what generated the plot in the link:
set term x11
set title "My title "
set polar
set angles degrees
npoints = 6
a1 = 360/npoints*1
a2 = 360/npoints*2
a3 = 360/npoints*3
a4 = 360/npoints*4
a5 = 360/npoints*5
a6 = 360/npoints*6
set grid polar 360
set size square
set style data lines
unset border
set grid ls 0
set linetype 1 lc rgb 'red' lw 2 pt 7 ps 2
M=2.2
set arrow from 0,0 to first M*cos(a1), M*sin(a1)
set arrow from 0,0 to first M*cos(a2), M*sin(a2)
set arrow from 0,0 to first M*cos(a3), M*sin(a3)
set arrow from 0,0 to first M*cos(a4), M*sin(a4)
set arrow from 0,0 to first M*cos(a5), M*sin(a5)
set arrow from 0,0 to first M*cos(a6), M*sin(a6)
a1_min = 0
a1_max = 1
a2_min = 0
a2_max = 1
a3_min = 0
a3_max = 1
a4_min = 0
a4_max = 1
a5_min = 0
a5_max = 1
a6_min = 0
a6_max = 1
set label "M1" at M*cos(a1),M*sin(a1) center offset char 1,1
set label "M2" at M*cos(a2),M*sin(a2) center offset char 1,1
set label "M3" at M*cos(a3),M*sin(a3) center offset char 1,1
set label "M4" at M*cos(a4),M*sin(a4) center offset char 1,1
set label "M5" at M*cos(a5),M*sin(a5) center offset char 1,1
set label "M6" at M*cos(a6),M*sin(a6) center offset char 1,1
set xrange [0:1]
set yrange [0:1]
set xtics axis 0,0.5,M
unset ytics
set rrange [0:M]
set rtics (""0,""0.25,""0.5,""0.75,"Limit"1,""1.25,""1.50,""1.75,""2)
set rtics scale 0 format ''
set style fill transparent solid 0.5
set style function filledcurves y1=0.5
set grid noxtics nomxtics noytics nomytics front
plot '-' u ($1==1?a1:($1==2?a2:($1==3?a3:($1==4?a4:($1==5?a5:($1==6?a6:$1)))))):($1==1?(($2-a1_min)/(a1_max-a1_min)):($1==2?(($2-a2_min)/(a2_max-a2_min)):($1==3?(($2-a3_min)/(a3_max-a3_min)):($1==4?(($2-a4_min)/(a4_max-a4_min)):($1==5?(($2-a5_min)/(a5_max-a5_min)):($1==6?(($2-a6_min)/(a6_max-a6_min)):$1)))))) w filledcurve lt 1 title "AAA",\
'-' u ($1==1?a1:($1==2?a2:($1==3?a3:($1==4?a4:($1==5?a5:($1==6?a6:$1)))))):($1==1?(($2-a1_min)/(a1_max-a1_min)):($1==2?(($2-a2_min)/(a2_max-a2_min)):($1==3?(($2-a3_min)/(a3_max-a3_min)):($1==4?(($2-a4_min)/(a4_max-a4_min)):($1==5?(($2-a5_min)/(a5_max-a5_min)):($1==6?(($2-a6_min)/(a6_max-a6_min)):$1)))))) w filledcurve lt 2 title "BBB"
1 2.1
2 1
3 0.1
4 0.5
5 0.5
6 0.1
1 2.1
EOF
1 2.2
2 0.9
3 0.9
4 0.2
5 0.3
6 0.1
1 2.2
EOF
set output
I've taken the liberty to streamline your script a bit, you can now easily adjust the number of arms in the web. Also added a coloured background for 1 >r > M.
Btw., there is no need to enter the first datapoint again at the end to close the contour.
Update: That is, there shouldn't be. However the line between the last and first point is missing then, even with giving the "closed" option to "with filledcurve". I wonder if this is a bug.
set term wxt
set title "My title "
set polar
set angles degrees
set grid polar 360
set size square
set style data lines
set key top left
unset border
set grid ls 0
set linetype 1 lc rgb 'red' lw 2 pt 7 ps 2
M=2.2
npoints = 7
minima = "0 0 0 0 0 0 0" # adjust and add more as necessary
maxima = "1 1 1 1 1 1 1"
a(n) = 360./npoints*n
amin(n) = 0.0 + word(minima,int(n))
amax(n) = 0.0 + word(maxima,int(n))
do for [i=1:npoints] {
set arrow i from 0,0 to first M*cos(a(i)), M*sin(a(i))
set label i sprintf("M%.f",i) at M*cos(a(i)),M*sin(a(i)) \
center offset char 1,1
}
set object 1 circle at 0,0 size M fillc rgb "yellow" behind
set object 2 circle at 0,0 size 1 fillc rgb "white" behind
set xrange [0:1]
set yrange [0:1]
set xtics axis 0,0.5,M
unset ytics
set rrange [0:M]
set rtics (""0,""0.25,""0.5,""0.75,"{/:Bold Limit}"1,""1.25,""1.50,""1.75,""2)
set rtics scale 0 format ''
set style fill transparent solid 0.5
set style function filledcurves y1=0.5
set grid noxtics nomxtics noytics nomytics front
plot '-' us (a($1)):(($2-amin($1))/(amax($1)-amin($1))) \
w filledcurve closed lt 1 title "AAA",\
'-' us (a($1)):(($2-amin($1))/(amax($1)-amin($1))) \
w filledcurve closed lt 2 title "BBB"
1 2.1
2 1
3 0.1
4 0.5
5 0.5
6 0.1
7 0.5
EOF
1 2.2
2 0.9
3 0.9
4 0.2
5 0.3
6 0.1
7 1.8
EOF

gnuplot: filledcurves with color from data

I would like to use filledcurves with palette.
My data looks like this:
0 0 0 1 1 1 1 0 0.5
2 2 2 3 3 3 3 2 0.6
My plotting commands:
set terminal pngcairo size 800,600
set output "test.png"
set style fill solid 1.0 noborder
unset border
unset xtics
unset ytics
plot '< awk ''{print $1,$2,$9,"\n",$3,$4,$9,"\n",$5,$6,$9,"\n",$7,$8,$9,"\n",$1,$2,$9,"\n"}'' rect.txt' \
using 1:2:3 with filledcurves fillcolor palette notitle
This unfortunately only yields black squares where as I would like them to be colored. Is there a way to achieve correctly colored figures with gnuplot?
EDIT:
Using as suggested:
set terminal pngcairo size 800,600
set output "test.png"
set style fill solid 1.0 noborder
unset border
unset xtics
unset ytics
file = 'rect.txt'
lines = system(sprintf('wc -l %s | cut -d'' '' -f 1', file))
frac(x) = system(sprintf('awk ''{if (NR==%d){ print $9 }}'' %s', x, file))
rect(x) = sprintf('awk ''{if (NR==%d){ print $1,$2,$4,"\n",$5,$8,$6,"\n"}}'' %s', x, file)
plot for [i=1:lines] '< '.rect(i) using 1:2:3 with filledcurves palette frac frac(i) notitle
with the content of rect.txt:
0 0 0 1 1 1 1 0 0.5
2 2 2 3 3 3 3 2 0.6
2 2 2 1 1 1 1 2 0.2
yields the following result:
The filledcurves plotting style doesn't support coloring by palette with data from a file. The main issue here is, that usually, when using palette, one wants to change the color within a single area depending on some data values.
To color a single rectangle taking the color value from a fractional position of the palette, you can use palette frac <value>. This requires you to iterate over all rectangles.
And for proper use with filledcurves, you need a different data format, like
x1 y1_low y1_high
x2 x2_low y2_high
Since you are using awk anyways, you can extract some more information for the actual plotting:
set terminal pngcairo size 800,600
set output "test.png"
set style fill solid 1.0 noborder
unset border
unset xtics
unset ytics
file = 'rect.txt'
lines = system(sprintf('wc -l %s | cut -d'' '' -f 1', file))
frac(x) = system(sprintf('awk ''{if (NR==%d){ print $9 }}'' %s', x, file))
rect(x) = sprintf('awk ''{if (NR==%d){ print $1,$2,$4,"\n",$5,$8,$6,"\n"}}'' %s', x, file)
plot for [i=1:lines] '< '.rect(i) using 1:2:3 with filledcurves palette frac frac(i) notitle
With the data file
0 0 0 1 1 1 1 0 0.5
2 2 2 3 3 3 3 2 0.6
2 2 2 1 1 1 1 2 0.2
you get the output

Show Y Label in groups with Gnuplot

I have this points:
0.00049 1.509
0.00098 1.510
0.00195 1.511
0.00293 1.509
0.00391 1.510
0.00586 1.523
0.00781 1.512
0.01172 1.514
0.01562 1.510
0.02344 1.511
0.03125 1.510
0.04688 7.053
0.06250 7.054
0.09375 7.187
0.125 7.184
0.1875 7.177
0.25 7.207
0.375 16.588
0.5 24.930
0.75 39.394
1 56.615
1.5 77.308
2 84.909
3 89.056
4 88.485
6 88.678
8 89.022
12 88.513
16 88.369
24 88.512
32 88.536
48 87.792
64 87.716
96 87.589
128 87.608
192 87.457
256 87.388
And this gnuplot script:
#! /usr/bin/gnuplot
set terminal png
set output "lat_mem_rd.png"
set title "Memory Latency Benchmark (Stride 512)"
set xlabel "Memory Depth (MB)"
set ylabel "Latency (ns)"
set xtics rotate by 45 offset 0,-1
set xtics font "Times-Roman, 8"
set grid
set style line 1 lc rgb '#0060ad' lt 1 lw 2 pt 7 ps 1 # --- blue
plot "lat_mem_rd.dat" using (log($1)):2:xtic(1) smooth unique title "" with linespoints ls 1
which generates this graphic:
But i want to show the y values in the y label with one of the approximated values in those approximations, for example, for all of the values with x values between 3 and 256, the y label is set to just one, maybe 88.513 that corresponds to x=12 or other (or maybe the average of those points if its not very difficult)...
The same for x values between 0 and 0.02344 and for x values between 0.03125 and 0.1875.
This y values will substitute the values 10, 20, ..., 90.
Here is a modification of your script that might do what you want, if I understand you correctly:
set title "Memory Latency Benchmark (Stride 512)"
set xlabel "Memory Depth (MB)"
set ylabel "Latency (ns)"
set xtics rotate by 45 offset 0,-1
set xtics font "Times-Roman, 8"
set grid
a = ""; p = 0; nn = 1; nt = 37; d = 4; s = 0
f(x) = (x>p+d || nn >= nt)?(nn=nn+1, p=x, a=a." ".sprintf("%5.2f", s/n), n=1, s=x):(nn=nn+1, p=x, s=s+x, n=n+1)
plot "lat_mem_rd.dat" using 1:(f($2)) # Just to set array "a"
set ytics 0,0,0
set yrange [0:90]
set for [aa in a] ytics add (aa aa)
set style line 1 lc rgb '#0060ad' lt 1 lw 2 pt 7 ps 1 # --- blue
set terminal png
set output "lat_mem_rd.png"
plot "lat_mem_rd.dat" using (log($1)):2:xtic(1) smooth unique title "" with linespoints ls 1
This script produces this plot:
The strategy is to accumulate a sum of Y-values and calculate an average every time the Y-value increases by at least an amount d; these averages are stored in a string variable "a", which is looped over to set the ytic values before the final plot command. This way clusters of closely-spaced Y-values give rise to a ytic at their average value; I think that was what you wanted.

Resources