On Tuesday 31 July 2007 02:12:06 pm you wrote:
> Looking at the profile outputs, a couple of things stand out in the new
> version. =A0First, various Traits things are prominent near the top.
pycachegrind is telling me that traits_db is responsible for about 20%,=20
configobj is responsible for about 30%, and the config package another 30%.
> Second, look at the lines for posixpath functions, which are taking
> quite a bit of time. =A0Here are two examples:
>
> =A0 =A0 =A0 5651 =A0 =A00.108 =A0 =A00.000 =A0 =A00.188 =A0 =A00.000 posi=
xpath.py:56(join)
> [...]
> =A0 =A0 =A0 =A0273 =A0 =A00.012 =A0 =A00.000 =A0 =A00.164 =A0 =A00.001 po=
sixpath.py:410(realpath)
>
> If I understand correctly, path.join is being called 5651 times! =A0And
> realpath is being called 273 times! =A0
I think the posix_path stuff is being called most often by python while it=
=20
attempts to locate modules.=20
[...]
> I would not like to see mpl become a library that is painfully sluggish
> to start up; it is already too slow for my liking, with font setup being
> a major contributor.
I agree.
Darren

On 7/31/07, Michael Droettboom <mdroe@...> wrote:
> Eric Firing wrote:
> > I don't have a lot of experience with profiling...
> Slightly OT, but I do have a recommendation for anyone doing Python
> profiling. I don't usually get very excited about GUI tools, but
> KCachegrind (Linux only) is very slick and works great with Python.
> It's really handy to be able to "browse" the calltree interactively to
> explore what's going on.
>
> The trick (which is very non-obvious from the documentation), is that
> you use Python's 'hotspot' profiler, then convert that to 'calltree'
> format using hotspot2calltree (included with KCachegrind), and then load
> that with KCachegrind.
>
> Just my two cents for something you may want to try,
Yup. The link I posted earlier is basically a little wrapper that
does all that. I wrote it so you wouldn't have to think :)
I keep it in my path and can profile any python script with
kcachegrind just by running one command. And yes, kcachegrind rocks.
I'm also very much a non-gui person, yet I've found it invaluable for
doing really complex profiling of very large python codes.
Cheers,
f

Eric Firing wrote:
> I don't have a lot of experience with profiling...
Slightly OT, but I do have a recommendation for anyone doing Python
profiling. I don't usually get very excited about GUI tools, but
KCachegrind (Linux only) is very slick and works great with Python.
It's really handy to be able to "browse" the calltree interactively to
explore what's going on.
The trick (which is very non-obvious from the documentation), is that
you use Python's 'hotspot' profiler, then convert that to 'calltree'
format using hotspot2calltree (included with KCachegrind), and then load
that with KCachegrind.
Just my two cents for something you may want to try,
Mike

