Change line color during a plot - gnuplot

This command draws nice green sine waves from a data file, but the col4 value goes negative periodically.
"" u (myDateSP(1,2)):4 lc rgb "green" lt 1 lw 6 sm cspl notitle,\
I'd like to have it draw the line red for negative values of col4 and green for positive values and it seems as if I should be able to use the ternary operator for that but I'm having problems with the grammar:
"" u (myDateSP(1,2)):4:($4<= 0) ? lc rgb "red" lt 1 lw 6 sm cspl notitle,\:lc rgb "green" lt 1 lw 6 sm cspl notitle,\
and other variants throw errors. Can someone point out where I have this wrong?
Your table example works nicely, many thanks.
I tried to apply it to a data file like this:
2015-01-03 18:02 01 29.49 feet High Tide
2015-01-04 01:12 01 -2.29 feet Low Tide
2015-01-04 07:02 01 29.09 feet High Tide
2015-01-04 13:22 01 4.54 feet Low Tide
2015-01-04 18:41 01 29.80 feet High Tide
2015-01-04 19:54 01 Full Moon
2015-01-05 01:52 01 -1.87 feet Low Tide
2015-01-05 07:36 01 29.30 feet High Tide
2015-01-05 14:00 01 4.51 feet Low Tide
2015-01-05 19:17 01 29.99 feet High Tide
2015-01-06 02:26 01 -1.30 feet Low Tide
and am not having much luck.
Using this:
set linetype 11 linecolor rgb "green"
set linetype 12 linecolor rgb "red"
set xdata time
set timefmt '%Y-%m-%d'
set format x '%s'
set table 'data-smoothed1.txt'
set samples 1000
plot 'data.txt' using 1:4 smooth cspline
unset table
set timefmt '%s'
set format x '%Y-%m-%d'
set xzeroaxis
plot 'data-smoothed.txt' using 1:4:($4 < 0 ? 12 : 11) linecolor variable with lines no title
It complains that the xrange is wrong, so when I add an range with the beginning and ending dates, it still doesn't help. The "01" column is the month number.

You must use linecolor variable, which allows you to give an additional column which specifies the linecolor to use. But that doesn't work directly with smooth, so that you must first write the smoothed data to an external file (with gnuplot 5 you can also use a heredoc) and then plot this file with linecolor variable.
When doing this, you must also take care of which time format is used to write the smoothed data. The format is taken from the set format x settings. I would use %s, i.e. Unix timestamp.
Here is a full, self-contained example showing the different steps:
An example file data.txt:
2014-02-11 2
2014-03-12 -1
2014-04-15 3
2014-05-22 -2
And the script
set linetype 11 linecolor rgb "green"
set linetype 12 linecolor rgb "red"
set xdata time
set timefmt '%Y-%m-%d'
set format x '%s'
set table 'data-smoothed.txt'
set samples 1000
plot 'data.txt' using 1:2 smooth cspline
unset table
set timefmt '%s'
set format x '%Y-%m-%d'
set xzeroaxis
plot 'data-smoothed.txt' using 1:2:($2 < 0 ? 12 : 11) linecolor variable with lines notitle

Related

gnuplot: how to draw a set of triangles from a file?

In gnuplot, we can set object polygon to draw a polygon, including triangles, given its coordinates.
But how to do draw a set of triangles whose coordinates are stored in a file where each line is in the format <x1> <y1> <x2> <y2> <x3> <y3>?
As for rectrangles/circles, this task can be done using plot and with boxxy/with circles options, but there is no with triangles option in gnuplot.
A possible solution is to use with vectors by drawing each edge, but it is a bit complicated and this method does not support color filling.
I cannot think of a way to do this in one step; the data format does not match any of gnuplot's plotting styles.
One approach is to transform the data via a temporary file. Here is an example that works in version 5.2 and newer. If you are using a newer gnuplot then you could substitute with polygons for with filledcurves closed.
$DATA << EOD
1 1 2 2 3 1
11 11 14 14 17 11
21 21 22 22 23 21
15 5 16 6 17 5
6 6 7 7 8 6
EOD
set table "temp.dat"
plot $DATA using (sprintf("%g %g\n %g %g\n %g %g\n \n",$1,$2,$3,$4,$5,$6)) with table
unset table
unset key
set style fill solid noborder
plot "temp.dat" using 1:2 with filledcurves closed fillcolor "forest-green"
Note: I was originally going to show use of a temporary datablock rather than an intermediate temporary file, but it this doesn't work because the formatted output from with table does not translate the newline characters \n into empty datablock lines.
Edit (show variable color)
The extra data field containing a RGB color must be present in every input line of the reformatted data, but only the value from the first vertex of each polygon is used. The sprintf format in this example has been modified to reproduce the color (NB: hexadecimal integer value) from the original data file accordingly, with zeros for the dummy values in the remaining polygon vertices.
$DATA << EOD
1 1 2 2 3 1 0x00ffff
11 11 14 14 17 11 0x191970
21 21 22 22 23 21 0x2e8b57
15 5 16 6 17 5 0xffc020
6 6 7 7 8 6 0x8b000
EOD
set table "temp.dat"
plot $DATA using (sprintf("%g %g 0x%x\n %g %g 0\n %g %g 0\n \n",$1,$2,int($7),$3,$4,$5,$6)) with table
unset table
unset key
set style fill solid noborder
plot "temp.dat" using 1:2:3 with filledcurves closed fillcolor rgb variable
My suggestion would have been the same as #Ethan's. Therefore, here is an alternative approach using set object polygon.
It also requires gnuplot>=5.2 since it uses indexing of datablock lines. Hence, the data should already be in a datablock without empty or commented lines. But how to get a file into a datablock?
Either something like:
set table $Data
plot FILE u 1:2:3:4:5:6:7 w table
unset table
or alternatively see here: gnuplot: load datafile 1:1 into datablock
Script:
### draw some colored triangles from a datablock
reset session
$Data <<EOD
0 0 2 1 1 2 0xff0000
5 1 3 2 4 4 0x00ff00
3 3 2 5 1 4 0x0000ff
EOD
vx(n,t) = word($Data[n],t*2-1) # vertex x-coordinate
vy(n,t) = word($Data[n],t*2) # vertex y-coordinate
color(n) = word($Data[n],7) # triangle color
set linetype 1 lc rgb "black"
do for [n=1:|$Data|] {
set obj n polygon from vx(n,1),vy(n,1) to vx(n,2),vy(n,2) to vx(n,3),vy(n,3) to vx(n,1),vy(n,1)
set obj n fc rgb color(n) fs solid 0.5 border lt 1 lw 3
}
set size square
set xrange[0:5]
set yrange[0:5]
plot NaN notitle # or plot something else
### end of script
Result:
Addition:
Alternatively, similar to Ethan's solution, plotting triangles instead of drawing triangles, but without using a temporary file on disk (but a datablock). The result is identical to the graph above. I haven't tested whether drawing or plotting is faster and/or more efficient if you want to draw/plot thousands of triangles.
Script:
### plot some colored triangles from a datablock
reset session
$Data <<EOD
0 0 2 1 1 2 0xff0000
5 1 3 2 4 4 0x00ff00
3 3 2 5 1 4 0x0000ff
EOD
vx(n,t) = word($Data[n],t*2-1) # vertex x-coordinate
vy(n,t) = word($Data[n],t*2) # vertex y-coordinate
color(n) = word($Data[n],7) # triangle color
set print $Triangles
do for [n=1:|$Data|] {
print sprintf("%s %s %s\n%s %s 0\n%s %s 0\n%s %s 0\n\n", \
vx(n,1),vy(n,1),color(n), vx(n,2),vy(n,2), vx(n,3),vy(n,3), vx(n,1),vy(n,1))
}
set print
set size square
set xrange[0:5]
set yrange[0:5]
set linetype 1 lc rgb "black" lw 3
set style fill solid 0.5
plot $Triangles u 1:2:3 w filledcurves lc rgb var notitle
### end of script

gnuplot drawing multiple plots in same chart

