bugGNU Octave - Bugs: bug #50493, datetick crashes on certain date...

 
 

bug #50493: datetick crashes on certain date ranges

Submitter:  Lars Kindermann <larskindermann>
Submitted:  Wed 08 Mar 2017 12:06:56 PM UTC
   
 
Category:  Plotting Severity:  3 - Normal
Priority:  5 - Normal Item Group:  Unexpected Error or Warning
Status:  Fixed Assigned to:  None
Originator Name:  Open/Closed:  * Closed
Release:  * dev Operating System:  * Any
Fixed Release:  None Planned Release:  None
* Mandatory Fields

Add a New Comment Rich Markup
   

Jump to the original submission

Thu 16 Mar 2017 04:30:33 PM UTC, comment #12: 

Slowly clearing these bug reports.  I pushed the change for datetick to the stable branch here (http://hg.savannah.gnu.org/hgweb/octave/rev/6cbf5c2d4d55).  I made two changes: 1) I added a space between the function name and opening parenthesis which is Octave style, and 2) I added the bug number to the commit message and a description of what was done to the datetick.m file.

Rik <rik5>
Group administrator
Thu 16 Mar 2017 02:30:27 PM UTC, comment #11: 

Here is an example why the current version with just the fix in datenum may produce misleading plots in some cases.


#100 days in 10 minute resulution
t = datenum([2000 01 01]) + (0 : 1/144 : 100);
#simulation of global radiation
x = cos(2*pi*t) + cos(2*pi*t/365);
graphics_toolkit gnuplot
plot(t,x)
datetick x
grid on
xlim([datenum([2000 02 28]) datenum([2000 03 18])])
print example.png


The example is attached. One tick is placed at midnight, the other at noon.


Lars Kindermann <larskindermann>
Mon 13 Mar 2017 08:46:55 AM UTC, comment #10: 

@Rik: The old datetick using the new datenum will place ticks at

feb-15 00:00 for a 28 day february
feb-15 12:00 for a 29 day leap february
xxx-16 00:00 for a 30 day month
xxx-16 12:00 for a 31 day month

While this is mathematically correct, it is confusing in plots as the tick labels are inconsistent with the tick locations now, because they print out only the trunctated day without the time. This looks strange sometimes, e.g. plotting global radiation, as sometimes maxima and sometimes minima are on the intersection with the grid.

I think tick labels should always precisely name their location: when showing just the day and no time they should be placed right at midnight.

My patch puts ticks always at midnight of the 15th of each month,  which might be questionable but which is the default e.g. in financial applications. I would also be perfectly satisfied if they sit sometimes on the 15th and sometimes on the 16th - as long as one can derive their precise and consistent location from the label.

Lars Kindermann <larskindermann>
Mon 13 Mar 2017 03:52:15 AM UTC, comment #9: 

I pushed a patch for bug #50808 which allows datenum to accept vectors that contain fractional months.

@Lars: Is your patch from this report still necessary?  If so, could you give an example of where the current behavior is wrong so I can see how your patch is fixing it?

I'm attaching two png images made with the existing code (after fix for bug #50808) (regular.png) and your proposed patch (patched.png).

One thing I note is that the ticks are unevenly spaced in both versions.  That seems strange, but maybe it is just related to the number of days in each month.

Code to reproduce


x = datenum ([2004, 1 , 15;
              2004, 2 , 15;
              2004, 3 , 15;
              2004, 4, 15]);
plot (x, 1:4);
datetick ('mm/DD/YY');



Rik <rik5>
Group administrator
Sun 12 Mar 2017 06:21:51 PM UTC, comment #8: 

Yes, the issue is with vectors that contain a mix of leap and non-leap years with fractional months.  With Lars' patch from bug #50508 applied


datestr (datenum ([2001 2.99 1; 2004 2.99 1]))
ans =

01-Mar-2001 17:02:24
29-Feb-2004 17:02:24


With my patch for #50508


datestr (datenum ([2001 2.99 1; 2004 2.99 1]))
ans =

28-Feb-2001 17:16:48
29-Feb-2004 17:02:24



Rik <rik5>
Group administrator
Sun 12 Mar 2017 12:49:35 PM UTC, comment #7: 

The result in Matlab R2016a:

>> datestr (datenum ([2001 1 0; 2001 0 1; 2001 3 0; 2000 3 0; 2001 2 29]))

ans =

31-Dec-2000
01-Jan-2001
28-Feb-2001
29-Feb-2000
01-Mar-2001


I got the same with Octave 4.2.1 and default (without any patches).

Markus Mützel <mmuetzel>
Group administrator
Sat 11 Mar 2017 09:33:51 PM UTC, comment #6: 

@Markus: Could you try the following in Matlab?  Leap year processing of vectors in Octave is wrong at the moment.


datestr (datenum ([2001 1 0; 2001 0 1; 2001 3 0; 2000 3 0; 2001 2 29]))



Rik <rik5>
Group administrator
Fri 10 Mar 2017 05:18:02 PM UTC, comment #5: 

Thanks, Markus. I located the bug in datenum(). I will create a new report for that and submit a patch for it.

That will avoid this crash in datetick(), but I suggest to apply the final patch provided here, too, because it might generate somehow nicer tick positions.


Lars Kindermann <larskindermann>
Fri 10 Mar 2017 12:46:08 PM UTC, comment #4: 

Here the output in Matlab R2016a:

>> format compact
>> datestr(datenum([2017 1.5 1]))
ans =
01-Jan-2017
>> datestr(datenum([2017 1.8 1]))
ans =
01-Jan-2017
>> datestr(datenum([2017.6 1 1]))
ans =
08-Aug-2017
>> datestr(datenum([2017 1 1.8]))
ans =
01-Jan-2017 19:12:00
>> datestr(datenum([2017 1 1; 2017 1.5 1]))
ans =
01-Jan-2017
01-Jan-2017
>> datestr(datenum([2017 1 1; 2017.6 1 1]))
ans =
01-Jan-2017
08-Aug-2017
>> datestr(datenum([2017 1 1; 2017.7 1 1]))
ans =
01-Jan-2017 00:00:00
13-Sep-2017 12:00:00
>> datestr(datenum([2017 1 1; 2017 1 1.8]))
ans =
01-Jan-2017 00:00:00
01-Jan-2017 19:12:00


So the month seems to be always rounded down. Year and day on the other hand float.

It might be worth to double check in a more recent version of Matlab whether that rather inconsistent behavior has changed.

Markus Mützel <mmuetzel>
Group administrator
Fri 10 Mar 2017 12:24:23 PM UTC, comment #3: 

I attached an updated patch that fixes it in all calls to datenum() but the real problem might rather be datenum() itself which shows pretty inconsistent behaviour for non integer inputs:



>> datestr(datenum([2017 1 1]))
ans = 01-Jan-2017


>> datestr(datenum([2017 1 1; 2017 1 1]))
ans =

01-Jan-2017
01-Jan-2017


>> datestr(datenum([2017 1.5 1]))
ans = 16-Jan-2017 12:00:00


>> datestr(datenum([2017 1 1; 2017 1.5 1]))
error: monthstart(1.5): subscripts must be either integers 1 to (2^63)-1 or logicals
error: called from
    datenum at line 154 column 9


>> datestr(datenum([2017 1.5 1; 2017 1.5 1]))
error: datenum: operator *: nonconformant arguments (op1 is 2x1, op2 is 2x1)
error: called from
    datenum at line 137 column 11


Probably datenum() should be fixed instead as non-integer years and days always work fine. Non-int month also work for a single date but fail for a date array.

For compatibility, could somebody check how Matlab's datenum() behaves for non-integer inputs?


However, the attached updated patch avoids all non-integer datenum() calls in datetick() and sets ticks to more sane positions (midnight,1st of month) than calls for a fixed datenum would (noon, arbitrary day):



# HG changeset patch
# User larskindermann
# Date 1489148123 -3600
#      Fri Mar 10 13:15:23 2017 +0100
# Node ID 10a22466008eae6356116ebef7597c74e747f4da
# Parent  99ee4dd83ceb49edcc6d6e76e3f9188613bde7a5
fix range bugs in datetick.m

diff -r 99ee4dd83ceb -r 10a22466008e scripts/plot/appearance/datetick.m
--- a/scripts/plot/appearance/datetick.m        Wed Mar 08 21:11:54 2017 -0800
+++ b/scripts/plot/appearance/datetick.m        Fri Mar 10 13:15:23 2017 +0100
@@ -219,15 +219,19 @@
         minmonth = ifelse (minmonth == 0, 1, minmonth);
         maxmonth = sep * ceil (maxmonth / sep);
         rangemonth = (minmonth:sep:maxmonth)';
+        tickdays = round(1 + 28 * mod(rangemonth,1));
         ticks = datenum ([repmat(minyear, size(rangemonth)), ...
-                          rangemonth, ...
-                          ones(size (rangemonth))]);
+                          floor(rangemonth), ...
+                          tickdays]);
       else
         sep = __calc_tick_sep__ (minyear, maxyear);
         minyear = sep * floor (minyear / sep);
         maxyear = sep * ceil (maxyear / sep);
         rangeyear = (minyear:sep:maxyear)';
