From: John H. <jdh...@ac...> - 2005-01-27 22:12:38
|
>>>>> "Baptiste" == Baptiste Carvello <bap...@al...> writes: >> Baptiste> That sounds like a good syntax. Its not a problem the Baptiste> share the x/ylims. As long as you can get the lazy Baptiste> values at Axes creation, you can set the transforms Baptiste> correctly. The question is whether or not to share the Baptiste> Axis instance. If you do, you will have trouble drawing, Baptiste> if you don't, you have trouble when you want to change Baptiste> the attributes (see below). I got away with this only Baptiste> because I have to draw only one "physical" axis. Hi Baptiste, After reading your email and studying your patch more, I now see how to generalize this to the case of non-overlapping axes which share either the x or y axis, eg ganged plots. I have added some changes to CVS to support sharex and sharey kwargs (I thought this was a better name than twinx and twiny). I had to make some minor changes to axis to support sharing tick locators and formatters, but nothing substantial. You can now instantiate an axes with, eg subplot(212, sharex=ax1) and ditto for sharey. The view limits, transform function, and tick Locator and Formatter are shared. This allows you to pan and zoom on one axes and have the others follow, which is very nice. There is a new example showing how to use this example/shared_axis_demo.py. I was able to remove the TwinAxes class altogether and use the shared kwargs in its stead, which is cleaner. I preserved the "twin" convenience function (naming it twinx) and all it does is pass the proper kwargs and make the calls to tick_right. examples/two_scales.py is updated Baptiste> I'm starting to wonder which properties of Axis we Baptiste> really want to share between axes: limits, scale Baptiste> (linear/log), fmtdata, label, tick positions (thus a Baptiste> common "tick factory"), tick label texts, viewLim, Baptiste> dataLim (we need to think about update_datalim). Baptiste> and which we do *not* want to share: all graphic Baptiste> objects, visibility of labels (ticks ?), style of ticks Baptiste> and tick labels (you may want smaller fonts in an Baptiste> inset), type of axis (XAxis, YAxis, ThetaAxis, Color, Baptiste> ..., for ex. we may want to plot z(x,y) as pcolor and Baptiste> z(x) as line with shared z lims) Baptiste> Maybe we want to split an axis into 2 objects ? I need Baptiste> to think more about this. I don't think the datalim need to be shared because they are responsible only for autoscaling. The new approach allows the different axes to have different properties on their labels, eg font size as you mentioned. While you cannot turn off labels selectively on one axes with set(ax2, xticklabels=[]) because this changes the Formatter which is shared, you can achieve the same effect by setting the visibility property, which is not shared set( ax2.get_xticklabels(), visible=False) examples/ganged_plots.py, examples/two_scales.py, and examples/shared_axis_demo.py show off the new features. Let me know if this design covers the use cases you can think of. Baptiste> This is uncorrelated, and probably easier than the one Baptiste> above. We would need to modify event.inaxes to be a list Baptiste> (in backend_bases), and act upon all those axes in Baptiste> pan/zoom. When only one axes can be used (for ex. the Baptiste> coordinates of the mouse in the status bar), we would Baptiste> use event.inaxes[0], or maybe the most recently used Baptiste> axes (more difficult, but maybe more consistent...we'll Baptiste> see at implementation time). Yes, this needs to be fixed and it is not very hard to do. There are three event variables affected, inaxes, xdata and ydata, the latter two give the data coords of the point in the axes the mouse is over. As you know, the problem is that the current implementation only registers the first axes and then breaks out of the loop. It would be easy to fix this but I'm worried about two things: backward compatibility (not a huge problem since only power users are using this feature) and ease of use. It is really a corner case to be over multiple axes, and I am hesitant to force the newbie to deal with this in the typical case when there are no overlapping axes. One possibility is to leave inaxes, xdata and ydata alone which satisfies both problems above. And then to add a new attribute, axseq which is a list of (ax, xdata, ydata ) tuples to handle the overlapping axes case. Internally, we could use axseq so that pan/zoom will be handled properly in the two_scales case. The draw back here is that having more than one obvious way to do it may also confuse people down the road. For clarity, the two interfaces I'm discussing are def callback1(event): # current impl. if event.inaxes is not None: do_something with event.inaxes, event.xdata, event.ydata def callback2(event): # candidate impl. for ax, xdata, ydata in event.axseq: do_something with ax, xdata, ydata I'm weakly inclined to break backward compatibility and go with the cleaner, comprehensive design in callback2, which on the face of it doesn't look too hard to use. Suggestions? JDH |