I'm trying to follow the guide to plotting financial data on gnuplot found here:
http://gnuplot.sourceforge.net/demo/finance.html
I generated some data and tried plotting with the following script:
1 set datafile separator ","
2 set object 1 rectangle from screen 0,0 to screen 1,1 fillcolor rgb"#cccccc" behind
3
4 set xdata time
5 set timefmt "%Y-%M-%dT%H:%M:%S"
6 set format x "%d-%H"
7
8 set ylabel "Price"
9 set xlabel 'Time'
10
11 set style line 100 lt 1 lc rgb "grey" lw 0.5
12 set style line 101 lt 1 lc rgb "orange" lw 1
13
14 set grid ls 100
15 set key off
16
17 plot "lastrun.dat" using 1:2 with lines, '' using 1:3 with lines ls 101, '' using 1:4 with lines ls 101
however the resulting graph seems to not stich together the data correctly, so instead of one chart, i have three in the same space.
i'm sure i'm making a simple error but I've been stumped about what that is.
Check help time_specifiers:
%d day of the month, 01–31
%H hour, 00–23 (always two digits)
%m month, 01–12
%M minute, 0–60
%S second, integer 0–60 on output, (double) on input
%Y year, 4-digit

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

GNUPLOT LINUX Value y-axis near every point of a graph

I need to do a graph with gnoplot linux where on x-axis there are a date and on y-axis value of ok, ko and warning.
I've written the following code
#!/usr/bin/gnuplot
reset
unset title
set xlabel "Date (day/month)"
set ylabel "num Instance"
set yrange [0:40]
set term png large
set output "graph2.png"
set grid
set xdata time
set timefmt "%d/%m"
set format x "%d/%m"
plot \
'input.dat' using 1:2 with points pointtype 11 linecolor rgb "#00FF00" ti 'OK',\
'input.dat' using 1:3 with points pointtype 11 linecolor rgb "#ff0000" ti 'KO',\
'input.dat' using 1:4 with points pointtype 3 linecolor rgb "#ffed00" ti 'Warning'
with this input file
#date ok ko warning
06/02 1 30 3
07/02 5 14 16
08/02 30 15 14
09/02 9 14 9
10/02 7 30 3
11/02 2 7 21
12/02 30 12 15
13/02 10 15 14
14/02 24 14 16
15/02 20 12 15
and the graph is this
new_graph
Now I've to insert, near every point, also a value of y-axis.
Any idea?
I appreciate your help and thank you in advance

GNUplot: string value in ternary operator

Coming back to an old project and have obviously forgotten something here.
Datafile:
2017-03-31 14:38 6.42 feet High Tide
2017-03-31 20:40 -0.30 feet Low Tide
2017-04-01 02:56 6.92 feet High Tide
2017-04-01 06:34 Full Moon
2017-04-01 09:19 -0.58 feet Low Tide
2017-04-01 15:33 6.17 feet High Tide
When I plot as follows, all works fine except the ternary operator to test for the string(s) in strcol(3):
set terminal aqua size 950,594
set timefmt "%Y-%m-%d %H:%M"
unset key
set samples 1000
set xtics 86400
set x2tics 86400
set xtics nomirror font "Gill Sans Light,14" tc rgb "blue"
set grid ytics back
set grid x2tics
set format x "%a"
set format x2 "%d"
set xdata time
set x2data time
set yrange [-1:7.5]
set xzeroaxis lt 1 lw 1 lc rgb "red"
myDate(col1,col2)=sprintf("%s %s",strcol(1),strcol(2))
myLabel(col3,col2) = sprintf("%s ft.\n%s",strcol(col3),strcol(col2))
plot "tidefiles-test2.txt" \
u (myDate(1,2)):3:((strcol(5) eq "High") ? (myLabel(3,2)) :1/0) with labels font "Gill Sans Light,12" offset 0,-2 tc rgb "blue",\
"" u (myDate(1,2)):3:((strcol(5) eq "Low") ? (myLabel(3,2)) :1/0) with labels font "Gill Sans Light,12" offset 0,+2 tc rgb "red",\
"" u (myDate(1,2)):3:(strcol(3) eq "Full") ? ("●"):1/0 w labels left font "Symbola,48" offset -4,0,\
"" u (myDate(1,2)):3 lc rgb "green" lw 1 sm cspl notitle
The line with the string Full doesn't have a y-value. So, when the condition strcol(3) eq "Full" is fulfilled, at the same time the actual y-value is not a valid number and so that point is also skipped.
Using e.g.
plot "tidefiles-test2.txt" \
"" u (myDate(1,2)):(strcol(3) eq "Full" ? 0 : $3):((strcol(3) eq "Full") ? ("●"):1/0) w labels left font "Symbola,24" offset -4,0
works fine, but requires you to use a hard-coded y-value. Otherwise you must add an appropriate y-value in your data file for the "Full"-case.

Resources