Re: [matplotlib-devel] Matplotlib-devel Digest, Vol 29, Issue 19

2008-10-20 Thread Ben North
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

2010-07-15 Thread Ben North
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()

2010-08-09 Thread Ben North
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()

2010-08-09 Thread Ben North
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()

2010-08-09 Thread Ben North
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()

2010-08-09 Thread Ben North
>> 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()

2010-08-12 Thread Ben North
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

2007-07-18 Thread Ben North
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

2007-11-20 Thread Ben North
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