From: <jd...@us...> - 2009-09-06 21:16:40
|
Revision: 7661 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7661&view=rev Author: jdh2358 Date: 2009-09-06 21:16:27 +0000 (Sun, 06 Sep 2009) Log Message: ----------- fix to empty datetime bug; add datetime tests Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/axes.py trunk/matplotlib/lib/matplotlib/axis.py trunk/matplotlib/lib/matplotlib/dates.py trunk/matplotlib/lib/matplotlib/transforms.py trunk/matplotlib/lib/matplotlib/units.py Added Paths: ----------- trunk/matplotlib/lib/matplotlib/tests/test_dates.py Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2009-09-06 20:13:36 UTC (rev 7660) +++ trunk/matplotlib/lib/matplotlib/axes.py 2009-09-06 21:16:27 UTC (rev 7661) @@ -2299,74 +2299,19 @@ *tz* is the time zone to use in labeling dates. Defaults to rc value. """ + # should be enough to inform the unit conversion interface + # dates are comng in + self.xaxis.update_units(datetime.date(2009,1,1)) - xmin, xmax = self.dataLim.intervalx - if xmin==0.: - # no data has been added - let's set the default datalim. - # We should probably use a better proxy for the datalim - # have been updated than the ignore setting - dmax = today = datetime.date.today() - dmin = today-datetime.timedelta(days=10) - self._process_unit_info(xdata=(dmin, dmax)) - dmin, dmax = self.convert_xunits([dmin, dmax]) - self.viewLim.intervalx = dmin, dmax - self.dataLim.intervalx = dmin, dmax - - locator = self.xaxis.get_major_locator() - if not isinstance(locator, mdates.DateLocator): - locator = mdates.AutoDateLocator(tz) - self.xaxis.set_major_locator(locator) - - # the autolocator uses the viewlim to pick the right date - # locator, but it may not have correct viewlim before an - # autoscale. If the viewlim is still zero..1, set it to the - # datalim and the autoscaler will update it on request - if self.viewLim.intervalx[0]==0.: - self.viewLim.intervalx = tuple(self.dataLim.intervalx) - locator.refresh() - - formatter = self.xaxis.get_major_formatter() - if not isinstance(formatter, mdates.DateFormatter): - formatter = mdates.AutoDateFormatter(locator, tz) - self.xaxis.set_major_formatter(formatter) - def yaxis_date(self, tz=None): """Sets up y-axis ticks and labels that treat the y data as dates. *tz* is the time zone to use in labeling dates. Defaults to rc value. """ - ymin, ymax = self.dataLim.intervaly - if ymin==0.: - # no data has been added - let's set the default datalim. - # We should probably use a better proxy for the datalim - # have been updated than the ignore setting - dmax = today = datetime.date.today() - dmin = today-datetime.timedelta(days=10) - self._process_unit_info(ydata=(dmin, dmax)) + # should be enough to inform the unit conversion interface + # dates are comng in + self.yaxis.update_units(datetime.date(2009,1,1)) - dmin, dmax = self.convert_yunits([dmin, dmax]) - self.viewLim.intervaly = dmin, dmax - self.dataLim.intervaly = dmin, dmax - - - locator = self.yaxis.get_major_locator() - if not isinstance(locator, mdates.DateLocator): - locator = mdates.AutoDateLocator(tz) - self.yaxis.set_major_locator(locator) - - # the autolocator uses the viewlim to pick the right date - # locator, but it may not have correct viewlim before an - # autoscale. If the viewlim is still zero..1, set it to the - # datalim and the autoscaler will update it on request - if self.viewLim.intervaly[0]==0.: - self.viewLim.intervaly = tuple(self.dataLim.intervaly) - locator.refresh() - - formatter = self.xaxis.get_major_formatter() - if not isinstance(formatter, mdates.DateFormatter): - formatter = mdates.AutoDateFormatter(locator, tz) - self.yaxis.set_major_formatter(formatter) - def format_xdata(self, x): """ Return *x* string formatted. This function will use the attribute Modified: trunk/matplotlib/lib/matplotlib/axis.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axis.py 2009-09-06 20:13:36 UTC (rev 7660) +++ trunk/matplotlib/lib/matplotlib/axis.py 2009-09-06 21:16:27 UTC (rev 7661) @@ -666,6 +666,19 @@ 'Set the axis data limits' raise NotImplementedError('Derived must override') + def set_default_intervals(self): + 'set the default limits for the axis data and view interval if they are not mutated' + + # this is mainly in support of custom object plotting. For + # example, if someone passes in a datetime object, we do not + # know automagically how to set the default min/max of the + # data and view limits. The unit conversion AxisInfo + # interface provides a hook for custom types to register + # default limits through the AxisInfo.default_limits + # attribute, and the derived code below will check for that + # and use it if is available (else just use 0..1) + pass + def _set_artist_props(self, a): if a is None: return a.set_figure(self.figure) @@ -1010,6 +1023,7 @@ self.set_label_text(info.label) self.isDefault_label = True + self.set_default_intervals() def have_units(self): return self.converter is not None or self.units is not None @@ -1420,6 +1434,25 @@ self.axes.dataLim.intervalx = min(vmin, Vmin), max(vmax, Vmax) + def set_default_intervals(self): + 'set the default limits for the axis interval if they are not mutated' + xmin, xmax = 0., 1. + dataMutated = self.axes.dataLim.mutatedx() + viewMutated = self.axes.viewLim.mutatedx() + if not dataMutated or not viewMutated: + if self.converter is not None: + info = self.converter.axisinfo(self.units, self) + if info.default_limits is not None: + valmin, valmax = info.default_limits + xmin = self.converter.convert(valmin, self.units, self) + xmax = self.converter.convert(valmax, self.units, self) + if not dataMutated: + self.axes.dataLim.intervalx = xmin, xmax + if not viewMutated: + self.axes.viewLim.intervalx = xmin, xmax + + + class YAxis(Axis): __name__ = 'yaxis' axis_name = 'y' @@ -1665,3 +1698,22 @@ else: Vmin, Vmax = self.get_data_interval() self.axes.dataLim.intervaly = min(vmin, Vmin), max(vmax, Vmax) + + def set_default_intervals(self): + 'set the default limits for the axis interval if they are not mutated' + ymin, ymax = 0., 1. + dataMutated = self.axes.dataLim.mutatedy() + viewMutated = self.axes.viewLim.mutatedy() + if not dataMutated or not viewMutated: + if self.converter is not None: + info = self.converter.axisinfo(self.units, self) + if info.default_limits is not None: + valmin, valmax = info.default_limits + ymin = self.converter.convert(valmin, self.units, self) + ymax = self.converter.convert(valmax, self.units, self) + if not dataMutated: + self.axes.dataLim.intervaly = ymin, ymax + if not viewMutated: + self.axes.viewLim.intervaly = ymin, ymax + + Modified: trunk/matplotlib/lib/matplotlib/dates.py =================================================================== --- trunk/matplotlib/lib/matplotlib/dates.py 2009-09-06 20:13:36 UTC (rev 7660) +++ trunk/matplotlib/lib/matplotlib/dates.py 2009-09-06 21:16:27 UTC (rev 7661) @@ -1062,42 +1062,15 @@ def axisinfo(unit, axis): 'return the unit AxisInfo' # make sure that the axis does not start at 0 - if axis: - ax = axis.axes - if axis is ax.get_xaxis(): - xmin, xmax = ax.dataLim.intervalx - if xmin==0.: - # no data has been added - let's set the default datalim. - # We should probably use a better proxy for the datalim - # have been updated than the ignore setting - dmax = today = datetime.date.today() - dmin = today-datetime.timedelta(days=10) - - ax._process_unit_info(xdata=(dmin, dmax)) - dmin, dmax = ax.convert_xunits([dmin, dmax]) - - ax.viewLim.intervalx = dmin, dmax - ax.dataLim.intervalx = dmin, dmax - elif axis is ax.get_yaxis(): - ymin, ymax = ax.dataLim.intervaly - if ymin==0.: - # no data has been added - let's set the default datalim. - # We should probably use a better proxy for the datalim - # have been updated than the ignore setting - dmax = today = datetime.date.today() - dmin = today-datetime.timedelta(days=10) - - ax._process_unit_info(ydata=(dmin, dmax)) - dmin, dmax = ax.convert_yunits([dmin, dmax]) - - ax.viewLim.intervaly = dmin, dmax - ax.dataLim.intervaly = dmin, dmax - majloc = AutoDateLocator(tz=unit) majfmt = AutoDateFormatter(majloc, tz=unit) - return units.AxisInfo( majloc=majloc, majfmt=majfmt, label='' ) + datemin = datetime.date(2000, 1, 1) + datemax = datetime.date(2010, 1, 1) + return units.AxisInfo( majloc=majloc, majfmt=majfmt, label='', + default_limits=(datemin, datemax)) + @staticmethod def convert(value, unit, axis): if units.ConversionInterface.is_numlike(value): return value Added: trunk/matplotlib/lib/matplotlib/tests/test_dates.py =================================================================== --- trunk/matplotlib/lib/matplotlib/tests/test_dates.py (rev 0) +++ trunk/matplotlib/lib/matplotlib/tests/test_dates.py 2009-09-06 21:16:27 UTC (rev 7661) @@ -0,0 +1,76 @@ +import datetime +import numpy as np +import matplotlib +matplotlib.use('Agg') +from matplotlib.testing.decorators import image_comparison +import matplotlib.pyplot as plt + +@image_comparison(baseline_images=['empty_datetime.png']) +def test_empty_datetime(): + # make sure mpl does the right thing when told to plot dates even + # if no date data has been presented, cf + # http://sourceforge.net/tracker/?func=detail&aid=2850075&group_id=80706&atid=560720 + fig = plt.figure() + ax = fig.add_subplot(1,1,1) + ax.xaxis_date() + fig.savefig('empty_datetime.png') + +@image_comparison(baseline_images=['date_axhspan.png']) +def test_date_axhspan(): + # test ax hspan with date inputs + t0 = datetime.datetime(2009, 1, 20) + tf = datetime.datetime(2009, 1, 21) + fig = plt.figure() + ax = fig.add_subplot(1,1,1) + ax.axhspan( t0, tf, facecolor="blue", alpha=0.25 ) + ax.set_xlim(t0-datetime.timedelta(days=5), + tf+datetime.timedelta(days=5)) + fig.autofmt_xdate() + fig.savefig('date_axhspan.png') + +@image_comparison(baseline_images=['date_axvspan.png']) +def test_date_axvspan(): + # test ax hspan with date inputs + t0 = datetime.datetime(2000, 1, 20) + tf = datetime.datetime(2010, 1, 21) + fig = plt.figure() + ax = fig.add_subplot(1,1,1) + ax.axvspan( t0, tf, facecolor="blue", alpha=0.25 ) + ax.set_xlim(t0-datetime.timedelta(days=5), + tf+datetime.timedelta(days=5)) + fig.autofmt_xdate() + fig.savefig('date_axvspan.png') + + +@image_comparison(baseline_images=['date_axhline.png']) +def test_date_axhline(): + # test ax hline with date inputs + t0 = datetime.datetime(2009, 1, 20) + tf = datetime.datetime(2009, 1, 31) + fig = plt.figure() + ax = fig.add_subplot(1,1,1) + ax.axhline( t0, tf, facecolor="blue", lw=3) + ax.set_xlim(t0-datetime.timedelta(days=5), + tf+datetime.timedelta(days=5)) + fig.autofmt_xdate() + fig.savefig('date_axhline.png') + +@image_comparison(baseline_images=['date_axvline.png']) +def test_date_axvline(): + # test ax hline with date inputs + t0 = datetime.datetime(2000, 1, 20) + tf = datetime.datetime(2010, 1, 21) + fig = plt.figure() + ax = fig.add_subplot(1,1,1) + ax.axvline( t0, tf, facecolor="blue", lw=3) + ax.set_xlim(t0-datetime.timedelta(days=5), + tf+datetime.timedelta(days=5)) + fig.autofmt_xdate() + fig.savefig('date_axvline.png') + + +if __name__=='__main__': + import nose + nose.runmodule(argv=['-s','--with-doctest'], exit=False) + + Modified: trunk/matplotlib/lib/matplotlib/transforms.py =================================================================== --- trunk/matplotlib/lib/matplotlib/transforms.py 2009-09-06 20:13:36 UTC (rev 7660) +++ trunk/matplotlib/lib/matplotlib/transforms.py 2009-09-06 21:16:27 UTC (rev 7661) @@ -711,7 +711,10 @@ self._points = np.asarray(points, np.float_) self._minpos = np.array([0.0000001, 0.0000001]) self._ignore = True - + # it is helpful in some contexts to know if the bbox is a + # default or has been mutated; we store the orig points to + # support the mutated methods + self._points_orig = self._points.copy() if DEBUG: ___init__ = __init__ def __init__(self, points): @@ -939,7 +942,22 @@ self._points = other.get_points() self.invalidate() + def mutated(self): + 'return whether the bbox has changed since init' + return self.mutatedx() or self.mutatedy() + def mutatedx(self): + 'return whether the x-limits have changed since init' + return (self._points[0,0]!=self._points_orig[0,0] or + self._points[1,0]!=self._points_orig[1,0]) + def mutatedy(self): + 'return whether the y-limits have changed since init' + return (self._points[0,1]!=self._points_orig[0,1] or + self._points[1,1]!=self._points_orig[1,1]) + + + + class TransformedBbox(BboxBase): """ A :class:`Bbox` that is automatically transformed by a given Modified: trunk/matplotlib/lib/matplotlib/units.py =================================================================== --- trunk/matplotlib/lib/matplotlib/units.py 2009-09-06 20:13:36 UTC (rev 7660) +++ trunk/matplotlib/lib/matplotlib/units.py 2009-09-06 21:16:27 UTC (rev 7661) @@ -46,14 +46,15 @@ from matplotlib.cbook import iterable, is_numlike, is_string_like class AxisInfo: - 'information to support default axis labeling and tick labeling' + 'information to support default axis labeling and tick labeling, and default limits' def __init__(self, majloc=None, minloc=None, - majfmt=None, minfmt=None, label=None): + majfmt=None, minfmt=None, label=None, + default_limits=None): """ majloc and minloc: TickLocators for the major and minor ticks majfmt and minfmt: TickFormatters for the major and minor ticks label: the default axis label - + default_limits: the default min, max of the axis if no data is present If any of the above are None, the axis will simply use the default """ self.majloc = majloc @@ -61,6 +62,7 @@ self.majfmt = majfmt self.minfmt = minfmt self.label = label + self.default_limits = default_limits class ConversionInterface: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |