|
From: Peter G. <pgr...@ge...> - 2004-08-07 23:33:41
|
Hi:
Below is a little part of my post from a while ago regarding x-axis
scaling on plot_date plots.
>
> 2) The auto-scaling in plot_date() does not scale properly in some
> special cases. Consider this:
>
> -----------------
> from matplotlib.matlab import *
>
> time2= [
> 1087321489.89, 1087321500.0,
> 1087321789.89, 1087321800.0, 1087322089.89, 1087322100.0,
> 1087322389.89, 1087322700.0, 1087322989.89,
> 1087323000.0, 1087323289.89, 1087323300.0, 1087323589.89,
> 1087323600.0, 1087323889.89, 1087323900.0,
> 1087324189.89, 1087324200.0, 1087324489.89, 1087324500.0, ]
> data2=[ 3.02,
> 3.02,
> 3.14,
> 3.14,
> 3.21,
> 3.21,
> 3.26,
> 3.26,
> 3.39,
> 3.39,
> 3.51,
> 3.51,
> 3.58,
> 3.58,
> 3.75,
> 3.75,
> 4.0,
> 4.0,
> 4.22,
> 4.22,]
>
> plot_date(time2, data2, None, '-', color='b')
> xlabel('time')
> grid(True)
>
> show()
> ---------------
>
> The same thing happens over differnt ranges when the amount of ticks
> is large. Perhaps you may use something similar to the code below
> (from axes.py) to deal with these things. Note the ceilings get rid of
> the AssertErrors in ticks.Base when int() gives zero. Also, to
> finalize this,
> one would have to write a DayMultiLocator type class for the Weeks,
> otherwise when the number of weeks is close, but less then the number
> of weeks in numticks*months it will get crowded. This will probably be
> a little more involved than dealing with days, but perhaps one could use
> your existent WeekdayLocator class to simplify the problem.
I added a quick and dirty version of this WeekMultiLocator that handles
cases when the time range is many weeks but less than 5 months (say 17
weeks) and the ticks get over-crowded. Ideally one could have the weeks
always start on some particular day - say Monday, but for me it doesnt
really matter, and with the simple code below, thing seem to come out
quite nice.
In axes.py need:
Line ~19:
from ticker import YearLocator, MonthLocator, WeekdayLocator, \
DayLocator, HourLocator, MinuteLocator, DateFormatter,
DayMultiLocator, WeekMultiLocator
Line ~1475:
def plot_date(self, d, y, converter, fmt='bo', **kwargs):
"""
plot_date(d, y, converter, fmt='bo', **kwargs)
d is a sequence of dates; converter is a dates.DateConverter
instance that converts your dates to seconds since the epoch for
plotting. y are the y values at those dates. fmt is a plot
format string. kwargs are passed on to plot. See plot for more
information.
pass converter = None if your dates are already in epoch format
"""
if not self._hold: self.cla()
if converter is not None:
e = array([converter.epoch(thisd) for thisd in d])
else:
e = d
assert(len(e))
ret = self.plot(e, y, fmt, **kwargs)
span = self.dataLim.intervalx().span()
if span==0: span = SEC_PER_HOUR
minutes = span/SEC_PER_MIN
hours = span/SEC_PER_HOUR
days = span/SEC_PER_DAY
weeks = span/SEC_PER_WEEK
months = span/(SEC_PER_DAY*31) # approx
years = span/(SEC_PER_WEEK*52) # approx
numticks = 5
if years>numticks:
locator = YearLocator(math.ceil(years/numticks))
fmt = '%Y'
elif months>numticks:
locator = MonthLocator(math.ceil(months/numticks))
fmt = '%b %Y'
elif weeks>numticks:
locator = WeekMultiLocator(math.ceil(weeks/numticks))
fmt = '%a, %b %d'
elif days>numticks:
locator = DayMultiLocator(math.ceil(days/numticks))
fmt = '%b %d'
elif hours>numticks:
locator = HourLocator(math.ceil(hours/numticks))
fmt = '%H:%M\n%b %d'
elif minutes>numticks:
locator = MinuteLocator(math.ceil(minutes/numticks))
fmt = '%H:%M:%S'
else:
locator = MinuteLocator(1)
fmt = '%H:%M:%S'
formatter = DateFormatter(fmt)
self.xaxis.set_major_locator(locator)
self.xaxis.set_major_formatter(formatter)
self.autoscale_view()
return ret
In ticks.py:
Need to add:
class WeekMultiLocator(MultipleLocator):
"""
Make ticks on day which are multiples of base
"""
def __init__(self, base):
MultipleLocator.__init__(self, base*SEC_PER_WEEK)
--
Peter Groszkowski Gemini Observatory
Tel: +1 808 974-2509 670 N. A'ohoku Place
Fax: +1 808 935-9235 Hilo, Hawai'i 96720, USA
|