cycling mechanism

Hello all,

So, I am getting to the point where I need to implement a color cycling mechanism throughout pyplot. So, before I get too deep in implementing it, I have some thoughts that I need feedback on.

  1. Not all plotting functions use color cycling right now. Currently, only plot() and any function that calls plot in its process (such as errorbar()). Glaring omissions are bar() and scatter(), and pie() could also benefit from having a uniform cycling mechanism. So, the issue going forward is, do we want to enable common cycling for all the pyplot/axes plotting functions which would require updating the test images and break backwards compatibility (in a sense), or do we want to have a per-function default rcparams that would contain one-element cycles that would effectively maintain current drawing results?

  2. I also have the need to implement line-style cycling for b&w publications. Of course if I implement that, then why not hatch-cycling? marker-cycling? I have seen use-cases for all of these, and I am considering how to have a generalized framework for this. So my question is, what attributes would we like to see cycle-able? Here is a short list and some usecases I have come up with. Please extend this with ideas of your own.

color - plot(), errorbar(), scatter(), bar(), hist(), pie(), stem()
linestyle - plot(), errorbar(), stem()
hatch - bar(), hist(), pie()
marker - plot(), errorbar(), scatter(), stem()

linewidth? facecolor/edgecolor? joinstyle?

  1. rcparam names. I was thinking about how to name these cycles in the matplotlibrc file. Possibly:

cycle.colors
cycle.linestyles
cycle.hatches
cycle.markers

And these would represent the global default, meanwhile, function-specific cycles could be given by:

cycle.colors.pie
cycle.colors.bar
cycle.linestyles.plot
cycle.linestyles.errorbar

I was thinking that in code, one would access the full name attribute for the function, and I would extend the get function to intelligently fall back to the global default if the full-name attribute is not specified. However, would there be confusion in a situation such as a person who wanted to use barh() but only had specified cycle.colors.bar?

  1. Ultimately, my goal is to be able to create some typical profiles that have useful cycle specs, and possibly make some available as convenience functions, such as a b&w mode. Such a mode would set the default colormap to a grayscale-friendly colorscale, and use line style, hatch and marker cycles instead of a full color cycle.

Thoughts? Comments?

Cheers!
Ben Root

None other than my eternal gratitude if you do this: it's one of the
few things (perhaps the only one) I still miss from the old gnuplot,
which made it trivial to switch from color to b/w mode and it would
produce sensible output immediately in either mode.

Cheers,

f

···

On Wed, Jan 4, 2012 at 6:52 PM, Benjamin Root <ben.root@...1304...> wrote:

Thoughts? Comments?

My first thought is that maybe we need an object to collect and abstract all of these style attributes, and then cycle through a sequence of those. In the future we could move the matplotlib API to use such an object instead of the billion parameters that are individually passed now.

Just 0.02 to distract me from the dissertation.

Ryan

···

On Jan 4, 2012, at 20:52, Benjamin Root <ben.root@...1304...> wrote:

Hello all,

So, I am getting to the point where I need to implement a color cycling mechanism throughout pyplot. So, before I get too deep in implementing it, I have some thoughts that I need feedback on.

1) Not all plotting functions use color cycling right now. Currently, only plot() and any function that calls plot in its process (such as errorbar()). Glaring omissions are bar() and scatter(), and pie() could also benefit from having a uniform cycling mechanism. So, the issue going forward is, do we want to enable common cycling for all the pyplot/axes plotting functions which would require updating the test images and break backwards compatibility (in a sense), or do we want to have a per-function default rcparams that would contain one-element cycles that would effectively maintain current drawing results?

2) I also have the need to implement line-style cycling for b&w publications. Of course if I implement that, then why not hatch-cycling? marker-cycling? I have seen use-cases for all of these, and I am considering how to have a generalized framework for this. So my question is, what attributes would we like to see cycle-able? Here is a short list and some usecases I have come up with. Please extend this with ideas of your own.

color - plot(), errorbar(), scatter(), bar(), hist(), pie(), stem()
linestyle - plot(), errorbar(), stem()
hatch - bar(), hist(), pie()
marker - plot(), errorbar(), scatter(), stem()

linewidth? facecolor/edgecolor? joinstyle?

3) rcparam names. I was thinking about how to name these cycles in the matplotlibrc file. Possibly:

cycle.colors
cycle.linestyles
cycle.hatches
cycle.markers

And these would represent the global default, meanwhile, function-specific cycles could be given by:

cycle.colors.pie
cycle.colors.bar
cycle.linestyles.plot
cycle.linestyles.errorbar

I was thinking that in code, one would access the full name attribute for the function, and I would extend the __get__ function to intelligently fall back to the global default if the full-name attribute is not specified. However, would there be confusion in a situation such as a person who wanted to use barh() but only had specified cycle.colors.bar?

4) Ultimately, my goal is to be able to create some typical profiles that have useful cycle specs, and possibly make some available as convenience functions, such as a b&w mode. Such a mode would set the default colormap to a grayscale-friendly colorscale, and use line style, hatch and marker cycles instead of a full color cycle.

Thoughts? Comments?

Hello all,

So, I am getting to the point where I need to implement a color cycling mechanism throughout pyplot. So, before I get too deep in implementing it, I have some thoughts that I need feedback on.

  1. Not all plotting functions use color cycling right now. Currently, only plot() and any function that calls plot in its process (such as errorbar()). Glaring omissions are bar() and scatter(), and pie() could also benefit from having a uniform cycling mechanism. So, the issue going forward is, do we want to enable common cycling for all the pyplot/axes plotting functions which would require updating the test images and break backwards compatibility (in a sense), or do we want to have a per-function default rcparams that would contain one-element cycles that would effectively maintain current drawing results?
  1. I also have the need to implement line-style cycling for b&w publications. Of course if I implement that, then why not hatch-cycling? marker-cycling? I have seen use-cases for all of these, and I am considering how to have a generalized framework for this. So my question is, what attributes would we like to see cycle-able? Here is a short list and some usecases I have come up with. Please extend this with ideas of your own.

color - plot(), errorbar(), scatter(), bar(), hist(), pie(), stem()

linestyle - plot(), errorbar(), stem()

hatch - bar(), hist(), pie()

marker - plot(), errorbar(), scatter(), stem()

linewidth? facecolor/edgecolor? joinstyle?

  1. rcparam names. I was thinking about how to name these cycles in the matplotlibrc file. Possibly:

cycle.colors

cycle.linestyles

cycle.hatches

cycle.markers

And these would represent the global default, meanwhile, function-specific cycles could be given by:

cycle.colors.pie

cycle.colors.bar

cycle.linestyles.plot

cycle.linestyles.errorbar

I was thinking that in code, one would access the full name attribute for the function, and I would extend the get function to intelligently fall back to the global default if the full-name attribute is not specified. However, would there be confusion in a situation such as a person who wanted to use barh() but only had specified cycle.colors.bar?

  1. Ultimately, my goal is to be able to create some typical profiles that have useful cycle specs, and possibly make some available as convenience functions, such as a b&w mode. Such a mode would set the default colormap to a grayscale-friendly colorscale, and use line style, hatch and marker cycles instead of a full color cycle.

Thoughts? Comments?

My first thought is that maybe we need an object to collect and abstract all of these style attributes, and then cycle through a sequence of those. In the future we could move the matplotlib API to use such an object instead of the billion parameters that are individually passed now.

+10000

Just 0.02 to distract me from the dissertation.

Oh yeah… I got one of those to complete as well…

Ben Root

···

On Wed, Jan 4, 2012 at 9:33 PM, Ryan May <rmay31@…287…> wrote:

On Jan 4, 2012, at 20:52, Benjamin Root <ben.root@…1304…> wrote:

Ryan

2) I also have the need to implement line-style cycling for b&w
publications.

What about also grey level cycling for b&w? Sometimes for b&w it looks
better to use different gray levels rather than different
line-styles. See this for an example:

http://media.aau.dk/null_space_pursuits/2011/06/recovery-of-compressively-sensed-sparse-signals-in-noise-pt-2.html

Alejandro.

The cycles can be specified either in code and/or in matplotlibrc as a list of colors. We can certainly make sure that tuples of rgb values would be valid. The point of this project is to get the plotting functions to universally use cycles that can be specified by the user. Profiles can be created for different styles and combinations of effects.

Ben Root

···

On Wed, Jan 4, 2012 at 9:53 PM, Alejandro Weinstein <alejandro.weinstein@…287…> wrote:

  1. I also have the need to implement line-style cycling for b&w

publications.

What about also grey level cycling for b&w? Sometimes for b&w it looks

better to use different gray levels rather than different

line-styles. See this for an example:

http://media.aau.dk/null_space_pursuits/2011/06/recovery-of-compressively-sensed-sparse-signals-in-noise-pt-2.html

Alejandro.

This is great! Absolutely a much-needed and much-requested feature.

I wonder, however, about the need for function-specific color

cycles. Is there a use case there? I’d be just as happy with a
single global color cycle that all functions would use.

I also like the suggestion of a "style" class that would store a

bunch of drawing attributes on a single object.

From that, a feature that might be nice would be the ability to pass

“style=‘last’” (or something) to a plotting function and have it use
the last style in the cycle again. This would allow one to draw
(for example) a line and a bar plot that are related in the same
color, and then draw another line and bar pair in a different color.
But that’s icing on top of the more important features you’ve
already proposed.

Mike
···

http://p.sf.net/sfu/Citrix-VDIinaboxMatplotlib-users@lists.sourceforge.nethttps://lists.sourceforge.net/lists/listinfo/matplotlib-users

This is great! Absolutely a much-needed and much-requested feature.

I wonder, however, about the need for function-specific color

cycles. Is there a use case there? I’d be just as happy with a
single global color cycle that all functions would use.

There are two reasons I see for this. First, maintaining current behavior. For example, pyplot currently uses the same color regardless of the number of times a user calls scatter. That might be a feature for some, or at least, it would be undesired to change that for existing code. I don’t know how strong this argument is, but I did not want to unilaterally make this change.

Second, and possibly more strongly is the following two use-cases:

for y1, y2 in zip(linedata, bardata) :
plt.plot(x, y1)
plt.bar(x, y2)

and

for y in linedata :
plt.plot(x, y)

for y in bardata :
plt.bar(x, y)

I would assume that in these cases, the user would expect that the line plot using y1 would have the same color as the bars using y2. Also, that the two figures would be identical. Implementation-wise, if there is a single color cycle object for these functions to draw from, then this can not be guaranteed without internally creating a per-function color-cycle objects. Once you are at that point, then it is only a short jump to just allowing users to specify per-function color-cycles anyway.

I also like the suggestion of a "style" class that would store a

bunch of drawing attributes on a single object.

At the very least, it would help in compartmentallizing all the possible drawing attributes that are common across all artists. Currently, I am envisioning using a defaultdict object (which was introduced in python 2.5) or subclassing from it. This might help in keeping compatibility with existing code. Subclassing would allow for modifying get and set to treat some elements like ‘c’ and ‘color’, ‘lw’ and ‘linewidth’ and so on as the same.

From that, a feature that might be nice would be the ability to pass

“style=‘last’” (or something) to a plotting function and have it use
the last style in the cycle again. This would allow one to draw
(for example) a line and a bar plot that are related in the same
color, and then draw another line and bar pair in a different color.
But that’s icing on top of the more important features you’ve
already proposed.

Hmmm, this could possibly be a solution to avoid the problem I mention above. So, in the pyplot state-machine, there would not only be the cycle objects, but also a current style state that would not trigger a next() call on the cycles if the plotting function states that it wants the current style. Interesting…

Ben Root

···

On Thu, Jan 5, 2012 at 6:45 AM, Michael Droettboom <mdroe@…878…86…> wrote:

Grrrr, in defaultdict(), the default_factory is called without arguments, so a factory can’t be made to produce a default value for a given key, unless I resort to more hackary…

Ben Root

···

On Thu, Jan 5, 2012 at 10:40 AM, Benjamin Root <ben.root@…1304…> wrote:

At the very least, it would help in compartmentallizing all the possible drawing attributes that are common across all artists. Currently, I am envisioning using a defaultdict object (which was introduced in python 2.5) or subclassing from it. This might help in keeping compatibility with existing code. Subclassing would allow for modifying get and set to treat some elements like ‘c’ and ‘color’, ‘lw’ and ‘linewidth’ and so on as the same.

Might be better to explicitly use properties for this rather than
overriding dict:

class Style(object):
    __slots__ = ('_lw')

    def __init__(self, lw=None):
        self.lw = lw

    def _set_linewidth(self, lw):
        self._lw = lw

    def _get_linewidth(self):
        return self._lw

    lw = property(_get_linewidth, _set_linewidth)
    linewidth = property(_get_linewidth, _set_linewidth)

Declaring slots allows you to keep the available attributes to those
explicity listed. This way, you can't set a random (misspelled?)
attribute and wonder for hours why style.edgcolor = 'blue' doesn't
work.

Ryan

···

On Thu, Jan 5, 2012 at 10:58 AM, Benjamin Root <ben.root@...1304...> wrote:

On Thu, Jan 5, 2012 at 10:40 AM, Benjamin Root <ben.root@...1304...> wrote:

At the very least, it would help in compartmentallizing all the possible
drawing attributes that are common across all artists. Currently, I am
envisioning using a defaultdict object (which was introduced in python 2.5)
or subclassing from it. This might help in keeping compatibility with
existing code. Subclassing would allow for modifying __get__ and __set__ to
treat some elements like 'c' and 'color', 'lw' and 'linewidth' and so on as
the same.

Grrrr, in defaultdict(), the default_factory is called without arguments, so
a factory can't be made to produce a default value for a given key, unless I
resort to more hackary...

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

This is actually a great idea. This codifies in stone the alternative names of various properties. I have also taken this idea a step further. Some getter functions, such as for facecolor, will return the value of color if facecolor is None. This way, we can explicitly code the fallbacks and relationships the properties have with each other. So far, I have:

‘_c’, ‘_ec’, ‘_fc’, ‘_hatch’, ‘_ls’, ‘_lw’, ‘_marker’, ‘_mec’, ‘_mew’, ‘_mfc’, ‘_mfca’, ‘_ms’

The fallbacks are:

_ec --> _c
_fc --> _c
_mec --> _ec
_mew --> _lw
_mfc --> _fc
_mfca --> _mfc

Any other properties anybody can think of to add?

Ben Root

···

On Thu, Jan 5, 2012 at 11:34 AM, Ryan May <rmay31@…287…> wrote:

On Thu, Jan 5, 2012 at 10:58 AM, Benjamin Root <ben.root@…1304…> wrote:

On Thu, Jan 5, 2012 at 10:40 AM, Benjamin Root <ben.root@…1304…> wrote:

At the very least, it would help in compartmentallizing all the possible

drawing attributes that are common across all artists. Currently, I am

envisioning using a defaultdict object (which was introduced in python 2.5)

or subclassing from it. This might help in keeping compatibility with

existing code. Subclassing would allow for modifying get and set to

treat some elements like ‘c’ and ‘color’, ‘lw’ and ‘linewidth’ and so on as

the same.

Grrrr, in defaultdict(), the default_factory is called without arguments, so

a factory can’t be made to produce a default value for a given key, unless I

resort to more hackary…

Might be better to explicitly use properties for this rather than

overriding dict:

class Style(object):

__slots__ = ('_lw')



def __init__(self, lw=None):

    self.lw = lw



def _set_linewidth(self, lw):

    self._lw = lw



def _get_linewidth(self):

    return self._lw



lw = property(_get_linewidth, _set_linewidth)

linewidth = property(_get_linewidth, _set_linewidth)

Declaring slots allows you to keep the available attributes to those

explicity listed. This way, you can’t set a random (misspelled?)

attribute and wonder for hours why style.edgcolor = ‘blue’ doesn’t

work.

Ryan

At the very least, it would help in compartmentallizing all the possible
drawing attributes that are common across all artists. Currently, I am
envisioning using a defaultdict object (which was introduced in python 2.5)
or subclassing from it. This might help in keeping compatibility with
existing code. Subclassing would allow for modifying __get__ and __set__ to
treat some elements like 'c' and 'color', 'lw' and 'linewidth' and so on as
the same.

Grrrr, in defaultdict(), the default_factory is called without arguments, so
a factory can't be made to produce a default value for a given key, unless I
resort to more hackary...

Might be better to explicitly use properties for this rather than
overriding dict:

class Style(object):
     __slots__ = ('_lw')

     def __init__(self, lw=None):
         self.lw = lw

     def _set_linewidth(self, lw):
         self._lw = lw

     def _get_linewidth(self):
         return self._lw

     lw = property(_get_linewidth, _set_linewidth)
     linewidth = property(_get_linewidth, _set_linewidth)

Declaring slots allows you to keep the available attributes to those
explicity listed. This way, you can't set a random (misspelled?)
attribute and wonder for hours why style.edgcolor = 'blue' doesn't
work.

