Re: [matplotlib-devel] Apparent bug with EPS files using Liberation fonts

2010-09-02 Thread Benjamin Root
On Wed, Sep 1, 2010 at 11:29 AM, Stan West  wrote:

>  *From:* ben.v.r...@gmail.com [mailto:ben.v.r...@gmail.com] *On Behalf Of
> *Benjamin Root
> *Sent:* Tuesday, August 31, 2010 23:20
>
> I can confirm that evince also has a problem with the second image, but not
> the first or the third images.  This is using the latest matplotlib from
> svn.
>
> Thank you for the confirmation, Ben.
>
> Here's what I've found so far. I examined the Liberation sources (the SFD
> files) in FontForge and as text, and I gather that some of them use a
> non-standard encoding. Liberation Sans, for example, does not define a space
> glyph with the name "space"; instead it defines a glyph for the non-breaking
> space at code point U+00A0 with the name "uni00A0" and gives U+0020 (the
> plain space) as an alternate encoding. (In the file
> LiberationSans-Regular.sfd, these definitions start at line 2929.) However,
> matplotlib assumes that the font uses Postscript's StandardEncoding. I
> suppose that when Postscript processes "(some text) show", it looks for the
> space glyph under the standard name "space" but finds nothing. Here is an
> excerpt of matplotlib/ttconv/pprdrv_tt.cpp from SVN starting at line 415:
>
> /*-
> ** Define the encoding array for this font.
> ** Since we don't really want to deal with converting all of
>
> ** the possible font encodings in the wild to a standard PS
> ** one, we just explicitly create one for each font.
> -*/
> void ttfont_encoding(TTStreamWriter& stream, struct TTFONT *font, 
> std::vector& glyph_ids, font_type_enum target_type)
>
> {
> stream.putline("/Encoding StandardEncoding def");
>
> // if (target_type == PS_TYPE_3) {
> // stream.printf("/Encoding [ ");
>
> // for (std::vector::const_iterator i = glyph_ids.begin();
> //  i != glyph_ids.end(); ++i) {
> // const char* name = ttfont_CharStrings_getname(font, *i);
>
> // stream.printf("/%s ", name);
> // }
>
> // stream.printf("] def\n");
> // } else {
> // stream.putline("/Encoding StandardEncoding def");
>
> // }
> } /* end of ttfont_encoding() */
>
> I saw in the SVN logs that the commented code for non-standard encodings
> had a brief life of about a month earlier this year before being declared
> more trouble than it was worth.
>
> Getting back to the fonts, I found that not all of the Liberation fonts use
> this non-standard encoding. The Liberation Sans Narrow fonts in the current
> release define "space" at U+0020 with U+00A0 as an alternate encoding, and
> they work fine in matplotlib EPS files. I also checked a few of the fonts in
> one older release, 
> 1.0,
> and they also work correctly.
>
> One work-around I found is to use Unicode strings for text containing
> spaces, which in the EPS file causes spaces to be looked up under the glyph
> name "uni00A0". If embedding Type 3 fonts, another work-around (which I
> only spot-checked) is to effectively standardize the encoding by editing the
> EPS file, changing "/uni00A0" to "/space" in the font definition and in
> glyphshow operations that call for "/uni00A0".
>
>
Stan,

Thanks for the insightful analysis.  Could you file a bug report with some
of this information (at the very least, reference your message on the
mailing list)?

Ben Root
--
This SF.net Dev2Dev email is sponsored by:

Show off your parallel programming skills.
Enter the Intel(R) Threading Challenge 2010.
http://p.sf.net/sfu/intel-thread-sfd___
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel


[matplotlib-devel] clf(), Axes3D and add_subplot

2010-09-02 Thread Benjamin Root
There was a bug report recently (not to the mailing list) where the reporter
noted that if an Axes3D was created using the fig.add_subplot(111,
projection='3d') or fig.gca(projection='3d'), then you can not clear the
figure using fig.clf().  Doing so causes an exception to be thrown.

Tracing down the problem revealed that the Axes3D object was added twice to
the figure's self.axes, but exists only once in self._axstack.  So, when
looping through self.axes, a delete is attempted on an axes that no longer
exists in the stack.

