Date plotting

John, I've just started using the new tick locating,

    > formatting and date plotting and noticed if you want to
    > show day of month, month and year its quite easy to end up
    > with major and minor tick labels overwriting each other.
    > Is there a way to draw the major tick label underneath the
    > minor tick label so they're not competing for the same
    > space?

There are a few ways to go here. First of all, with no change to the
code, you can set the tick positions of the minor tick labels as
follow. I'm just winging this code so apologies if there is a minor
mistake somewhere

ax = subplot(111)

#your plot here
for tick in ax.xaxis.get_minor_ticks():
    tick.label1.set_y(-0.1)

Note that the y coord of the x tick label is in axes coordinates,
where 0 is the bottom and 1 is the top of the axes, so -0.1 is 10%
below the bottom of the axes. label1 and label2 are the bottom and
top label text.Text instances (this is a recent feature to support
left/right labeling or top/bottom tick labeling) so you can call any
of the Text methods on them.

Note this code only affects the current ticks, so if you were doing
interactive navigation and zoomed out, thereby creating new minor
ticks, the new minor ticks would have their default locations (but I
can fix this fairly easily by updating the copy properties function
that transfers old tick properties to new ones when ticks are created
during interaction).

There is an additional consideration. Currently, the tick drawing
code will skip a minor tick if a major tick has already been drawn at
that exact location. In axis.py there is a line in the axis drawing
code that reads

            if seen.has_key(loc): continue

where seen is a dict that has a key if the tick location loc was drawn
by the major tick drawing code. We could add an attribute, something
like forceDraw, to the tick and modify this code so that you could do

            if not tick.forceDraw and seen.has_key(loc): continue

and in your code

for tick in ax.xaxis.get_minor_ticks():
    tick.forceDraw = True
    tick.label1.set_y(-0.1)

Let me know how this works for you.

We could automate this a bit if you think it's worthwhile, eg by
setting a 'draw under' flag for the minor ticks, getting the bounding
boxes of the major ticks in the axis drawing code, and setting the
offsets automagically. This would have the dual advantages of working
in the presence of changes in font size, interaction, etc. The
question is whether it's sufficiently common to justify the extra work
or if the manual control approach above suffices. If you want to add
this feature, I can get you some additional pointers to code showing
how to get the bounding box of all the major tick labels and using
this to control the positioning of the minor tick labels.

JDH

One way to avoid having the minor ticklabels collide with the major ones
is to put them on separate lines as illustrated in the original post.
Supporting multi-line text (embedded '\n's in ticklabels) would permit
this. All you would have to do is begin the minor ticklabels with one
or more '\n's. How is this coming along?

  -Al

···

On Sat, 2004-05-08 at 08:47, John Hunter wrote:

    > John, I've just started using the new tick locating,
    > formatting and date plotting and noticed if you want to
    > show day of month, month and year its quite easy to end up
    > with major and minor tick labels overwriting each other.
    > Is there a way to draw the major tick label underneath the
    > minor tick label so they're not competing for the same
    > space?

There are a few ways to go here. First of all, with no change to the
code, you can set the tick positions of the minor tick labels as
follow. I'm just winging this code so apologies if there is a minor
mistake somewhere

ax = subplot(111)

#your plot here
for tick in ax.xaxis.get_minor_ticks():
    tick.label1.set_y(-0.1)

Note that the y coord of the x tick label is in axes coordinates,
where 0 is the bottom and 1 is the top of the axes, so -0.1 is 10%
below the bottom of the axes. label1 and label2 are the bottom and
top label text.Text instances (this is a recent feature to support
left/right labeling or top/bottom tick labeling) so you can call any
of the Text methods on them.

Note this code only affects the current ticks, so if you were doing
interactive navigation and zoomed out, thereby creating new minor
ticks, the new minor ticks would have their default locations (but I
can fix this fairly easily by updating the copy properties function
that transfers old tick properties to new ones when ticks are created
during interaction).

There is an additional consideration. Currently, the tick drawing
code will skip a minor tick if a major tick has already been drawn at
that exact location. In axis.py there is a line in the axis drawing
code that reads

            if seen.has_key(loc): continue

where seen is a dict that has a key if the tick location loc was drawn
by the major tick drawing code. We could add an attribute, something
like forceDraw, to the tick and modify this code so that you could do

            if not tick.forceDraw and seen.has_key(loc): continue

and in your code

for tick in ax.xaxis.get_minor_ticks():
    tick.forceDraw = True
    tick.label1.set_y(-0.1)

Let me know how this works for you.

We could automate this a bit if you think it's worthwhile, eg by
setting a 'draw under' flag for the minor ticks, getting the bounding
boxes of the major ticks in the axis drawing code, and setting the
offsets automagically. This would have the dual advantages of working
in the presence of changes in font size, interaction, etc. The
question is whether it's sufficiently common to justify the extra work
or if the manual control approach above suffices. If you want to add
this feature, I can get you some additional pointers to code showing
how to get the bounding box of all the major tick labels and using
this to control the positioning of the minor tick labels.

JDH

-------------------------------------------------------
This SF.Net email is sponsored by Sleepycat Software
Learn developer strategies Cisco, Motorola, Ericsson & Lucent use to
deliver higher performing products faster, at low TCO.
http://www.sleepycat.com/telcomwpreg.php?From=osdnemail3
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

Thanks for the advice, but I tried this and the tick labels disappeared
completely. I then tried
  tick.label1.set_y(0.0)
which I would expect to leave the labels at the same place, but the
labels disappeared also.

I had a look at matplotlib.dates and found what looks like a
problem/limitation.
This is my understanding, which may be completely wrong.
The python 'time' module (and epochtime) limits years to 1970-2038.
The 'egenix' and python 'datetime' modules support a much larger range
of years ('datetime supports years from 1-9999).

matplotlib.dates converter classes supports 'epochtime', 'datetime' and
'egenix' date formats. However, internally it uses epochtime for all
dates and so limits all years to the range 1970-2038, even though
'datetime' and 'egeinx' themselves support much more that this.

I think there is a lot of data available before 1970 that people might
like to plot. Taking stock data as an example, Yahoo has data going back
to 1962 for some companies.

Regards
Steve

···

On Sat, 2004-05-08 at 20:47, John Hunter wrote:

ax = subplot(111)

#your plot here
for tick in ax.xaxis.get_minor_ticks():
    tick.label1.set_y(-0.1)