This seems useful, and may be OK for this application; but a little googling indicates that it is not really what __slots__ was intended for, it is at best controversial, and it should be used very sparingly and carefully.

Eric

···

On 01/05/2012 07:34 AM, Ryan May wrote:

On Thu, Jan 5, 2012 at 10:58 AM, Benjamin Root<ben.root@...1304...> wrote:

On Thu, Jan 5, 2012 at 10:40 AM, Benjamin Root<ben.root@...1304...> wrote:

Ryan

Right, slots is definitely not a good idea to use except in very specific situations. I would strongly recommend against its usage here.

http://groups.google.com/group/comp.lang.python/msg/0f2e859b9c002b28

···

On Thu, Jan 5, 2012 at 3:50 PM, Eric Firing <efiring@…202…> wrote:

On 01/05/2012 07:34 AM, Ryan May wrote:

On Thu, Jan 5, 2012 at 10:58 AM, Benjamin Root<ben.root@…1304…> wrote:

On Thu, Jan 5, 2012 at 10:40 AM, Benjamin Root<ben.root@…1304…> wrote:

At the very least, it would help in compartmentallizing all the possible

drawing attributes that are common across all artists. Currently, I am

envisioning using a defaultdict object (which was introduced in python 2.5)

or subclassing from it. This might help in keeping compatibility with

existing code. Subclassing would allow for modifying get and set to

treat some elements like ‘c’ and ‘color’, ‘lw’ and ‘linewidth’ and so on as

the same.

Grrrr, in defaultdict(), the default_factory is called without arguments, so

a factory can’t be made to produce a default value for a given key, unless I

resort to more hackary…

Might be better to explicitly use properties for this rather than

overriding dict:

class Style(object):

 __slots__ = ('_lw')
 def __init__(self, lw=None):
     self.lw = lw
 def _set_linewidth(self, lw):
     self._lw = lw
 def _get_linewidth(self):
     return self._lw
 lw = property(_get_linewidth, _set_linewidth)
 linewidth = property(_get_linewidth, _set_linewidth)

Declaring slots allows you to keep the available attributes to those

explicity listed. This way, you can’t set a random (misspelled?)

attribute and wonder for hours why style.edgcolor = ‘blue’ doesn’t

work.

This seems useful, and may be OK for this application; but a little

googling indicates that it is not really what slots was intended

for, it is at best controversial, and it should be used very sparingly

and carefully.

Eric

Ryan


Ridiculously easy VDI. With Citrix VDI-in-a-Box, you don’t need a complex

infrastructure or vast IT resources to deliver seamless, secure access to

virtual desktops. With this all-in-one solution, easily deploy virtual

desktops for less than the cost of PCs and save 60% on VDI infrastructure

costs. Try it free! http://p.sf.net/sfu/Citrix-VDIinabox


Matplotlib-users mailing list

Matplotlib-users@lists.sourceforge.net

https://lists.sourceforge.net/lists/listinfo/matplotlib-users


Daniel Hyams
dhyams@…287…

Good to know. I haven’t used slots regularly before and was unaware of the controversy around it.

The good news is that the slots mechanism isn’t critical to the Style() class anyway. What is more important is the use of properties and setting up the fallbacks. Heck, I am not entirely convinced that I would need to include the alternative spellings for the properties.

Ben Root

···

On Thu, Jan 5, 2012 at 2:59 PM, Daniel Hyams <dhyams@…287…> wrote:

Right, slots is definitely not a good idea to use except in very specific situations. I would strongly recommend against its usage here.

http://groups.google.com/group/comp.lang.python/msg/0f2e859b9c002b28

Right, __slots__ is definitely not a good idea to use except in very
specific situations. I would strongly recommend against its usage here.

http://groups.google.com/group/comp.lang.python/msg/0f2e859b9c002b28

I see that now. I had seen __slots__ used in a namedtuple example (in
the Python docs) and assumed it was a good idea. The same idea could
be achieved by using an internal _fields list and overriding
__getattr__ if the fixed list of attributes was deemed a useful
feature.

Ryan

···

On Thu, Jan 5, 2012 at 2:59 PM, Daniel Hyams <dhyams@...287...> wrote:

On Thu, Jan 5, 2012 at 3:50 PM, Eric Firing <efiring@...202...> wrote:

On 01/05/2012 07:34 AM, Ryan May wrote:
> On Thu, Jan 5, 2012 at 10:58 AM, Benjamin Root<ben.root@...1304...> wrote:
>>
>>
>> On Thu, Jan 5, 2012 at 10:40 AM, Benjamin Root<ben.root@...1304...> wrote:
>>>
>>>
>>>> At the very least, it would help in compartmentallizing all the
>>>> possible
>>>> drawing attributes that are common across all artists. Currently, I
>>>> am
>>>> envisioning using a defaultdict object (which was introduced in
>>>> python 2.5)
>>>> or subclassing from it. This might help in keeping compatibility
>>>> with
>>>> existing code. Subclassing would allow for modifying __get__ and
>>>> __set__ to
>>>> treat some elements like 'c' and 'color', 'lw' and 'linewidth' and so
>>>> on as
>>>> the same.
>>
>>
>> Grrrr, in defaultdict(), the default_factory is called without
>> arguments, so
>> a factory can't be made to produce a default value for a given key,
>> unless I
>> resort to more hackary...
>
> Might be better to explicitly use properties for this rather than
> overriding dict:
>
> class Style(object):
> __slots__ = ('_lw')
>
> def __init__(self, lw=None):
> self.lw = lw
>
> def _set_linewidth(self, lw):
> self._lw = lw
>
> def _get_linewidth(self):
> return self._lw
>
> lw = property(_get_linewidth, _set_linewidth)
> linewidth = property(_get_linewidth, _set_linewidth)
>
> Declaring slots allows you to keep the available attributes to those
> explicity listed. This way, you can't set a random (misspelled?)
> attribute and wonder for hours why style.edgcolor = 'blue' doesn't
> work.

This seems useful, and may be OK for this application; but a little
googling indicates that it is not really what __slots__ was intended
for, it is at best controversial, and it should be used very sparingly
and carefully.

Eric

>
> Ryan
>

------------------------------------------------------------------------------
Ridiculously easy VDI. With Citrix VDI-in-a-Box, you don't need a complex
infrastructure or vast IT resources to deliver seamless, secure access to
virtual desktops. With this all-in-one solution, easily deploy virtual
desktops for less than the cost of PCs and save 60% on VDI infrastructure
costs. Try it free! http://p.sf.net/sfu/Citrix-VDIinabox
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

--
Daniel Hyams
dhyams@...287...

------------------------------------------------------------------------------
Ridiculously easy VDI. With Citrix VDI-in-a-Box, you don't need a complex
infrastructure or vast IT resources to deliver seamless, secure access to
virtual desktops. With this all-in-one solution, easily deploy virtual
desktops for less than the cost of PCs and save 60% on VDI infrastructure
costs. Try it free! http://p.sf.net/sfu/Citrix-VDIinabox
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

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

Some thoughts I have had while trying to tackle this problem:

  1. Major difficulty is that different plotting functions currently have different default values for various parameters. For example, spy() uses a square marker by default. Furthermore, there are differences in how plotting functions determine default-ness.

1.1 - call signature uses **kwarg
Therefore, if something like ‘c’ is in kwarg, then it gets popped and used. If not, then sometimes a None is used which then means some sort of default elsewhere, or a value from a cycle somewhere is extracted.

1.2 - call signature uses prop=None idiom
Therefore, it is impossible to know if the user explicitly wanted the default property value or did not pass anything in.

1.3 - call signature explicitly sets a default (i.e., fmt=“b-”) in call signature

This prevents being able to extract a default value from a rcparam unless the user explicitly passes None. Therefore, it is difficult to have common style across all plots with a common/similar function calls. Sometimes, you explicitly pass None, sometimes you don’t.

  1. Plot property information being mixed in with the core process of creating plot elements. This makes the process of making sure that all desired properties are applied in a uniform and consistent manner. If each function could break its job into two basic parts: create plot elements for each dataset, apply style properties for each dataset plotted. In other words, for creating a bar chart, the process should first create Rectangle patches that places them at the correct locations and sized correctly (information that is based entirely on the dataset), but they would have no color, linewidth, hatch, etc. information yet. Then, styles are applied to each before returning them to the user.

  2. rcparam naming. I wanted to name things like “cycle.color” and “cycle.marker”, however, we currently have “axes.color_cycle”. While I am fine with continuing this naming convention, do we want to codify a set of naming rules for future additions, or can they continue to be named anyway we wish?

No matter how I look at this problem, we are looking at significant behavioral changes and output results. This will likely have to be an ongoing project and should probably be slated for a major version number change (i.e., v2.0.0). One particular feature I am tinkering on is a subclassed dict() that performs automatic translations of various property names (i.e., style[‘c’] and style[‘color’] are both the same element) and also performs fallbacks (i.e., if style[‘ec’] hasn’t been set yet, then retrieve style[‘c’]). This object might then be the basis of holding the core appearance information that is applied to the artist elements. Using it, we can codify various behaviors with respect to default values, rcparams and any other idiomatic things we have been doing.

For my own purposes, I am essentially continuing the current pattern for a few more properties and trying to apply them to a few more functions. However, because it breaks many things while continuing bad coding styles, I doubt it should be marged into the official repos.

Cheers!
Ben Root

···

On Thu, Jan 5, 2012 at 3:18 PM, Ryan May <rmay31@…287…> wrote:

On Thu, Jan 5, 2012 at 2:59 PM, Daniel Hyams <dhyams@…287…> wrote:

Right, slots is definitely not a good idea to use except in very

specific situations. I would strongly recommend against its usage here.

http://groups.google.com/group/comp.lang.python/msg/0f2e859b9c002b28

I see that now. I had seen slots used in a namedtuple example (in

the Python docs) and assumed it was a good idea. The same idea could

be achieved by using an internal _fields list and overriding

getattr if the fixed list of attributes was deemed a useful

feature.

Ryan

On Thu, Jan 5, 2012 at 3:50 PM, Eric Firing <efiring@…202…> wrote:

On 01/05/2012 07:34 AM, Ryan May wrote:

On Thu, Jan 5, 2012 at 10:58 AM, Benjamin Root<ben.root@…1304…> wrote:

On Thu, Jan 5, 2012 at 10:40 AM, Benjamin Root<ben.root@…1304…> wrote:

At the very least, it would help in compartmentallizing all the

possible

drawing attributes that are common across all artists. Currently, I

am

envisioning using a defaultdict object (which was introduced in

python 2.5)

or subclassing from it. This might help in keeping compatibility

with

existing code. Subclassing would allow for modifying get and

set to

treat some elements like ‘c’ and ‘color’, ‘lw’ and ‘linewidth’ and so

on as

the same.

Grrrr, in defaultdict(), the default_factory is called without

arguments, so

a factory can’t be made to produce a default value for a given key,

unless I

resort to more hackary…

Might be better to explicitly use properties for this rather than

overriding dict:

class Style(object):

 __slots__ = ('_lw')
 def __init__(self, lw=None):
     self.lw = lw
 def _set_linewidth(self, lw):
     self._lw = lw
 def _get_linewidth(self):
     return self._lw
 lw = property(_get_linewidth, _set_linewidth)
 linewidth = property(_get_linewidth, _set_linewidth)

Declaring slots allows you to keep the available attributes to those

explicity listed. This way, you can’t set a random (misspelled?)

attribute and wonder for hours why style.edgcolor = ‘blue’ doesn’t

work.

This seems useful, and may be OK for this application; but a little

googling indicates that it is not really what slots was intended

for, it is at best controversial, and it should be used very sparingly

and carefully.

Eric

Ryan

FWIW, defaultdict() only uses the __missing__ dictionary hook, and that one is
passed the key. It's easy to implement a similar class that calls the factory
with a key argument.

Georg

···

On 01/05/2012 05:58 PM, Benjamin Root wrote:

On Thu, Jan 5, 2012 at 10:40 AM, Benjamin Root <ben.root@…1304… > <mailto:ben.root@…1304…>> wrote:

        At the very least, it would help in compartmentallizing all the possible
        drawing attributes that are common across all artists. Currently, I am
        envisioning using a defaultdict object (which was introduced in python
        2.5) or subclassing from it. This might help in keeping compatibility
        with existing code. Subclassing would allow for modifying __get__ and
        __set__ to treat some elements like 'c' and 'color', 'lw' and
        'linewidth' and so on as the same.

Grrrr, in defaultdict(), the default_factory is called without arguments, so a
factory can't be made to produce a default value for a given key, unless I
resort to more hackary...