Gnuplot labels in column with different shape - gnuplot

I have a little problem. I try create gnu plot with many lines or shapes but header is in last column . Example data in file
18:40:03 0.00 K/s 3.65 K/s 0.00 % 0.25 % AA
18:40:03 0.00 K/s 69.44 K/s 0.00 % 0.05 % BB
18:40:03 0.40 K/s 0.00 K/s 0.00 % 0.03 % AA
my gnuplot code
set xlabel "Date\nTime"
set timefmt "%H:%M:%S"
set format x "%H:%M:%S"
set xdata time
set autoscale xy
set term png
set output "io.png"
plot 'io.log' using 0:8 title 'title', \
'' using 0:8:10 with labels offset 0,char 1
~
But I want create plot where this same type (AA) have this same color or shape and different from BB CC .....
in

A rather old question with no feedback of the OP, but maybe still of interest to others.
As I understand, you are basically looking for a lookup table with string input.
You can define your keys, pointtypes, colors in strings and "mis-use" the function sum to define a lookup function.
Check help sum, help word, help variable.
Script:
### lookup tables with string input for different point types and colors
reset session
$Data <<EOD
1 9 AA
2 8 BB
3 6 CC
4 8 AA
5 6 BB
6 4 DD
7 2 CC
8 4 AA
EOD
myLabels = "AA BB CC DD"
myPts = "5 7 9 11" # pointtypes
myColors = "0xff0000 0x00ff00 0x0000ff 0xff00ff"
myPt(col) = int(word(myPts,Lookup(strcol(col))))
myColor(col) = int(word(myColors,int(Lookup(strcol(col)))))
Lookup(s) = int(sum [_i=1:words(myLabels)] (word(myLabels,_i) eq s ? _i : 0))
set key noautotitle
set grid x,y
set offset 0.5,0.5,0.5,0.5
plot $Data u 1:2:3:(myColor(3)) w labels tc rgb var font ",12" offset 0,1, \
'' u 1:2:(myPt(3)):(myColor(3)) w p ps 2 pt var lc rgb var
### end of script
Result:

In order to simplify things, let's assume that the input data is stored in a file test.dat and it has following form:
1 2 AA
2 4 BB
3 6 AA
Then there are several possibilities to distinguish the style based on the value of the label in the third column.
One could for example invoke external processing to filter out records of the "special type" (label "AA" in your case) and specify a particular style:
unset key
set xr [0:4]
set yr [0:10]
plot \
'< gawk ''$3=="AA"'' test.dat' using 1:2 w p pt 1, \
'' u 1:2:3 w labels offset 0,char 1 tc rgb 'red', \
'< gawk ''$3!="AA"'' test.dat' using 1:2 w p pt 2, \
'' u 1:2:3 w labels offset 0,char 1 tc rgb 'blue'
This produces:
Alternatively, in order to distinguish just the style of the labels, one could filter individual cases directly in Gnuplot as:
set terminal png enhanced
set output 'fig2.png'
unset key
set xr [0:4]
set yr [0:10]
checkLabel(label)=(label eq 'AA')
filter(label, val, flag)=(((flag && checkLabel(label))||(!flag && !checkLabel(label)))?val:1/0)
plot \
'test.dat' using 1:2 w p , \
'' using 1:(filter(stringcolumn(3), $2, 1)):3 w labels offset 0,char 1 tc rgb 'red', \
'' using 1:(filter(stringcolumn(3), $2, 0)):3 w labels offset 0,char 1 tc rgb 'blue'
which yields:

Related

gnuplot - how to plot invisible points so that the plot is only used to mark x-axis

