John Hunter wrote:
>>>>>> >>>>>> "Manuel" == Manuel Metz <[EMAIL PROTECTED]> writes:
> >
> >     Manuel> There is a subtle but essential difference  ;-)  : for i in
> >     Manuel> xrange(1,len(r), 2 ) ^^^ , i.e. every second value gets
> >     Manuel> rescaled. But there is probably a more "pythonic" way to
> >     Manuel> do that:
> >
> >     Manuel>         r = 1.0/math.sqrt(math.pi) # unit area r = asarray(
> >     Manuel> [r,0.5*r]*self.numsides )
> >
> >     Manuel> I'm not aware of a better way to do this with numerix  :-(
> >
> > Oops, sorry I missed that.  I think what you want is then
> >
> >         scale = 0.5/math.sqrt(math.pi)
> >         r = scale*ones(self.numsides*2)
> >         r[1::2] *= 0.5
> >

I've fixed that - and I've learned something !

> >
> > OK, if I could make a few more suggestions (I feel like a customer at
> > a restaurant where every time the waiter brings me a cup of coffee I
> > ask "just one more thing"...)
> >
> > +        old_ymin,old_ymax = self.get_ylim()
> >
> > The matplotlib style guidelines are
> >
> >   UpperCase : classes
> >   lower_underscore  : functions and methods
> >   lower or lowerUpper : variables or attributes
> >
> > For shortish variable names, I prefer
> >
> >         oldymin, oldymax = self.get_ylim()

Ah - there are three lines that I touched for only one reason: the line
indention was done with a "tab" instead of "spaces". When I recognised
this in my text editor, I changed it to space-indention. That's the only
reason for these patched lines.

> > +        if isinstance(marker, str) or isinstance(marker, unicode):
> > +            # the standard way to define symbols using a string
character
> > +            sym = syms.get(marker)
> >
> > +        if isinstance(marker, tuple) or isinstance(marker, list):
> > +            # accept marker to be:
> > +            #    (numsides, style, [angle])
> >
> > +            if isinstance(marker[0], int) or isinstance(marker[0],
long):
> > +                # (numsides, style, [angle])
> >
> > Here you should use "duck typing" not "type checking" (google "duck
> > typing").  matplotlib.cbook provides several duck typing functions, eg
> > is_stringlike, iterable and is_numlike.  Take a look at is_numlike
> >
> > def is_numlike(obj):
> >     try: obj+1
> >     except TypeError: return False
> >     else: return True
> >
> > Ie, if it acts like a number (you can add one to it) then we'll treat
> > it as a number.  This allows users to provide other integer like
> > classes which are not ints or longs.  Everytime you use isinstance,
> > take a 2nd look.  There may be a better way.
> >
> > I'll await your updated patch  :-)

I've fixed that too - and learned even more  ;-)  Thanks !

Patch against latest revision is attached.

Manuel

Index: axes.py
===================================================================
--- axes.py	(revision 2811)
+++ axes.py	(working copy)
@@ -14,8 +14,9 @@
 from artist import Artist, setp
 from axis import XAxis, YAxis
 from cbook import iterable, is_string_like, flatten, enumerate, \
-     allequal, dict_delall, popd, popall, silent_list
-from collections import RegularPolyCollection, PolyCollection, LineCollection, QuadMesh
+     allequal, dict_delall, popd, popall, silent_list, is_numlike
+from collections import RegularPolyCollection, PolyCollection, LineCollection, QuadMesh, \
+     StarPolygonCollection
 from colors import colorConverter, normalize, Colormap, \
         LinearSegmentedColormap, looks_like_color, is_color_like
 import cm
@@ -1211,7 +1212,7 @@
         if xmax is None and hasattr(xmin,'__len__'):
             xmin,xmax = xmin
 
-	old_xmin,old_xmax = self.get_xlim()
+        old_xmin,old_xmax = self.get_xlim()
         if xmin is None: xmin = old_xmin
         if xmax is None: xmax = old_xmax
 
@@ -1223,7 +1224,7 @@
             xmin -= 1e-38
             xmax += 1e-38
 
-	self.viewLim.intervalx().set_bounds(xmin, xmax)
+        self.viewLim.intervalx().set_bounds(xmin, xmax)
         if emit: self._send_xlim_event()
         return xmin, xmax
 
@@ -1324,7 +1325,7 @@
         if ymax is None and hasattr(ymin,'__len__'):
             ymin,ymax = ymin
 
-	old_ymin,old_ymax = self.get_ylim()
+        old_ymin,old_ymax = self.get_ylim()
         if ymin is None: ymin = old_ymin
         if ymax is None: ymax = old_ymax
 
@@ -3100,10 +3101,9 @@
             'h' : hexagon
             '8' : octagon
 
+        If marker is None and verts is not None, verts is a sequence
+        of (x,y) vertices for a custom scatter symbol.
 
-        if marker is None and verts is not None, verts is a sequence
-        of (x,y) vertices for a custom scatter symbol.  The
-
         s is a size argument in points squared.
 
         Any or all of x, y, s, and c may be masked arrays, in which
@@ -3171,26 +3171,74 @@
         if faceted: edgecolors = None
         else: edgecolors = 'None'
 
-        sym = syms.get(marker)
-        if sym is None and verts is None:
-            raise ValueError('Unknown marker symbol to scatter')
-
+        sym = None
+        starlike = False
+        
+        # to be API compatible
+        if sym is None and not (verts is None):
+            marker = (verts, 0)
+            verts = None
+        
+        if is_string_like(marker):
+            # the standard way to define symbols using a string character
+            sym = syms.get(marker)
+            if sym is None and verts is None:
+                raise ValueError('Unknown marker symbol to scatter')
+            numsides, rotation = syms[marker]
+        
+        elif iterable(marker):
+            # accept marker to be:
+            #    (numsides, style, [angle])
+            # or
+            #    (verts[], style, [angle])
+            
+            if len(marker)<2 or len(marker)>3:
+                raise ValueError('Cannot create markersymbol from marker')
+            
+            if is_numlike(marker[0]):
+                # (numsides, style, [angle])
+                
+                if len(marker)==2:
+                    numsides, rotation = marker[0], math.pi/4.
+                elif len(marker)==3:
+                    numsides, rotation = marker[0], marker[2]
+                sym = True
+                
+                if marker[1]==1:
+                    # starlike symbol, everthing else is interpreted as solid symbol
+                    starlike = True
+            
+            else:
+                verts = asarray(marker[0])
+                
         if sym is not None:
-            numsides, rotation = syms[marker]
-            collection = RegularPolyCollection(
-                self.figure.dpi,
-                numsides, rotation, scales,
-                facecolors = colors,
-                edgecolors = edgecolors,
-                linewidths = linewidths,
-                offsets = zip(x,y),
-                transOffset = self.transData,
-                )
+            if not starlike:
+                collection = RegularPolyCollection(
+                    self.figure.dpi,
+                    numsides, rotation, scales,
+                    facecolors = colors,
+                    edgecolors = edgecolors,
+                    linewidths = linewidths,
+                    offsets = zip(x,y),
+                    transOffset = self.transData,
+                    )
+            else:
+                collection = StarPolygonCollection(
+                    self.figure.dpi,
+                    numsides, rotation, scales,
+                    facecolors = colors,
+                    edgecolors = edgecolors,
+                    linewidths = linewidths,
+                    offsets = zip(x,y),
+                    transOffset = self.transData,
+                    )
         else:
-            verts = asarray(verts)
-            # hmm, the scaling is whacked -- how do we want to scale with custom verts?
+            # rescale verts
+            rescale = sqrt(max(verts[:,0]**2+verts[:,1]**2))
+            verts /= rescale
+            
             scales = asarray(scales)
-            #scales = sqrt(scales * self.figure.dpi.get() / 72.)
+            scales = sqrt(scales * self.figure.dpi.get() / 72.)
             if len(scales)==1:
                 verts = [scales[0]*verts]
             else:
Index: collections.py
===================================================================
--- collections.py	(revision 2811)
+++ collections.py	(working copy)
@@ -15,7 +15,7 @@
 from cbook import is_string_like, iterable
 from colors import colorConverter
 from cm import ScalarMappable
-from numerix import arange, sin, cos, pi, asarray, sqrt, array, newaxis
+from numerix import arange, sin, cos, pi, asarray, sqrt, array, newaxis, ones
 from transforms import identity_transform
 
 class Collection(Artist):
@@ -293,7 +293,7 @@
         * dpi is the figure dpi instance, and is required to do the
           area scaling.
 
-        * numsides: the number of sides of the  polygon
+        * numsides: the number of sides of the polygon
 
         * sizes gives the area of the circle circumscribing the
           regular polygon in points^2
@@ -374,6 +374,43 @@
         raise NotImplementedError('Vertices in data coordinates are calculated\n'
                 + 'only with offsets and only if _transOffset == dataTrans.')
 
+class StarPolygonCollection(RegularPolyCollection):
+    def __init__(self,
+                 dpi,
+                 numsides,
+                 rotation = 0 ,
+                 sizes = (1,),
+                 **kwargs):
+        """
+        Draw a regular star like Polygone with numsides.
+        
+        * dpi is the figure dpi instance, and is required to do the
+          area scaling.
+
+        * numsides: the number of sides of the polygon
+
+        * sizes gives the area of the circle circumscribing the
+          regular polygon in points^2
+
+        * rotation is the rotation of the polygon in radians
+
+        kwargs: See PatchCollection for more details
+
+          * offsets are a sequence of x,y tuples that give the centers of
+            the polygon in data coordinates
+
+          * transOffset is the Transformation instance used to
+            transform the centers onto the canvas.
+        """
+        RegularPolyCollection.__init__(self, dpi, numsides, rotation, sizes, **kwargs)
+    
+    def _update_verts(self):
+        scale = 1.0/math.sqrt(math.pi)
+        r = scale*ones(self.numsides*2)
+        r[1::2] *= 0.5
+        theta  = (2.*math.pi/(2*self.numsides))*arange(2*self.numsides) + self.rotation
+        self._verts = zip( r*sin(theta), r*cos(theta) )
+
 class LineCollection(Collection, ScalarMappable):
     """
     All parameters must be sequences.  The property of the ith line
-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel

Reply via email to