-        ticks = datenum ([rangeyear, ones(rows(rangeyear),2)]);
+        tickmonth = round(1 + 12 * mod(rangeyear,1));
+        ticks = datenum ([floor(rangeyear), ...
+                          tickmonth, ...
+                          ones(rows(rangeyear),1)]);
       endif
     endif
   endif



(file #39956)

Lars Kindermann <larskindermann>
Fri 10 Mar 2017 09:59:11 AM UTC, comment #2: 

Rik, do not push my changeset yet. Reviewing my fix, I suggest the line



tickdays = ones(size (rangemonth)) + 28 * mod(rangemonth,1);


should better read



tickdays = round (1 + 28 * mod (rangemonth,1));


Otherwise a similar problem may arise in case



sep = __calc_tick_sep__ (minmonth, maxmonth);


does not yield exactly 0.5. Additionally, there are several other locations in datetick() with a similar construct. They should be checked for possible problems, too. I'll have a look at this.


Lars Kindermann <larskindermann>
Fri 10 Mar 2017 05:02:56 AM UTC, comment #1: 

Confirmed.  This happens on 4.2.1 as well so the fix should probably go on stable.

Rik <rik5>
Group administrator
Wed 08 Mar 2017 12:06:56 PM UTC, original submission:  

The datetick command crashes if the date range is between 3 and about 3 1/2 month.



t=datenum([2017 01 01]):datenum([2017 04 1]);
plot(t,t)
datetick x

error: monthstart(1.5): subscripts must be either integers 1 to (2^63)-1 or logicals
error: called from
    datenum at line 154 column 9
    datetick>__datetick__ at line 222 column 15
    datetick at line 56 column 5


This results from an attempt in datetick to plot ticks in 1/2 month distance and the datenum function won't accept fractional values for the month.

I have attached a patch for datetick.m that fixes this problem:



# HG changeset patch
# User larskindermann
# Date 1488974463 -3600
#      Wed Mar 08 13:01:03 2017 +0100
# Node ID 3d6aca89d3bae2171379d108669fe5d7c1d02940
# Parent  4890b1c4a6bd53f409f994d327054ddd61a5e548
fix range bug in datetick.m

diff -r 4890b1c4a6bd -r 3d6aca89d3ba scripts/plot/appearance/datetick.m
--- a/scripts/plot/appearance/datetick.m        Tue Mar 07 08:15:24 2017 -0800
+++ b/scripts/plot/appearance/datetick.m        Wed Mar 08 13:01:03 2017 +0100
@@ -219,9 +219,10 @@
         minmonth = ifelse (minmonth == 0, 1, minmonth);
         maxmonth = sep * ceil (maxmonth / sep);
         rangemonth = (minmonth:sep:maxmonth)';
+        tickdays = ones(size (rangemonth)) + 28 * mod(rangemonth,1);
         ticks = datenum ([repmat(minyear, size(rangemonth)), ...
-                          rangemonth, ...
-                          ones(size (rangemonth))]);
+                          floor(rangemonth), ...
+                          tickdays]);
       else
         sep = __calc_tick_sep__ (minyear, maxyear);
         minyear = sep * floor (minyear / sep);