I have the following data in data file test1.txt:
A 36 1
A 35 1
B 48 2
B 37 2
B 15 2
C 36 3
C 25 3
and test2.txt
A 16 1
A 25 1
B 38 2
B 45 2
C 36 3
the plotting is done as:
dat1="test1.txt"
dat2="test2.txt"
plot dat1 u ($3-0.2):2 w p t 'title 1', \
dat2 u ($3+0.2):2 w p t 'title 2', \
dat1 using 3:(0):xticlabels(1):x2ticlabels(1) notitle, \
dat2 using 3:(0):xticlabels(1):x2ticlabels(1) notitle
The whole point is to have the labels from the first column on the x axis. The issue is that the last two parts of plot
dat1 using 3:(0):xticlabels(1):x2ticlabels(1) notitle, \
dat2 using 3:(0):xticlabels(1):x2ticlabels(1) notitle
produce points at y=0. And because I cannot (or I do not know how to) use
plot dat1 u ($3-0.2):2:xticlabels(1) w p t 'title 1'
(since it plots the label at x coordinate $3-0.2 and not at $3, which i require), I am forced to do two more dummy plots, but they produce points and I do not know how to effectively avoid this other than shifting the outside of the range of the plot by e.g. dat1 using 3:(0):xticlabels(-1):x2ticlabels(-1) in the case of plotting only positive values. Is there any good way of solving this?
I don't really understand what you are trying to do with your data, however if you want to make the points over the x axis invisible you can set the line color to full transparency for the last two plots:
dat1 using 3:(0):xticlabels(1):x2ticlabels(1) linecolor "#FFFF0000" notitle, \
dat2 using 3:(0):xticlabels(1):x2ticlabels(1) linecolor "#FFFF0000" notitle
In recent versions of Gnuplot (link) it is possible to add transparency, in this particular case you want to set full transparency to the line color so that the points are invisible. The color format and transparency can be set using the hexadecimal notation #AARRGGBB where AA (alpha) controls how transparent the color is, for full transparency you want FF which is equivalent to 255, notice how my line color is RED but because is completely transparent we don't see it.
Plot with Full Transparency
My understanding of your question is the following: You have some data which you want to shift in x by +/-0.2 but the corresponding tic shouldn't be shifted.
You've been almost there. Of course, there are points at y=0 because you tell gnuplot to do so.
What you mean with "invisible" could of course be also achieved by fully transparent points, but the easier way is probably to "plot" the points at NaN, i.e. nowhere.
Code:
### plotting data with offset and tic without offset
reset session
set colorsequence classic
$Data1 <<EOD
A 36 1
A 35 1
B 48 2
B 37 2
B 15 2
C 36 3
C 25 3
EOD
$Data2 <<EOD
A 16 1
A 25 1
B 38 2
B 45 2
C 36 3
EOD
set offsets 0.5,0.5,0.5,0.5
set link x2
set x2tics
plot $Data1 u ($3-0.2):2 w p pt 7 t 'title 1', \
$Data2 u ($3+0.2):2 w p pt 7 t 'title 2', \
$Data1 using 3:(NaN):xtic(1):x2tic(1) notitle, \
$Data2 using 3:(NaN):xtic(1):x2tic(1) notitle
### end of code
Result:

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

Separate key (legend) for colors and markers

I have a plot with several types of objects (each read from a separate file). I'm plotting the same several functions for all of them, all on the same graph (same X-axis).
I set the markers (pt) explicitly for each, and the color (lc), so the same object has the same marker, but the same function has the same color. As an example we have 2 files, one for each object (| is just to separate the files here):
0 0 0 | 0 1 1
1 1 2 | 1 1 2
Let's call the left file A, the right B. Column 1 in each file is the x axis, column 2 is using 1:2, and column 3 is using 1:3. So using the above files in an interactive session:
gnuplot> plot "A" using 1:2 with lp pt 1 lc 'black'
gnuplot> replot "A" using 1:3 with lp pt 1 lc 'red'
gnuplot> replot "B" using 1:2 with lp pt 2 lc 'black'
gnuplot> replot "B" using 1:3 with lp pt 2 lc 'red'
we get:
Is it possible to have the key separated, so A/B appear next to their respective marker, and the function name ("using...") appears next to a line (or anything) with the appropriate color?
Right now by omitting titles (notitle in the plot command) I can get one or the other, though I would have to settle on some uniform arbitrary marker/color (depending on what I chose to set as key). Can I:
Get two keys somehow? - Preferably setting the missing attribute (color or marker) to something not in the plot.
If not, can I customize a manual legend somehow?
I am not fully sure what you want to achieve, nevertheless as for the splitting of the key, I don't think that Gnuplot has some "out-of-the-box" feature for this. However, you could (ab)use multiplot to achieve this effect. The idea is basically to generate two overlapping plots - one with points and one with lines - and to position the keys independently:
set terminal pngcairo rounded font ",16"
set output 'fig.png'
$A << EOD
0 0 0
1 1 2
EOD
$B << EOD
0 1 1
1 1 2
EOD
set multiplot
set xtics out nomirror
set ytics out nomirror
eps = 0.1
set lmargin at screen eps
set rmargin at screen 1 - eps/2
set bmargin at screen eps
set tmargin at screen 1 - eps/2
#common key settings
set key left top Left reverse spacing 1.5
set key at screen 0.1,screen 1-eps
plot \
$A u 1:2 with p ps 1.5 pt 1 lc 'black' t 'A', \
$A u 1:3 with p ps 1.5 pt 1 lc 'red' t 'A' , \
$B u 1:2 with p ps 1.5 pt 2 lc 'black' t 'B', \
$B u 1:3 with p ps 1.5 pt 2 lc 'red' t 'B'
unset border; unset xtics; unset ytics
set key at screen 0.3,screen 1-eps
plot \
$A u 1:2 with l lc 'black' t 'using 1:2', \
$A u 1:3 with l lc 'red' t 'using 1:3', \
$B u 1:2 with l lc 'black' t '', \
$B u 1:3 with l lc 'red' t ''
This would give you:

Gnuplot: Find y value for given x value

I have a set of data points I plot with gnuplot. Know I calculate a value for x and want to find the corresponding y value within the data.
Does anybody know how to manage this with gnuplot?
I found kind of a solution here on StackOverflow
Basically you have to invert the function you use to calculate y (or x in the case of the link) and then, thanks to the sprintf function, you gate the corresponding value.
NOTE
Have a look also here if you did not find the solution at the first link!
Although this is a rather old question, the following solution for interpolation might still be of interest to others.
The code can be simplified depending on whether you are just interested in nearest datapoint or in the interpolated value or whether you want to plot the value as point and/or label.
Code:
### interpolate between datapoints
reset session
$Data <<EOD
0 0
0.30 0.20
0.60 0.40
0.80 0.80
1 1
EOD
$Data2 <<EOD
1 0
0.80 0.15
0.50 0.30
0.50 0.50
0.30 0.80
0 1
EOD
InterpolY(x,x0,x1,y0,y1) = (x-x0)*(x-x1)<0 || x1-x0==0 ? x1-x0==0 ? (y0+y1)/2 : (y1-y0)/(x1-x0)*(x-x0) +y0 : NaN
set key noautotitle
array Point[1] # dummy array for plotting a single datapoint
# x-value for interpolation is defined in xp
plot x1=y1=yp=(xp=0.7,NaN) $Data u (x0=x1,x1=$1):(y0=y1,y1=$2, yp==yp ? NaN : yp=InterpolY(xp,x0,x1,y0,y1),y1) w lp pt 7, \
Point u (xp):(yp) w p pt 7 lc "red", \
Point u (xp):(yp):(sprintf("(%.2g|%.2g)",xp,yp)) w labels right offset -1,0 lc "red", \
x1=y1=yp=(xp=0.5,NaN) $Data2 u (x0=x1,x1=$1):(y0=y1,y1=$2, yp==yp ? NaN : yp=InterpolY(xp,x0,x1,y0,y1),y1) w lp pt 7, \
Point u (xp):(yp) w p pt 7 lc "green", \
Point u (xp):(yp):(sprintf("(%.2g|%.2g)",xp,yp)) w labels right offset -1,0 lc "green", \
### end of code
Result: (interpolated values at x=0.7 and x=0.5)

Gnuplot: plotting points with variable point types

