Revision: 5066
          http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5066&view=rev
Author:   jdh2358
Date:     2008-04-23 10:44:15 -0700 (Wed, 23 Apr 2008)

Log Message:
-----------
added manuels scatter pie example

Modified Paths:
--------------
    trunk/matplotlib/lib/matplotlib/mlab.py
    trunk/matplotlib/unit/mlab_unit.py

Added Paths:
-----------
    trunk/matplotlib/examples/scatter_piecharts.py

Added: trunk/matplotlib/examples/scatter_piecharts.py
===================================================================
--- trunk/matplotlib/examples/scatter_piecharts.py                              
(rev 0)
+++ trunk/matplotlib/examples/scatter_piecharts.py      2008-04-23 17:44:15 UTC 
(rev 5066)
@@ -0,0 +1,40 @@
+"""
+This example makes custom 'pie charts' as the markers for a scatter plotqu
+
+Thanks to Manuel Metz for the example
+"""
+import math
+import numpy as np
+import matplotlib.pyplot as plt
+
+# first define the ratios
+r1 = 0.2      # 20%
+r2 = r1 + 0.4 # 40%
+
+# define some sizes of the scatter marker
+sizes = [60,80,120]
+
+# calculate the points of the first pie marker
+#
+# these are just the origin (0,0) +
+# some points on a circle cos,sin
+x = [0] + np.cos(np.linspace(0, 2*math.pi*r1, 10)).tolist()
+y = [0] + np.sin(np.linspace(0, 2*math.pi*r1, 10)).tolist()
+xy1 = zip(x,y)
+
+# ...
+x = [0] + np.cos(np.linspace(2*math.pi*r1, 2*math.pi*r2, 10)).tolist()
+y = [0] + np.sin(np.linspace(2*math.pi*r1, 2*math.pi*r2, 10)).tolist()
+xy2 = zip(x,y)
+
+x = [0] + np.cos(np.linspace(2*math.pi*r2, 2*math.pi, 10)).tolist()
+y = [0] + np.sin(np.linspace(2*math.pi*r2, 2*math.pi, 10)).tolist()
+xy3 = zip(x,y)
+
+
+fig = plt.figure()
+ax = fig.add_subplot(111)
+ax.scatter( np.arange(3), np.arange(3), marker=(xy1,0), s=sizes, 
facecolor='blue' )
+ax.scatter( np.arange(3), np.arange(3), marker=(xy2,0), s=sizes, 
facecolor='green' )
+ax.scatter( np.arange(3), np.arange(3), marker=(xy3,0), s=sizes, 
facecolor='red' )
+plt.show()

Modified: trunk/matplotlib/lib/matplotlib/mlab.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/mlab.py     2008-04-23 16:54:21 UTC (rev 
5065)
+++ trunk/matplotlib/lib/matplotlib/mlab.py     2008-04-23 17:44:15 UTC (rev 
5066)
@@ -87,6 +87,7 @@
 
 import numpy as npy
 
+
 from matplotlib import nxutils
 from matplotlib import cbook
 
@@ -2143,10 +2144,10 @@
 
 
 def csv2rec(fname, comments='#', skiprows=0, checkrows=0, delimiter=',',
-            converterd=None, names=None, missing=None):
+            converterd=None, names=None, missing='', missingd=None):
     """
     Load data from comma/space/tab delimited file in fname into a
-    numpy record array and return the record array.
+    numpy (m)record array and return the record array.
 
     If names is None, a header row is required to automatically assign
     the recarray names.  The headers will be lower cased, spaces will
@@ -2172,13 +2173,24 @@
     names, if not None, is a list of header names.  In this case, no
     header will be read from the file
 
+    missingd - is a dictionary mapping munged column names to field values
+    which signify that the field does not contain actual data and should
+    be masked, e.g. '0000-00-00' or 'unused'
+
+    missing - a string whose value signals a missing field regardless of
+    the column it appears in, e.g. 'unused'
+
     if no rows are found, None is returned -- see examples/loadrec.py
     """
 
     if converterd is None:
         converterd = dict()
 