Lars Kindermann <larskindermann>

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:
   
   
Comment:
   

Attached Files
file #40016:  example.png added by larskindermann (17KiB - image/png - Example of the problem)
file #39986:  regular.png added by rik5 (16KiB - image/png)
file #39987:  patched.png added by rik5 (15KiB - image/png)
file #39956:  datetickV2.diff added by larskindermann (1KiB - text/x-patch - Updated patch)
file #39939:  datetick.diff added by larskindermann (1KiB - text/x-patch)

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by mmuetzel (Posted a comment)
  • -email is unavailable- added by rik5 (Posted a comment)
  • -email is unavailable- added by larskindermann (Submitted the item)
  •  

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

    Only group members can vote.

     

    Follow 8 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2017-03-16 rik5 StatusPatch Submitted Fixed
        Open/ClosedOpen Closed
    2017-03-16 larskindermann Attached File- Added example.png, #40016
    2017-03-13 rik5 Attached File- Added regular.png, #39986
        Attached File- Added patched.png, #39987
    2017-03-10 larskindermann Attached File- Added datetickV2.diff, #39956
    2017-03-10 rik5 StatusNone Patch Submitted
    2017-03-08 larskindermann Attached File- Added datetick.diff, #39939

    Back to the top

    Powered by Savane 3.13-4448.
    Corresponding source code