vary point color based on column value for multiple data blocks gnuplot - gnuplot

My question is very similar to this one, from which I was able to learn a lot. However, I am working with multiple data blocks, like this:
1 2 3
4 5 6
7 8 0
4 3 0
4 5 7
2 3 0
4 5 0
5 6 7
and I am plotting them like this:
plot "file.txt" index 0 u 1:2 w points pt 1,\
"file.txt" index 1 u 1:2 w points pt 2
which creates 2 different sets of points, each a different color. Now, my goal is to modify this script so that if the 3rd data column is 0, the color of the point will become black. I would like for the other points to remain the colors that they currently are though (meaning different from one another). I have done this:
set palette model RGB defined ( 0 'black', 1 'green' )
unset colorbox
plot file index 0 u 1:2:( $3 == 0 ? 0 : 1 ) w points pt 1 palette,\
file index 1 u 1:2:( $3 == 0 ? 0 : 1 ) w points pt 2 palette
This does exactly what I want, except of course both sets are now plotted in green. Is there any way to plot the black ones as desired, but also make each index a different color?

This is what the special "variable" color is for:
plot 'test.dat' i 0 u 1:2:($3 == 0? 0:1) w p pt 1 lc variable,\
'test.dat' i 1 u 1:2:($3 == 0? 0:2) w p pt 2 lc variable
variable in this context says to use the color of whatever "style index" was given in the third column. I set filters on the 3rd column variable which transforms the third column into a constant (1 or 2) if the data in that column isn't 0.
Another, less direct approach (which works since you're using points) is:
plot 'test.dat' i 0 u 1:($3 == 0? 1/0: $2) w p pt 1 lc rgb "red",\
'test.dat' i 0 u 1:($3 == 0? $2:1/0) w p pt 1 lc rgb "black,\
'test.dat' i 1 u 1:($3 == 0? 1/0: $2) w p pt 1 lc rgb "green",\
'test.dat' i 1 u 1:($3 == 0? $2:1/0) w p pt 1 lc rgb "black,\

It should work to define an extra point in the palette:
set palette model RGB defined ( 0 'black', 1 'green', 2 'red')
unset colorbox
plot file index 0 u 1:2:( $3 == 0 ? 0 : 1 ) w points pt 1 palette,\
file index 1 u 1:2:( $3 == 0 ? 0 : 2 ) w points pt 2 palette

Related

How to plot energy diagram using gnuplot

I have data file:
0 0 3 -0.17 6 -0.05
0 0 3 -0.23 6 0.90
0 0 3 -0.41 6 0.50
0 0 3 -0.50 6 -0.33
0 0 3 -0.20 6 0.80
I want to plot the figure like this which connects each point in the lines. Can you tell me how?
The following suggestion uses the plotting styles with boxxyerror, with vectors and with labels.
The zero level gets the color of the last entry because everything is plotted on top of each other. Check the following example as starting point for further tweaking.
Script:
### energy diagram
reset session
$Data <<EOD
0 0 3 -0.17 6 -0.05 A_{one}
0 0 3 -0.23 6 0.90 B_{two}
0 0 3 -0.41 6 0.50 C_{three}
0 0 3 -0.50 6 -0.33 D_{four}
0 0 3 -0.20 6 0.80 E_{five}
EOD
set key noautotitle
set xrange [-1:8]
myWidth = 0.3
plot for [i=1:3] $Data u (column(2*i-1)):(column(i*2)):(myWidth):(0):0:xtic(i*2-1) w boxxy lw 3 lc var, \
for [i=1:2] '' u (column(2*i-1)+myWidth):(column(i*2)): \
(column(2*i+1)-column(2*i-1)-2*myWidth):(column(i*2+2)-column(i*2)):0 w vec nohead lw 1 dt 3 lc var, \
'' u 5:6:7:0 w labels offset 6,0 tc var font ",16"
### end of script
Result:
Addition:
From your comments: If the levels are to close such that the labels overlap, you could add an individual offset (here in column 8).
Check the following example where the data is modified that the levels B and E are very close.
Script:
Edit after OP's comment: simplifications, with xerrorbar instead of with boxxyerror and with custom xtics
Edit 2: simplified input data
reduce the input data to the minimum
add xticlabel from columnheader
use column number as x-coordinate. Mind the difference in ...$Data u (col):col:...: e.g. if col=1, (col) is the fixed value of 1, and col is the value from column 1.
### energy diagram with individual offset of labels
reset session
$Data <<EOD
A B C Label Offset
0.0 -0.17 -0.05 A_{one} 0
0.0 -0.23 0.90 B_{two} 0.05
0.0 -0.41 0.50 C_{three} 0
0.0 -0.50 -0.33 D_{four} 0
0.0 -0.20 0.85 E_{five} -0.05
EOD
set key noautotitle
set errorbars 0
set offset 0.5,0.5,0,0
myWidth = 0.1
plot for [col=1:3] $Data u (col):col:(myWidth):0:xtic(columnhead(col)) w xerr lw 3 ps 0 lc var, \
for [col=1:2] '' u (col+myWidth):col:(1-2*myWidth):(column(col+1)-column(col)):0 \
w vec nohead lw 1 dt 3 lc var, \
'' u (3+myWidth):($3+$5):4:0 w labels left offset 1,0 tc var font ",16"
### end of script
Result:

gnuplot plotting multiple errorbars depending on first column

I have a data file with the following format:
col1: plot[0-9]+
col2: x
col3: y
col4: delta
For example:
plot0, 1, 1, 2
plot1, 1, 2, 2
plot0, 2, 2, 1
plot1, 2, 3, 2
I am trying to plot a yerrorbars for each plotX of the first column with separated legend and color.
A none scalable example would be:
plot 'ex.dat' using 1:2:3 with yerrorbars, 'ex1.dat' using 1:2:3 with yerrorbars
Maybe something like this? The color of the datapoint+yerrorbar is taken from the first column via the function GetPlotNo(n) = int(strcol(n)[5:]).
The second plot command is actually plotting a dummy outside of the range just to get the colors of the legend right. If you need the datapoints of each plot1, plot2, ... to be connected, this might get a bit more complicated.
Code:
### color of datapoints depending on a column
reset session
set colorsequence classic
$Data <<EOD
plot0, 1.0, 1, 2
plot1, 1.1, 2, 2
plot0, 2.0, 2, 1
plot1, 2.1, 3, 2
plot2, 1.2, 3, 2
plot0, 3.0, 3, 1
plot1, 3.1, 4, 1
plot2, 2.2, 5, 1
plot2, 3.2, 4, 1
EOD
set datafile separator ","
set xrange[0:4]
set yrange[-1:7]
GetPlotNo(n) = int(strcol(n)[5:])
plot \
$Data u 2:3:4:(GetPlotNo(1)+1) w yerrorbars pt 7 lc var lw 2 notitle, \
for [i=0:2] -999 w lp pt 7 lc i+1 lw 2 title sprintf("plot%i",i) noautoscale
### end of code
Result:
Addition:
Actually, if you want the lines to be connected it requires a small modification. Add/exchange the following lines and the lines of each plot will be connected.
set datafile missing NaN
plot \
$Data u 2:3:4:(GetPlotNo(1)+1) w yerrorbars pt 7 lc var lw 2 notitle, \
for [i=0:2] '' u (i==GetPlotNo(1)?$2:NaN):3:(GetPlotNo(1)+1) w lp pt 7 lc var lw 2 title sprintf("plot%i",i)

Drawing polygons with holes using Gnuplot

Is there a way using Gnuplot 5.0 to plot a polygon with a hole with filledcurves?
Here are my test data:
# Outer ring
0 -2
-2 0
0 2
2 0
0 -2
# Inner ring
-0.5 0.5
-0.5 -0.5
0.5 -0.5
0.5 0.5
-0.5 0.5
And here is the result:
I know I could re-order the vertices in order to hide the connecting line (in fact the polygon frontier) between the outer and inner ring. But I will deal with machine-generated data, and I would prefer minimize the amount of data preprocessing.
In some other drawing programs, we can draw holes inside polygons by changing the winding-rule to even-odd. But I didn't find such option in gnuplot.
Finally, I cannot just draw the "hole" in white, since in my application I have several shapes to draw, And I want to see other shapes behind the "hole".
Why not just plot the hole in white on top of the shape?
Separate your date into
# shape.txt
0 -2
-2 0
0 2
2 0
0 -2
and
# hole.txt
-0.5 0.5
-0.5 -0.5
0.5 -0.5
0.5 0.5
-0.5 0.5
and then use
plot "shape.txt" u 1:2 w filledcurves, 'hole.txt' u 1:2 w filledcurves lc 'white'
The following solution does what you already mentioned in your question: It reorders the points of the inner polygon in such a way, that the endpoint of the outer polygon and the starting point of the inner polygon have minimal distance (hence no line across the inner polygon). It does is automatically with gnuplot only, so this still might be an acceptable solution for you.
Assumptions:
the outer curve is closed (start point = end point)
the outer curve does not have duplicated points
Procedure:
go through the data and when the first x and y values are found again, the outer structure is finished and the inner structure starts (row index stored in idx0)
when the inner structure starts, it looks for the minimum distance to the start/end point of the outer structure (x0,y0) (row index stored in idx1)
the data is plotted into a datablock $Hollow: first the outer as is and then the inner starting from idx1 to end, and then the inner starting from (idx0+2) to idx1.
In the example below red lines are drawn first to illustrate the empty polygon in the center. Tested with gnuplot 5.0.0.
For multiple holes in a filled curve you might want to check gnuplot: How to draw a filled area with hole? with a rather general but pretty lengthy solution.
Code:
### draw hollow polygon
reset session
$Data <<EOD
# Outer ring
0 -2
-2 0
0 2
2 0
0 -2
# Inner ring
-0.5 0.5
-0.5 -0.5
0.5 -0.5
0.5 0.5
-0.5 0.5
EOD
Distance(x0,y0,x1,y1) = sqrt((x1-x0)**2 + (y1-y0)**2)
GetIdxs(colX,colY) = LastOuter==1 ? ( d1=Distance(x0,y0,column(colX),column(colY)), \
d0==d0 ? (d1<dmin ? (idx1=column(0), dmin=d1) : 0) : \
(idx1=column(0),dmin=d1), d0=d1, LastOuter) : \
column(0)==0 ? (d0=d1=dmin=NaN,x0=column(colX),y0=column(colY)) : \
column(colX)==x0 && column(colY)==y0 && LastOuter==0 ? \
(idx0=column(0),x0=column(colX),y0=column(colY),LastOuter=1 ) \
: LastOuter
set table $Dummy
plot LastOuter=0 $Data u 1:2:(GetIdxs(1,2)):(d1) w table
set table $Hollow
plot $Data u 1:2 every ::::idx0 w table
plot $Data u 1:2 every ::idx1 w table
plot $Data u 1:2 every ::idx0+2::idx1 w table
unset table
plot for [i=-5:5] -x+i/5.lw 2 lc "red" notitle, \
$Hollow u 1:2 w filledcurves lc 1
### end of code
Result:
Just for better understanding the content of $Dummy and $Hollow.
$Dummy
0 -2 -2 nan
-2 0 0 nan
0 2 0 nan
2 0 0 nan
0 -2 1 nan
-0.5 0.5 1 2.54951
-0.5 -0.5 1 1.58114
0.5 -0.5 1 1.58114
0.5 0.5 1 2.54951
-0.5 0.5 1 2.54951
$Hollow
0 -2
-2 0
0 2
2 0
0 -2
-0.5 -0.5
0.5 -0.5
0.5 0.5
-0.5 0.5
-0.5 -0.5
My other solution is based on reordering the inner curve in order to avoid the connection line from outer to inner curve crossing the open area. However, this was rather cumbersome with dummy and extra tables and with a lengthy, confusing expression.
Here is a another much simpler solution:
It is based on variable linecolors, i.e. invisible (fully-transparent) lines, when you switch from the outer curve to the inner curve. This should be fine unless you want to create a SVG or DXF and use the graph as pattern for a cutter.
Prerequisites:
outer and inner curves must be closed (first point = last point)
you have to make sure that outer and inner curves have opposite directions (CW=clockwise and CCW=counterclockwise), this was the case in your example. Otherwise the area will not be hollow but filled.
there should be no empty line between inner and outer curves, but two empty lines between the shapes.
You can easily tell gnuplot when the outer curve ends: when the first x,y-coordinates appears again. It doesn't matter where the inner curve starts as long as the direction is reversed to the outer one.
Just for illustration, I plotted sin(x) and made the 1st structure opaque and 2nd and 3rd structure in semitransparent color.
Script: (works for gnuplot>=5.0.3)
### plot areas with holes
reset session
$Data <<EOD
0 -2 0 # outer CW
-2 0 0
0 2 0
2 0 0
0 -2 0
-0.5 0.5 1 # inner CCW
-0.5 -0.5 1
0.5 -0.5 1
0.5 0.5 1
-0.5 0.5 1
-0.5 -1 0 # outer CCW
-0.1 -0.1 0
-1 0.5 0
-1.5 -1 0
-0.5 -1 0
-0.8 0.2 1 # inner CW
-0.2 -0.1 1
-0.6 -0.8 1
-1.2 -0.8 1
-0.8 0.2 1
0 -1 0 # outer CCW
1 -1 0
1.3 0 0
0.3 0 0
0 -1 0
1.1 -0.2 1 # inner CW
0.9 -0.8 1
0.2 -0.8 1
0.4 -0.2 1
1.1 -0.2 1
EOD
myColors = "0x00ff00 0x770000ff 0x77ff0000"
myColor(i) = i+1>words(myColors) ? 0x000000 : int(word(myColors,i+1))
myColorX(i) = (x0=x1, x1=$1, y0=y1, y1=$2, \
$0==0 ? (fx=x1,fy=y1) : x1==fx && y1==fy ? last=1 : 0, \
last ? 0xff123456 : myColor(i))
set key noautotitle
set multiplot layout 1,2
set title "fixed linecolor"
plot 2*sin(2*x) lw 2, \
for [i=0:2] $Data u 1:2:(myColor(i)) index i w filledcurves lc rgb var lw 2
set title "variable line color with fully transparent lines"
plot 2*sin(2*x) lw 2, \
for [i=0:2] x1=y1=(last=0,NaN) $Data u 1:2:(myColorX(i)) index i \
w filledcurves lc rgb var lw 2
unset multiplot
### end of script
Result:

gnuplot: 3d scatter plot with circles

I am trying to do a 3d plot, where I want each point to be with my choice of color/shape/shade. The fact is that I want to use the colour palettes from here.
Lets say my data is like this --
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1
and my gnuplot command looks like this --
set style fill transparent solid 0.75 noborder
set style circle radius screen 0.01
splot "data.out" with circles linecolor rgb "blue"
and I am getting this plot --
as you can see, there is no circle, every point is +.
How do I draw with circles ?
To draw with circles you need
splot "data.out" linecolor "blue" pointtype 6
To get circle try type 6 or 7. Size of circle can be changed by adding option pointsize 2 (number is value of size)

gnuplot hypertext is not working

I have the below gnuplot script, I'm trying to display the third column when the mouse hover over a point of the plot.
set title "Cloud"
set xlabel "Date"
set ylabel "Number"
filename ='data.dat'
stats filename using 4 nooutput
set xdata time
set timefmt '%Y-%m-%d'
set format x '%Y'
rand_x(x) = x + 60*60*24*7 * (rand(0) - 0.5)
rand_y(y) = y + (rand(0) - 0.5)
set xrange [ "1995-01-19":"2013-12-12" ]
plot for [i=0:int(STATS_max)-1] filename \
using (rand_x(timecolumn(1))):(i < $4 ? rand_y($2) : 1/0):3 pointtype 7 linecolor palette notitle
u 0:1:2 with labels hypertext point pt 7 ps var lc rgb "#ffee99"
And the data file looks like below:
1999-01-19 21 0 1
2009-07-01 0 1 1
2008-08-20 2 1 1
2008-12-18 1 1 1
2004-05-12 4 1 1
2009-07-29 2 1 1
2008-08-07 0 1 1
2006-03-08 1 1 1
2004-08-31 9 1 1
2001-03-27 12 1 1
2009-08-19 0 1 1
2010-07-14 2 1 1
2009-06-24 0 1 1
2009-11-11 0 1 1
2010-10-13 0 1 1
2012-02-22 0 1 1
2011-05-11 0 1 1
2011-03-03 0 1 1
2011-09-21 0 1 1
2011-12-20 0 1 1
2011-10-05 0 1 1
2012-05-03 0 1 1
2011-10-05 0 2 1
2013-01-09 0 2 1
2011-06-03 0 2 1
So can you please tell me what's wrong with my script?
Thanks.
First a remark for the readers: hypertext works only with the 4.7 development version.
To your problem: For plotting the labels, you must also use the same x and y columns 1 and 2 (you use 0 and 1). And you need the third column for the labels and a fourth one for the ps var. So your plot part for the labels is:
plot for [i=0:int(STATS_max)-1] filename \
using (rand_x(timecolumn(1))):(i < $4 ? rand_y($2) : 1/0):3 pointtype 7 linecolor palette notitle,\
'' u 1:2:3:3 with labels hypertext point pt 7 ps var lc rgb "#ffee99"

Resources