Search code examples
plotgnuplottransparency

Plot data points with connecting lines but which leave gaps


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:

plot of data points with non-touching lines

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

enter image description here


Solution

  • 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)

    enter image description here

    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).