I have x,y values for points in the first 2 colums and a number that indicates the point type (symbol) in the 3. column, in one data file. How do I plot data points with different symbols?
Unfortunately, there isn't a way (AFAIK) to automatically set the point of the plot from a column value using vanilla GNUPLOT.
However, there is a way to get around that by setting a linestyle for each data series, and then plotting the values based on that defined style:
set style line 1 lc rgb 'red' pt 7 #Circle
set style line 2 lc rgb 'blue' pt 5 #Square
Remember that the number after pt is the point-type.
Then, all you have to do is plot (assuming that the data in "data.txt" is ordered ColX ColY Col3):
plot "data.txt" using 1:2 title 'Y Axis' with points ls 1, \
"data.txt" using 1:3 title 'Y Axis' with points ls 2
Try it here using this data (in the section titled "Data" - also note that column 3 "Symbol" is noted used, it's mainly there for illustrative purposes):
# This file is called force.dat
# Force-Deflection data for a beam and a bar
# Deflection Col-Force Symbol
0.000 0 5
0.001 104 5
0.002 202 7
0.003 298 7
And in the Plot Script Heading:
set key inside bottom right
set xlabel 'Deflection (m)'
set ylabel 'Force (kN)'
set title 'Some Data'
set style line 1 lc rgb 'red' pt 7
set style line 2 lc rgb 'blue' pt 5
plot "data.txt" using 1:2 title 'Col-Force' with points ls 1, \
"data.txt" using 1:3 title 'Beam-Force' with points ls 2
The one caveat is of course that you have have to reconfigure your data input source.
REFERENCES:
http://www.gnuplotting.org/plotting-single-points/
http://www.gnuplotting.org/plotting-data/
Here is a possible solution (which is a simple extrapolation from gnuplot conditional plotting with if), that works as long as you don't have tens of different symbols to handle.
Suppose I want to plot 2D points in a coordinate system. I have only two symbols, that I arbitrarily represented with a 0 and a 1 in the last column of my data file :
0 -0.29450470209121704 1.2279523611068726 1
1 -0.4006965458393097 1.0025811195373535 0
2 -0.7109975814819336 0.9022682905197144 1
3 -0.8540692329406738 1.0190201997756958 1
4 -0.5559651851654053 0.7677079439163208 0
5 -1.1831613779067993 1.5692367553710938 0
6 -0.24254602193832397 0.8055955171585083 0
7 -0.3412654995918274 0.6301406025886536 0
8 -0.25005266070365906 0.7788659334182739 1
9 -0.16853423416614532 0.09659398347139359 1
10 0.169997438788414 0.3473801910877228 0
11 -0.5252010226249695 -0.1398928463459015 0
12 -0.17566296458244324 0.09505800902843475 1
To achieve what I want, I just plot my file using conditionals. Using an undefined value like 1/0 results in no plotting of the given point:
# Set styles
REG_PTS = 'pointtype 7 pointsize 1.5 linecolor rgb "purple"'
NET_PTS = 'pointtype 4 pointsize 1.5 linecolor rgb "blue"'
set grid
# Plot each category with its own style
plot "data_file" u 2:($4 == 0 ? $3 : 1/0) title "regular" #REG_PTS, \
"data_file" u 2:($4 == 1 ? $3 : 1/0) title "network" #NET_PTS
Here is the result :
Hope this helps
Variable pointype (pt variable) was introduced (I guess) not until gnuplot 5.2.0 (Sept 2017) (check help points).
Just in retrospective, another (awkward) solution would be the following for those who are still using such early versions.
Data:
1 1.0 4 # empty square
2 2.0 5 # filled square
3 3.0 6 # empty circle
4 4.0 7 # filled circle
5 5.0 8 # empty triangle up
6 6.0 9 # filled triangle down
7 7.0 15 # filled pentagon (cross in gnuplot 4.6 to 5.0)
Script: (works from gnuplot>=4.6.0, March 2012; but not necessary since 5.2.0)
### variable pointtype for gnuplot>=4.6
reset
FILE = 'SO23707979.dat'
set key noautotitle
set offsets 1,1,1,1
set pointsize 4
stats FILE u 0 nooutput
N = STATS_records # get the number of rows
p0=x1=y1=NaN
plot for [n=0:N-1 ] FILE u (x0=x1, x1=$1, x0):(y0=y1, y1=$2, y0):(p0=$3) \
every ::n::n w p pt p0 lc rgb "red", \
FILE u 1:2 every ::N-1::N-1 w p pt p0 lc rgb "red"
### end of script
Result:

Resources