You can subscribe to this list here.
2003 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(1) |
Nov
(33) |
Dec
(20) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2004 |
Jan
(7) |
Feb
(44) |
Mar
(51) |
Apr
(43) |
May
(43) |
Jun
(36) |
Jul
(61) |
Aug
(44) |
Sep
(25) |
Oct
(82) |
Nov
(97) |
Dec
(47) |
2005 |
Jan
(77) |
Feb
(143) |
Mar
(42) |
Apr
(31) |
May
(93) |
Jun
(93) |
Jul
(35) |
Aug
(78) |
Sep
(56) |
Oct
(44) |
Nov
(72) |
Dec
(75) |
2006 |
Jan
(116) |
Feb
(99) |
Mar
(181) |
Apr
(171) |
May
(112) |
Jun
(86) |
Jul
(91) |
Aug
(111) |
Sep
(77) |
Oct
(72) |
Nov
(57) |
Dec
(51) |
2007 |
Jan
(64) |
Feb
(116) |
Mar
(70) |
Apr
(74) |
May
(53) |
Jun
(40) |
Jul
(519) |
Aug
(151) |
Sep
(132) |
Oct
(74) |
Nov
(282) |
Dec
(190) |
2008 |
Jan
(141) |
Feb
(67) |
Mar
(69) |
Apr
(96) |
May
(227) |
Jun
(404) |
Jul
(399) |
Aug
(96) |
Sep
(120) |
Oct
(205) |
Nov
(126) |
Dec
(261) |
2009 |
Jan
(136) |
Feb
(136) |
Mar
(119) |
Apr
(124) |
May
(155) |
Jun
(98) |
Jul
(136) |
Aug
(292) |
Sep
(174) |
Oct
(126) |
Nov
(126) |
Dec
(79) |
2010 |
Jan
(109) |
Feb
(83) |
Mar
(139) |
Apr
(91) |
May
(79) |
Jun
(164) |
Jul
(184) |
Aug
(146) |
Sep
(163) |
Oct
(128) |
Nov
(70) |
Dec
(73) |
2011 |
Jan
(235) |
Feb
(165) |
Mar
(147) |
Apr
(86) |
May
(74) |
Jun
(118) |
Jul
(65) |
Aug
(75) |
Sep
(162) |
Oct
(94) |
Nov
(48) |
Dec
(44) |
2012 |
Jan
(49) |
Feb
(40) |
Mar
(88) |
Apr
(35) |
May
(52) |
Jun
(69) |
Jul
(90) |
Aug
(123) |
Sep
(112) |
Oct
(120) |
Nov
(105) |
Dec
(116) |
2013 |
Jan
(76) |
Feb
(26) |
Mar
(78) |
Apr
(43) |
May
(61) |
Jun
(53) |
Jul
(147) |
Aug
(85) |
Sep
(83) |
Oct
(122) |
Nov
(18) |
Dec
(27) |
2014 |
Jan
(58) |
Feb
(25) |
Mar
(49) |
Apr
(17) |
May
(29) |
Jun
(39) |
Jul
(53) |
Aug
(52) |
Sep
(35) |
Oct
(47) |
Nov
(110) |
Dec
(27) |
2015 |
Jan
(50) |
Feb
(93) |
Mar
(96) |
Apr
(30) |
May
(55) |
Jun
(83) |
Jul
(44) |
Aug
(8) |
Sep
(5) |
Oct
|
Nov
(1) |
Dec
(1) |
2016 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
|
Jun
(2) |
Jul
|
Aug
(3) |
Sep
(1) |
Oct
(3) |
Nov
|
Dec
|
2017 |
Jan
|
Feb
(5) |
Mar
|
Apr
|
May
|
Jun
|
Jul
(3) |
Aug
|
Sep
(7) |
Oct
|
Nov
|
Dec
|
2018 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(2) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
S | M | T | W | T | F | S |
---|---|---|---|---|---|---|
|
1
|
2
(1) |
3
(8) |
4
(4) |
5
|
6
(2) |
7
(1) |
8
(7) |
9
(2) |
10
(3) |
11
(14) |
12
(3) |
13
|
14
|
15
(6) |
16
(4) |
17
(3) |
18
(1) |
19
|
20
(1) |
21
|
22
|
23
|
24
(1) |
25
|
26
(2) |
27
|
28
|
29
|
30
(1) |
31
|
|
|
|
From: Eric F. <ef...@ha...> - 2007-01-06 19:23:23
|
Steve, Darren Dale raised a question offline that I think will be of general interest to mpl devels, and that you are the person to answer: How do you see the future of a cairo backend as a prospective replacement for most or all of the primary mpl backends? What would need to be completed in cairo? Based on the cairo web page, I get the impression that quite a bit is still missing, including eps generation and genuine vector ps. But maybe the web page is just out of date. What would need to be done in mpl, and how hard would it be? Would mpl get slower if everything went through cairo? Any other considerations? Thanks. Eric |
From: Eric F. <ef...@ha...> - 2007-01-04 20:15:43
|
John Hunter wrote: >>>>>> "Eric" == Eric Firing <ef...@ha...> writes: [...] > Indeed, lots of grand ideas. I've been toying with the idea of trying > to organize an mpl sprint in some fabulous destination, and trying to Somewhere in Hawaii, of course! > raise funds for several developers via donations. Sometime in the > early summer perhaps. > > Eric> For the backends, maybe it would be easier to let (-1,*,*,*) > Eric> mean "don't draw"; if it has to be interpreted by C-code in > Eric> some backends, always having a tuple and simply checking for > Eric> a negative first element is much easier than having to check > Eric> for None in place of a tuple. > > If we are already passing in rgba, and are expecting the backends to > inspect it, wouldn't it make more sense for them to simply check for > rgba[-1]>0, as we do in backend_bases? Yes, I think this is already fully supported by common backends, and it may be all that is needed. Eric |
From: John H. <jdh...@ac...> - 2007-01-04 19:17:09
|
>>>>> "Eric" == Eric Firing <ef...@ha...> writes: Eric> But in the process of making that pass, I ran into a small Eric> worm can: in the collections the kwargs and the setters Eric> don't match, so kwdocd['PatchCollection'], for example, is Eric> not quite right. The collection setter names are singular Eric> (set_color) to mirror the corresponding non-collection Eric> objects, but the kwargs are plural (colors). Although I see Eric> the (grammatical) logic of the plural form I like the Eric> singular form because I see little gain and considerable When I was doing the kwdocd stuff I noticed the same but was focused on getting the documentation infrastructure working and didn't want to get distracted. But this is in part what I was alluding to in an earlier email about the need for a cleanup. Eg, in Axes we have axisbg in the init function and the axis_bgcolor property, both of which do the same thing; ditto for frameon and frame_on I think we should handle all properties in __init__ methods with **kwargs and artist.update, rather than using explicitly named keywords. artist init methods can take explicit keyword args, but these will not be properties. When I wrote some of these methods, I put named keyword args in the __init__ methods because it made them more readable, eg with "help", and because some of these did not exist as properties. As properties were added, apparently sometimes bad names were chosen. Now that we have a system for documenting keywords automatically, the docstring aspect is not so important so we should remove the bad or inconsistent names. For deprecated kwargs (eg axisbg) we could something like the following, eg for Axes: OLD: def __init__(self, fig, rect, axisbg = None, # defaults to rc axes.facecolor frameon = True, sharex=None, # use Axes instance's xaxis info sharey=None, # use Axes instance's yaxis info label='', **kwargs ): """ New: def __init__(self, fig, rect, sharex=None, # use Axes instance's xaxis info sharey=None, # use Axes instance's yaxis info **kwargs ): """ # check for deprecated usage: kwargs = kwargs.copy() frame_on = kwargs.get(frameon) if frame_on is not None: #deprecation warning kwargs['frame_on'] = frame_on axis_bgcolor = kwargs.get(axisbg) if axis_bgcolor is not None: #deprecation warning; use axis_bgcolor rather than axisbg kwargs['axis_bgcolor'] = axis_bgcolor .... self.update(kwargs) Alternatively, we can raise a helpful exception, eg 'Use axis_bgcolor rather than axisbg' Another approach is to support these alternate names through aliases like we do in Line2D: lw for linewidth, etc.... I don't feel strongly about any of the three approaches, but we can agree on something and both fix them as we find them. It should go pretty quickly. Eric> loss in having different names for the same functionality in Eric> LineCollection as compared to Line2D, for example. We could Eric> get around the problem by allowing the singular forms of the Eric> kwargs as well and deprecating the plural forms. Or use aliases. Again, if you have a preference I am happy to go with it. I guess simplicity should rule the day rather than having an ever growing number of ways to specify what you want. Eric> Another small glitch: it looks like you used the inspector Eric> to assemble the kwargs list for the Axes docstring, but some Eric> of these, like figure and position, duplicate required Eric> arguments so they don't really makes sense as kwargs--even Eric> though they would work. Did you edit out other such Eric> examples? Is that the reason the Axes.__init__ kwargs list Eric> is not being generated automatically? No, the reason here is that you can't mutate the docstring outside the class, and you can't use the inspector until the class is defined. So init methods are special cases. There may be some sophisticated way to do it but the naive way class C: def somefunc(): 'a test %d' pass C.somefunc.__doc__ = C.somefunc.__doc__%1 Traceback (most recent call last): File "<ipython console>", line 1, in ? TypeError: attribute '__doc__' of 'instancemethod' objects is not writable Absent something sophisticated, this morning while I was thinking about the need to systematize the __init__ method kwarg handling, I considered that maybe we should build a kwdocd module using the analog of boilerplate.py. Eg we would manually build the file which defines the kwdocd dictionary in a separate file. Something like: import matplotlib.artist import matplotlib.patches for o in dir(matplotlib.patches): if not isinstance(o, Patch): continue name = o.__name__ s = matplotlib.artist.kwdoc(o) # now write a dictionary entry to kwdoc.py with key=name and val=s and ditto for all other artists. We could then use this dict in __init__ methods and class methods. Not terribly elegant, but neither is boilerplate.py, but it would generate readable code, and having the kwdocd strings in a file would have some utility for developers and users. There is a bit of a bootstrapping problem here but it could be solved w/o too much difficulty. But if we can solve the problem of outside class docstring interpolation, this will be moot. This looks like a job for c.l.py. I googled a bit and it looks like their are some approaches using metaclasses: http://groups.google.com/group/comp.lang.python/browse_frm/thread/80a529a7ed6e239e/f77e00ffefadf223?lnk=st&q=__doc__+%22not+writable%22+group%3A*python*&rnum=1#f77e00ffefadf223 http://groups.google.com/group/comp.lang.python/browse_frm/thread/a25b1ec9478c1cfb/af19c967ab0a87eb?lnk=st&q=__doc__+%22not+writable%22+group%3A*python*&rnum=2#af19c967ab0a87eb Both of these discuss generating a new class with a modified class docstring rather than with a modified class method docstring, but perhaps there is an analog. I confess this metaclass stuff makes me feel queezy for reasons I don't fully understand, but I like to avoid python black magic when possible. JDH |
From: Eric F. <ef...@ha...> - 2007-01-04 07:34:40
|
John Hunter wrote: >>>>>> "Eric" == Eric Firing <ef...@ha...> writes: > > Eric> I can continue making the necessary changes if that is OK > Eric> with you, but I don't want our versions to get tangled up if > Eric> you are still working on this aspect, or if you don't like > Eric> the strategy modification outlined above. I committed > Eric> dedent but not the other changes. > > This looks very good and a definite improvement. You might consider > extending this a bit to have a custom class that handles all the > details. The general sketch is Very nice. I thought about making a standalone expand_doc() function, but your incorporation of it in the class is much nicer. I think I will put this on the stack and not do it immediately. I already made all the changes I outlined (couldn't stop once I got going) and can't quite face another pass through the files right now. But in the process of making that pass, I ran into a small worm can: in the collections the kwargs and the setters don't match, so kwdocd['PatchCollection'], for example, is not quite right. The collection setter names are singular (set_color) to mirror the corresponding non-collection objects, but the kwargs are plural (colors). Although I see the (grammatical) logic of the plural form I like the singular form because I see little gain and considerable loss in having different names for the same functionality in LineCollection as compared to Line2D, for example. We could get around the problem by allowing the singular forms of the kwargs as well and deprecating the plural forms. Another small glitch: it looks like you used the inspector to assemble the kwargs list for the Axes docstring, but some of these, like figure and position, duplicate required arguments so they don't really makes sense as kwargs--even though they would work. Did you edit out other such examples? Is that the reason the Axes.__init__ kwargs list is not being generated automatically? Eric > > class Kwdocd(dict): > > def inspect(self, artist): > # add artist to kwdocd, using __name__ or __class__ to get the key > > def expand_doc(self, method): > # interpolate kwdocd into method.__doc__ altering > # method.__doc__ in place > > kwdocd = Kwdocd() > > and then we have > > class Line2D: > pass > > kwdocd.inspect(Line2D) > > class Axes: > def plot(self, *args, **kwargs): > """ > %(Line2D)s > """ > pass > kwdocd.expand_doc(plot) > > > This is untested but it is consistent with the work you've done so far > to simplify the API at the level of the derived Artist classes by > hiding the gory details. > > JDH |
From: John H. <jdh...@ac...> - 2007-01-04 03:59:32
|
>>>>> "Eric" == Eric Firing <ef...@ha...> writes: Eric> I can continue making the necessary changes if that is OK Eric> with you, but I don't want our versions to get tangled up if Eric> you are still working on this aspect, or if you don't like Eric> the strategy modification outlined above. I committed Eric> dedent but not the other changes. This looks very good and a definite improvement. You might consider extending this a bit to have a custom class that handles all the details. The general sketch is class Kwdocd(dict): def inspect(self, artist): # add artist to kwdocd, using __name__ or __class__ to get the key def expand_doc(self, method): # interpolate kwdocd into method.__doc__ altering # method.__doc__ in place kwdocd = Kwdocd() and then we have class Line2D: pass kwdocd.inspect(Line2D) class Axes: def plot(self, *args, **kwargs): """ %(Line2D)s """ pass kwdocd.expand_doc(plot) This is untested but it is consistent with the work you've done so far to simplify the API at the level of the derived Artist classes by hiding the gory details. JDH |
From: Eric F. <ef...@ha...> - 2007-01-03 23:36:22
|
John Hunter wrote: [...] I am in the process of changing your shiny new kwdocd machinery slightly. I added artist.kwdoc so that > artist.kwdocd['Line2D'] = '\n'.join(artist.ArtistInspector(Line2D).pprint_setters(leadingspace=12)) > becomes artist.kwdocd['Line2D'] = artist.kwdoc(Line2D) > Then in any function accepting Line2D passthrough kwargs, eg > matplotlib.axes.Axes.plot > > def plot(self, *args, **kwargs): > """ > Some stuff omitted > > The kwargs are Line2D properties: > %(Line2D)s and the line above is changed to be indented the same as the rest of the string (improves readability to my eye) > > kwargs scalex and scaley, if defined, are passed on > to autoscale_view to determine whether the x and y axes are > autoscaled; default True. See Axes.autoscale_view for more > information > """ > pass because this > plot.__doc__ = plot.__doc__ % artist.kwdocd becomes plot.__doc__ = dedent(plot.__doc__) % artist.kwdocd where dedent is now in cbook.py I can continue making the necessary changes if that is OK with you, but I don't want our versions to get tangled up if you are still working on this aspect, or if you don't like the strategy modification outlined above. I committed dedent but not the other changes. Eric |
From: John H. <jdh...@ac...> - 2007-01-03 23:06:45
|
>>>>> "John" == John Hunter <jdh...@ac...> writes: John> I think we could lose python2.2 support if there is a good John> reason. Is anyone still using it? I'll also post to the John> user's list. Perhaps in the next release we should issue John> deprecation warnings for 2.2 and encourage people to post to John> the list if they have an objection. Typically with these John> things you don't see complaints until you take something John> away. Well, I was just about to post to the user list to see if anyone objected to remove 2.2 support, and wondered, do we really support 2.2 currently? I just tried to compile under 2.2 and got peds-pc311:~/mpl> sudo python2.2 setup.py install Traceback (most recent call last): File "setup.py", line 63, in ? from setupext import build_agg, build_gtkagg, build_tkagg, build_wxagg,\ File "setupext.py", line 120, in ? win32_compiler = get_win32_compiler() File "setupext.py", line 117, in get_win32_compiler if 'mingw32' in v: TypeError: 'in <string>' requires character as left operand And this has probably been in there for a while. So we haven't supported 2.2 for sometime and noone is complaining so let's make 2.3 the official target rather than fix this. At least 2.3 compiles and runs. I'll update the docs and website when I get a minute. JDH |
From: John H. <jdh...@ac...> - 2007-01-03 21:43:17
|
>>>>> "Eric" == Eric Firing <ef...@ha...> writes: Eric> Nice, simple, elegant, but it doesn't quite match what I had Eric> in mind for axes. I was thinking that the place to put the Eric> hook call is inside the draw() method, so it can take Eric> advantage of the intial work done there: getting a cached Eric> renderer, checking for visibility. Maybe this doesn't Eric> matter. Well for these two pieces, perhaps the method should look like def draw(self, renderer=None, **kwargs): if renderer is None: renderer = self._cachedRenderer if renderer is None: raise RuntimeError('No renderer defined') if not self.get_visible(): return for func in self.before_draw_hook.ordered_values(): func(self, renderer) self._draw(renderer, **kwargs) for func in self.after_draw_hook.ordered_values(): func(self, renderer) and perhaps the renderer caching should be done at the figure level if renderer is None: renderer = self.figure._cachedRenderer Eric> Also, looking at backend_bases, I can't figure out where Eric> this goes. There is a RendererBase class, but it doesn't Eric> have a draw method. And there is a FigureCanvasBase, but Eric> its draw method is overridden by each backend. What am I Eric> missing? I meant artist.Artist.draw -- sorry for the bad info. Eric> and have def register_before_draw(self, name, func): if Eric> self.before_draw_hook is None: self.before_draw_hook = Eric> OrderedDictionary() self.before_draw_hook.append(name, func) We also need a connectionid for connecting and disconnecting or something like it. Eric> Looking at the axes draw method, I am wondering whether a Eric> more general application of an OrderedDictionary (or Eric> ListDict, or whatever) wouldn't be a better approach. Why Eric> should there be before_draw_hook, draw, and after_draw_hook, Eric> with a big list generation and sorting operation at draw Eric> time? Could everything be done by having artists register Eric> all draw-time functions in a single ListDict, with Eric> sufficient ordering information to keep everything straight? Eric> That's pretty vague, and there is a lot I don't Eric> understand--but it just seems like there is an opportunity Eric> here for simplifying the overall structure with improved Eric> flexibility and no loss of speed. (Again, some kind of Eric> result-caching and need-for-recomputation-signalling would Eric> be needed.) This is interesting -- the devil will be in the details. Eg when one artist changes it's zorder, the whole connection hierarchy will need to be redone, which is currently accomplished by doing the sort w/ every draw. Your way would be faster since we would only need to do the ordering when the zscore changes, or when new artists are added, and not with every draw. But it might become difficult to manage resorting if users have added their own hooks. And then it wouldn't really be a before draw hook but a draw hook.... Actually, if we go this route, we may need to have one registry for user hooks, and another registry from internal calls. So any artist could support drawing other artists, eg Lines and Labels register with Ticks register which registers with an Axis which registers with an Axes which registers with a Figure. Of course at this point we are talking about a major architectural change and so there would need to be some clear utility, and I'm not sure what it is. The current design assumes an artist knows how to draw it's child artist, the one you are proposing it seems assumes the child artist knows how to insert itself into the parent. JDH |
From: John H. <jdh...@ac...> - 2007-01-03 21:09:42
|
>>>>> "Eric" == Eric Firing <ef...@ha...> writes: >> * Are your changes python2.3 compatible? We are still trying >> to support 2.3, so avoid 2.4 only features like decorators >> until we remove 2.3 support Eric> Good, I thought we were still restricted to 2.2! I was wondering how long it would take for someone to notice that <wink> I think we could lose python2.2 support if there is a good reason. Is anyone still using it? I'll also post to the user's list. Perhaps in the next release we should issue deprecation warnings for 2.2 and encourage people to post to the list if they have an objection. Typically with these things you don't see complaints until you take something away. We haven't been compiling 2.2 for windows for sometime now. JDH |
From: Eric F. <ef...@ha...> - 2007-01-03 20:20:02
|
> * Are your changes python2.3 compatible? We are still trying to > support 2.3, so avoid 2.4 only features like decorators until we > remove 2.3 support Good, I thought we were still restricted to 2.2! Does this mean boilerplate.py should be updated? (Or maybe it isn't worth fiddling with it.) # wrap the plot commands defined in axes. The code generated by this # file is pasted into pylab.py. We did try to do this the smart way, # with callable functions and new.function, but could never get the # docstrings right for python2.2. See http://groups-beta.google.com/group/comp.lang.python/browse_thread/thread/dcd63ec13096a0f6/17739e70ac6f710c?lnk=gst&q=dcd63ec13096a0f6&rnum=1#17739e70ac6f710c Eric |
From: Eric F. <ef...@ha...> - 2007-01-03 19:57:35
|
John Hunter wrote: > Hey Eric, I'm CC-ing the devel list because some of this has > potentially far reaching consequences. > >>>>>> "Eric" == Eric Firing <ef...@ha...> writes: > > Eric> In connection with the colorbar sizing problem I have been > Eric> thinking about adding a function list to axes, with the > Eric> functions to be executed early in the draw() method, to > Eric> handle this sort of thing. Using this mechanism to handle > > I think this is a very nice idea -- I saw a talk at pycon one year about > the utility of adding hooks, eg before_somefunc_hook and after_somefunc_hook > that are customizable *for every function in your API*. The questions are > > 1) what is the right data structure -- a single callable, a > sequence, or a dictionary registry with connect/disconnect > semantics (eg the backend event callback handler) > > 2) what is the signature (see below) > > 3) which artists should support it > > Most elegant, but most expensive, is something like a ordered > dictionary which is supported for every artist. By renaming all the > artist draw methods _draw, we can do this quite simply in > backend_bases.Renderer with > > def draw(self, renderer): > for func in self.before_draw_hook.ordered_values(): > func(self, renderer) > > self._draw(renderer) > > for func in self.after_draw_hook.ordered_values(): > func(self, renderer) > Nice, simple, elegant, but it doesn't quite match what I had in mind for axes. I was thinking that the place to put the hook call is inside the draw() method, so it can take advantage of the intial work done there: getting a cached renderer, checking for visibility. Maybe this doesn't matter. Also, looking at backend_bases, I can't figure out where this goes. There is a RendererBase class, but it doesn't have a draw method. And there is a FigureCanvasBase, but its draw method is overridden by each backend. What am I missing? > > I think this could be really useful and would help handle problems > that crop up all the time -- how to handle physical layout problems > where we need the renderer to get size information like you are > experiencing with colorbar. This problem also crops up in a lot of > text layout problems. Unfortunately, draw time layout creates other > problems (sometimes users want this info at the API level), and order > effects becomes very important and potentially complicated. But that > said, given the current architecture, something like this would be a > definite improvement. > > I'm inclined to use an ordered dictionary because one wants the > connect/disconnect semantics that keys make easy, and because ordering > matters. There is a python cookbook recipe for an ordered dictionary, > and we could easily roll our own. Because the calls are potentially > expensive, we might want an optimization like > I agree, an ordered dictionary is ideal if one needs the option of multiple functions being executed. I would probably have it inherit from list and tack on the dictionary; I think this might make for the fastest cycling through the list, and that is the place where speed is needed. > class MyOrderedDictionary: > def __init__(blah): > self.isempty = True > > > so we can do > > def draw(renderer): > if not self.before_draw_hook.isempty: > for func in self.before_draw_hook.ordered_values(): > func(self, renderer) > > self._draw(renderer) > > if not self.after_draw_hook.isempty: > for func in self.after_draw_hook.ordered_values(): > func(self, renderer) > > Since 99% of the time I guess these will be empty and then we are just > adding a few attribute lookups and a boolean check for each draw. Detail: Maybe it would be simpler and faster to initialize like this: self.before_draw_hook=None and have def register_before_draw(self, name, func): if self.before_draw_hook is None: self.before_draw_hook = OrderedDictionary() self.before_draw_hook.append(name, func) It saves one attribute lookup at draw time. Larger picture: Looking at the axes draw method, I am wondering whether a more general application of an OrderedDictionary (or ListDict, or whatever) wouldn't be a better approach. Why should there be before_draw_hook, draw, and after_draw_hook, with a big list generation and sorting operation at draw time? Could everything be done by having artists register all draw-time functions in a single ListDict, with sufficient ordering information to keep everything straight? That's pretty vague, and there is a lot I don't understand--but it just seems like there is an opportunity here for simplifying the overall structure with improved flexibility and no loss of speed. (Again, some kind of result-caching and need-for-recomputation-signalling would be needed.) Eric |
From: John H. <jdh...@ac...> - 2007-01-03 19:52:41
|
Eric Firing had the excellent idea of making a CODING_GUIDE which summarizes the conventions used in matplotlib development, and I've added this to svn. Feel free to make changes, additions and comments. I think we could add a lot here, including an overview of the API. Here is the document I just committed:: Devs, feel free to edit this document. This is meant to be a guide to developers on the mpl coding practices and standards == Committing Changes == When committing changes to matplotlib, there are a few things to bear in mind. * if your changes are nontrivial, please make an entry in the CHANGELOG * if you change the API, please document it in API_CHANGES, and consider posing to mpl-devel * Are your changes python2.3 compatible? We are still trying to support 2.3, so avoid 2.4 only features like decorators until we remove 2.3 support * Are your changes Numeric, numarray and numpy compatible? Try running simple_plot.py or image_demo.py with --Numeric, --numarray and --numpy (Note, someone should add examples to backend_driver.py which explicitly require numpy, numarray and Numeric so we can automatically catch these) * Can you pass examples/backend_driver.py? This is our poor man's unit test. * If you have altered extension code, do you pass unit/memleak_hawaii.py? == Naming conventions == functions and class methods : lower or lower_underscore_separated attributes and variables : lower or lowerUpper classes : Upper or MixedCase Personally, I prefer the shortest names that are still readable. == kwargs processing == Matplotlib makes extensive use of **kwargs for pass through customizations from one function to another, eg the pylab plot -> Axes.plot pass through. As a general rule, the use of **kwargs should be reserved for pass-through keyword arguments, eg def somefunc(x, k1='something', **kwargs): # do some thing with x, k1 return some_other_func(..., **kwargs) If I intend for all the keyword args to be used in somefunc alone, I just use the key/value keyword args in the function definition rather than the **kwargs idiom. In some cases I want to consume some keys and pass through the others, in which case I pop the ones I want to use locally and pass on the rest, eg I pop scalex and scaley in Axes.plot and assume the rest are Line2D keyword arguments. Whenever you mutate a kwargs dictionary (eg by popping it), you must first copy it since the user may be explitly passing in a dictionary which is used across many function calls. As an example of a copy, pop, passthrough usage, see Axes.plot: def plot(self, *args, **kwargs): kwargs = kwargs.copy() scalex = popd(kwargs, 'scalex', True) scaley = popd(kwargs, 'scaley', True) if not self._hold: self.cla() lines = [] for line in self._get_lines(*args, **kwargs): self.add_line(line) lines.append(line) popd is a matplotlib.cbook function to pop an item from a dictionary with a default value if the item doesn't exist Note there is a use case when kwargs are meant to be used locally in the function (not passed on), but you still need the **kwargs idiom. That is when you want to use *args to allow variable numbers of non-keyword args. In this case, python will not allow you to use named keyword args after the *args usage, so you will be forced to use **kwargs. An example is matplotlib.contour.ContourLabeler.clabel def clabel(self, *args, **kwargs): fontsize = kwargs.get('fontsize', None) inline = kwargs.get('inline', 1) self.fmt = kwargs.get('fmt', '%1.3f') colors = kwargs.get('colors', None) if len(args) == 0: levels = self.levels indices = range(len(self.levels)) elif len(args) == 1: ...etc... == class documentation == matplotlib uses artist instrospection of docstrings to support properties. All properties that you want to support through setp and getp should have a set_property and get_property method in the Artist class. Yes this is not ideal given python properties or enthought traits, but it is a historical legacy for now. The setter methods use the docstring with the ACCEPTS token to indicate the type of argument the method accepts. Eg in matplotlib.lines.Line2D def set_linestyle(self, linestyle): """ Set the linestyle of the line ACCEPTS: [ '-' | '--' | '-.' | ':' | 'steps' | 'None' | ' ' | '' ] """ Since matplotlib uses a lot of pass through kwargs, eg in every function that creates a line (plot, semilogx, semilogy, etc...), it can be difficult for the new user to know which kwargs are supported. I have developed a docstring interpolation scheme to support documentation of every function that takes a **kwargs. The requirements are: 1) single point of configuration so changes to the properties don't require multiple docstring edits 2) as automated as possible so that as properties change the docs are updated automagically. I have added a matplotlib.artist.kwdocd to faciliate this. This combines python string interpolation in the docstring with the matplotlib artist introspection facility that underlies setp and getp. The kwdocd is a single dictionary that maps class name to a docstring of kwargs. Here is an example at the bottom of matplotlib.lines artist.kwdocd['Line2D'] = '\n'.join(artist.ArtistInspector(Line2D).pprint_setters(leadingspace=12)) Then in any function accepting Line2D passthrough kwargs, eg matplotlib.axes.Axes.plot def plot(self, *args, **kwargs): """ Some stuff omitted The kwargs are Line2D properties: %(Line2D)s kwargs scalex and scaley, if defined, are passed on to autoscale_view to determine whether the x and y axes are autoscaled; default True. See Axes.autoscale_view for more information """ pass plot.__doc__ = plot.__doc__ % artist.kwdocd Note there is a problem for Artist __init__ methods, eg Patch.__init__ which supports Patch kwargs, since the artist inspector cannot work until the class is fully defined and we can't modify the Patch.__init__.__doc__ docstring outside the class definition. I have made some manual hacks in this case which violates the "single entry point" requirement above; hopefully we'll find a more elegant solution before too long |
From: John H. <jdh...@ac...> - 2007-01-03 18:08:41
|
Hey Eric, I'm CC-ing the devel list because some of this has potentially far reaching consequences. >>>>> "Eric" == Eric Firing <ef...@ha...> writes: Eric> In connection with the colorbar sizing problem I have been Eric> thinking about adding a function list to axes, with the Eric> functions to be executed early in the draw() method, to Eric> handle this sort of thing. Using this mechanism to handle I think this is a very nice idea -- I saw a talk at pycon one year about the utility of adding hooks, eg before_somefunc_hook and after_somefunc_hook that are customizable *for every function in your API*. The questions are 1) what is the right data structure -- a single callable, a sequence, or a dictionary registry with connect/disconnect semantics (eg the backend event callback handler) 2) what is the signature (see below) 3) which artists should support it Most elegant, but most expensive, is something like a ordered dictionary which is supported for every artist. By renaming all the artist draw methods _draw, we can do this quite simply in backend_bases.Renderer with def draw(self, renderer): for func in self.before_draw_hook.ordered_values(): func(self, renderer) self._draw(renderer) for func in self.after_draw_hook.ordered_values(): func(self, renderer) I think this could be really useful and would help handle problems that crop up all the time -- how to handle physical layout problems where we need the renderer to get size information like you are experiencing with colorbar. This problem also crops up in a lot of text layout problems. Unfortunately, draw time layout creates other problems (sometimes users want this info at the API level), and order effects becomes very important and potentially complicated. But that said, given the current architecture, something like this would be a definite improvement. I'm inclined to use an ordered dictionary because one wants the connect/disconnect semantics that keys make easy, and because ordering matters. There is a python cookbook recipe for an ordered dictionary, and we could easily roll our own. Because the calls are potentially expensive, we might want an optimization like class MyOrderedDictionary: def __init__(blah): self.isempty = True so we can do def draw(renderer): if not self.before_draw_hook.isempty: for func in self.before_draw_hook.ordered_values(): func(self, renderer) self._draw(renderer) if not self.after_draw_hook.isempty: for func in self.after_draw_hook.ordered_values(): func(self, renderer) Since 99% of the time I guess these will be empty and then we are just adding a few attribute lookups and a boolean check for each draw. JDH |
From: Glen W. M. <gle...@sw...> - 2007-01-02 18:37:31
|
On Wed, Dec 27, 2006 at 12:58:24PM -0500, Robert Kern wrote: > Gennan Chen wrote: > > Hi! all, > > > > There are so many fft routines in Scipy/Numpy. Does anyone know > > which one should be used officially? > > For maximum portability and speed, use numpy.dual.fft() and its friends. That > will use the optimized functions in scipy.fftpack if it is available and > numpy.fft otherwise. This was seen on numpy-discussion. Is this the behavior implemented in matplotlib/numerix/fft/__init__.py ? Doesn't look like it to me ... Glen ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys - and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV _______________________________________________ Matplotlib-users mailing list Mat...@li... https://lists.sourceforge.net/lists/listinfo/matplotlib-users |