I traced down the cause for why the axes is added twice.  Because of how
Axes3D used to be attached to a figure (and is still valid), the __init__()
function for Axes3D calls figure.add_axes(self) on its own.  This
initialization is done after the check in add_subplot to see if the axes
exists already in the figure.  So, add_subplot then adds the axes without
knowing that it already happened.

I think there are multiple issues here.  Primarially, there is the issue
that Axes3D is attaching itself to a figure.  However, in the interest of
backwards-compatibility, we can't just fix this outright.  There is also the
issue that there are multiple places in the Figure class that are adding
axes to the figure object.  Ideally, shouldn't we have a single function
that performs proper checks and adds an axes?  Then that function should be
used in the other class functions to perform this action.  In my opinion,
there is too much duplicated code here.

Thoughts, concerns, ideas?
Ben Root
--
This SF.net Dev2Dev email is sponsored by:

Show off your parallel programming skills.
Enter the Intel(R) Threading Challenge 2010.
http://p.sf.net/sfu/intel-thread-sfd___
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel


Re: [matplotlib-devel] clf(), Axes3D and add_subplot

2010-09-02 Thread Ryan May
On Sep 2, 2010, at 14:14, Benjamin Root  wrote:

> There was a bug report recently (not to the mailing list) where the reporter 
> noted that if an Axes3D was created using the fig.add_subplot(111, 
> projection='3d') or fig.gca(projection='3d'), then you can not clear the 
> figure using fig.clf().  Doing so causes an exception to be thrown.
> 
> Tracing down the problem revealed that the Axes3D object was added twice to 
> the figure's self.axes, but exists only once in self._axstack.  So, when 
> looping through self.axes, a delete is attempted on an axes that no longer 
> exists in the stack.
> 
> I traced down the cause for why the axes is added twice.  Because of how 
> Axes3D used to be attached to a figure (and is still valid), the __init__() 
> function for Axes3D calls figure.add_axes(self) on its own.  This 
> initialization is done after the check in add_subplot to see if the axes 
> exists already in the figure.  So, add_subplot then adds the axes without 
> knowing that it already happened.
> 
> I think there are multiple issues here.  Primarially, there is the issue that 
> Axes3D is attaching itself to a figure.  However, in the interest of 
> backwards-compatibility, we can't just fix this outright.  There is also the 
> issue that there are multiple places in the Figure class that are adding axes 
> to the figure object.  Ideally, shouldn't we have a single function that 
> performs proper checks and adds an axes?  Then that function should be used 
> in the other class functions to perform this action.  In my opinion, there is 
> too much duplicated code here.

I agree the duplicated code should be eliminated. Depending on how complex it 
would be to clean that up and not break existing code, could we in the short 
term make use of sets to eliminate duplicates?

Ryan
--
This SF.net Dev2Dev email is sponsored by:

Show off your parallel programming skills.
Enter the Intel(R) Threading Challenge 2010.
http://p.sf.net/sfu/intel-thread-sfd
___
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel


Re: [matplotlib-devel] clf(), Axes3D and add_subplot

2010-09-02 Thread Benjamin Root
On Thu, Sep 2, 2010 at 3:51 PM, Ryan May  wrote:

> On Sep 2, 2010, at 14:14, Benjamin Root  wrote:
>
> > There was a bug report recently (not to the mailing list) where the
> reporter noted that if an Axes3D was created using the fig.add_subplot(111,
> projection='3d') or fig.gca(projection='3d'), then you can not clear the
> figure using fig.clf().  Doing so causes an exception to be thrown.
> >
> > Tracing down the problem revealed that the Axes3D object was added twice
> to the figure's self.axes, but exists only once in self._axstack.  So, when
> looping through self.axes, a delete is attempted on an axes that no longer
> exists in the stack.
> >
> > I traced down the cause for why the axes is added twice.  Because of how
> Axes3D used to be attached to a figure (and is still valid), the __init__()
> function for Axes3D calls figure.add_axes(self) on its own.  This
> initialization is done after the check in add_subplot to see if the axes
> exists already in the figure.  So, add_subplot then adds the axes without
> knowing that it already happened.
> >
> > I think there are multiple issues here.  Primarially, there is the issue
> that Axes3D is attaching itself to a figure.  However, in the interest of
> backwards-compatibility, we can't just fix this outright.  There is also the
> issue that there are multiple places in the Figure class that are adding
> axes to the figure object.  Ideally, shouldn't we have a single function
> that performs proper checks and adds an axes?  Then that function should be
> used in the other class functions to perform this action.  In my opinion,
> there is too much duplicated code here.
>
> I agree the duplicated code should be eliminated. Depending on how complex
> it would be to clean that up and not break existing code, could we in the
> short term make use of sets to eliminate duplicates?
>
> Ryan


