full_range_monthly.gnuplot: fix sampling when drawing boxes
[experiments/gnuplot_seasonal_plot.git] / full_range_monthly.gnuplot
index 98c6578..e5c6b57 100755 (executable)
@@ -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")
 
 # 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
 # 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.
 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
 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'
 
 #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 \
 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"
   'data.dat' using 1:2 w l lc rgb "black" title "data"