From d2f20bb5c7a6313c76580ff953a0abfd7ee1cf17 Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Fri, 30 Nov 2018 11:29:09 +0100 Subject: [PATCH] full_range_monthly.gnuplot: fix sampling when drawing boxes Instead of working around the problem by doubling the sample rate, fix the actual problem and prevent different samples to refer to the same box, resulting in holes in the background. The solution is to have samples fall in the middle of months instead of their boundaries, this compensates for the fact that different months having a slightly different number of days. Now two different samples are always in two different months. --- full_range_monthly.gnuplot | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/full_range_monthly.gnuplot b/full_range_monthly.gnuplot index 98c6578..e5c6b57 100755 --- a/full_range_monthly.gnuplot +++ b/full_range_monthly.gnuplot @@ -72,6 +72,9 @@ start_of_month(x) = strptime("%Y-%m-%d", "" . int(tm_year(x)) . "-". int(tm_mon( # strptime() seems to adjust the year automatically when passing a month > 12 start_of_next_month(x) = strptime("%Y-%m-%d", "" . int(tm_year(x)) . "-" . (int(tm_mon(x)) + 2) . "-01") +# Calculate the difference between two dates. +months_between_dates(a, b) = int((tm_year(b) - tm_year(a)) * 12 + tm_mon(b) - tm_mon(a)) + # Dummy plot to gather some stats from the dataset set terminal unknown plot 'data.dat' using 1:2 @@ -85,16 +88,8 @@ set xrange [xmin:xmax] set yrange [ymin:ymax] # Calculate the x sampling rate for the '+' plot below. -# -# The sample rate below is two times the strictly needed one because in this -# way the month spacing error is reduced: "set samples" assumes evenly -# distributed data, but starts of months are not, so it may happen that -# a month gets skipped or repeated. -# -# With this workaround most of the tiles of the background gradient will be -# drawn twice but there will be less chance of missing intervals because of -# accumulation of errors. -x_samples = int((xmax - xmin) / one_month) * 2 +# Have one sample per month, the +1 is to include the month of xmax. +x_samples = months_between_dates(xmin, xmax) + 1 set samples x_samples, 100 set xtics three_months @@ -103,8 +98,28 @@ set terminal qt 0 #set terminal png notransparent nocrop truecolor rounded enhanced font "arial,8" fontscale 1.0 #set output 'full_range_monthly.png' -# Use the boxxyerrorbars style to draw the background choosing the color -# according to the month. +# The plot is done in three steps: +# +# 1. Plot an undefined function to force gnuplot to use the specified xrange +# and yrange without rescaling them, this makes sure that changing the +# sampling interval later does not affect the displayed xrange. +# +# 2. Use the boxxyerrorbars style to draw the background choosing the color +# according to the month. +# +# When doing this, shift samples to make them fall in the middle of months. +# +# This is needed to avoid "holes" between the boxes because samples are +# evenly spaced while months lengths are not, so it may happen that +# a sample crosses the month boundary even when it's not supposed to, +# resulting in two different samples to draw the same box because of +# start_of_month() and start_of_next_month(). +# +# Having some "buffering days" can compensate for the varying months +# lengths. +# +# 3. Finally plot the actual data plot \ - '+' using ($1):(0):(start_of_month($1)):(start_of_next_month($1)):(ymin):(ymax):(tm_mon($1)) with boxxy fc palette fs solid notitle, \ + NaN notitle, \ + [xmin - one_month/2 : xmax - one_month/2] '+' using ($1):(0):(start_of_month($1)):(start_of_next_month($1)):(ymin):(ymax):(tm_mon($1)) with boxxy fc palette fs solid notitle, \ 'data.dat' using 1:2 w l lc rgb "black" title "data" -- 2.1.4