producing variable colors with decimal numbers - gnuplot

I created a file which looks like where the first column is the color line in decimal and the second column is y-axis. The x-axis is the row number.
0 0
1 1
2 2
...
Then I run this command
plot "test.dat" u 0:2:1 pt 7 ps 1 lc rgb variable
As you can see in the picture, the output contains a range of black to blue colors only.
Why?
How can I produce other colors?

Basically you have the choice between three options, linecolor rgb variable, linecolor variable and linecolor palette. Which one you use and how depends on your actual requirements.
When you use linecolor rgb variable, the value given in the last column is used as integer representation of an rgb-tuple, i.e. the lowest byte is the blue part, the second lowest the green part and the third byte is the red component. This is what you have.
For using this option you must either have the full rgb-integer values in your data file, like
0 13.5 # black
0 17
65280 12 # green (255 * 2**8)
0 19.3
16711680 14.7 # red (255 * 2**16)
65280 10
16711680 22
and then use
plot 'test.txt' using 0:2:1 linecolor rgb variable pt 7
Alternatively you save the red, green and blue components in one column each and use a gnuplot function to calculate the rgb-integer:
0 0 0 13.5 # black
0 0 0 17
0 255 0 12 # green
0 0 0 19.3
255 0 0 14.7 # red (255 * 2**16)
0 255 0 10
255 0 0 22
and then use
rgb(r,g,b) = 65536 * int(r) + 256 * int(g) + int(b)
plot 'test.txt' using 0:4:(rgb($1,$2,$3)) linecolor rgb variable pt 7
Using linecolor variable would use the last column as linetype index. Large indices are wrapped to the set of defined linetype:
set xrange [0:1000]
plot '+' using 1:1:0 linecolor variable pt 7
Using linecolor palette uses the last column as index for the color palette:
set xrange [0:1000]
plot '+' using 1:1:0 linecolor palette pt 7
Which variant you use may depend both on the number of different colors and the distribution of the colors.

Related

Drawing a simple polygon using Gnuplot with "angle signs"