+    if missingd is None:
+        missingd = {}
+
     import dateutil.parser
+    import datetime
     parsedate = dateutil.parser.parse
 
 
@@ -2226,14 +2238,28 @@
 
     process_skiprows(reader)
 
-    dateparser = dateutil.parser.parse
+    def ismissing(name, val):
+        "Should the value val in column name be masked?"
 
-    def myfloat(x):
-        if x==missing:
-            return npy.nan
+        if val == missing or val == missingd.get(name) or val == '':
+            return True
         else:
-            return float(x)
+            return False
 
+    def with_default_value(func, default):
+        def newfunc(name, val):
+            if ismissing(name, val):
+                return default
+            else:
+                return func(val)
+        return newfunc
+
+    dateparser = dateutil.parser.parse
+    mydateparser = with_default_value(dateparser, datetime.date(1,1,1))
+    myfloat = with_default_value(float, npy.nan)
+    myint = with_default_value(int, -1)
+    mystr = with_default_value(str, '')
+
     def mydate(x):
         # try and return a date object
         d = dateparser(x)
@@ -2241,16 +2267,16 @@
         if d.hour>0 or d.minute>0 or d.second>0:
             raise ValueError('not a date')
         return d.date()
+    mydate = with_default_value(mydate, datetime.date(1,1,1))
 
-
-    def get_func(item, func):
+    def get_func(name, item, func):
         # promote functions in this order
-        funcmap = {int:myfloat, myfloat:mydate, mydate:dateparser, 
dateparser:str}
-        try: func(item)
+        funcmap = {myint:myfloat, myfloat:mydate, mydate:mydateparser, 
mydateparser:mystr}
+        try: func(name, item)
         except:
-            if func==str:
+            if func==mystr:
                 raise ValueError('Could not find a working conversion 
function')
-            else: return get_func(item, funcmap[func])    # recurse
+            else: return get_func(name, item, funcmap[func])    # recurse
         else: return func
 
 
@@ -2266,7 +2292,7 @@
         converters = None
         for i, row in enumerate(reader):
             if i==0:
-                converters = [int]*len(row)
+                converters = [myint]*len(row)
             if checkrows and i>checkrows:
                 break
             #print i, len(names), len(row)
@@ -2276,10 +2302,10 @@
                 if func is None:
                     func = converterd.get(name)
                 if func is None:
-                    if not item.strip(): continue
+                    #if not item.strip(): continue
                     func = converters[j]
                     if len(item.strip()):
-                        func = get_func(item, func)
+                        func = get_func(name, item, func)
                 converters[j] = func
         return converters
 
@@ -2307,7 +2333,7 @@
             item = itemd.get(item, item)
             cnt = seen.get(item, 0)
             if cnt>0:
-                names.append(item + '%d'%cnt)
+                names.append(item + '_%d'%cnt)
             else:
                 names.append(item)
             seen[item] = cnt+1
@@ -2327,15 +2353,24 @@
     # iterate over the remaining rows and convert the data to date
     # objects, ints, or floats as approriate
     rows = []
+    rowmasks = []
     for i, row in enumerate(reader):
         if not len(row): continue
         if row[0].startswith(comments): continue
-        rows.append([func(val) for func, val in zip(converters, row)])
+        rows.append([func(name, val) for func, name, val in zip(converters, 
names, row)])
+        rowmasks.append([ismissing(name, val) for name, val in zip(names, 
row)])
     fh.close()
 
     if not len(rows):
         return None
-    r = npy.rec.fromrecords(rows, names=names)
+    if npy.any(rowmasks):
+        try: from numpy.ma import mrecords
+        except ImportError:
+            raise RuntimeError('numpy 1.05 or later is required for masked 
array support')
+        else:
+            r = mrecords.fromrecords(rows, names=names, mask=rowmasks)
+    else:
+        r = npy.rec.fromrecords(rows, names=names)
     return r
 
 
@@ -2529,26 +2564,59 @@
 
 
 
-def rec2csv(r, fname, delimiter=',', formatd=None):
+def rec2csv(r, fname, delimiter=',', formatd=None, missing='',
+            missingd=None):
     """
-    Save the data from numpy record array r into a comma/space/tab
+    Save the data from numpy (m)recarray r into a comma/space/tab
     delimited file.  The record array dtype names will be used for
     column headers.
 
 
     fname - can be a filename or a file handle.  Support for gzipped
     files is automatic, if the filename ends in .gz
+
+    See csv2rec and rec2csv for information about missing and
+    missingd, which can be used to fill in masked values into your CSV
+    file.
     """
+
+    if missingd is None:
+        missingd = dict()
+
+    def with_mask(func):
+        def newfunc(val, mask, mval):
+            if mask:
+                return mval
+            else:
+                return func(val)
+        return newfunc
+
     formatd = get_formatd(r, formatd)
     funcs = []
     for i, name in enumerate(r.dtype.names):
-        funcs.append(csvformat_factory(formatd[name]).tostr)
+        funcs.append(with_mask(csvformat_factory(formatd[name]).tostr))
 
     fh, opened = cbook.to_filehandle(fname, 'w', return_opened=True)
     writer = csv.writer(fh, delimiter=delimiter)
     header = r.dtype.names
     writer.writerow(header)
+
+    # Our list of specials for missing values
+    mvals = []
+    for name in header:
+        mvals.append(missingd.get(name, missing))
+
+    ismasked = False
+    if len(r):
+        row = r[0]
+        ismasked = hasattr(row, '_fieldmask')
+
     for row in r:
-        writer.writerow([func(val) for func, val in zip(funcs, row)])
+        if ismasked:
+            row, rowmask = row.item(), row._fieldmask.item()
+        else:
+            rowmask = [False] * len(row)
+        writer.writerow([func(val, mask, mval) for func, val, mask, mval
+                         in zip(funcs, row, rowmask, mvals)])
     if opened:
         fh.close()

Modified: trunk/matplotlib/unit/mlab_unit.py
===================================================================
--- trunk/matplotlib/unit/mlab_unit.py  2008-04-23 16:54:21 UTC (rev 5065)
+++ trunk/matplotlib/unit/mlab_unit.py  2008-04-23 17:44:15 UTC (rev 5066)
@@ -55,5 +55,27 @@
                 print 'repr(dt.type)',repr(dt.type)
             self.failUnless( numpy.all(ra[name] == ra2[name]) ) # should not 
fail with numpy 1.0.5
 
+    def test_csv2rec_masks(self):
+        # Make sure masked entries survive roundtrip
+
+        csv = """date,age,weight,name
+2007-01-01,12,32.2,"jdh1"
+0000-00-00,0,23,"jdh2"
+2007-01-03,,32.5,"jdh3"
+2007-01-04,12,NaN,"jdh4"
+2007-01-05,-1,NULL,"""
+        missingd = dict(date='0000-00-00', age='-1', weight='NULL')
+        fh = StringIO.StringIO(csv)
+        r1 = mlab.csv2rec(fh, missingd=missingd)
+        fh = StringIO.StringIO()
+        mlab.rec2csv(r1, fh, missingd=missingd)
+        fh.seek(0)
+        r2 = mlab.csv2rec(fh, missingd=missingd)
+
+        self.failUnless( numpy.all( r2['date'].mask   == [0,1,0,0,0] ))
+        self.failUnless( numpy.all( r2['age'].mask    == [0,0,1,0,1] ))
+        self.failUnless( numpy.all( r2['weight'].mask == [0,0,0,0,1] ))
+        self.failUnless( numpy.all( r2['name'].mask   == [0,0,0,0,1] ))
+
 if __name__=='__main__':
     unittest.main()


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference 
Don't miss this year's exciting event. There's still time to save $100. 
Use priority code J8TL2D2. 
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
Matplotlib-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins

Reply via email to