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 |