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 commandset 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> 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
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
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
with somehwat shortened lines between the points. For this, you need to create a preliminary plot in order to get the gnuplot variables GPVAL_...
and do a bit of geometry calculations. The parameter pxGap
determines the line gap in pixels.
Revised version: The previous version was only running for gnuplot 5.0.0 to 5.2.7. The following script now works additionally for gnuplot>=5.2.8. However, does not work (yet) with logarithmic scale.
The desired line gaps are given in pixels and independent of the terminal size and the graph scale. However, since it requires the size of the terminal and graph which are stored in GPVAL_...
-variables which you only get after plotting, therefore the procedure unfortunately requires replotting.
I'm not sure whether this works for all terminals. I only tested on wxt and qt terminals.
Script: (works for gnuplot>=5.0.0)
### "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 0.9
2 1.15
2 2
3 1
3.9 0.9
EOD
set style line 1 pt 6 ps 3 lw 2 lc rgb "black"
set style line 2 pt 6 ps 3 lw 2 lc rgb "red"
set offsets 1,1,1,1
# preliminary plot to get variables GPVAL_...
plot $Data1 u 1:2 w lp ls 1, \
$Data2 u 1:2 w lp ls 3
pxGap = 18. # gap in pixels, 6 pixels per 1 pointsize
Factor = GPVAL_VERSION+real(GPVAL_PATCHLEVEL)/100<=5.27 ? \
GPVAL_TERM eq "wxt" ? 20 : GPVAL_TERM eq "qt" ? 10 : 1 : 1
Rx = (GPVAL_X_MAX-GPVAL_X_MIN)/(GPVAL_TERM_XMAX-GPVAL_TERM_XMIN)*Factor # x ratio axes units to pixel units
Ry = (GPVAL_Y_MAX-GPVAL_Y_MIN)/(GPVAL_TERM_YMAX-GPVAL_TERM_YMIN)*Factor # y
xa2p(x) = (x-GPVAL_X_MIN)/Rx + GPVAL_TERM_XMIN # x axes coordinates to pixel coordinates
ya2p(y) = (y-GPVAL_Y_MIN)/Ry + GPVAL_TERM_YMIN # y
xp2a(x) = (x-GPVAL_TERM_XMIN)*Rx + GPVAL_X_MIN # x pixel coordinates to axes coordinates
yp2a(y) = (y-GPVAL_TERM_YMIN)*Ry + GPVAL_Y_MIN # y
angle(dx,dy) = dx==0 && dy==0 ? NaN : atan2(dy,dx) # -180° to +180°, NaN if dx,dy==0
dxp(n) = pxGap*cos(angle(xp1-xp0,yp1-yp0))
dyp(n) = pxGap*sin(angle(xp1-xp0,yp1-yp0))
set key noautotitle
plot xp1=yp1=NaN, \
$Data1 u (xp0=xp1,xp1=xa2p($1), yp0=yp1,yp1=ya2p($2), xp2a(xp0+dxp(0))):(yp2a(yp0+dyp(0))): \
(xp2a(xp1-dxp(0)) - xp2a(xp0+dxp(0))):(yp2a(yp1-dyp(0)) - yp2a(yp0+dyp(0))) w vec nohead ls 1, \
'' u 1:2 w p ls 1, \
xp1=yp1=NaN, \
$Data2 u (xp0=xp1,xp1=xa2p($1), yp0=yp1,yp1=ya2p($2), xp2a(xp0+dxp(0))):(yp2a(yp0+dyp(0))): \
(xp2a(xp1-dxp(0)) - xp2a(xp0+dxp(0))):(yp2a(yp1-dyp(0)) - yp2a(yp0+dyp(0))) w vec nohead ls 2, \
'' u 1:2 w p ls 2,
### end of script
Result: (gap in pixels, independent of terminal size)
Explanations: (adapted to the new version, originally inserted by Hotschke)
Question: Why is there the argument (n)
for dxp(n)
, dyp(n)
?
n
is always 0
when dxp(n)
,... are computed and is not used on the right hand side.
Answer:
To make them non constant-expressions. Alternatively, one could
add xp0, yp0, xp1, yp1
as variables, e.g. dxp(xp0, yp0, xp1, yp1)
; however, the
compactness would be lost.
Question: What does the using
part in plot $Data1 using (xp0=xp1,xp1=xa2p($1), yp0=yp1,yp1=ya2p($2), xp2a(xp0+dxp(0)))
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 (xp0,yp0,xp1,yp1)
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 xp1=NaN, yp1=NaN
when plotting points ensures that for the
first data point the initial data point (xp0,yp0)
is set to (NaN,NaN)
which has the consequence that the evaluation of dxp(0)
and dyp(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 e.g. around (yp2a(yp0+dyp(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)
.