Search code examples
gnuplot

How to stack impulses in Gnuplot?


I am using Gnuplot to show the precipitation measured during the last 13 monthts. Data is read from two data files, rain.dat and snow.dat. I use impulses, but on days with both rain and snow the impulses are plotted over each other. It had been better if the impulses were stacked.

#!/usr/bin/gnuplot -persist
set xdata time
set timefmt "%d.%m.%Y"
set ylabel "Precipitation (mm)"
set xrange ["01.`date --date="1 year ago" +%m.%Y`":"01`date --date="1 month" +.%m.%Y`"]
set xtics "01.`date --date="1 year ago" +%m.%Y`",2800000, \
          "01.`date --date="now 1 month" +%m.%Y`" offset 3,0.2
set format x "%b"
set style line 100 lt 3 lc rgb "gray" lw 0.5
set style line 101 lt 3 lc rgb "gray" lw 0.5
set grid back xtics ytics mytics ls 100, ls 100, ls 101
set terminal png size 1000,200
set output 'precipitation.png'
plot 'rain.dat' using 1:2 title 'Rain' w impulses lt rgb '#ff0000' lw 4 , \
     'snow.dat' using 1:2 title 'Snow' w impulses lt rgb '#0000ff' lw 2

rain.dat:
16.02.2021 8
22.02.2021 6
04.03.2021 10
08.03.2021 13
14.03.2021 5

snow.dat:
19.02.2021 19
22.02.2021 10
04.03.2021 14
12.03.2021 8

enter image description here

How can impulses be stacked with Gnuplot?


Solution

  • As @Ethan already mentioned, with impulses will always start at 0. If you don't mind some little extra effort, you can mimic "stacking" impulses if you first plot the sum of rain and snow with the "snow color", and then plot rain alone with the "rain color" on top of it.

    But how do you get the sum of rain and snow?

    • plot your datablocks (or files) into the temporary datablock $Temp.
    • plot datablock $Temp into the datablock $SnowAndRain using the option smooth frequency which sums up snow and rain for each day. Check help smooth.

    Script: (works for gnuplot>=5.2.0, Sept. 2017)

    ### "stacked" impulses
    reset session
    
    $Rain <<EOD
    16.02.2021 8
    22.02.2021 6
    04.03.2021 10
    08.03.2021 13
    14.03.2021 5
    EOD
    
    $Snow <<EOD
    19.02.2021 19
    22.02.2021 10
    04.03.2021 14
    12.03.2021 8
    EOD
    
    myTimeFmt = "%d.%m.%Y"
    
    set table $Temp
        plot $Snow u (sprintf("%.0f",timecolumn(1,myTimeFmt))):2 w table
        plot $Rain u (sprintf("%.0f",timecolumn(1,myTimeFmt))):2 w table
    set table $SnowAndRain
        set format x "%.0f"
        plot $Temp u 1:2 smooth freq
    unset table
    
    set format x "%d %b" timedate
    plot $SnowAndRain u 1:2 w impulses lw 4 lc "blue" title 'Snow', \
                $Rain u (timecolumn(1,myTimeFmt)):2 w impulses lc "red" lw 4 title 'Rain', \
    ### end of script
    

    Result:

    enter image description here

    Addition:

    A bit more cumbersome solution which seem to work with gnuplot 5.0.0 (at least with Win10). I hope somebody can simplify this.

    Script: (tested with Win10 gnuplot 5.0.0. Same result as above)

    ### "stacked" impulses (should work with gnuplot 5.0.0)
    reset session
    
    $Rain <<EOD
    16.02.2021 8
    22.02.2021 6
    04.03.2021 10
    08.03.2021 13
    14.03.2021 5
    EOD
    
    $Snow <<EOD
    19.02.2021 19
    22.02.2021 10
    04.03.2021 14
    12.03.2021 8
    EOD
    
    myTimeFmt = "%d.%m.%Y"
    
    set table $Temp
        plot $Snow u (t=timecolumn(1,myTimeFmt)/1e5,int(t)):2:((t-int(t))*1e5) w table
        plot $Rain u (t=timecolumn(1,myTimeFmt)/1e5,int(t)):2:((t-int(t))*1e5) w table
    unset table
    
    set table $SnowAndRain
        set format x "%.0f"
        plot $Temp u ($1*1e5+$3):2 smooth freq
    unset table
    
    set format x "%d %b" timedate 
    plot $SnowAndRain u 1:2 w impulses lw 4 lc "blue" title 'Snow', \
                $Rain u (timecolumn(1,myTimeFmt)):2 w impulses lc "red" lw 4 title 'Rain'
    ### end of script