Darren,
The two cases you ran have almost identical timing, so the problem is
not in reading matplotlib.conf. Instead, it seems to be in the
initialization of all the machinery, and I suspect that something may
be getting run many times in a loop instead of just once. I used the
profile.py script method to profile the whole simple_plot.py demo
modified to use Agg, with NEWCONFIG True versus False. Attached are the
top 100 lines of the output, sorted by cumulative time, with "new"
meaning NEWCONFIG=True. The execution time of the new version is 3.2
seconds versus 1.8 for the old. (Both are pretty slow for making a
minimal plot from a script.)
Looking at the profile outputs, a couple of things stand out in the new
version. First, various Traits things are prominent near the top.
Second, look at the lines for posixpath functions, which are taking
quite a bit of time. Here are two examples:
5651 0.108 0.000 0.188 0.000 posixpath.py:56(join)
[...]
273 0.012 0.000 0.164 0.001 posixpath.py:410(realpath)
If I understand correctly, path.join is being called 5651 times! And
realpath is being called 273 times! Now, these calls are contributing
only a little to the total time difference between the mpl versions, but
they may be providing clues as to what is wrong. My guess is that there
is a glitch in the program logic that is causing some operations that
should be done once or a few times to be done hundreds or thousands of
times, and this will turn out to be the biggest factor in the slowdown.
If so, then we will still have to see whether a significant slowdown
remains after the glitch is corrected.
I don't have a lot of experience with profiling, but it seems to me that
ordering results by cumulative time is good for finding the major
operations that are slow, whereas ordering by time is good for finding
the lowest-level functions that are holding things up. Ordering by time
shows these as the top two for the new system:
32581/31616 0.152 0.000 0.168 0.000 :0(len)
98 0.132 0.001 0.372 0.004 has_traits.py:558(__init__)
This doesn't mean that the len builtin is too slow, but that it is
getting called a lot of times, and we have to look elsewhere to figure
out how to reduce that, if possible. The second line, however, suggests
to me that even after the glitch problem is solved, we will be stuck
with a distressing startup overhead from using traits. This line is
saying that we are initializing 98 trait instances, and this
initialization alone is taking 0.37 seconds, of which 0.13 seconds is in
the init code, not in functions that it is calling. If you look at the
code for that __init__, you will see that it is huge. It may be that
the traits overhead is small once a program is up and running, but it
certainly looks to me like the startup overhead is a killer if more than
a few traits are to be used.
I would not like to see mpl become a library that is painfully sluggish
to start up; it is already too slow for my liking, with font setup being
a major contributor.
Eric
Darren Dale wrote:
> On Monday 30 July 2007 07:10:01 pm Eric Firing wrote:
>> Darren Dale wrote:
>>> I just committed changes in svn that will allow matplotlib to use the
>>> experimental traited mplconfig module. The traited config object itself
>>> is called mplConfig, but I wrapped it in an object called rcParams to
>>> make it compatible with matplotlib, so we can kick the tires without
>>> extensive changes.
>> Darren,
>>
>> There is *major* speed problem. Running "backend_driver.py Template":
>>
>> 0.95 minutes with NEWCONFIG = True
>> 0.51 minutes False
>
> I used the following script in the matplotlib/config directory to profile the
> mplconfig module:
> def main():
> import mplconfig
>
> if __name__=='__main__':
> import profile
> import pstats
> profile.run('main()', 'config.prof')
>
> p = pstats.Stats('config.prof')
> p.sort_stats('cumulative').print_stats(55)
>
> I am attaching the results for two different tests. One is loading the default
> mpl-data/matplotlib.conf, the other is loading an empty
> ~/.matplotlib/matplotlib.conf. I haven't done much work with profiling, maybe
> others can make some comments about the results.

On 7/31/07, Darren Dale <dd55@...> wrote:
> I am attaching the results for two different tests. One is loading the default
> mpl-data/matplotlib.conf, the other is loading an empty
> ~/.matplotlib/matplotlib.conf. I haven't done much work with profiling, maybe
> others can make some comments about the results.
I'm afraid I can't help with this right now, but you may want to look at
http://amath.colorado.edu/faculty/fperez/python/profiling/
the little code I put in there makes using kcachegrind very easy for
python profiling, and it's really a useful tool for analyzing
profiling info.
Cheers,
f

On Monday 30 July 2007 07:10:01 pm Eric Firing wrote:
> Darren Dale wrote:
> > I just committed changes in svn that will allow matplotlib to use the
> > experimental traited mplconfig module. The traited config object itself
> > is called mplConfig, but I wrapped it in an object called rcParams to
> > make it compatible with matplotlib, so we can kick the tires without
> > extensive changes.
>
> Darren,
>
> There is *major* speed problem. Running "backend_driver.py Template":
>
> 0.95 minutes with NEWCONFIG = True
> 0.51 minutes False
I used the following script in the matplotlib/config directory to profile the
mplconfig module:
def main():
import mplconfig
if __name__=='__main__':
import profile
import pstats
profile.run('main()', 'config.prof')
p = pstats.Stats('config.prof')
p.sort_stats('cumulative').print_stats(55)
I am attaching the results for two different tests. One is loading the default
mpl-data/matplotlib.conf, the other is loading an empty
~/.matplotlib/matplotlib.conf. I haven't done much work with profiling, maybe
others can make some comments about the results.

Hi Eric,
On Monday 30 July 2007 10:14:22 pm Eric Firing wrote:
> I have not made any matplotlib.conf other than the one that is now being
> installed correctly in mpl-data, and it contains
>
> # display grid on regular or polar axes
> grid = False
> polargrid = True
>
> grep indicates the True value is coming from mplconfig:
>
> config/mplconfig.py: grid = T.Trait(True, mplT.BoolHandler())
>
> config/rcsetup.py: 'axes.grid' : [False, validate_bool]
>
> so it looks like somehow this mplconfig initialization is overriding the
> value in matplotlib.conf.
Ok, sorry for the confusion. There were two problems:
-The .conf file in mpl-data was not being read. It is fixed in svn 3645.
-The .conf file is not auto-generated by setup.py. This is a more difficult
problem, so I am not going to work on it unless we decide to adopt the new
module. In the mean time, the file can be auto-generated by running
mplconfig.
Darren