Disclaimer: I am new to Gnuplot, and I need to plot some "simple" things for my studies.
I want to plot a part of a polygon with some names and vectors added.
The picutre below was created with Euklid Dynageo, and I am now trying to create this with Gnuplot.
The biggest problem I am facing right now is the labeling u,v,w and adding the angles to the plot. I think I would use vectors and lines.
Do you now a 'simple' way to create this plot?
If you really need to use Gnuplot for this, you have to make it all manually by placing various objects, labels and arrows (keep in mind that complex plots will be cumbersome). A minimal example for two arrows and alpha_1, similar like in your example, could like like this:
# two arrows:
set arrow 1 from 0,0 to sqrt(2)/2,sqrt(2)/2
set arrow 2 from 0,0 to 1,0
# the alpha_1 symbol:
set label 1 '{/Symbol a}_1' at 0.2,0.1 front
# the filled yellow arc (from 0 to 45deg):
set style fill solid 1.0 border
set object 1 circle at 0,0 radius 0.2 arc[0:45] fc rgb "yellow"
# proper ratio, range, and plot 'something':
set xrange[-0.1:1.1]
set yrange[-0.1:1.1]
set size ratio 1
plot 1/0
Lookup the manual for possible object properties.
gnuplot is a very versatile plotting tool, but certainly not optimized for such tasks. For this type of drawing maybe Inkscape or others tools might be better choices, especially for interactive drawing by clicking, dragging and snapping.
And as #JackGlasshard already mentioned, of course you can do such graphs with gnuplot which will be rather time consuming if you do it manually.
Alternatively, you can facilitate the work if you use a "template".
Creating such a template probably only makes sense if you need to create more than one drawing.
Just for fun and feasibility, I tried to create such a template for general use to make such graphs easier.
For the input data you need 3 datablocks (without headers)
$Points: # no., x, y, label, xoff, yoff, pt, ps, color
you define: point number, x-coordinate, y-coordinate, point label, x-offset, y-offset, pointtype, pointsize, point color
$Vectors: # p1, p2, label, arrow, lw, dt, xoff, yoff, color
you define: first point number, second point number, label, arrowsstyle (-1=backhead, 0=nohead, 1=head, 2=heads), linewidth, dashtype, x-offset, y-offset, vector color
$Angles: # p1, p2, p3, r, label, aoff, roff, color
you define: 1st point number, 2nd point number (=angle center point), 3rd point number, radius, label, angular label offset, radial label offset, color
Now, you only have to change the data part of the script for your custom graph. In case you want to insert "invisible" vector starting or end points, simply set pointsize to 0 in $Points. The plotting of the variable arrowheads is a bit cumbersome because of the issue mentioned in this question.
For sure, more features and more flexibility can be added to the template. No warranty that the script is free of bugs. There is certainly room for improvements.
Update: (linewidth and dashtype added)
Since there is no variable linewidth (lw var) and no variable dashtype (dt var)
you have to plot each line separately in a for loop and every ::n::n.
Furthermore, I noticed that the order of variable pointsize (ps var) and and variable pointtype (pt var) apparently has changed from gnuplot 5.2 to 5.4. Not sure whether this intentional or a "bug".
The version below has the order for gnuplot 5.4.
Script:
### drawing sketch with points, vectors and angles
reset session
# no., x, y, label, xoff, yoff, pt, ps, color
$Points <<EOD
1 1 1 "" 0 0 5 1 0xff0000
2 10 2 V_{i-1} 0 0 5 1 0xff0000
3 15 10 V_i 0 0 5 1 0xff0000
4 4 12 X -1.5 0 5 1 0xff0000
5 14 16 V_{i+1} 0 0 5 1 0xff0000
6 5 20 "" 0 0 5 1 0xff0000
EOD
# p1, p2, label, arrow, lw, dt, xoff, yoff, color
# arrows: -1=backhead, 0=nohead, 1=head, 2=heads
$Vectors <<EOD
1 2 "" 0 1.0 1 0 0 0xff0000
2 3 "" 0 2.0 1 0 0 0x000000
3 5 "" 0 1.5 3 0 0 0x000000
4 2 w 1 1.0 1 1.0 0 0x000000
4 3 v 1 1.0 1 0 0.7 0x0000ff
4 5 u 1 1.0 1 0 0.7 0x000000
5 6 "" 0 1.0 1 0 0 0x000000
EOD
# p1, p2, p3, r, label, aoff, roff, color
# p2=angle center point
$Angles <<EOD
2 4 3 4.0 α_{i-1} 7.0 0.5 0xffcccc
3 4 5 4.5 α_i 3.0 0.7 0xffffcc
EOD
### end of data input
### start of template
# point/vector coordinates
px(n,m) = real(word($Points[int(word($Vectors[n],m))],2)) # x coordinate of point n
py(n,m) = real(word($Points[int(word($Vectors[n],m))],3)) # y coordinate of point n
vxd(n) = px(n,2)-px(n,1) # vector delta x
vyd(n) = py(n,2)-py(n,1) # vector delta y
vxc(n) = (px(n,2)+px(n,1))/2. # vector center x
vyc(n) = (py(n,2)+py(n,1))/2. # vector center y
lw(n) = real(word($Vectors[n],5))
dt(n) = int(word($Vectors[n],6))
# angles
as(n) = int(column(5)+2) # arrow style
ax(n) = real(word($Points[int(word($Angles[int(column(0)+1)],n))],2)) # angle center x
ay(n) = real(word($Points[int(word($Angles[int(column(0)+1)],n))],3)) # angle center y
set angle degrees
Angle(x0,y0,x1,y1) = (_dx=x1-x0, _dy=y1-y0, _L=sqrt(_dx**2 + _dy**2), _L==0 ? NaN : \
(_dy>=0 ? acos(_dx/_L) : -acos(_dx/_L) ))
a1(m) = Angle(ax(2),ay(2),ax(1),ay(1)) # starting angle
a2(m) = Angle(ax(2),ay(2),ax(3),ay(3)) # end angle
set style arrow 1 backhead filled # -1
set style arrow 2 nohead filled # 0
set style arrow 3 head filled # 1
set style arrow 4 heads filled # 2
set size ratio -1 # ensure same x- and y-ratio
set key noautotitle
set xrange [0:22]
set yrange [0:22]
set mxtics 5
set mytics 5
set grid x,y,mx,my
set style fill solid 0.5 border lc "black"
plot $Angles u (ax(2)):(ay(2)):4:(a1(0)):(a2(0)):8 w circles lc rgb var, \
'' u (ax(2)+($4*0.5+$7)*cos(0.5*(a1(0)+a2(0))+$6)): \
(ay(2)+($4*0.5+$7)*sin(0.5*(a1(0)+a2(0))+$6)):5 w labels font "Times New Roman,13" center, \
for [i=1:|$Vectors|] $Vectors \
u (px(i,1)):(py(i,1)):(vxd(i)):($4==-1?vyd(i):NaN):9 every ::i-1::i-1 w vectors lc rgb var lw lw(i) dt dt(i) filled backhead, \
for [i=1:|$Vectors|] '' \
u (px(i,1)):(py(i,1)):(vxd(i)):($4== 0?vyd(i):NaN):9 every ::i-1::i-1 w vectors lc rgb var lw lw(i) dt dt(i) filled nohead, \
for [i=1:|$Vectors|] '' \
u (px(i,1)):(py(i,1)):(vxd(i)):($4== 1?vyd(i):NaN):9 every ::i-1::i-1 w vectors lc rgb var lw lw(i) dt dt(i) filled head, \
for [i=1:|$Vectors|] '' \
u (px(i,1)):(py(i,1)):(vxd(i)):($4== 2?vyd(i):NaN):9 every ::i-1::i-1 w vectors lc rgb var lw lw(i) dt dt(i) filled heads, \
for [i=1:|$Vectors|] '' \
u (vxc(i)+$7):(vyc(i)+$8):3:9 every ::i-1::i-1 w labels font ",12" tc rgb var, \
$Points u 2:3:7:8:9 w p ps var pt var lc rgb var, \
'' u ($2+$5):($3+$6):4:9 w labels tc rgb var font ",12" left offset 1,0
### end of script
Result:

gnuplot : using a logarithmic axis for a histogram

I have a data file that I am creating a histogram from.
The data file is :
-0.1 0 0 JANE
1 1 1 BILL
2 2 1 BILL
1 3 1 BILL
6 4 0 JANE
35 5 0 JANE
9 6 1 BILL
4 7 1 BILL
24 8 1 BILL
28 9 1 BILL
9 10 0 JANE
16 11 1 BILL
4 12 0 JANE
45 13 1 BILL
My gnuplot script is :
file='test.txt'
binwidth=10
bin(x,width)=width*floor(x/width)
set boxwidth 1
plot file using (bin($1,binwidth)):(1.0) smooth freq with boxes, \
file using (1+(bin($2,binwidth))):(1.0) smooth freq with boxes
I would like to plot this data on a logscale in y. However there are some 0 values (because some of the bins are empty) that cannot be handled by set logscale y. I get the error Warning: empty y range [1:1], adjusting to [0.99:1.01].
According to gnuplot's help, "The frequency option makes the data monotonic in x; points with the same x-value are replaced by a single point having the summed y-values."
How can I take the log10() of the summed y-values computed by smooth freq with boxes?
There are at least two things that you could do. One is to use a linear axis between 0 and 1 and then use the logarithmic one as explained in this answer. The other one is to plot to a table first and then set the log scale ignoring the points with zero value.
With a normal linear axis and your code (plus set yrange [0:11]) your data looks:
Now lets plot to a table, then set the log scale, then plot ignoring the zero values:
file='test.txt'
binwidth=10
bin(x,width)=width*floor(x/width)
set table "data"
plot file using (bin($1,binwidth)):(1.0) smooth freq, \
file using (1+(bin($2,binwidth))):(1.0) smooth freq
unset table
set boxwidth 1
set logscale y
set yrange [0.1:11]
plot "data" index 0 using ($1):($2 == 0 ? 1/0 : $2) with boxes lc 1, \
"data" index 1 using ($1):($2 == 0 ? 1/0 : $2) with boxes lc 2
set table sometimes generates some undesirable points in the plot, which you can see at x = 0. To get rid of them you can use "< grep -v u data" instead of "data".

Gnuplot histogram with rgb colours from file

I have a file formatted as follows:
A 12.0 255,20,147
B 325.0 255,255,0
C 134456.0 255,255,0
D 13869.0 0,0,0
E 4321.0 255,0,0
F 43676.0 165,42,42
I would like to produce a histogram where $2 is the height of the bar, $1 is the label (i.e.: it is written below the bar, under the x axis) and $3 is the RGB colour of the bar.
I have read this and this but I still can't figure out how to do what I just described.
I found a way to do it: you first have to change the formatting of the rgb colours changing the commas to spaces, so that the new file becomes:
A 12.0 255 20 147
B 325.0 255 255 0
C 134456.0 255 255 0
D 13869.0 0 0 0
E 4321.0 255 0 0
F 43676.0 165 42 42
then you have to instruct gnuplot on how to parse the rgb colours:
rgb(r,g,b) = int(r)*65536 + int(g)*256 + int(b)
finally you can specify that you want column 1 to be the label (xticlabels(1)) and that you want variable colour (lc rgb variable), passing your rgb function the appropriate columns of your file (rgb($3,$4,$5)).
Summing it all up, the following commands worked for me:
set style fill solid
rgb(r,g,b) = int(r)*65536 + int(g)*256 + int(b)
plot 'hist_test.dat' using (column(0)):2:(0.5):(rgb($3,$4,$5)):xticlabels(1) w boxes lc rgb variable;

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:

Gnuplot different colors

I'm trying to color a plot and a fit in gnuplot in different colors, but it doesn't work:
set ylabel "s in m"
set xlabel "t in s"
unset key
set style line 1 lt 2 lc rgb "red" lw 3
set style line 2 lt 2 lc rgb "orange" lw 2
plot "-" with lines ls1
0 0
1 4.2
2 7.9
3 11.7
4 16.3
fit "-" with lines ls2
0 0
1 4.2
2 7.9
3 11.7
4 16.3
Does anybody have an idea what I am doing wrong?
There are several things you are doing wrong:
The fit command is a bit different from the plot command. You must define a function like f(x) = a*x + b and fit this to your data. This calculates appropriate values for a and b. Afterwards you can plot the function.
You must terminate the inline data with an e.
To select a line style, use ls 1 (with the space before the number).
So your script should look as follows:
set ylabel "s in m"
set xlabel "t in s"
unset key
set style line 1 lt 2 lc rgb "red" lw 3
set style line 2 lt 2 lc rgb "orange" lw 2
f(x) = a*x + b
fit f(x) '-' via a,b
0 0
1 4.2
2 7.9
3 11.7
4 16.3
e
plot f(x) with lines ls 2, "-" with points ls 1
0 0
1 4.2
2 7.9
3 11.7
4 16.3
e
This plots your fit as a line, and the according data as points.

Resources