I am not exactly sure how possible that would be.  I am not exactly sure I
understand the rationale behind the current implementation.  There is a
dictionary self._seen that stores key/axes pairs, a self.axes list storing
the axes, and a self._axstack Stack (from cbook, I believe) that also
contains the axes.

I think I understand the purpose for each container by itself, but not for
having all three together at the same time.  At the very least, maybe we can
eliminate the list container?  I think the difficulty there would be with
clearing the stack properly.

Ben Root
--
This SF.net Dev2Dev email is sponsored by:

Show off your parallel programming skills.
Enter the Intel(R) Threading Challenge 2010.
http://p.sf.net/sfu/intel-thread-sfd___
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel


Re: [matplotlib-devel] clf(), Axes3D and add_subplot

2010-09-02 Thread Eric Firing
On 09/02/2010 01:21 PM, Benjamin Root wrote:
> On Thu, Sep 2, 2010 at 3:51 PM, Ryan May  > wrote:
>
> On Sep 2, 2010, at 14:14, Benjamin Root  > wrote:
>
>  > There was a bug report recently (not to the mailing list) where
> the reporter noted that if an Axes3D was created using the
> fig.add_subplot(111, projection='3d') or fig.gca(projection='3d'),
> then you can not clear the figure using fig.clf().  Doing so causes
> an exception to be thrown.
>  >
>  > Tracing down the problem revealed that the Axes3D object was
> added twice to the figure's self.axes, but exists only once in
> self._axstack.  So, when looping through self.axes, a delete is
> attempted on an axes that no longer exists in the stack.
>  >
>  > I traced down the cause for why the axes is added twice.  Because
> of how Axes3D used to be attached to a figure (and is still valid),
> the __init__() function for Axes3D calls figure.add_axes(self) on
> its own.  This initialization is done after the check in add_subplot
> to see if the axes exists already in the figure.  So, add_subplot
> then adds the axes without knowing that it already happened.
>  >
>  > I think there are multiple issues here.  Primarially, there is
> the issue that Axes3D is attaching itself to a figure.  However, in
> the interest of backwards-compatibility, we can't just fix this
> outright.  There is also the issue that there are multiple places in
> the Figure class that are adding axes to the figure object.
>   Ideally, shouldn't we have a single function that performs proper
> checks and adds an axes?  Then that function should be used in the
> other class functions to perform this action.  In my opinion, there
> is too much duplicated code here.
>
> I agree the duplicated code should be eliminated. Depending on how
> complex it would be to clean that up and not break existing code,
> could we in the short term make use of sets to eliminate duplicates?
>
> Ryan
>
>
> I am not exactly sure how possible that would be.  I am not exactly sure
> I understand the rationale behind the current implementation.  There is
> a dictionary self._seen that stores key/axes pairs, a self.axes list
> storing the axes, and a self._axstack Stack (from cbook, I believe) that
> also contains the axes.
>
> I think I understand the purpose for each container by itself, but not
> for having all three together at the same time.  At the very least,
> maybe we can eliminate the list container?  I think the difficulty there
> would be with clearing the stack properly.

You can't just blow away self.axes, because that is a public interface, 
and a convenient one.  Maybe self.axes needs to be an object that can 
behave like a list, to preserve the public interface, but that 
underneath has the mechanisms required for the functionality now 
provided by self._seen and self._axstack, so that they can be eliminated.

Eric


>
> Ben Root
>

--
This SF.net Dev2Dev email is sponsored by:

Show off your parallel programming skills.
Enter the Intel(R) Threading Challenge 2010.
http://p.sf.net/sfu/intel-thread-sfd
___
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel


Re: [matplotlib-devel] clf(), Axes3D and add_subplot

2010-09-02 Thread Benjamin Root
On Thu, Sep 2, 2010 at 7:57 PM, Eric Firing  wrote:

> On 09/02/2010 01:21 PM, Benjamin Root wrote:
> > On Thu, Sep 2, 2010 at 3:51 PM, Ryan May  > > wrote:
> >
> > On Sep 2, 2010, at 14:14, Benjamin Root  > > wrote:
> >
> >  > There was a bug report recently (not to the mailing list) where
> > the reporter noted that if an Axes3D was created using the
> > fig.add_subplot(111, projection='3d') or fig.gca(projection='3d'),
> > then you can not clear the figure using fig.clf().  Doing so causes
> > an exception to be thrown.
> >  >
> >  > Tracing down the problem revealed that the Axes3D object was
> > added twice to the figure's self.axes, but exists only once in
> > self._axstack.  So, when looping through self.axes, a delete is
> > attempted on an axes that no longer exists in the stack.
> >  >
> >  > I traced down the cause for why the axes is added twice.  Because
> > of how Axes3D used to be attached to a figure (and is still valid),
> > the __init__() function for Axes3D calls figure.add_axes(self) on
> > its own.  This initialization is done after the check in add_subplot
> > to see if the axes exists already in the figure.  So, add_subplot
> > then adds the axes without knowing that it already happened.
> >  >
> >  > I think there are multiple issues here.  Primarially, there is
> > the issue that Axes3D is attaching itself to a figure.  However, in
> > the interest of backwards-compatibility, we can't just fix this
> > outright.  There is also the issue that there are multiple places in
> > the Figure class that are adding axes to the figure object.
> >   Ideally, shouldn't we have a single function that performs proper
> > checks and adds an axes?  Then that function should be used in the
> > other class functions to perform this action.  In my opinion, there
> > is too much duplicated code here.
> >
> > I agree the duplicated code should be eliminated. Depending on how
> > complex it would be to clean that up and not break existing code,
> > could we in the short term make use of sets to eliminate duplicates?
> >
> > Ryan
> >
> >
> > I am not exactly sure how possible that would be.  I am not exactly sure
> > I understand the rationale behind the current implementation.  There is
> > a dictionary self._seen that stores key/axes pairs, a self.axes list
> > storing the axes, and a self._axstack Stack (from cbook, I believe) that
> > also contains the axes.
> >
> > I think I understand the purpose for each container by itself, but not
> > for having all three together at the same time.  At the very least,
> > maybe we can eliminate the list container?  I think the difficulty there
> > would be with clearing the stack properly.
>
> You can't just blow away self.axes, because that is a public interface,
> and a convenient one.  Maybe self.axes needs to be an object that can
> behave like a list, to preserve the public interface, but that
> underneath has the mechanisms required for the functionality now
> provided by self._seen and self._axstack, so that they can be eliminated.
>
> Eric
>
>
>
Right, of course... must have had a brain-fart moment.

Creating another list-like object would probably be an ideal way to tuck
away self._seen and self._axstack.  Especially given the public nature of
self.axes, we could never really be sure that self._axstack and self._seen
had all the axes listed in self.axes. I am gonna have to look through the
code and see what needs to be implemented.

Does Python 2.4 support subclassing things like list?

Ben Root
--
This SF.net Dev2Dev email is sponsored by:

Show off your parallel programming skills.
Enter the Intel(R) Threading Challenge 2010.
http://p.sf.net/sfu/intel-thread-sfd___
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel


Re: [matplotlib-devel] clf(), Axes3D and add_subplot