Darren Dale wrote:
> On Monday 30 July 2007 6:58:17 pm Eric Firing wrote:
>> Darren,
>>
>> It looks like there is a problem with the grid lines. Although the
>> matplotlib.conf file is specifying linestyle = ':', and False for the
>> axes.grid parameter, everything is coming up with solid lines (see
>> barh_demo.py, for example) by default. It looks like those two keys are
>> not setting their respective rcParams entries.
>
> barh_demo turns the grid on. I accidentally set the default linestyle to '-'
> in mplconfig for the grids, thats been fixed.
Darren,
barh_demo turns the grid on for the first plot only, but the grid is
shown for both. ipython -pylab also plots with a grid by default, and
shows
In [3]:rcParams['axes.grid']
Out[3]:True
I have not made any matplotlib.conf other than the one that is now being
installed correctly in mpl-data, and it contains
# display grid on regular or polar axes
grid = False
polargrid = True
grep indicates the True value is coming from mplconfig:
config/mplconfig.py: grid = T.Trait(True, mplT.BoolHandler())
config/rcsetup.py: 'axes.grid' : [False, validate_bool]
so it looks like somehow this mplconfig initialization is overriding the
value in matplotlib.conf.
Eric

On Monday 30 July 2007 6:58:17 pm Eric Firing wrote:
> Darren,
>
> It looks like there is a problem with the grid lines. Although the
> matplotlib.conf file is specifying linestyle = ':', and False for the
> axes.grid parameter, everything is coming up with solid lines (see
> barh_demo.py, for example) by default. It looks like those two keys are
> not setting their respective rcParams entries.
barh_demo turns the grid on. I accidentally set the default linestyle to '-'
in mplconfig for the grids, thats been fixed.

On Monday 30 July 2007 7:10:01 pm Eric Firing wrote:
> Darren Dale wrote:
> > I just committed changes in svn that will allow matplotlib to use the
> > experimental traited mplconfig module. The traited config object itself
> > is called mplConfig, but I wrapped it in an object called rcParams to
> > make it compatible with matplotlib, so we can kick the tires without
> > extensive changes.
>
> Darren,
>
> There is *major* speed problem. Running "backend_driver.py Template":
>
> 0.95 minutes with NEWCONFIG = True
> 0.51 minutes False
It looks like creating the mplConfig object is adding to the startup time.
I'll look into it when I get a chance.
Darren

Darren Dale wrote:
> I just committed changes in svn that will allow matplotlib to use the
> experimental traited mplconfig module. The traited config object itself is
> called mplConfig, but I wrapped it in an object called rcParams to make it
> compatible with matplotlib, so we can kick the tires without extensive
> changes.
Darren,
There is *major* speed problem. Running "backend_driver.py Template":
0.95 minutes with NEWCONFIG = True
0.51 minutes False
Eric

Darren,
It looks like there is a problem with the grid lines. Although the
matplotlib.conf file is specifying linestyle = ':', and False for the
axes.grid parameter, everything is coming up with solid lines (see
barh_demo.py, for example) by default. It looks like those two keys are
not setting their respective rcParams entries.
Eric

Darren,
When I make a clean build and install, set NEWCONFIG, and try to run I
get a permission problem. It looks like the problem is that the global
matplotlib.conf is not getting generated and installed at build/install
time, but I have not investigated it.
Eric
convert!
Traceback (most recent call last):
File "backend_driver.py", line 20, in <module>
import matplotlib.backends as mplbe
File "/usr/local/lib/python2.5/site-packages/matplotlib/__init__.py",
line 712, in <module>
from config import rcParams, rcdefaults
File
"/usr/local/lib/python2.5/site-packages/matplotlib/config/__init__.py",
line 10, in <module>
from mplconfig import rcParams, mplConfig, save_config, rcdefaults
File
"/usr/local/lib/python2.5/site-packages/matplotlib/config/mplconfig.py",
line 473, in <module>
filePriority=True)
File
"/usr/local/lib/python2.5/site-packages/matplotlib/config/tconfig.py",
line 549, in __init__
rconf = RecursiveConfigObj(configFilename)
File
"/usr/local/lib/python2.5/site-packages/matplotlib/config/tconfig.py",
line 311, in __init__
self.conf = self._load(filename)
File
"/usr/local/lib/python2.5/site-packages/matplotlib/config/tconfig.py",
line 314, in _load
conf = mkConfigObj(filename,makeMissingFile)
File
"/usr/local/lib/python2.5/site-packages/matplotlib/config/tconfig.py",
line 289, in mkConfigObj
unrepr=True)
File
"/usr/local/lib/python2.5/site-packages/matplotlib/config/configobj.py",
line 1189, in __init__
h = open(infile, 'w')
IOError: [Errno 13] Permission denied:
'/usr/local/lib/python2.5/site-packages/matplotlib/mpl-data/matplotlib.conf'

On Monday 30 July 2007 4:49:24 pm Eric Firing wrote:
> Darren,
>
> When I make a clean build and install, set NEWCONFIG, and try to run I
> get a permission problem. It looks like the problem is that the global
> matplotlib.conf is not getting generated and installed at build/install
> time, but I have not investigated it.
That was exactly the problem, I forgot to add the new file to the setup
script. It is fixed in svn 3640.
Darren

Darren Dale wrote:
> On Monday 30 July 2007 03:33:11 pm you wrote:
>
>> Darren Dale wrote:
>>
>>> I ran backend_driver with the traited config enabled, and the only errors
>>> I got were related to broken mathtext support in backend_svg, and I think
>>> those are unrelated to my changes.
>>>
>> I think I broke that for a few hours this morning, but it's working for
>> me now. Next time you update, please let me know if it still isn't
>> working for you.
>>
>
> It's still broken here:
>
> File "/usr/lib64/python2.5/site-packages/matplotlib-0.90.1_r3636-py2.5-linux-x86_64.egg/matplotlib/backends/backend_svg.py",
> line 378, in _draw_mathtext
> (fontsize, fontname))
> NameError: global name 'fontname' is not defined
>
Should be fixed now. The bug was only exercised when
svg.embed_char_paths was turned off.
Cheers,
Mike

Darren Dale wrote:
> I ran backend_driver with the traited config enabled, and the only errors I
> got were related to broken mathtext support in backend_svg, and I think those
> are unrelated to my changes.
>
I think I broke that for a few hours this morning, but it's working for
me now. Next time you update, please let me know if it still isn't
working for you.
Cheers,
Mike

I just committed changes in svn that will allow matplotlib to use the
experimental traited mplconfig module. The traited config object itself is
called mplConfig, but I wrapped it in an object called rcParams to make it
compatible with matplotlib, so we can kick the tires without extensive
changes.
Some notes:
- All of the code associated with reading config files and creating config
objects has been organized into an experimental config package, and is
therefore disabled by default. To enable the config package, set "NEWCONFIG =
True" in matplotlib.__init__.py.
- Once enabled, the config package supports either the old matplotlibrc files
(used by the rcparams module) or the newer matplotlib.conf files (used by the
traited mplconfig module). The config package defaults to the traited
mplconfig option. The config package will use the old matplotlibrc system if
you set "USE_TRAITED_CONFIG = False" in matplotlib/config/__init__.py
-The traited config module will create a new matplotlib.conf file from a
standard matplotlibrc file when appropriate.
-Fernando's tconfig module will not work with the version of traits ships with
matplotlib (we can update our version when Enthought makes their release).
This will get you a more recent version:
sudo easy_install -f
http://code.enthought.com/enstaller/eggs/source/unstable "enthought.traits <
3.0a"
I ran backend_driver with the traited config enabled, and the only errors I
got were related to broken mathtext support in backend_svg, and I think those
are unrelated to my changes. If you have the luxury, please update from svn
and try working with the traited config module enabled. Any feedback would be
appreciated.
Darren

Hi all,
this is mostly for those of you using TConfig for the rcparams work, I
suppose.
IPython has now traits-aware 'smart' tab-completion. Svn update
ipython to r2568 at least. You'll get:
http://projects.scipy.org/ipython/ipython/browser/ipython/trunk/IPython/Extensions/ipy_traits_completer.py
>From the module docstring, this is how it works:
Usage
=====
The system works as follows. If t is an empty object that HasTraits, then
(assuming the threshold is at the default value of 3):
In [7]: t.ed<TAB>
doesn't show anything at all, but:
In [7]: t.edi<TAB>
t.edit_traits t.editable_traits
shows these two names that come from traits. This allows you to complete on
the traits-specific names by typing at least 3 letters from them (or whatever
you set your threshold to), but to otherwise not see them in normal completion.
######
Let me know if that sounds like a reasonable solution, it was the best
I could think of.
Cheers,
f

