From: Michael F. <mp...@be...> - 2006-08-25 02:16:37
|
Hi all, Sometime in the past couple months, there's been a change in SVN that's causing me problems when trying to hide tick labels. I think the problem is related to the get_xticklabels()/get_yticklabels() methods of the Axes class, in that they only return a list consisting of a single tick label no matter how many there should be. I'm encountering this problem in SVN rev. 2706. Here is some example code: from pylab import * # set up a plot x = arange(5) ax = subplot(111) ax.plot(x, x) # hide the first tick label on the x axis xtl = ax.get_xticklabels() xtl[0].set_visible(False) print len(xtl) ax.set_xlabel('foo') show() For me, no x tick labels are drawn, and the length of xtl is one instead of the expected 9. Can anyone reproduce this? Mike |
From: Michael F. <mp...@be...> - 2006-08-31 02:25:37
Attachments:
test.py
|
Hi all, I'm still having trouble figuring out what's going on with tick labels. I can't figure out why Axes.get_{x,y}ticklabels() is returning a list of length unity when I expect to have the list of all labels. If I run the code below (test.py), I expect a list of 9 x tick labels. If I run the code once ('run test' in ipython), then it gives me a list of 1 tick label. If I close the interactive window it generates and run it again, it again returns 1 tick label. However, if I leave the window open and re-run the test, it gives the right answer. Can anyone else reproduce this? Is there something I'm missing? I'm using svn rev 2730 of matplotlib, and I think this is new behavior in the last couple months. |
From: John H. <jdh...@ac...> - 2006-08-31 11:49:24
|
>>>>> "Michael" == Michael Fitzgerald <mp...@be...> writes: Michael> Hi all, Michael> I'm still having trouble figuring out what's going on Michael> with tick labels. I can't figure out why Michael> Axes.get_{x,y}ticklabels() is returning a list of length Michael> unity when I expect to have the list of all labels. Michael> If I run the code below (test.py), I expect a list of 9 x Michael> tick labels. If I run the code once ('run test' in Michael> ipython), then it gives me a list of 1 tick label. If I Michael> close the interactive window it generates and run it Michael> again, it again returns 1 tick label. However, if I Michael> leave the window open and re-run the test, it gives the Michael> right answer. Michael> Can anyone else reproduce this? Is there something I'm Michael> missing? I'm using svn rev 2730 of matplotlib, and I Michael> think this is new behavior in the last couple months. It's a feature, not a bug :-) Here is what is happening. matplotlib allocates a different number of ticks depending on the zoom level, and the axis seeds itself with a single tick called the "protoTick". If you zoom to the right and new ticks need to be created, the properties from the protoTick are copied to the newly created ticks. 99% of the time, this is what you want. If you have large bold tick labels, and zoom to the right, you want the new ticks that appear to be large and bold. So this explains why you see a single tick before the window is drawn (the protoTick), a list of ticks after the window is drawn, and why the properties of the first tick (the "visible" property in this case) are transferred to the other ticks. So: how do you solve your problem, of making the first tick invisible? What I do when I need to solve this problem, which comes up a lot with multiple axes where ticks can overlap, is the following from matplotlib.ticker import ScalarFormatter class MyFormatter(ScalarFormatter): def __call__(self, x, pos=None): if pos==0: return '' else: return ScalarFormatter(self, x, pos) ax.xaxis.set_major_formatter(MyFormatter()) I often want to do this for the last tick as well, but there is currently no convenient way to do this, as the tick locator produces the tick location list and the tick formatter doesn't know how many of them there are. I've been considering modifying the tick locator code to pass -1 for the pos for the last tick to solve just this use case. If others need this or think it desirable, just give me a nudge and I'll do it. Details about the tick locators and formatter can be found at http://matplotlib.sourceforge.net/matplotlib.ticker.html and there are a number of examples ~/mpl/examples> grep -l Formatter *.py custom_ticker1.py dashtick.py date_demo1.py date_demo2.py date_demo_rrule.py finance_demo.py major_minor_demo1.py major_minor_demo2.py newscalarformatter_demo.py shared_axis_demo.py Hope this helps, JDH |
From: Michael F. <mp...@be...> - 2006-08-31 21:03:09
|
On Aug 31, 2006, at 4:36 AM, John Hunter wrote: > So: how do you solve your problem, of making the first tick invisible? > What I do when I need to solve this problem, which comes up a lot with > multiple axes where ticks can overlap, is the following > > from matplotlib.ticker import ScalarFormatter > > class MyFormatter(ScalarFormatter): > def __call__(self, x, pos=None): > if pos==0: return '' > else: return ScalarFormatter(self, x, pos) > > ax.xaxis.set_major_formatter(MyFormatter()) > > I often want to do this for the last tick as well, but there is > currently no convenient way to do this, as the tick locator produces > the tick location list and the tick formatter doesn't know how many of > them there are. I've been considering modifying the tick locator code > to pass -1 for the pos for the last tick to solve just this use case. > If others need this or think it desirable, just give me a nudge and > I'll do it. Hi John, Hmm.... I have 3 use cases where I want to isolate individual tick labels and make them invisible: 1) the first tick (0; for stacked plots) 2) the last tick (-1; for stacked plots) 3) every other tick for the last few ticks (e.g. -2, -4, -6; for a log-scale axis with large tick labels, which can overlap on one end) Is there a way to force some sort of pseudo-draw event, such that the sizing is done and the ticks are created from the protoTick, but the draw isn't actually performed by the backend? That way one could set the visibility property rather than wrap the Formatter. Thanks, Mike |
From: John H. <jdh...@ac...> - 2006-08-31 22:09:18
|
>>>>> "Michael" == Michael Fitzgerald <mp...@be...> writes: Michael> Is there a way to force some sort of pseudo-draw event, Michael> such that the sizing is done and the ticks are created Michael> from the protoTick, but the draw isn't actually performed Michael> by the backend? That way one could set the visibility Michael> property rather than wrap the Formatter. Try fig.canvas.draw() and see if that helps. If not, we'll come up with something else... JDH |
From: Michael F. <mp...@be...> - 2006-08-31 22:17:53
|
On Aug 31, 2006, at 2:56 PM, John Hunter wrote: >>>>>> "Michael" == Michael Fitzgerald <mp...@be...> writes: > > Michael> Is there a way to force some sort of pseudo-draw event, > Michael> such that the sizing is done and the ticks are created > Michael> from the protoTick, but the draw isn't actually performed > Michael> by the backend? That way one could set the visibility > Michael> property rather than wrap the Formatter. > > Try fig.canvas.draw() and see if that helps. > > If not, we'll come up with something else... I placed that command before the ax.get_xticklabels(), and no dice. Thanks for looking into this, Mike |
From: John H. <jdh...@ac...> - 2006-09-04 16:43:05
|
>>>>> "Michael" == Michael Fitzgerald <mp...@be...> writes: Michael> I placed that command before the ax.get_xticklabels(), Michael> and no dice. Michael> Thanks for looking into this, Mike I took a look at the formatter code and it turns out it *does* know the list of locations it has to format. I was wrong about this in my previous post. The formatter has a locs attribute you can inspect to see how many ticks there are. So you should be able to do something like class MyFormatter(ScalarFormatter): def __call__(self, x, pos=None): N = len(self.locs) if pos==0: return '' # turn off first elif pos==(N-1): return '' # turn off last else: return ScalarFormatter(self, x, pos) and you can do other things similarly, eg to turn off every other tick if (pos%2)==0: return '' If you want to get very clever with turning on and off certain ticks, you can also create a custom locator derived from the Locator class you are using. JDH |