I like following linespoints plotting style:
http://www.gnuplotting.org/join-data-points-with-non-continuous-lines/
However, I have encountered an issue when I plot several lines with this style:
As you can see the second series of points blank-out also the first series (lines and points), what I don't want to happen.
Feature of gnuplot which makes this possible is pointinterval and pointintervalbox.
Documentation of gnuplot:
A negative value of pointinterval, e.g. -N, means that point symbols
are drawn only for every Nth point, and that a box (actually circle)
behind each point symbol is blanked out by filling with the background
color. The command set pointintervalbox controls the radius of this
blanked-out region. It is a multiplier for the default radius, which
is equal to the point size.
http://www.bersch.net/gnuplot-doc/set-show.html#set-pointintervalbox
Since the doc says, fill with background color I was hoping using a transparent background the issue could be resolved, but it seems to be that the color white is used.
Gnuplot version
gnuplot> show version long
G N U P L O T
Version 5.0 patchlevel 0 last modified 2015-01-01
Copyright (C) 1986-1993, 1998, 2004, 2007-2015
Thomas Williams, Colin Kelley and many others
gnuplot home: http://www.gnuplot.info
faq, bugs, etc: type "help FAQ"
immediate help: type "help" (plot window: hit 'h')
Compile options:
-READLINE +LIBREADLINE +HISTORY
-BACKWARDS_COMPATIBILITY +BINARY_DATA
+GD_PNG +GD_JPEG +GD_TTF +GD_GIF +ANIMATION
-USE_CWDRC +HIDDEN3D_QUADTREE
+DATASTRINGS +HISTOGRAMS +OBJECTS +STRINGVARS +MACROS +THIN_SPLINES +IMAGE +USER_LINETYPES +STATS +EXTERNAL_FUNCTIONS
Minimal Working Example (MWE):
gnuplot-space-line-mark-style.gp
reset
set terminal pngcairo transparent size 350,262 enhanced font 'Verdana,10'
show version
set output 'non-continuous_lines.png'
set border linewidth 1.5
set style line 1 lc rgb '#0060ad' lt 1 lw 2 pt 7 pi -1 ps 1.5
set style line 2 lc rgb '#0020ad' lt 1 lw 2 pt 7 pi -1 ps 1.5
set pointintervalbox 3
unset key
set ytics 1
set tics scale 0.75
set xrange [0:5]
set yrange [0:4]
plot 'plotting_data1.dat' with linespoints ls 1,\
'plotting_data2.dat' with linespoints ls 2
plotting_data1.dat
# X Y
1 2
2 3
3 2
4 1
plotting_data2.dat
# X Y
1.2 2.4
2 3.5
3 2.5
4 1.2
UPDATE
A working pgfplots solution is given on tex.stackoverflow.com
You can do a lot with gnuplot. It's just a matter of how complicated you allow it to get.
You can realize the gap by a two step plotting. First: only with points and second: with vectors which are lines between the points shortened by performing a bit of geometry calculations.
The parameter L1 determines the gap and needs to be adjusted to the data and graph scale. Tested with gnuplot 5.0 and 5.2.
Revised version:
Here is the version which creates gaps independent of the terminal size and the graph scale. It just requires bit more scaling. However, since it requires the size of terminal and graph which are stored in GPVAL_...-variables which you only get after plotting, therefere the procedure unfortunately requires replotting.
I'm not sure whether this works for all terminals. I just tested on a wxt terminal.
Empirical findings (for wxt-terminal on Win7):
pointsize 100 (ps) corresponds to 600 pixels (px), hence: Rpxps=6 (ratio pixel to pointsize )
term size 400,400 (px) corresponds to 8000,8000 terminal units (tu), hence: Rtupx=20 (ratio terminal units to pixels)
Edit: the factor Rtupx apparently is different for different terminals: wxt: 20, qt: 10, pngcairo: 1, you could use the variable GPVAL_TERM for checking the terminal.
Rtupx = 1. # for pngcairo terminal 1 tu/px
if (GPVAL_TERM eq "wxt") { Rtupx = 20. } # 20 tu/px, 20 terminal units per pixel
if (GPVAL_TERM eq "qt") { Rtupx = 10. } # 10 tu/px, 10 terminal units per pixel
The ratios of axis units (au) to terminal units (tu) are different for x and y and are:
Rxautu = (GPVAL_X_MAX-GPVAL_X_MIN)/(GPVAL_TERM_XMAX-GPVAL_TERM_XMIN)
Ryautu = (GPVAL_Y_MAX-GPVAL_Y_MIN)/(GPVAL_TERM_YMAX-GPVAL_TERM_YMIN)
The variable GapSize is given in pointsize units. Actually, the real gap size depends on the pointsize (and also linewidth of the line). For simplicity, here gap size means the distance from the center of the point to where the line starts. So, GapSize=1.5 when having pointsize 1.5 will result in a gap of 0.75 on each side. L3(n) from the earlier version is now replaced by L3px(n) in pixel dimensions and L1 from the earlier version is not needed anymore.
Code:
### "linespoints" with gaps between lines and points
reset session
$Data1 <<EOD
# X Y
0 3
1 2
1.5 1
3 2
4 1
EOD
$Data2 <<EOD
0 0
1 1
2 1
2 2
3 1
3.98 0.98
EOD
GapSize = 1.5
Rtupx = 20. # 20 tu/px, 20 terminal units per pixel
Rpxps = 6. # 6 px/ps, 6 pixels per pointsize
# Ratio: axis units per terminal units
Rxautu(n) = (GPVAL_X_MAX-GPVAL_X_MIN)/(GPVAL_TERM_XMAX-GPVAL_TERM_XMIN)
Ryautu(n) = (GPVAL_Y_MAX-GPVAL_Y_MIN)/(GPVAL_TERM_YMAX-GPVAL_TERM_YMIN)
dXpx(n) = (x3-x0)/Rxautu(n)/Rtupx
dYpx(n) = (y3-y0)/Ryautu(n)/Rtupx
L3px(n) = sqrt(dXpx(n)**2 + dYpx(n)**2)
x1px(n) = dXpx(n)*GapSize*Rpxps/L3px(n)
y1px(n) = dYpx(n)*GapSize*Rpxps/L3px(n)
x2px(n) = dXpx(n)*(L3px(n)-GapSize*Rpxps)/L3px(n)
y2px(n) = dYpx(n)*(L3px(n)-GapSize*Rpxps)/L3px(n)
x1(n) = x1px(n)*Rtupx*Rxautu(n) + x0
y1(n) = y1px(n)*Rtupx*Ryautu(n) + y0
x2(n) = x2px(n)*Rtupx*Rxautu(n) + x0
y2(n) = y2px(n)*Rtupx*Ryautu(n) + y0
set style line 1 pt 7 ps 1.5 lc rgb "black"
set style line 2 lw 2 lc rgb "black
set style line 3 pt 7 ps 1.5 lc rgb "red"
set style line 4 lw 2 lc rgb "red"
plot \
$Data1 u (x3=NaN, y3=NaN,$1):2 w p ls 1 notitle, \
$Data1 u (y0=y3,y3=$2,x0=x3,x3=$1,x1(0)):(y1(0)): \
(x2(0)-x1(0)):(y2(0)-y1(0)) w vectors ls 2 nohead notitle, \
$Data2 u (x3=NaN, y3=NaN,$1):2 w p ls 3 notitle, \
$Data2 u (y0=y3,y3=$2,x0=x3,x3=$1,x1(0)):(y1(0)): \
(x2(0)-x1(0)):(y2(0)-y1(0)) w vectors ls 4 nohead notitle
replot
### end of code
Result: (two different terminal sizes)
Explanations:
Question: Why is there the argument (n) for L3(n), x1(n), y1(n), x2(n), y2(n)?
n is always 0 when L3(n),... are computed and is not used on the right hand side.
Answer:
To make them non constant-expressions. Alternatively, one could
add x0,x3,y0,y3 as variables, e.g. L3(x0, y0, x3, y3); however, the
compactness would be lost.
Question: What does the using part in plot $Data1 using (x3=NaN,y3=NaN,$1):2 mean?
Answer:
(,) is called a serial evaluation which is documented under the
section Expressions > Operator > Binary in the gnuplot documentation
(only v4.4 or newer).
Serial evaluation occurs only in parentheses and is guaranteed to
proceed in left to right order. The value of the rightmost subexpression
is returned.
This is done here for the initialialization of (x3,y3) for the
subsequent plot of the line segments as vectors. It is irrelevant for
the plotting of points.
Question: How does this draw N-1 segments/vectors for N points?
Answer:
Setting x3=NaN, y3=NaN when plotting points ensures that for the
first data point the initial data point (x0,y0) is set to (NaN,NaN)
which has the consequence that the evaluation of x1(0) and y1(0) also returns NaN.
Gnuplot in general skips points with NaN, i.e. for the first
data point no vector is drawn. The code draws the line between the
first and second point when the iteration reaches the second point.
Question: How does the second plot '' u ... iterates over all points?
Answer:
gnuplot> h special-filenames explains this:
There are a few filenames that have a special meaning: '', '-', '+' and '++'.
The empty filename '' tells gnuplot to re-use the previous input file in the
same plot command. So to plot two columns from the same input file:
plot 'filename' using 1:2, '' using 1:3
Question: Do we need the parentheses around (y1(0))?
Answer: gnuplot> h using explains this:
Each may be a simple column number that selects the value from one
field of the input file, a string that matches a column label in the first
line of a data set, an expression enclosed in parentheses, or a special
function not enclosed in parentheses such as xticlabels(2).
Related
I have a datafile that has three columns :
1 1.0 1
2 1.5 2
3 0.0 3
4 1.2 2.5
5 1.0 1
6 1.1 5
where the first column is my X value, the second column is my Y value, and the third column is the line width. I'd like for each line segment to be plotted according to the third column line width.
I tried:
plot 'file1.dat' using 1:2:3 with lines lw var
But I get undefined variable: var error.
Is this possible in gnuplot?
Thanks.
If you define column 3 as the linewidth between points n and n+1 (so the value of col. 3 of the row will be ignored) you can cheat:
stat 'file1.dat'
n=STATS_records
plot for [i=0:0] 'file1.dat' using 1:2:(alma=$3) every ::i::i w l lc 1 lw 1
plot for [i=0:n-1] 'file1.dat' using 1:2:(alma=$3) every ::i::i+1 w l lc 1 lw alma notitle
OR
plot 'file1.dat' u 0:1
n=GPVAL_DATA_X_MAX
plot for [i=0:0] 'file1.dat' using 1:2:(alma=$3) every ::i::i w l lc 1 lw 1
plot for [i=0:n] 'file1.dat' using 1:2:(alma=$3) every ::i::i+1 w l lc 1 lw alma notitle
You need the first plot for[i=0:0] to 'initialize' variable 'alma'.
stat 'varwidth.dat' nooutput
n=STATS_records; prex=0; prey=0; SC=2 # How y-axis is expanded relative to the x-axis
plot for [i=0:n-1] for [try=0:1] '' using 1:((try==0?dx=$1-prex:1),(try==0?sl=($2-prey)/(dx==0?1:dx):1),(try==0?prex=$1:1),(try==0?prey=$2:1),$2+(w=$3/80*sqrt(1+(SC*sl)**2))/2):($2-w/2) every ::i::i+1 w filledcurves lc 1 notitle
This produces the correct line width (as opposed to the “line height”, as in the answer to a related question). I have no clue how to make the “lines” match where they join (seems to be impossible without support from inside gnuplot).
(This assumes that the data in the question is in a file varwidth.dat.)
As mentioned by #Christoph in the comments, you have N points (rows) and N linewidth values, but only N-1 connecting lines.
So, you have to decide which linewidth value should be applied to which line. Which one to skip? The first one or the last one? Here, the last one is skipped.
It's basically, a shortened version of #Tom Solid's solution. Actually, you can get the initial value already during the stats command.
As #Joce mentioned and #Ilya Zakharevich is suggesting in his answer, if you do not fear some extra effort you can also draw tapered lines.
Data:
# x y linewidth
1 1.0 1
2 1.5 2
3 0.0 3
4 1.2 2.5
5 1.0 1
6 1.1 5
Script: (works with gnuplot 4.6.0, March 2012)
### workaround for variable linewidth
reset
FILE = "SO/SO37925489.dat"
stats FILE u ((N=$0)==0?Lw0=$3:0) nooutput
set grid
plot for [i=0:N] FILE u 1:2:(Lw0=$3) every ::i::i+1 w l lw Lw0 lc rgb "red" notitle
### end of script
Result:
I want to plot a file with linespoints in Gnuplot but the line using all the data samples and the points using fewer data samples. For example the following file plots the data but the line is not visible at all.
set terminal png
set out "plot_sample.png"
plot [t=-1000:1000] t w linespoints pt 64 lt 10 ps 1.5
How to do it if I want to define a custom sampling interval for the points but use all the data samples for the line? I could do two separate plots in the same figure but then the key will show both of them separately.
Use pointinterval to reduce the number of plotted points, but keep all points for drawing the line:
set samples 100
plot x**2 w linespoints pointinterval 10
Use every to reduce the samples taken from file!
Plot the line and
the points in two part, and use notitle at one of them!
Don't forget to 'synchronize' the color of the 2 plots!
Something like:
plot [t=-1000:1000] 'data.dat' w l lt 10 lc 10 t 'something', '' every 10 w p pt 64 ps 1.5 lc 10 notitle
NOTES
Usage of every: plot 'alma.dat' every A:B:C:D:E:F
where
A is the data increment (every Ath)
B is the datablock increment (datablocks are separated by empty lines)
C/D is the first data/datablock (start from C/D)
E/F is the last data/datablock (end at E/F)
You can use all the features described above, but if you don't need, just leave it empty, eg. ...every 2 or every 2::1 or every 2::1:0 ect...
I want to create a streamline like arrow lines in Gnuplot,I already have the data points that I needed, so I think my problem is not the same as this post says and different from this post because I have already obtain the data needed for stramlines.
What I have done is like this:
So the red lines are vectors show flow field and green line is streamlines to guide the readers the direction of the flux. And all the large blue arrows are my aim to be plotted in GNUPLOT. I have kown how to plot middle arrows as this post has shown but what code I need to do if I want to plot more arrows along the lines?
To be more detailed, How can I plot like this:
I supply my data file here :
velocity.txt is for vector flow field data as "index,X,Y,vx,vy,particle-numbers"
line.txt is for streamline data as "X,Y"
and My gnu file is bleow:
set terminal postscript eps size 108,16 enhanced font "Arial-Bold,100"
set output 'vector.eps'
unset key
set tics
set colorbox
set border 0
set xtics 2
#set xlabel 'x'
#set ylabel 'y'
set xrange [0:108]
set yrange [0:16]
#set cbrange [0:40]
set nolabel
set style line 4 lt 2 lc rgb "green" lw 2
plot 'velcoity.txt' u 2:3:(250*$4):(250*$5) with vectors lc 1,'line.txt' u 1:2 ls 4
Thank you!
To plot arrows along a line you can again use the vectors plotting style like you do already for the stream field.
But to get a proper plot you must consider several points:
Usually gnuplot limits the size of the arrow heads to a fraction of the arrow length. So, if you want to plot a continuous line with arrows heads, the arrows themselves should have a very short length. To avoid downscaling of the arrow heads, use the size ... fixed option, which is available only since version 5.0
You have only the trajectory, x and y values, of the line. To extract the arrow direction, the simplest approach would be to use the difference between two neighbouring points (or at a distance of two or three points).
You can extract these differences in the using statement. As pseudo code, one could do the following:
if rownumber modulo 10 == 0:
save x and y values
else if rownumber modulo 10 == 1:
draw arrow from previous point to current point, only with a head
else
ignore the point.
Putting this pseudo-code in the using statement gives the following:
ev = 10
avg = 1
sc = 0.1
plot 'line.txt' u (prev_x = (int($0)%ev == 0 ? $1 : prev_x), prev_y = (int($0)%ev == 0 ? $2 : prev_y), int($0)%ev == avg ? $1 : 1/0):2:(sc*(prev_x-$1)):(sc*(prev_y-$2)) w vectors backhead size 2,20,90 fixed ls 4
To make things more flexible, I introduced some variables: ev tells you the difference count between two arrows heads, avg the distance between two points used to calculate the arrow direction, and sc the length of the arrow shaft.
As further improvement you can use the length of the stream field arrows to colour the stream field vectors. This gives the following script
reset
unset key
set tics
set colorbox
set border 0
set xtics 2
set autoscale xfix
set autoscale yfix
set autoscale cbfix
set style line 4 lt 2 lc rgb "green" lw 2
ev=30
avg=3
sc=0.1
field_scale=500
plot 'velcoity.txt' u 2:3:(field_scale*$4):(field_scale*$5):(sqrt($4**2+$5**2)) with vectors size 1,15,45 noborder lc palette,\
'line.txt' u 1:2 ls 4 w l,\
'' u (prev_x = (int($0)%ev == 0 ? $1 : prev_x), prev_y = (int($0)%ev == 0 ? $2 : prev_y), int($0)%ev == avg ? $1 : 1/0):2:(sc*(prev_x-$1)):(sc*(prev_y-$2)) w vectors backhead size 2,20,90 fixed ls 4
With the result (qt terminal):
I have used gnuplot succesfully to plot boxplots. But now I would like to stick to gnuplot for all my plotting needs and looking to do something that eg. Prism can do:
http://www.graphpad.com/support/faqid/132/
I only have two columns of data (before and after) and want all pairs to be joined up with a line. If anyone has any idea, it would be great.
That is not possible out of the box, so it requires some fiddling.
The xtics are set manually, 0 is the x-value of 'Before', 1 for 'After'. These numerical values must be used explicitely later in the plots.
The lines are plotted as arrows without heads. Using lc variable (i.e. linecolor variable), we can use the last column of the using statement to select the color from the respective line type.
The 'Before' points are plotted first. Unfortunately, there is no option pointtype variable, so I use the plot for iteration to assign each point a different pointtype (pt).
I use the stats command to determine the number of points to plot. To get the total count, I must sum up the records, which are the inside points, and the outofrange points, because the classification is done based on the first column's value, which conflict with the 'manual' xtics settings for the 'Before' and 'After' labels.
These are the main points. Of course, there are many other possibilities (using line styles etc.), but should be a good starting point.
The script is:
reset
file='beforeafter.txt'
set xtics ('Before' 0, 'After' 1)
set xrange [-0.2:1.2]
set offset 0,0,0.2,0.2
stats file nooutput
cnt = int(STATS_records+STATS_outofrange)
plot for [i=0:cnt-1] file using (0):1 every ::i::i with points lc i+1 pt (6+i) ps 2 t '',\
for [i=0:cnt-1] file using (1):2 every ::i::i with points lc i+1 pt (6+i) ps 2 t '',\
file using (0):1:(1):($2-$1):($0+1) with vectors nohead lc variable t ''
With the test data beforeafter.txt:
1 5.5
2 0.3
3 3
And you get the result:
Using line styles
Another variant uses line styles to set the color, line type, and point type. For the iterations you must use explicitely ls (i+1), whereas for the vectors the as variable (arrowstyle variable) is used. With the lc variable it is not possible to set different dash patterns for the arrows.
So here is a, in my opinion, much more readable and flexible variant:
reset
set termoption dashed
file='beforeafter.txt'
set xtics ('Before' 0, 'After' 1)
set xrange [-0.2:1.2]
set offset 0,0,0.2,0.2
stats file nooutput
cnt = int(STATS_records+STATS_outofrange)
set style line 1 lt 1 pt 5 ps 2 lw 2 lc rgb '#AE1100'
set style line 2 lt 2 pt 7 ps 2 lw 2 lc rgb '#6EB043'
set style line 3 lt 3 pt 9 ps 2 lw 2 lc rgb '#7777ff'
set for [i=1:3] style arrow i ls i nohead
unset key
plot file using (0):1:(1):($2-$1):($0+1) with vectors as variable,\
for [i=0:cnt-1] file using (0):1 every ::i::i with points ls (i+1),\
for [i=0:cnt-1] file using (1):2 every ::i::i with points ls (i+1)
With the result:
I have a data in file which I would like to plot using gnuplot. In the file, there are 3 data sets separated by two blank lines so that gnuplot can differentiate between the data sets by 'index'. I can plot three data sets separately via 'index' option of 'plot' command.
However, I am not sure how can I plot the data which is sum of 2nd column of all three data sets?
Note: all three data sets have same x data, i.e. 1st column
To do this the simplest thing would be to change your file format. Gnuplot manipulates columns pretty well. Since you are sharing the x data, you can change the file format to have four columns (assuming you are just plotting (x,y) data):
<x data> <y1 data> <y2 data> <y3 data>
and use a command like
plot 'data.dat' using 1:2 title 'data 1', \
'' u 1:3 t 'data 2', \
'' u 1:4 t 'data 3', \
'' u 1:($2+$3+$4) t 'sum of datas'
The dollar signs inside the parens in the using column specification allow you to add/subtract/perform other functions on columnar data.
This way your data file will also be smaller since you won't repeat the x data.
#Youjun Hu, never say that there is "no way" to do something with gnuplot. Most of the cases there is a way with gnuplot only, sometimes maybe not obvious or sometimes a bit cumbersome.
Data: SO16861334.dat
1 11
2 12
3 13
4 14
1 21
2 22
3 23
4 24
1 31
2 32
3 33
4 34
Code 1: (works with gnuplot 4.6.0, needs some adaptions for >=4.6.5)
In gnuplot 4.6.0 (version at the time of OP's question) there were no datablocks and no plot ... with table. The example below only works for 3 subdatasets, but could be adapted for other numbers. However, arbitrary large number of subdatasets will be difficult with this approach.
### calculate sum from 3 different (sub)datasets, gnuplot 4.6.0
reset
FILE = "SO16861334.dat"
stats FILE u 0 nooutput
N = int(STATS_records/STATS_blocks) # get number of lines per subblock
set table FILE."2"
plot FILE u 1:2
set table FILE."3"
x1=x2=y1=y2=NaN
myValueX(col) = (x0=x1,x1=x2,x2=column(col), r=int($0-2)/N, r<1 ? x0 : r<2 ? x1 : x2)
myValueY(col) = (y0=y1,y1=y2,y2=column(col), r<1 ? y0 : r<2 ? y1 : y2)
plot FILE."2" u (myValueX(1)):(myValueY(2))
unset table
set key top left
set offset graph 0.1, graph 0.1, graph 0.2, graph 0.1
plot for [i=0:2] FILE u 1:2 index i w lp pt 7 lc i+1 ti sprintf("index %d",i), \
FILE."3" u 1:2 every ::2 smooth freq w lp pt 7 lc rgb "magenta" ti "sum"
### end of code
Code 2: (works with gnuplot>=5.0.0)
This code works with arbitrary number of subdatasets.
### calculate sum from 3 different (sub)datasets, gnuplot>=5.0.0
reset
FILE = "SO16861334.dat"
set table $Data2
plot FILE u 1:2 w table
unset table
set key top left
set offset graph 0.1, graph 0.1, graph 0.2, graph 0.1
set colorsequence classic
plot for [i=0:2] FILE u 1:2 index i w lp pt 7 lc i+1 ti sprintf("index %d",i), \
$Data2 u 1:2 smooth freq w lp pt 7 lc rgb "magenta" ti "sum"
### end of code
Result: (same result for Code1 with gnuplot 4.6.0 and Code2 for gnuplot 5.0.0)