On Sun, Jul 29, 2007 at 09:03:30AM +0900, Bill Baxter wrote:
> Curious, I gave it a try in photoshop. I think you have to line up the
> doorways & windows to see the effect.
> I see someone who looks kinda like they're holding a baby, but I don't =
know
> what a Templar knight is supposed to look like, so I'm not sure if I sa=
w that
> or not.
The picture on the website is a chalk reproduction of the original, so
I doubt whether you would see anything there. Of course, to see
anything in the first place requires a healthy amount of imagination
:)
Here is a copy of the original, with its mirror-image aligned and
super-imposed.
http://mentat.za.net/results/last_supper_mirror.jpg
Cheers
St=E9fan

Curious, I gave it a try in photoshop. I think you have to line up the
doorways & windows to see the effect.
I see someone who looks kinda like they're holding a baby, but I don't know
what a Templar knight is supposed to look like, so I'm not sure if I saw
that or not.
--bb
On 7/29/07, Darren Dale <dd55@...> wrote:
>
> I just saw this article on Reuters, which covers a theory that if you
> superimpose DaVinci's Last Supper with its own mirror image, you get a new
> image of a Templar night and someone holding a small baby:
>
>
> http://news.yahoo.com/s/nm/20070727/wr_nm/italy_lastsupper_theory_dc;_ylt=AimIrSA2KgCxm6wB1a0LXuas0NUE
> ?
>
> The websites that supposedly contain the image are unreachable, so I
> thought
> it would be fun to recreate the image myself using matplotlib and the PIL.
> The image is attached, I dont see a Templar knight or anyone holding a
> small
> baby.
>
> Darren
>
> -------------------------------------------------------------------------
> This SF.net email is sponsored by: Splunk Inc.
> Still grepping through log files to find problems? Stop.
> Now Search log events and configuration files using AJAX and a browser.
> Download your FREE copy of Splunk now >> http://get.splunk.com/
> _______________________________________________
> Matplotlib-devel mailing list
> Matplotlib-devel@...
> https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
>
>
>

I just saw this article on Reuters, which covers a theory that if you
superimpose DaVinci's Last Supper with its own mirror image, you get a new
image of a Templar night and someone holding a small baby:
http://news.yahoo.com/s/nm/20070727/wr_nm/italy_lastsupper_theory_dc;_ylt=AimIrSA2KgCxm6wB1a0LXuas0NUE?
The websites that supposedly contain the image are unreachable, so I thought
it would be fun to recreate the image myself using matplotlib and the PIL.
The image is attached, I dont see a Templar knight or anyone holding a small
baby.
Darren

On Jul 25, 2007, at 12:09 PM, John Hunter wrote:
>
> Hi Ken -- sorry for the radio silence, I'm not intentionally ignoring
> you. Real life has made some demands on my time of late, and probably
> will until next week, but I was able to download, read through and
> test your code.
I appreciate you making the time to take a look at my code in spite
of it.
> But I don't think that closes the book on the subject -- for
> example, I have realized I am introducing too much complexity and
> trait forwarding, and I think I know a way to work around this, so
> I will be hacking through my version one more time while at the
> same time taking a closer look at yours.
I'd hardly expect it to close the book on the subject. Although it
functions as a proof-of-concept, my rendering model needs more work
before it can handle special cases like the blended affine
transformation to plot an axis. I've been thinking about how best to
accomplish this and will try to have something for you to look at by
early next week. Please drop me a line when you're satisfied with
your changes to mpl1.py, as I'm looking forward to seeing them.
> I also would like to hear more about the "hard to optimize" part,
> because that is not intuitively clear to me.
Moving to a rendering model when the primitives modify the CTM
instead of replacing it with a pre-calculated value removes the
dependency between primitives and their containers. A Primitive
object, like a Path, may be reused and shared between renderers. The
native version of a Primitive object is stored by the Primitive
object itself, so it can be reused by any Canvas that draws the
Primitive. This also means that you incur very little cost in
clearing a Renderer and then repopulating it with existing
Primitives. An Artist-level implementation of z-order could leverage
this to avoid having to sort primitives by z-order every time a
figure is rendered.
Since primitives modify graphics state instead of replacing it
wholesale the it's easier for the Canvas to push as few changes to
the backend as possible. For example, if none of the child
primitives of a ScaledView have their own transforms then the CTM
only gets modified once when the ScaledView is rendered. The same is
true for all of the other graphics state parameters, like linewidth
and strokecolor. This saves on unnecessary backend overhead (e.g.
creating the same agg.trans_affine repeatedly). It could also lead
to tighter PDF and EPS output.
Finally, the Renderer class is canvas-independent so it can be used
to draw on multiple canvases during the course of its lifetime. I
hope this will substantially simplify the process of saving a figure
that was drawn interactively. I'm also contemplating making
Renderers able to contain child Renderers so parts of a figure can be
selectively updated. For example, drawing the non-Axis children of
an Axes by using a subrenderer could further improve animation
performance.
> I confess to being a meta-class ignoramus, so I am intrigued to study
> how you handled the canvas primitive cache problem using meta classes.
I hate to disappoint you, but metaclasses aren't involved. Right now
the caching is implemented cooperatively by Canvas and
CanvasPrimitive to reduce duplicate code.
CanvasPrimitive.get_canvas_primitive() handles the caching logic and
calls CanvasPrimitive.create_canvas_primitive() to create a new
native object if necessary. Subclasses of CanvasPrimitiveoverride
create_canvas_primitive() to delegate the call to the appropriate
method of Canvas, e.g. Path.create_canvas_primitive() returns the
result of Canvas.create_canvas_path(). Subclasses of Canvas that do
not cache Primitives should not override the create_canvas_xxx()
methods.
> How for example, if one modifies a Rectangle object which embodies a
> path primitive, would the canvas get the notification to update it's
> internal path representation (egg the agg_path_storage)?.
Native canvas objects are always created at render-time, so rectangle
would just update its associated Path instance when its bounds
changed. The next time the Path is drawn, Canvas.draw_path() would
call CanvasPrimitive.get_canvas_primitive() and end up with a new AGG
path. That being said, it might be more efficient if all Rectangles
share one Path that draws a unit square and change its size by
updating the CTM.
> With traits, I use the trait event handling mechanism so that when
> any of
> the box properties (left, width, top, etc...) are modified, the
> PathPrimitiveAgg would get a callback. So when the user does
>
> rect.left = 0.1
>
> the agg path knows to update itself. This is pretty cool.
Yes it is, and I agree that mpl1 should have an attribute-based API
for modifying plot object parameters.
> vis-a-vis properties vs traits, I second Peter's comment that once
> you've written 8,000 setters and getters and manually constructed
> properties, you'll probably evolve toward something like traits, w/o
> all the features. This is a library that has been bug and performance
> vetted in production applications for years, so we should seriously
> consider it as a properties alternative.
Traits does look excellent at what it does, but I'm still of the
opinion that the cost of adding a large external dependency that is
not available in Debian or Ubuntu outweighs the benefits of replacing
vanilla properties with traits.
> I strongly encourage you to download Fernando's mplconfig sandbox
> stuff and try the edit_traits demo in the presence of a wx enabled
> traits.
I'll give it a try.
> He is somewhat blown away by the fact that he got a sophisticated,
> nested GUI dialog w/o writing *any* code. Since you are a
> committed wx user, you might find this particularly appealing.
No one's committed me yet, mwahaha! Actually, that feature does
little to advance my primary use case for mpl, embedding plots in
applications. I my experience you have to put enough effort into
making the plots look good that you don't want users to be able to
edit them at runtime. That being said, I wouldn't be surprised to
learn that others' experiences differ.
> But at the end of the day, I think the *notification* aspect of
> traits is the killer feature.
I know, and I still think that for matplotlib it's a bad Software
Engineering move due to the implicit inter-object dependencies it
creates. I can't see why drawing plots should require that much
"spooky action at a distance". I could be wrong, but for now I'll
keep working to find a way that doesn't.
> I think your approach of working on a display PDF renderer interface
> is also a good one, for several reasons. It uses an established
> specification instead of a home grown one, and it makes it easier for
> us to consider things like integrating with Kiva or Chaco.
It's nice to hear you like it. Those are two of the specific goals I
have in mind. I also like the idea of having a generic retained
drawing system available in Python.
> I am glad you interpreted my mpl1 sketch in the right vein, as a
> lab in which
> people can advocate ideas as working code.
Well, I'm glad you've taken my criticisms of mpl1.py in the spirit
they were intended in. I also appreciate you taking the time to
review the code I submitted instead of just telling me how very nice
and convenient traits are. ;-)
> Hopefully next week we can come to some consensus and start merging
> our two lines.
That sounds like a plan. I'll try to make some progress on the
blended affines for drawing axis tickmarks and the Artists layer.
Ken