|
From: Andrew S. <str...@as...> - 2005-02-13 12:19:04
Attachments:
prelim-detach-axis.patch.gz
|
Hi mplibbies,
I've made a preliminary stab at implementing detachable axis spines,
and I include a set of patches here. This is not in a state ready for
prime-time yet, but is presented here only as a report of progress. The
biggest question I see is whether now would be a good time to jump to a
Traits-like mechanism. Things are getting pretty messy in the
axis.draw() method, and I've really only implemented a fraction of
what's really desired. For example, I've hand-coded propagation of the
axis spine's location to the origin of the ticks, but I haven't
continued down the chain to the tick labels or the axis label.
Although I haven't played around with Traits, my feeling is that this
sort of daisy-chained dependency could be much more easily handled with
them.
To get this ready for prime time in its current form (without going to
what I imagine Traits to be), I think it would be a simple but tedious
and error-prone effort to propagate display coordinates down the
spine->ticks->ticklabels->axislabel chain in the event of something
like "gca().xaxis.spineBottomPad=10". I think I could bite this off in
the next few days for inclusion into CVS, although I'd be the first to
agree that it doesn't appear to be the ideal solution that something
based on Traits does.
So... any takers at performing open-heart surgery on matplotlib and
replacing several of the most critical parts with (Trait-based)
replacements? (C'mon, John, this should be easy for neuro-surgery
types! :) Or should I press ahead with the dumb version? ("If you're
gonna be dumb, you gotta be tough")
Any other comments/questions?
Cheers!
Andrew
|
|
From: John H. <jdh...@ac...> - 2005-02-13 17:44:09
|
>>>>> "Andrew" == Andrew Straw <str...@as...> writes:
Andrew> So... any takers at performing open-heart surgery on
Andrew> matplotlib and replacing several of the most critical
Andrew> parts with (Trait-based) replacements? (C'mon, John, this
Andrew> should be easy for neuro-surgery types! :) Or should I
Andrew> press ahead with the dumb version? ("If you're gonna be
Andrew> dumb, you gotta be tough")
Andrew> Any other comments/questions?
I wonder if the current design of an Axis containing a list of ticks
is the best one. Eg, in the current design each xticklabel can have
it's own color, own y position and own rotation. In real life these
attributes should be shared, or should be a property of the xaxis.
But rather than refactor this containment relationship which is
documented and is used external code, your idea to use traits is
probably the right way. Eg, this is a natural place for delegation --
eg the tick line and label locations should delegate to an axis trait.
The rate-limiting step here has not been the application of traits to
matplotlib, it is getting the latest traits package out of the
envisage tree. I spent some time working on this this morning, and
succeeded in getting the core traits minus the UI component as a
standalone package using plain-ol distutils rather than
scipy_distutils. I put the tarball here
http://jdh.uchicago.edu/share/traits2-1.0.2.tar.gz
if you want to play with it. Also, Abraham, you may want to see if
you can get your config file stuff working with this core. I think
now is a good time to introduce traits into matplotlib. I'll probably
roll out 0.72 tomorrow, and am pretty busy this week with real work,
but then we can look into porting all mpl properties to traits. A
good start would be for you and Abraham to break the ground in your
respective patches and test my traits port.
I posted my port to envisage-dev -- I had to make only a few minor
changes to the traits src to get this to work under python2.2 and to
work w/o the UI package. I suspect there will be a number of
iterations before we can get a package fully synchronized with
enthought traits, but my guess is that this will not be too long since
they seem receptive to making traits more accessible. Robert Kern had
the good idea of providing a null UI interface so that the existing
code which uses the UI component would not have to be altered.
Let me know how it goes...
JDH
|
|
From: Stephen W. <ste...@cs...> - 2005-02-13 19:43:45
|
John Hunter wrote: >I'll probably >roll out 0.72 tomorrow... > Any idea when anonymous CVS from Sourceforge for projects beginning with m might be available again? I was hoping you might have "inside information." At the moment, it _looks_ like it's working, but in fact an apparently successful CVS checkout gets 0.72 as of 9 February. Steve |
|
From: John H. <jdh...@ac...> - 2005-02-13 20:07:52
|
>>>>> "Stephen" == Stephen Walton <ste...@cs...> writes:
Stephen> Any idea when anonymous CVS from Sourceforge for projects
Stephen> beginning with m might be available again? I was hoping
Stephen> you might have "inside information." At the moment, it
Stephen> _looks_ like it's working, but in fact an apparently
Stephen> successful CVS checkout gets 0.72 as of 9 February.
I have no idea when sourceforge will get itself sorted out....
On Friday, I found and fixed the last remaining known bug in the new
log handling. I've upload the 0.72 release candidate to
http://jdh.uchicago.edu/share/matplotlib-0.72rc1.tar.gz
so you can test it out.
Let me know if you see anything unexpected...
JDH
|
|
From: Stephen W. <ste...@cs...> - 2005-02-13 21:31:26
|
John Hunter wrote: >On Friday, I found and fixed the last remaining known bug in the new >log handling. I've upload the 0.72 release candidate to > > http://jdh.uchicago.edu/share/matplotlib-0.72rc1.tar.gz > >so you can test it out. > > So far it passes my simple tests. Whether I have time to do anything serious with it depends on how much I get done on this grant proposal I'm writing. Thanks, John! |
|
From: Andrew S. <str...@as...> - 2005-02-13 20:43:17
|
JDH wrote: > I think now is a good time to introduce traits into matplotlib. The online documentation for traits seems pretty sparse. Here's the best I could track down, Dave Morrill's scipy '04 lightning talk: http://www.scipy.org/wikis/scipy04/presentations2004/ scipy_conference_2004.pdf The gist is encapsulated in the following basic usage example. Whee, what fun, strong types with notification in Python! import traits2 class Person(traits2.HasTraits): weight = traits2.Float volume = traits2.Range(0.0, 11.0, default=5.0) stock = traits2.Trait(None, 0, 1, 2, 3, 'many') # enumerated list name = traits2.Str # method signatures not included in this example... joe = Person() joe.weight = 120.0 def joes_weight_changed( what, new ): print what, 'changed to', new joe.on_trait_change( joes_weight_changed, 'weight' ) joe.weight = 200.0 |
|
From: John H. <jdh...@ac...> - 2005-02-13 21:18:15
|
>>>>> "Andrew" == Andrew Straw <str...@as...> writes:
Andrew> The online documentation for traits seems pretty sparse.
Andrew> Here's the best I could track down, Dave Morrill's scipy
Andrew> '04 lightning talk:
Andrew> http://www.scipy.org/wikis/scipy04/presentations2004/
Andrew> scipy_conference_2004.pdf
No, the documentation is great -- it's just hard to find. You have to
get the PDF from the enthought subversion tree, in the
branches/converge/traits/doc directory. I put a copy of the latest
subversion pdf from that directory on my server,
http://jdh.uchicago.edu/share/Traits2_UM.pdf
but there appears to be an OSX font problem with it...
JDH
|
|
From: Robert K. <rk...@uc...> - 2005-02-14 04:19:19
|
John Hunter wrote: > http://jdh.uchicago.edu/share/Traits2_UM.pdf > > but there appears to be an OSX font problem with it... It's more of a "non-Adobe Reader font problem," I think. It looks fine in Adobe Reader. However, I just re-exported it to PDF using NeoOffice/J (the Java/Aqua/Mac version of OpenOffice). It seems to load fine in Preview.app, Adobe Reader, and Schubert|it's PDF plugin. Dunno about other platforms. http://starship.python.net/crew/kernr/Traits2_UM_mac.pdf -- Robert Kern rk...@uc... "In the fields of hell where the grass grows high Are the graves of dreams allowed to die." -- Richard Harter |
|
From: John H. <jdh...@ac...> - 2005-02-13 21:11:15
|
>>>>> "Andrew" == Andrew Straw <str...@as...> writes:
Andrew> Any other comments/questions?
Hey Andrew, just did a quick read through the diff and have a few
meandering comments meant solely to confuse and perplex :-)
Rather than all this cruft in rc
axes.spineLeftOn : True
axes.spineRightOn : True
axes.spineBottomOn : True
axes.spineTopOn : True
axes.spineLeftPad : 0
axes.spineRightPad : 0
axes.spineBottomPad : 0
axes.spineTopPad : 0
How about
xaxis.spine1 = 0
xaxis.spine2 = 0
yaxis.spine1 = 0
yaxis.spine2 = 0
Or xaxis spine1 is left and spine2 is right; for yaxis bottom and top.
Use None to turn the spine off. Otherwise use a floating point value
to represent the pad.
You would need a new rc method none_or_float, which will eventually
become a trait. Some care would have to be taken with this approach
though. If the text locations and tick line locations are using
*delegation*, None could cause some trouble. But if we use observer,
then we could simply toggle the visibility to off upon setting None.
This would work pretty well.
In the midst of this refactor, it would be nice to support three tick
position (inside, outside, center) rather than use the tick1inward
boolean you suggest. As you know we already have TICKUP, TICKDOWN
TICKLEFT and TICKRIGHT line styles. It would be trivial to add
TICK_HORIZONTAL_CENTER and TICK_VERTICAL_CENTER to support these three
tick placement schemes. We then do away with inward and outward and
simply use the tick line-style to indicate it's position. The trick
for doing label placement would be to query the tick line for top,
left, bottom and right. Then the only other param we need is the pad
in points that separates the label from the tick, right?
xaxis.tick.alignment = 'inside' # inside | outside | center
xaxis.tick.labelpad = 5 # distance from tickline in points
Hmm, the project is growing. I think there is something to be said
for doing this axis refactor once, generally, and right, though.
You also have to be a little careful here
self._tick1PadPixels = self.figure.dpi*Value(tick1Pad)*Value(1/72.0)
because changes to tick11pad will not be reflected in
self._tick1PadPixels. Compare with
self.tick1Pad = Value(tick1Pad)
self._tick1PadPixels = self.figure.dpi*self.tick1Pad*Value(1/72.0)
Then if later on you do self.tick1Pad.set(7) the tick1padPixels attr
is automagically updated
A lot of things I tried to solve with lazy values are addressed by
delegation and observers in traits though, so we may want to go for a
more traity impl.
On a related note, it would be really nice to develop a layout object
that was easy to use that was trait and mpl transform aware, so you
could rather easily say
val = to_the_right_of(x, 5*points)
Lazy values take you part of the way -- we'd also need all objects to
report their extent (pretty easy, but can be expensive for some artist
styles). With get_extent implemented for all artists, you could build
something like this will lazy values, but the syntax of constructing
these things is a bit awkward, and matplotlib doesn't allow you to use
lazy values and float interchangeably, which would be nice for example
when creating text instances. So a bit of redesign to support this
kind of layout would make your job a lot easier.
Anyway, more sketchy thoughts that concrete ideas.... Thanks for the
preliminary attempt!
JDh
|
|
From: Andrew S. <str...@as...> - 2005-02-13 22:10:41
|
On Feb 13, 2005, at 1:00 PM, John Hunter wrote: >>>>>> "Andrew" == Andrew Straw <str...@as...> writes: > Andrew> Any other comments/questions? > > Hey Andrew, just did a quick read through the diff and have a few > meandering comments meant solely to confuse and perplex :-) No, I like your suggestions... > Rather than all this cruft in rc > <snip> > How about > > xaxis.spine1 = 0 > xaxis.spine2 = 0 > yaxis.spine1 = 0 > yaxis.spine2 = 0 > > Or xaxis spine1 is left and spine2 is right; for yaxis bottom and top. > Use None to turn the spine off. Otherwise use a floating point value > to represent the pad. Yes, I like your suggestion. > You would need a new rc method none_or_float, which will eventually > become a trait. Some care would have to be taken with this approach > though. If the text locations and tick line locations are using > *delegation*, None could cause some trouble. But if we use observer, > then we could simply toggle the visibility to off upon setting None. > This would work pretty well. I think we might want a spine position variable separate from a spine visibility variable. It's conceivable, although seemingly unlikely, that people would want to move the spine but have it invisible such that the tick origins are offset... > In the midst of this refactor, it would be nice to support three tick > position (inside, outside, center) rather than use the tick1inward > boolean you suggest. As you know we already have TICKUP, TICKDOWN > TICKLEFT and TICKRIGHT line styles. It would be trivial to add > TICK_HORIZONTAL_CENTER and TICK_VERTICAL_CENTER to support these three > tick placement schemes. We then do away with inward and outward and > simply use the tick line-style to indicate it's position. The trick > for doing label placement would be to query the tick line for top, > left, bottom and right. Then the only other param we need is the pad > in points that separates the label from the tick, right? Yes, and then another step where I think we'd need the bounding boxes for the ticklabels to get the pad for the axis label (axis title). > Hmm, the project is growing. I think there is something to be said > for doing this axis refactor once, generally, and right, though. Agreed. I was fantasizing this morning about how, if we push the transforms into the backend, generalizing the whole thing to 3D and, for example, making an OpenGL backend wouldn't be the daunting task it once might've seemed. MPL's (2D) transforms now seem to be an example of parallel evolution to OpenGL's (3D) transforms. Furthermore, we could maybe support 3D in the frontend while allowing backends to implement at their own pace, throwing a NotImplementedError when the z transform becomes non-identity and if z values are non-zero... Maybe we could write a middle-layer (wrapper) backend which handles the 3D->2D transforms for the pure 2D backends. This would handle the projective transformation but preserve zorder. Anyhow, just a fantasy for the moment, but tantalizing. > You also have to be a little careful here > > self._tick1PadPixels = > self.figure.dpi*Value(tick1Pad)*Value(1/72.0) > > because changes to tick11pad will not be reflected in > self._tick1PadPixels. Compare with > > self.tick1Pad = Value(tick1Pad) > self._tick1PadPixels = > self.figure.dpi*self.tick1Pad*Value(1/72.0) > > Then if later on you do self.tick1Pad.set(7) the tick1padPixels attr > is automagically updated Yeah, I was running out of steam last night at 3 in the morning and got lazy, just wanting to get the thing to work. I knew about this... > A lot of things I tried to solve with lazy values are addressed by > delegation and observers in traits though, so we may want to go for a > more traity impl. Agreed. > On a related note, it would be really nice to develop a layout object > that was easy to use that was trait and mpl transform aware, so you > could rather easily say > > val = to_the_right_of(x, 5*points) > > Lazy values take you part of the way -- we'd also need all objects to > report their extent (pretty easy, but can be expensive for some artist > styles). With get_extent implemented for all artists, you could build > something like this will lazy values, but the syntax of constructing > these things is a bit awkward, and matplotlib doesn't allow you to use > lazy values and float interchangeably, which would be nice for example > when creating text instances. So a bit of redesign to support this > kind of layout would make your job a lot easier. This would really cool. It's beyond my brain capacity right now to think about implementation... > Anyway, more sketchy thoughts that concrete ideas.... Thanks for the > preliminary attempt! I think moving to traits would be a wise first step, so I'll hold off for now until we get traits implemented. What needs to happen first to implement traits? Change rcParams to be traits aware? I've been ignoring the threads about re-vamping the rcParams format and reader, so I'm clueless about what's going on in that department. Anyhow, I'm in no great hurry to get detachable axis spines working (as you know!), so I can happily return to this later. Cheers! Andrew |
|
From: John H. <jdh...@ac...> - 2005-02-14 01:46:17
|
>>>>> "Abraham" == Abraham Schneider <ab...@cn...> writes:
Abraham> Wow, that makes life much easier! I'll get started on
Abraham> re-porting the new style config library to use your
Abraham> modified Traits2.
OK, great, just be aware that the directory organization will likely
change a bit over the next couple of weeks as I try to synchronize my
quick port with the enthought core tree. But this change will be
localized to the one or two lines where the import occurs.
Eric Jones suggests we use continue to place traits under an enthought
basedir so it will be easier to keep our tree synched with theirs. So
it will probably either matplotlib.enthought.traits or simply
enthought.traits depending on how things shake out. He is also
interested in maintaining python2.2 compatibility so that bodes well
for us being able to work from their un/lightly-modified code base.
JDH
|
|
From: John H. <jdh...@ac...> - 2005-02-14 21:21:57
|
>>>>> "Abraham" == Abraham Schneider <ab...@cn...> writes:
Abraham> Wow, that makes life much easier! I'll get started on
Abraham> re-porting the new style config library to use your
Abraham> modified Traits2.
As I mentioned, I've been talking with the enthought folks about where
traits should live in matplotlib, and they suggested
matplotlib.enthought.traits, because
* it's important to have traits live inside of an enthought directory
because enthought.traits import statements are widely used in their
UI code, and this will help us keep our code in sync with theirs.
* because we have a stripped down version missing
lots-o-functionality, it shouldn't go into site-packages/enthought
because that will screw up folks who have a regular enthought
install
So I added the core enthought traits tree (minus UI) to CVS -- once
the mirrors update (tick, tock, tick, tock), you can do
from matplotlib.enthought.traits import HasTraits, etc.
Dave Morrill is working on a null UI (like backend_template), so that
we can develop UI functionality if we want to but it will only work on
some backends (currently WX). The other backends can fall back on the
null UI. Michel Sanner has expressed some interest in having his
group repair the currently defunct Tk traits backend. Now if we can
just get Steve to do GTK, Gregory to do FLTK and Ted and friends to do
QT, we could have a very nice way to manipulate plot attributes and rc
configuration through the GUI. But that is a story for another
day....
JDH
|