2010-09-02 Thread Ryan May
On Thu, Sep 2, 2010 at 8:33 PM, Benjamin Root  wrote:
> On Thu, Sep 2, 2010 at 7:57 PM, Eric Firing  wrote:
>> On 09/02/2010 01:21 PM, Benjamin Root wrote:
>> > I think I understand the purpose for each container by itself, but not
>> > for having all three together at the same time.  At the very least,
>> > maybe we can eliminate the list container?  I think the difficulty there
>> > would be with clearing the stack properly.
>>
>> You can't just blow away self.axes, because that is a public interface,
>> and a convenient one.  Maybe self.axes needs to be an object that can
>> behave like a list, to preserve the public interface, but that
>> underneath has the mechanisms required for the functionality now
>> provided by self._seen and self._axstack, so that they can be eliminated.
>
> Right, of course... must have had a brain-fart moment.
>
> Creating another list-like object would probably be an ideal way to tuck
> away self._seen and self._axstack.  Especially given the public nature of
> self.axes, we could never really be sure that self._axstack and self._seen
> had all the axes listed in self.axes. I am gonna have to look through the
> code and see what needs to be implemented.
>
> Does Python 2.4 support subclassing things like list?

Probably. But why not take advantage of properties as they were meant
to be? You can make self.axes a property that generates the list
from the self._axstack/self._seen only when accessed. We'd need to see
if self.axes is used in any performance sensitive areas, but this
seems like a *textbook* example of why properties are awesome.

Is there any instance where adding to self.axes is a public API?
Because given self._axstack/self._seen, it would seem that appending
to this list would not by itself work.

I'm willing to cook up the patch tomorrow if no one beats me to it.

Ryan

-- 
Ryan May
Graduate Research Assistant
School of Meteorology
University of Oklahoma

--
This SF.net Dev2Dev email is sponsored by:

Show off your parallel programming skills.
Enter the Intel(R) Threading Challenge 2010.
http://p.sf.net/sfu/intel-thread-sfd
___
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel


Re: [matplotlib-devel] clf(), Axes3D and add_subplot

2010-09-02 Thread Eric Firing
On 09/02/2010 04:12 PM, Ryan May wrote:
> On Thu, Sep 2, 2010 at 8:33 PM, Benjamin Root  wrote:
>> On Thu, Sep 2, 2010 at 7:57 PM, Eric Firing  wrote:
>>> On 09/02/2010 01:21 PM, Benjamin Root wrote:
 I think I understand the purpose for each container by itself, but not
 for having all three together at the same time.  At the very least,
 maybe we can eliminate the list container?  I think the difficulty there
 would be with clearing the stack properly.
>>>
>>> You can't just blow away self.axes, because that is a public interface,
>>> and a convenient one.  Maybe self.axes needs to be an object that can
>>> behave like a list, to preserve the public interface, but that
>>> underneath has the mechanisms required for the functionality now
>>> provided by self._seen and self._axstack, so that they can be eliminated.
>>
>> Right, of course... must have had a brain-fart moment.
>>
>> Creating another list-like object would probably be an ideal way to tuck
>> away self._seen and self._axstack.  Especially given the public nature of
>> self.axes, we could never really be sure that self._axstack and self._seen
>> had all the axes listed in self.axes. I am gonna have to look through the
>> code and see what needs to be implemented.
>>
>> Does Python 2.4 support subclassing things like list?

Yes: http://docs.python.org/release/2.4.4/lib/module-UserList.html

But I agree that turning Figure.axes into a property with the getter 
generating a list probably will do the trick.  Maybe you can use 
_ax_stack._elements? It looks like that may completely parallel the 
present Figure.axes.  Stack, or a subclass or derivative, could store 
(ax, key) tuples instead of just the ax list. Then the equivalent of 
_seen could be generated on the fly as needed.  (This is very fast.) 
This would completely eliminate the redundant storage of Axes references 
in Figure, and simplify some Figure methods.

Eric

>
> Probably. But why not take advantage of properties as they were meant
> to be? You can make self.axes a property that generates the list
> from the self._axstack/self._seen only when accessed. We'd need to see
> if self.axes is used in any performance sensitive areas, but this
> seems like a *textbook* example of why properties are awesome.
>
> Is there any instance where adding to self.axes is a public API?
> Because given self._axstack/self._seen, it would seem that appending
> to this list would not by itself work.
>
> I'm willing to cook up the patch tomorrow if no one beats me to it.
>
> Ryan
>


--
This SF.net Dev2Dev email is sponsored by:

Show off your parallel programming skills.
Enter the Intel(R) Threading Challenge 2010.
http://p.sf.net/sfu/intel-thread-sfd
___
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel