Re: [matplotlib-devel] Matplotlib-devel Digest, Vol 29, Issue 19
Hope nobody minds if I jump into this discussion: > Date: Mon, 20 Oct 2008 07:55:06 -0500 > From: "John Hunter" <[EMAIL PROTECTED]> > > [...] could you tell us why you prefer or require backend wx over wxagg? I tend to use matplotlib over an X connection, because the data I'm working with is on a Linux system whereas the machine I sit in front of is a Windows system. I therefore run python on the Linux machine, using my Windows machine just as an X server. I use the WX backend rather than WXAgg because WX is much more responsive for interactive use, e.g., zooming/panning. I'm willing to give up the much better-looking WXAgg output to gain responsiveness. For final output, I tend to save as EPS anyway. Don't know whether this is a widespread use case, but thought I'd mention it in case. [Apologies if this message doesn't get threaded properly; I'm replying to the digest.] - This SF.Net email is sponsored by the Moblin Your Move Developer's challenge Build the coolest Linux based applications with Moblin SDK & win great prizes Grand prize is a trip for two to an Open Source event anywhere in the world http://moblin-contest.org/redirect.php?banner_id=100&url=/ ___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
[matplotlib-devel] XAxis/YAxis set_ticks_position() behaviour
Hi, Firstly, excellent to see matplotlib reach its 1.0 release! I came across an inconsistency in the way XAxis and YAxis behave in the set_ticks_position() method. If you remove the X-axis ticks with my_axes.xaxis.set_ticks_position('none') it leaves the labels alone, whereas if you do the same on the Y-axis: my_axes.yaxis.set_ticks_position('none') it removes both sets of labels. The docstring for the X-axis method says "'none' and 'both' affect only the ticks, not the labels", and although the Y-axis docstring doesn't have this phrase, I guess it's probably intended that the labels are left alone there too. The patch below does this. Thanks, Ben. --- ORIG--axis.py 2010-07-15 10:37:08.68000 +0100 +++ axis.py 2010-07-15 10:43:14.000195000 +0100 @@ -1906,8 +1906,8 @@ self.set_tick_params(which='both', right=True, left=True) elif position == 'none': -self.set_tick_params(which='both', right=False, labelright=False, - left=False, labelleft=False) +self.set_tick_params(which='both', right=False, + left=False) elif position == 'default': self.set_tick_params(which='both', right=True, labelright=False, left=True, labelleft=True) -- This SF.net email is sponsored by Sprint What will you do first with EVO, the first 4G phone? Visit sprint.com/first -- http://p.sf.net/sfu/sprint-com-first ___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
[matplotlib-devel] Handle 'none' as color and edgecolor for bar()
Hi, Update to my recent email: perhaps it would make sense to handle the 'color' argument in the same way, allowing hollow bars. Combined patch below. Ben. --- ORIG-axes.py2010-07-06 15:43:35.0 +0100 +++ NEW-axes.py 2010-08-09 09:39:44.000256000 +0100 @@ -4575,15 +4575,17 @@ if len(linewidth) < nbars: linewidth *= nbars -if color is None: -color = [None] * nbars +if (color is None +or (is_string_like(color) and color.lower() == 'none')): +color = [color] * nbars else: color = list(mcolors.colorConverter.to_rgba_array(color)) if len(color) < nbars: color *= nbars -if edgecolor is None: -edgecolor = [None] * nbars +if (edgecolor is None +or (is_string_like(edgecolor) and edgecolor.lower() == 'none')): +edgecolor = [edgecolor] * nbars else: edgecolor = list(mcolors.colorConverter.to_rgba_array(edgecolor)) if len(edgecolor) < nbars: -- This SF.net email is sponsored by Make an app they can't live without Enter the BlackBerry Developer Challenge http://p.sf.net/sfu/RIM-dev2dev ___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
[matplotlib-devel] Fixing 'FIXME' in bar()
Hi, While looking at axes.py for the color/edgecolor patch just sent, I noticed the FIXME suggesting ValueError instead of assert. Is the below the kind of thing? Ben. --- ORIG-axes.py2010-07-06 15:43:35.0 +0100 +++ NEW-axes.py 2010-08-09 09:43:30.000257000 +0100 @@ -4589,15 +4589,12 @@ if len(edgecolor) < nbars: edgecolor *= nbars -# FIXME: convert the following to proper input validation -# raising ValueError; don't use assert for this. -assert len(left)==nbars, "incompatible sizes: argument 'left' must be length %d or scalar" % nbars -assert len(height)==nbars, ("incompatible sizes: argument 'height' must be length %d or scalar" % -nbars) -assert len(width)==nbars, ("incompatible sizes: argument 'width' must be length %d or scalar" % - nbars) -assert len(bottom)==nbars, ("incompatible sizes: argument 'bottom' must be length %d or scalar" % -nbars) +for argname in ['left', 'height', 'width', 'bottom']: +arg = locals()[argname] +if len(arg) != nbars: +raise ValueError("incompatible sizes:" + " argument '%s' must be length %d or scalar" + % (argname, nbars)) patches = [] -- This SF.net email is sponsored by Make an app they can't live without Enter the BlackBerry Developer Challenge http://p.sf.net/sfu/RIM-dev2dev ___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
[matplotlib-devel] Handle 'none' as edgecolor for bar()
Hi, I tried to use "edgecolor = 'none'" in a call to bar(), hoping to get no border to the bars, but instead got no bars at all. The patch below (against 1.0.0) seems to fix this; it adds a check for 'none' to the existing check for None as a special case of the edgecolor argument. Thanks, Ben. --- ORIG-axes.py2010-07-06 15:43:35.0 +0100 +++ NEW-axes.py 2010-08-09 09:16:51.04000 +0100 @@ -4582,8 +4582,9 @@ if len(color) < nbars: color *= nbars -if edgecolor is None: -edgecolor = [None] * nbars +if (edgecolor is None +or (is_string_like(edgecolor) and edgecolor.lower() == 'none')): +edgecolor = [edgecolor] * nbars else: edgecolor = list(mcolors.colorConverter.to_rgba_array(edgecolor)) if len(edgecolor) < nbars: -- This SF.net email is sponsored by Make an app they can't live without Enter the BlackBerry Developer Challenge http://p.sf.net/sfu/RIM-dev2dev ___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
Re: [matplotlib-devel] Handle 'none' as edgecolor for bar()
>> I tried to use "edgecolor = 'none'" in a call to bar(), hoping to get no >> border to the bars, but instead got no bars at all. > > Just to note, the documentation does specify a difference between None and > 'none'. None means to use the rcdefaults and 'none' means no color at all. > Is bar() just simply not properly handling the 'none' case? That's right, yes. Currently, bar() does not handle the string 'none' properly; it results in an empty graph. E.g.: bar([1, 2, 3], [12, 13, 14], edgecolor = None) behaves correctly, giving a bar chart with black-edged blue bars. bar([1, 2, 3], [12, 13, 14], edgecolor = 'none') gives no graph at all. After the patch, the second call gives the right result, a bar-chart with border-less blue bars. Same kind of thing with the kwarg 'color' instead of 'edgecolor', which is also fixed in my second recent email. Hope this clarifies things. Thanks, Ben. -- This SF.net email is sponsored by Make an app they can't live without Enter the BlackBerry Developer Challenge http://p.sf.net/sfu/RIM-dev2dev ___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
Re: [matplotlib-devel] Handle 'none' as edgecolor for bar()
Ben Root: >Ben North: >> Same kind of thing with >> the kwarg 'color' instead of 'edgecolor', which is also fixed in my >> second recent email. > > Looking through the code for bar(), I see the same thing occurs for the > 'color' keyword argument. So I guess we should fix that as well. Yes, the second of the emails I sent (pasted below) fixes the behaviour for 'edgecolor' and 'color'. Thanks for committing this. Ben. Date: 9 August 2010 09:42 Subject: Handle 'none' as color and edgecolor for bar() Hi, Update to my recent email: perhaps it would make sense to handle the 'color' argument in the same way, allowing hollow bars. Combined patch below. Ben. --- ORIG-axes.py2010-07-06 15:43:35.0 +0100 +++ NEW-axes.py 2010-08-09 09:39:44.000256000 +0100 @@ -4575,15 +4575,17 @@ if len(linewidth) < nbars: linewidth *= nbars -if color is None: -color = [None] * nbars +if (color is None +or (is_string_like(color) and color.lower() == 'none')): +color = [color] * nbars else: color = list(mcolors.colorConverter.to_rgba_array(color)) if len(color) < nbars: color *= nbars -if edgecolor is None: -edgecolor = [None] * nbars +if (edgecolor is None +or (is_string_like(edgecolor) and edgecolor.lower() == 'none')): +edgecolor = [edgecolor] * nbars else: edgecolor = list(mcolors.colorConverter.to_rgba_array(edgecolor)) if len(edgecolor) < nbars: -- This SF.net email is sponsored by Make an app they can't live without Enter the BlackBerry Developer Challenge http://p.sf.net/sfu/RIM-dev2dev ___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
[matplotlib-devel] Removal of code duplication in axes.py
Hi, I wrote (on -users, but have moved the discussion here to -devel): > > I was wondering, though, whether there'd be any support for some work > > which tidied up the near-duplicate code in axes.py. John Hunter replied: > Certainly, but probably not using meta-classes. > [...] > I'm disinclined to use python black magic -- I find it makes the code > harder to grok for the typical scientist, and these are our main > developers. Also, Darren Dale replied: > It's true. That bit of code looks like Perl to me. There's no need to be rude :-) The generalised docstrings are a bit ugly because they're unavoidably filled with phrases like "set the x-axis limits to go from xmin to xmax", which need to be changed to "set the y-axis limits to go from ymin to ymax" for the other function. The %(axis_letter)s stuff is quite verbose, unfortunately, but it's the same as in things like kwargs set the Text properties. Valid properties are %(Text)s This does make the docstring a bit harder to work with, but the alternative is to write it out twice, and then ensure the two near-copies are kept in sync as changes are made. Now of course this isn't impossible, but that kind of thing does add to the maintenance burden in my experience. Keeping the two copies of the code in sync requires effort, too, and it's easy to miss things; e.g., set_xlim() includes self._process_unit_info(xdata=(xmin, xmax)) but set_ylim() doesn't --- which is correct? panx() and zoomx() include xmin, xmax = self.viewLim.intervalx().get_bounds() but pany() and zoomy() have no analogous calls --- which is correct? The docstrings of set_xlabel() and set_ylabel() are formatted differently (obviously this is not a critical problem but still), and the examples in axhline() and axvline()'s docstrings are slightly different. There was the bug with hlines() and vlines() that lead to my query. I'm not trying to be annoying in pointing out these things, just saying that although there is a bit of a learning curve in the 'only write the function once' approach, I've found that it does save trouble in the long run. The metaclass itself is only really used to automate the process of creating the two specific functions from the one generic one. It could be left out, instead meaning that you'd write something like class Axes: [...] def set__AXISLETTER_scale(self, [...]): # [...] # do stuff # [...] set_xscale = make_specific_function(set__AXISLETTER_scale, X_TRAITS) set_yscale = make_specific_function(set__AXISLETTER_scale, Y_TRAITS) The make_specific_function() function is a little bit hairy and there might well be a better way to do it. My current implementation fiddles with the bytecode of the general function, and while I think it works correctly, this kind of malarkey can certainly lead to bugs which are very difficult to unravel if the "behind the scenes" stuff (i.e., make_specific_function() in this case) has problems. Without using something like make_specific_function(), you could do something more like John's suggestion: def set_xscale(self, value, basex = 10, subsx = None): """ [...] x docstring [...] """ self._set_scale(self.X_TRAITS, value, basex, subsx) def set_yscale(self, value, basey = 10, subsy = None): """ [...] y docstring [...] """ self._set_scale(self.Y_TRAITS, value, basey, subsy) def _set_scale(self, traits, value, base, subs): assert(value.lower() in ('log', 'linear', )) if value == 'log': traits.axis.set_major_locator(mticker.LogLocator(base)) traits.axis.set_major_formatter(mticker.LogFormatterMathtext(base)) traits.axis.set_minor_locator(mticker.LogLocator(base, subs)) traits.transfunc.set_type(mtrans.LOG10) min_val, max_val = traits.limfunc() if min(min_val, max_val) <= 0: self.autoscale_view() elif value == 'linear': traits.axis.set_major_locator(mticker.AutoLocator()) traits.axis.set_major_formatter(mticker.ScalarFormatter()) traits.axis.set_minor_locator(mticker.NullLocator()) traits.axis.set_minor_formatter(mticker.NullFormatter()) traits.transfunc.set_type(mtrans.IDENTITY) where the 'traits' stuff allows you to pass around the 'limfunc = self.get_xlim' etc. all in one go. 'X_TRAITS' and 'Y_TRAITS' would be set up in __init__(). Maybe 'X_METHODS' and 'Y_METHODS' would be better names. With the above approach, you do still end up with two near-copies of the docstring but at least the actual code is all in one place. Anyway. Just thought I'd make the suggestion. If there's interest I can tidy up what I've got and post it. Or a patch which takes the last-mentioned approach above. Ben. - This SF.net email is sponsored by DB2 Express Download DB2 Express C - the FREE version of DB2 express and take control
[matplotlib-devel] Patch for PostScript backend
Hi, I think there is a bug in the PostScript backend, when trying to draw a polygon with zero linewidth. If you have a zero linewidth, the generated PostScript is along the lines of 173.31 49.274 m 305.066 57.999 l 173.533 46.684 l closepath gsave fill grestore whereas if there is a non-zero linewidth, you get 173.31 49.274 m 305.066 57.999 l 173.533 46.684 l closepath gsave fill grestore stroke The problem is that in the zero-linewidth case, the path is not cleared. Therefore, next time there is a 'stroke', that part of the path is stroked. In theory, this doesn't matter because its linewidth is zero, but the PostScript docs say not completely unambiguously that a zero-width line is as thin as the device allows. Ghostview, for instance, makes this noticeably non-zero-width and the result looks wrong. Besides, it seems cleaner to leave the current path in the same state (i.e., empty) in both cases. The below patch, against SVN head, seems to fix this. Ben. - - - - 8< - - - - --- SVN--backend_ps.py 2007-11-20 12:08:51.036996600 + +++ backend_ps.py 2007-11-20 12:09:00.100300100 + @@ -947,6 +947,9 @@ if self.linewidth > 0: write("stroke\n") +else: +write("newpath\n") + if cliprect: write("grestore\n") - This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse012070mrt/direct/01/ ___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel