From: <jd...@us...> - 2009-01-30 16:11:29
|
Revision: 6857 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6857&view=rev Author: jdh2358 Date: 2009-01-30 16:11:25 +0000 (Fri, 30 Jan 2009) Log Message: ----------- Merged revisions 6856 via svnmerge from https://matplotlib.svn.sourceforge.net/svnroot/matplotlib/branches/v0_98_5_maint ........ r6856 | jdh2358 | 2009-01-30 08:09:39 -0800 (Fri, 30 Jan 2009) | 1 line conditionally set default clippath ........ Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/axes.py Property Changed: ---------------- trunk/matplotlib/ trunk/matplotlib/doc/pyplots/README trunk/matplotlib/doc/sphinxext/gen_gallery.py trunk/matplotlib/doc/sphinxext/gen_rst.py Property changes on: trunk/matplotlib ___________________________________________________________________ Modified: svnmerge-integrated - /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-6854 + /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-6856 Modified: svn:mergeinfo - /branches/v0_91_maint:5753-5771 /branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854 + /branches/v0_91_maint:5753-5771 /branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856 Property changes on: trunk/matplotlib/doc/pyplots/README ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854 + /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856 Property changes on: trunk/matplotlib/doc/sphinxext/gen_gallery.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854 + /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856 Property changes on: trunk/matplotlib/doc/sphinxext/gen_rst.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854 + /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856 Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2009-01-30 16:09:39 UTC (rev 6856) +++ trunk/matplotlib/lib/matplotlib/axes.py 2009-01-30 16:11:25 UTC (rev 6857) @@ -1326,7 +1326,9 @@ collection.set_label('collection%d'%len(self.collections)) self.collections.append(collection) self._set_artist_props(collection) - collection.set_clip_path(self.patch) + + if collection.get_clip_path() is None: + collection.set_clip_path(self.patch) if autolim: if collection._paths and len(collection._paths): self.update_datalim(collection.get_datalim(self.transData)) @@ -1339,7 +1341,8 @@ lines ''' self._set_artist_props(line) - line.set_clip_path(self.patch) + if line.get_clip_path() is None: + line.set_clip_path(self.patch) self._update_line_limits(line) if not line.get_label(): @@ -1364,7 +1367,8 @@ """ self._set_artist_props(p) - p.set_clip_path(self.patch) + if p.get_clip_path() is None: + p.set_clip_path(self.patch) self._update_patch_limits(p) self.patches.append(p) p._remove_method = lambda h: self.patches.remove(h) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2009-01-30 16:19:27
|
Revision: 6858 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6858&view=rev Author: jdh2358 Date: 2009-01-30 16:19:24 +0000 (Fri, 30 Jan 2009) Log Message: ----------- remove pyexcelerator support - use xlwt instead Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/doc/api/api_changes.rst trunk/matplotlib/lib/mpl_toolkits/exceltools.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009-01-30 16:11:25 UTC (rev 6857) +++ trunk/matplotlib/CHANGELOG 2009-01-30 16:19:24 UTC (rev 6858) @@ -1,3 +1,6 @@ +2009-01-30 Remove support for pyExcelerator in exceltools -- use xlwt + instead - JDH + 2009-01-29 Document 'resolution' kwarg for polar plots. Support it when using pyplot.polar, not just Figure.add_axes. - MGD Modified: trunk/matplotlib/doc/api/api_changes.rst =================================================================== --- trunk/matplotlib/doc/api/api_changes.rst 2009-01-30 16:11:25 UTC (rev 6857) +++ trunk/matplotlib/doc/api/api_changes.rst 2009-01-30 16:19:24 UTC (rev 6858) @@ -19,6 +19,8 @@ Changes for 0.98.x ================== +* Remove support for pyExcelerator in exceltools -- use xlwt + instead * Changed the defaults of acorr and xcorr to use usevlines=True, maxlags=10 and normed=True since these are the best defaults Modified: trunk/matplotlib/lib/mpl_toolkits/exceltools.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/exceltools.py 2009-01-30 16:11:25 UTC (rev 6857) +++ trunk/matplotlib/lib/mpl_toolkits/exceltools.py 2009-01-30 16:19:24 UTC (rev 6858) @@ -22,13 +22,7 @@ import copy import numpy as np -try: - import xlwt as excel -except ImportError: - try: - import pyExcelerator as excel - except ImportError: - raise ImportError('You must install xlwt or pyExcelterator to use the exceltools') +import xlwt as excel import matplotlib.cbook as cbook import matplotlib.mlab as mlab This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2009-01-30 16:21:18
|
Revision: 6860 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6860&view=rev Author: jdh2358 Date: 2009-01-30 16:21:14 +0000 (Fri, 30 Jan 2009) Log Message: ----------- Merged revisions 6859 via svnmerge from https://matplotlib.svn.sourceforge.net/svnroot/matplotlib/branches/v0_98_5_maint ........ r6859 | jdh2358 | 2009-01-30 08:19:49 -0800 (Fri, 30 Jan 2009) | 1 line purge pyexcelerator refs from docstrings, etc ........ Modified Paths: -------------- trunk/matplotlib/examples/pylab_examples/loadrec.py trunk/matplotlib/lib/mpl_toolkits/exceltools.py trunk/matplotlib/lib/mpl_toolkits/gtktools.py Property Changed: ---------------- trunk/matplotlib/ trunk/matplotlib/doc/pyplots/README trunk/matplotlib/doc/sphinxext/gen_gallery.py trunk/matplotlib/doc/sphinxext/gen_rst.py Property changes on: trunk/matplotlib ___________________________________________________________________ Modified: svnmerge-integrated - /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-6856 + /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-6859 Modified: svn:mergeinfo - /branches/v0_91_maint:5753-5771 /branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856 + /branches/v0_91_maint:5753-5771 /branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859 Property changes on: trunk/matplotlib/doc/pyplots/README ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856 + /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859 Property changes on: trunk/matplotlib/doc/sphinxext/gen_gallery.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856 + /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859 Property changes on: trunk/matplotlib/doc/sphinxext/gen_rst.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856 + /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859 Modified: trunk/matplotlib/examples/pylab_examples/loadrec.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/loadrec.py 2009-01-30 16:19:49 UTC (rev 6859) +++ trunk/matplotlib/examples/pylab_examples/loadrec.py 2009-01-30 16:21:14 UTC (rev 6860) @@ -10,7 +10,7 @@ ax.plot(a.date, a.adj_close, '-') fig.autofmt_xdate() -# if you have pyExcelerator installed, you can output excel +# if you have xlwt installed, you can output excel import mpl_toolkits.exceltools as exceltools exceltools.rec2excel(a, 'test.xls') show() Modified: trunk/matplotlib/lib/mpl_toolkits/exceltools.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/exceltools.py 2009-01-30 16:19:49 UTC (rev 6859) +++ trunk/matplotlib/lib/mpl_toolkits/exceltools.py 2009-01-30 16:21:14 UTC (rev 6860) @@ -1,5 +1,5 @@ """ -Some io tools for excel -- requires pypyExcelerator +Some io tools for excel -- requires xlwt Example usage: @@ -59,7 +59,7 @@ def rec2excel(r, ws, formatd=None, rownum=0, colnum=0, nanstr='NaN', infstr='Inf'): """ - save record array r to excel pyExcelerator worksheet ws + save record array r to excel xlwt worksheet ws starting at rownum. if ws is string like, assume it is a filename and save to it Modified: trunk/matplotlib/lib/mpl_toolkits/gtktools.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/gtktools.py 2009-01-30 16:19:49 UTC (rev 6859) +++ trunk/matplotlib/lib/mpl_toolkits/gtktools.py 2009-01-30 16:21:14 UTC (rev 6860) @@ -298,10 +298,6 @@ def rec2gtk(r, formatd=None, rownum=0, autowin=True): """ - save record array r to excel pyExcelerator worksheet ws - starting at rownum. if ws is string like, assume it is a - filename and save to it - formatd is a dictionary mapping dtype name -> mlab.Format instances This function creates a SortedStringsScrolledWindow (derived This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jo...@us...> - 2009-02-02 08:29:25
|
Revision: 6862 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6862&view=rev Author: jouni Date: 2009-02-02 08:29:18 +0000 (Mon, 02 Feb 2009) Log Message: ----------- Avoid malloc errors in ttconv for fonts that don't have e.g. PostName as entry (1,0,0,6) in the name table (a version of Tahoma triggered this) Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/ttconv/pprdrv_tt.cpp Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009-01-30 16:31:47 UTC (rev 6861) +++ trunk/matplotlib/CHANGELOG 2009-02-02 08:29:18 UTC (rev 6862) @@ -1,3 +1,6 @@ +2009-02-02 Avoid malloc errors in ttconv for fonts that don't have + e.g. PostName (a version of Tahoma triggered this) - JKS + 2009-01-30 Remove support for pyExcelerator in exceltools -- use xlwt instead - JDH Modified: trunk/matplotlib/ttconv/pprdrv_tt.cpp =================================================================== --- trunk/matplotlib/ttconv/pprdrv_tt.cpp 2009-01-30 16:31:47 UTC (rev 6861) +++ trunk/matplotlib/ttconv/pprdrv_tt.cpp 2009-02-02 08:29:18 UTC (rev 6862) @@ -178,10 +178,18 @@ table_ptr = NULL; - /* Set default values to avoid future references to */ - /* undefined pointers. */ - font->PostName = font->FullName = - font->FamilyName = font->Version = font->Style = (char*)"unknown"; + /* Set default values to avoid future references to undefined + * pointers. Allocate each of PostName, FullName, FamilyName, + * Version, and Style separately so they can be freed safely. */ + for (char **ptr = &(font->PostName); ptr != NULL; ) { + *ptr = (char*) calloc(sizeof(char), strlen("unknown")+1); + strcpy(*ptr, "unknown"); + if (ptr == &(font->PostName)) ptr = &(font->FullName); + else if (ptr == &(font->FullName)) ptr = &(font->FamilyName); + else if (ptr == &(font->FamilyName)) ptr = &(font->Version); + else if (ptr == &(font->Version)) ptr = &(font->Style); + else ptr = NULL; + } font->Copyright = font->Trademark = (char*)NULL; table_ptr = GetTable(font, "name"); /* pointer to table */ @@ -222,6 +230,7 @@ /* Font Family name */ if( platform == 1 && nameid == 1 ) { + free(font->FamilyName); font->FamilyName = (char*)calloc(sizeof(char),length+1); strncpy(font->FamilyName,(const char*)strings+offset,length); font->FamilyName[length]=(char)NULL; @@ -237,6 +246,7 @@ /* Font Family name */ if( platform == 1 && nameid == 2 ) { + free(font->Style); font->Style = (char*)calloc(sizeof(char),length+1); strncpy(font->Style,(const char*)strings+offset,length); font->Style[length]=(char)NULL; @@ -252,6 +262,7 @@ /* Full Font name */ if( platform == 1 && nameid == 4 ) { + free(font->FullName); font->FullName = (char*)calloc(sizeof(char),length+1); strncpy(font->FullName,(const char*)strings+offset,length); font->FullName[length]=(char)NULL; @@ -267,6 +278,7 @@ /* Version string */ if( platform == 1 && nameid == 5 ) { + free(font->Version); font->Version = (char*)calloc(sizeof(char),length+1); strncpy(font->Version,(const char*)strings+offset,length); font->Version[length]=(char)NULL; @@ -282,6 +294,7 @@ /* PostScript name */ if( platform == 1 && nameid == 6 ) { + free(font->PostName); font->PostName = (char*)calloc(sizeof(char),length+1); strncpy(font->PostName,(const char*)strings+offset,length); font->PostName[length]=(char)NULL; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2009-02-02 16:29:41
|
Revision: 6865 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6865&view=rev Author: mdboom Date: 2009-02-02 16:29:37 +0000 (Mon, 02 Feb 2009) Log Message: ----------- Create path_cleanup code for use by the Mac OS-X backend. Refactor C++ code to follow Numpy's guidelines for linking multiple C files into a single extension. Remove dependency of Agg backend on _image.cpp and _ft2font.cpp (simplifies linking problems and reduces generated code size). Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/delaunay/VoronoiDiagramGenerator.cpp trunk/matplotlib/setupext.py trunk/matplotlib/src/_backend_agg.cpp trunk/matplotlib/src/_backend_gdk.c trunk/matplotlib/src/_gtkagg.cpp trunk/matplotlib/src/_image.cpp trunk/matplotlib/src/_image.h trunk/matplotlib/src/_path.cpp trunk/matplotlib/src/agg_py_path_iterator.h trunk/matplotlib/src/agg_py_transforms.h trunk/matplotlib/src/ft2font.cpp trunk/matplotlib/src/numerix.h trunk/matplotlib/src/path_converters.h Added Paths: ----------- trunk/matplotlib/src/agg_py_transforms.cpp trunk/matplotlib/src/path_cleanup.cpp trunk/matplotlib/src/path_cleanup.h Modified: trunk/matplotlib/lib/matplotlib/delaunay/VoronoiDiagramGenerator.cpp =================================================================== --- trunk/matplotlib/lib/matplotlib/delaunay/VoronoiDiagramGenerator.cpp 2009-02-02 16:19:33 UTC (rev 6864) +++ trunk/matplotlib/lib/matplotlib/delaunay/VoronoiDiagramGenerator.cpp 2009-02-02 16:29:37 UTC (rev 6865) @@ -12,9 +12,9 @@ * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. */ -/* - * This code was originally written by Stephan Fortune in C code. Shane O'Sullivan, - * have since modified it, encapsulating it in a C++ class and, fixing memory leaks and +/* + * This code was originally written by Stephan Fortune in C code. Shane O'Sullivan, + * have since modified it, encapsulating it in a C++ class and, fixing memory leaks and * adding accessors to the Voronoi Edges. * Permission to use, copy, modify, and distribute this software for any * purpose without fee is hereby granted, provided that this entire notice @@ -26,13 +26,17 @@ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. */ - + /* * Subsequently, Robert Kern modified it to yield Python objects. * Copyright 2005 Robert Kern <rob...@gm...> * See LICENSE.txt in the scipy source directory. */ +#include <Python.h> +#define NO_IMPORT_ARRAY +#include "numpy/arrayobject.h" + #include "VoronoiDiagramGenerator.h" VoronoiDiagramGenerator::VoronoiDiagramGenerator() @@ -74,9 +78,9 @@ nsites=numPoints; plot = 0; - triangulate = 0; + triangulate = 0; debug = 1; - sorted = 0; + sorted = 0; freeinit(&sfl, sizeof (Site)); sites = (struct Site *) myalloc(nsites*sizeof( *sites)); @@ -108,9 +112,9 @@ //printf("\n%f %f\n",xValues[i],yValues[i]); } - + qsort(sites, nsites, sizeof (*sites), scomp); - + siteidx = 0; geominit(); double temp = 0; @@ -130,9 +134,9 @@ borderMinY = minY; borderMaxX = maxX; borderMaxY = maxY; - - siteidx = 0; + siteidx = 0; + voronoi(triangulate); return true; @@ -187,25 +191,25 @@ struct Halfedge * VoronoiDiagramGenerator::ELgethash(int b) { struct Halfedge *he; - - if(b<0 || b>=ELhashsize) + + if(b<0 || b>=ELhashsize) return((struct Halfedge *) NULL); - he = ELhash[b]; - if (he == (struct Halfedge *) NULL || he->ELedge != (struct Edge *) DELETED ) + he = ELhash[b]; + if (he == (struct Halfedge *) NULL || he->ELedge != (struct Edge *) DELETED ) return (he); - + /* Hash table points to deleted half edge. Patch as necessary. */ ELhash[b] = (struct Halfedge *) NULL; - if ((he -> ELrefcnt -= 1) == 0) + if ((he -> ELrefcnt -= 1) == 0) makefree((Freenode*)he, &hfl); return ((struct Halfedge *) NULL); -} +} struct Halfedge * VoronoiDiagramGenerator::ELleftbnd(struct Point *p) { int i, bucket; struct Halfedge *he; - + /* Use hash table to get close to desired halfedge */ bucket = (int)((p->x - xmin)/deltax * ELhashsize); //use the hash function to find the place in the hash map that this HalfEdge should be @@ -214,12 +218,12 @@ he = ELgethash(bucket); if(he == (struct Halfedge *) NULL) //if the HE isn't found, search backwards and forwards in the hash map for the first non-null entry - { + { for(i=1; 1 ; i += 1) - { - if ((he=ELgethash(bucket-i)) != (struct Halfedge *) NULL) + { + if ((he=ELgethash(bucket-i)) != (struct Halfedge *) NULL) break; - if ((he=ELgethash(bucket+i)) != (struct Halfedge *) NULL) + if ((he=ELgethash(bucket+i)) != (struct Halfedge *) NULL) break; }; totalsearch += i; @@ -228,22 +232,22 @@ /* Now search linear list of halfedges for the correct one */ if (he==ELleftend || (he != ELrightend && right_of(he,p))) { - do + do { he = he -> ELright; } while (he!=ELrightend && right_of(he,p)); //keep going right on the list until either the end is reached, or you find the 1st edge which the point he = he -> ELleft; //isn't to the right of } else //if the point is to the left of the HalfEdge, then search left for the HE just to the left of the point - do + do { he = he -> ELleft; } while (he!=ELleftend && !right_of(he,p)); - + /* Update hash table and reference counts */ if(bucket > 0 && bucket <ELhashsize-1) - { - if(ELhash[bucket] != (struct Halfedge *) NULL) + { + if(ELhash[bucket] != (struct Halfedge *) NULL) { ELhash[bucket] -> ELrefcnt -= 1; } @@ -277,9 +281,9 @@ struct Site * VoronoiDiagramGenerator::leftreg(struct Halfedge *he) { - if(he -> ELedge == (struct Edge *)NULL) + if(he -> ELedge == (struct Edge *)NULL) return(bottomsite); - return( he -> ELpm == le ? + return( he -> ELpm == le ? he -> ELedge -> reg[le] : he -> ELedge -> reg[re]); } @@ -293,7 +297,7 @@ } void VoronoiDiagramGenerator::geominit() -{ +{ double sn; freeinit(&efl, sizeof(Edge)); @@ -309,17 +313,17 @@ struct Edge * VoronoiDiagramGenerator::bisect(struct Site *s1, struct Site *s2) { double dx,dy,adx,ady; - struct Edge *newedge; + struct Edge *newedge; newedge = (struct Edge *) getfree(&efl); - + newedge -> reg[0] = s1; //store the sites that this edge is bisecting newedge -> reg[1] = s2; - ref(s1); + ref(s1); ref(s2); newedge -> ep[0] = (struct Site *) NULL; //to begin with, there are no endpoints on the bisector - it goes to infinity newedge -> ep[1] = (struct Site *) NULL; - + dx = s2->coord.x - s1->coord.x; //get the difference in x dist between the sites dy = s2->coord.y - s1->coord.y; adx = dx>0 ? dx : -dx; //make sure that the difference in positive @@ -327,18 +331,18 @@ newedge -> c = (double)(s1->coord.x * dx + s1->coord.y * dy + (dx*dx + dy*dy)*0.5);//get the slope of the line if (adx>ady) - { + { newedge -> a = 1.0; newedge -> b = dy/dx; newedge -> c /= dx;//set formula of line, with x fixed to 1 } else - { + { newedge -> b = 1.0; newedge -> a = dx/dy; newedge -> c /= dy;//set formula of line, with y fixed to 1 }; - + newedge -> edgenbr = nedges; //printf("\nbisect(%d) ((%f,%f) and (%f,%f)",nedges,s1->coord.x,s1->coord.y,s2->coord.x,s2->coord.y); - + nedges += 1; return(newedge); } @@ -351,40 +355,40 @@ double d, xint, yint; int right_of_site; struct Site *v; - + e1 = el1 -> ELedge; e2 = el2 -> ELedge; - if(e1 == (struct Edge*)NULL || e2 == (struct Edge*)NULL) + if(e1 == (struct Edge*)NULL || e2 == (struct Edge*)NULL) return ((struct Site *) NULL); //if the two edges bisect the same parent, return null - if (e1->reg[1] == e2->reg[1]) + if (e1->reg[1] == e2->reg[1]) return ((struct Site *) NULL); - + d = e1->a * e2->b - e1->b * e2->a; - if (-1.0e-10<d && d<1.0e-10) + if (-1.0e-10<d && d<1.0e-10) return ((struct Site *) NULL); - + xint = (e1->c*e2->b - e2->c*e1->b)/d; yint = (e2->c*e1->a - e1->c*e2->a)/d; - + if( (e1->reg[1]->coord.y < e2->reg[1]->coord.y) || (e1->reg[1]->coord.y == e2->reg[1]->coord.y && e1->reg[1]->coord.x < e2->reg[1]->coord.x) ) - { - el = el1; + { + el = el1; e = e1; } else - { - el = el2; + { + el = el2; e = e2; }; - + right_of_site = xint >= e -> reg[1] -> coord.x; - if ((right_of_site && el -> ELpm == le) || (!right_of_site && el -> ELpm == re)) + if ((right_of_site && el -> ELpm == le) || (!right_of_site && el -> ELpm == re)) return ((struct Site *) NULL); - + //create a new site at the point of intersection - this is a new vector event waiting to happen v = (struct Site *) getfree(&sfl); v -> refcnt = 0; @@ -400,22 +404,22 @@ struct Site *topsite; int right_of_site, above, fast; double dxp, dyp, dxs, t1, t2, t3, yl; - + e = el -> ELedge; topsite = e -> reg[1]; right_of_site = p -> x > topsite -> coord.x; if(right_of_site && el -> ELpm == le) return(1); if(!right_of_site && el -> ELpm == re) return (0); - + if (e->a == 1.0) { dyp = p->y - topsite->coord.y; dxp = p->x - topsite->coord.x; fast = 0; if ((!right_of_site & (e->b<0.0)) | (right_of_site & (e->b>=0.0)) ) - { above = dyp>= e->b*dxp; + { above = dyp>= e->b*dxp; fast = above; } - else + else { above = p->x + p->y*e->b > e-> c; if(e->b<0.0) above = !above; if (!above) fast = 1; @@ -442,7 +446,7 @@ { e -> ep[lr] = s; ref(s); - if(e -> ep[re-lr]== (struct Site *) NULL) + if(e -> ep[re-lr]== (struct Site *) NULL) return; clip_line(e); @@ -473,7 +477,7 @@ void VoronoiDiagramGenerator::deref(struct Site *v) { v -> refcnt -= 1; - if (v -> refcnt == 0 ) + if (v -> refcnt == 0 ) makefree((Freenode*)v, &sfl); } @@ -486,7 +490,7 @@ void VoronoiDiagramGenerator::PQinsert(struct Halfedge *he,struct Site * v, double offset) { struct Halfedge *last, *next; - + he -> vertex = v; ref(v); he -> ystar = (double)(v -> coord.y + offset); @@ -494,23 +498,23 @@ while ((next = last -> PQnext) != (struct Halfedge *) NULL && (he -> ystar > next -> ystar || (he -> ystar == next -> ystar && v -> coord.x > next->vertex->coord.x))) - { + { last = next; }; - he -> PQnext = last -> PQnext; + he -> PQnext = last -> PQnext; last -> PQnext = he; PQcount += 1; } -//remove the HalfEdge from the list of vertices +//remove the HalfEdge from the list of vertices void VoronoiDiagramGenerator::PQdelete(struct Halfedge *he) { struct Halfedge *last; - + if(he -> vertex != (struct Site *) NULL) - { + { last = &PQhash[PQbucket(he)]; - while (last -> PQnext != he) + while (last -> PQnext != he) last = last -> PQnext; last -> PQnext = he -> PQnext; @@ -523,7 +527,7 @@ int VoronoiDiagramGenerator::PQbucket(struct Halfedge *he) { int bucket; - + bucket = (int)((he->ystar - ymin)/deltay * PQhashsize); if (bucket<0) bucket = 0; if (bucket>=PQhashsize) bucket = PQhashsize-1 ; @@ -542,7 +546,7 @@ struct Point VoronoiDiagramGenerator::PQ_min() { struct Point answer; - + while(PQhash[PQmin].PQnext == (struct Halfedge *)NULL) {PQmin += 1;}; answer.x = PQhash[PQmin].PQnext -> vertex -> coord.x; answer.y = PQhash[PQmin].PQnext -> ystar; @@ -552,7 +556,7 @@ struct Halfedge * VoronoiDiagramGenerator::PQextractmin() { struct Halfedge *curr; - + curr = PQhash[PQmin].PQnext; PQhash[PQmin].PQnext = curr -> PQnext; PQcount -= 1; @@ -562,8 +566,8 @@ bool VoronoiDiagramGenerator::PQinitialize() { - int i; - + int i; + PQcount = 0; PQmin = 0; PQhashsize = 4 * sqrt_nsites; @@ -586,23 +590,23 @@ char * VoronoiDiagramGenerator::getfree(struct Freelist *fl) { - int i; + int i; struct Freenode *t; if(fl->head == (struct Freenode *) NULL) - { + { t = (struct Freenode *) myalloc(sqrt_nsites * fl->nodesize); if(t == 0) return 0; - + currentMemoryBlock->next = new FreeNodeArrayList; currentMemoryBlock = currentMemoryBlock->next; currentMemoryBlock->memory = t; currentMemoryBlock->next = 0; - for(i=0; i<sqrt_nsites; i+=1) - makefree((struct Freenode *)((char *)t+i*fl->nodesize), fl); + for(i=0; i<sqrt_nsites; i+=1) + makefree((struct Freenode *)((char *)t+i*fl->nodesize), fl); }; t = fl -> head; fl -> head = (fl -> head) -> nextfree; @@ -721,7 +725,7 @@ char * VoronoiDiagramGenerator::myalloc(unsigned n) { - char *t=0; + char *t=0; t=(char*)malloc(n); total_alloc += n; return(t); @@ -732,7 +736,7 @@ /* #include <plot.h> */ void VoronoiDiagramGenerator::openpl(){} void VoronoiDiagramGenerator::line(double x1, double y1, double x2, double y2) -{ +{ pushGraphEdge(x1,y1,x2,y2); } @@ -743,20 +747,20 @@ void VoronoiDiagramGenerator::out_bisector(struct Edge *e) { - + } void VoronoiDiagramGenerator::out_ep(struct Edge *e) { - - + + } void VoronoiDiagramGenerator::out_vertex(struct Site *v) { - + } @@ -764,13 +768,13 @@ { if(!triangulate & plot & !debug) circle (s->coord.x, s->coord.y, cradius); - + } void VoronoiDiagramGenerator::out_triple(struct Site *s1, struct Site *s2,struct Site * s3) { - + } @@ -778,7 +782,7 @@ void VoronoiDiagramGenerator::plotinit() { // double dx,dy,d; -// +// // dy = ymax - ymin; // dx = xmax - xmin; // d = (double)(( dx > dy ? dx : dy) * 1.1); @@ -804,7 +808,7 @@ // y1 = e->reg[0]->coord.y; // y2 = e->reg[1]->coord.y; // -// //if the distance between the two points this line was created from is less than +// //if the distance between the two points this line was created from is less than // //the square root of 2, then ignore it // if(sqrt(((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1))) < minDistanceBetweenSites) // { @@ -816,16 +820,16 @@ // pymax = borderMaxY; // // if(e -> a == 1.0 && e ->b >= 0.0) -// { +// { // s1 = e -> ep[1]; // s2 = e -> ep[0]; // } -// else +// else // { // s1 = e -> ep[0]; // s2 = e -> ep[1]; // }; -// +// // if(e -> a == 1.0) // { // y1 = pymin; @@ -833,7 +837,7 @@ // { // y1 = s1->coord.y; // } -// if(y1>pymax) +// if(y1>pymax) // { // // printf("\nClipped (1) y1 = %f to %f",y1,pymax); // y1 = pymax; @@ -841,17 +845,17 @@ // } // x1 = e -> c - e -> b * y1; // y2 = pymax; -// if (s2!=(struct Site *)NULL && s2->coord.y < pymax) +// if (s2!=(struct Site *)NULL && s2->coord.y < pymax) // y2 = s2->coord.y; // -// if(y2<pymin) +// if(y2<pymin) // { // //printf("\nClipped (2) y2 = %f to %f",y2,pymin); // y2 = pymin; // //return; // } // x2 = (e->c) - (e->b) * y2; -// if (((x1> pxmax) & (x2>pxmax)) | ((x1<pxmin)&(x2<pxmin))) +// if (((x1> pxmax) & (x2>pxmax)) | ((x1<pxmin)&(x2<pxmin))) // { // //printf("\nClipLine jumping out(3), x1 = %f, pxmin = %f, pxmax = %f",x1,pxmin,pxmax); // return; @@ -868,9 +872,9 @@ // else // { // x1 = pxmin; -// if (s1!=(struct Site *)NULL && s1->coord.x > pxmin) +// if (s1!=(struct Site *)NULL && s1->coord.x > pxmin) // x1 = s1->coord.x; -// if(x1>pxmax) +// if(x1>pxmax) // { // //printf("\nClipped (3) x1 = %f to %f",x1,pxmin); // //return; @@ -878,16 +882,16 @@ // } // y1 = e -> c - e -> a * x1; // x2 = pxmax; -// if (s2!=(struct Site *)NULL && s2->coord.x < pxmax) +// if (s2!=(struct Site *)NULL && s2->coord.x < pxmax) // x2 = s2->coord.x; -// if(x2<pxmin) +// if(x2<pxmin) // { // //printf("\nClipped (4) x2 = %f to %f",x2,pxmin); // //return; // x2 = pxmin; // } // y2 = e -> c - e -> a * x2; -// if (((y1> pymax) & (y2>pymax)) | ((y1<pymin)&(y2<pymin))) +// if (((y1> pymax) & (y2>pymax)) | ((y1<pymin)&(y2<pymin))) // { // //printf("\nClipLine jumping out(6), y1 = %f, pymin = %f, pymax = %f",y2,pymin,pymax); // return; @@ -901,7 +905,7 @@ // if(y2<pymin) // { y2 = pymin; x2 = (e -> c - y2)/e -> a;}; // }; -// +// // //printf("\nPushing line (%f,%f,%f,%f)",x1,y1,x2,y2); // line(x1,y1,x2,y2); } @@ -920,7 +924,7 @@ int pm; struct Halfedge *lbnd, *rbnd, *llbnd, *rrbnd, *bisector; struct Edge *e; - + PQinitialize(); bottomsite = nextone(); out_site(bottomsite); @@ -928,16 +932,16 @@ if(!retval) return false; - + newsite = nextone(); while(1) { - if(!PQempty()) + if(!PQempty()) newintstar = PQ_min(); - + //if the lowest site has a smaller y value than the lowest vector intersection, process the site - //otherwise process the vector intersection + //otherwise process the vector intersection if (newsite != (struct Site *)NULL && (PQempty() || newsite -> coord.y < newintstar.y || (newsite->coord.y == newintstar.y && newsite->coord.x < newintstar.x))) @@ -946,31 +950,31 @@ lbnd = ELleftbnd(&(newsite->coord)); //get the first HalfEdge to the LEFT of the new site rbnd = ELright(lbnd); //get the first HalfEdge to the RIGHT of the new site bot = rightreg(lbnd); //if this halfedge has no edge, , bot = bottom site (whatever that is) - e = bisect(bot, newsite); //create a new edge that bisects - bisector = HEcreate(e, le); //create a new HalfEdge, setting its ELpm field to 0 - ELinsert(lbnd, bisector); //insert this new bisector edge between the left and right vectors in a linked list + e = bisect(bot, newsite); //create a new edge that bisects + bisector = HEcreate(e, le); //create a new HalfEdge, setting its ELpm field to 0 + ELinsert(lbnd, bisector); //insert this new bisector edge between the left and right vectors in a linked list if ((p = intersect(lbnd, bisector)) != (struct Site *) NULL) //if the new bisector intersects with the left edge, remove the left edge's vertex, and put in the new one - { + { PQdelete(lbnd); PQinsert(lbnd, p, dist(p,newsite)); }; - lbnd = bisector; + lbnd = bisector; bisector = HEcreate(e, re); //create a new HalfEdge, setting its ELpm field to 1 ELinsert(lbnd, bisector); //insert the new HE to the right of the original bisector earlier in the IF stmt if ((p = intersect(bisector, rbnd)) != (struct Site *) NULL) //if this new bisector intersects with the - { + { PQinsert(bisector, p, dist(p,newsite)); //push the HE into the ordered linked list of vertices }; - newsite = nextone(); + newsite = nextone(); } - else if (!PQempty()) /* intersection is smallest - this is a vector event */ - { - lbnd = PQextractmin(); //pop the HalfEdge with the lowest vector off the ordered list of vectors + else if (!PQempty()) /* intersection is smallest - this is a vector event */ + { + lbnd = PQextractmin(); //pop the HalfEdge with the lowest vector off the ordered list of vectors llbnd = ELleft(lbnd); //get the HalfEdge to the left of the above HE rbnd = ELright(lbnd); //get the HalfEdge to the right of the above HE - rrbnd = ELright(rbnd); //get the HalfEdge to the right of the HE to the right of the lowest HE + rrbnd = ELright(rbnd); //get the HalfEdge to the right of the HE to the right of the lowest HE bot = leftreg(lbnd); //get the Site to the left of the left HE which it bisects top = rightreg(rbnd); //get the Site to the right of the right HE which it bisects @@ -980,16 +984,16 @@ makevertex(v); //set the vertex number - couldn't do this earlier since we didn't know when it would be processed endpoint(lbnd->ELedge,lbnd->ELpm,v); //set the endpoint of the left HalfEdge to be this vector endpoint(rbnd->ELedge,rbnd->ELpm,v); //set the endpoint of the right HalfEdge to be this vector - ELdelete(lbnd); //mark the lowest HE for deletion - can't delete yet because there might be pointers to it in Hash Map + ELdelete(lbnd); //mark the lowest HE for deletion - can't delete yet because there might be pointers to it in Hash Map PQdelete(rbnd); //remove all vertex events to do with the right HE - ELdelete(rbnd); //mark the right HE for deletion - can't delete yet because there might be pointers to it in Hash Map + ELdelete(rbnd); //mark the right HE for deletion - can't delete yet because there might be pointers to it in Hash Map pm = le; //set the pm variable to zero - + if (bot->coord.y > top->coord.y) //if the site to the left of the event is higher than the Site { //to the right of it, then swap them and set the 'pm' variable to 1 - temp = bot; - bot = top; - top = temp; + temp = bot; + bot = top; + top = temp; pm = re; } e = bisect(bot, top); //create an Edge (or line) that is between the two Sites. This creates @@ -1001,27 +1005,27 @@ //Site, then this endpoint is put in position 0; otherwise in pos 1 deref(v); //delete the vector 'v' - //if left HE and the new bisector don't intersect, then delete the left HE, and reinsert it + //if left HE and the new bisector don't intersect, then delete the left HE, and reinsert it if((p = intersect(llbnd, bisector)) != (struct Site *) NULL) - { + { PQdelete(llbnd); PQinsert(llbnd, p, dist(p,bot)); }; - //if right HE and the new bisector don't intersect, then reinsert it + //if right HE and the new bisector don't intersect, then reinsert it if ((p = intersect(bisector, rrbnd)) != (struct Site *) NULL) - { + { PQinsert(bisector, p, dist(p,bot)); }; } else break; }; - + for(lbnd=ELright(ELleftend); lbnd != ELrightend; lbnd=ELright(lbnd)) - { + { e = lbnd -> ELedge; clip_line(e); @@ -1031,7 +1035,7 @@ cleanup(); return true; - + } @@ -1050,16 +1054,16 @@ { struct Site *s; if(siteidx < nsites) - { + { s = &sites[siteidx]; siteidx += 1; return(s); } - else + else return( (struct Site *)NULL); } -bool VoronoiDiagramGenerator::getNextDelaunay(int& ep0, double& ep0x, double& ep0y, +bool VoronoiDiagramGenerator::getNextDelaunay(int& ep0, double& ep0x, double& ep0y, int& ep1, double& ep1x, double& ep1y, int& reg0, int& reg1) { @@ -1076,7 +1080,7 @@ reg1 = iterEdgeList->reg1nbr; iterEdgeList = iterEdgeList->next; - + return true; } Modified: trunk/matplotlib/setupext.py =================================================================== --- trunk/matplotlib/setupext.py 2009-02-02 16:19:33 UTC (rev 6864) +++ trunk/matplotlib/setupext.py 2009-02-02 16:29:37 UTC (rev 6865) @@ -1079,7 +1079,8 @@ deps.extend(glob.glob('CXX/*.cxx')) deps.extend(glob.glob('CXX/*.c')) - module = Extension('matplotlib.ft2font', deps) + module = Extension('matplotlib.ft2font', deps, + define_macros=[('PY_ARRAYAUNIQUE_SYMBOL', 'MPL_ARRAY_API')]) add_ft2font_flags(module) ext_modules.append(module) BUILT_FT2FONT = True @@ -1100,12 +1101,13 @@ def build_gtkagg(ext_modules, packages): global BUILT_GTKAGG if BUILT_GTKAGG: return # only build it if you you haven't already - deps = ['src/_gtkagg.cpp', 'src/mplutils.cpp']#, 'src/_transforms.cpp'] + deps = ['src/agg_py_transforms.cpp', 'src/_gtkagg.cpp', 'src/mplutils.cpp'] deps.extend(glob.glob('CXX/*.cxx')) deps.extend(glob.glob('CXX/*.c')) module = Extension('matplotlib.backends._gtkagg', deps, + define_macros=[('PY_ARRAY_UNIQUE_SYMBOL', 'MPL_ARRAY_API')] ) # add agg flags before pygtk because agg only supports freetype1 @@ -1164,6 +1166,7 @@ module = Extension('matplotlib.backends._macosx', ['src/_macosx.m'], extra_link_args = ['-framework','Cocoa'], + define_macros=[('PY_ARRAY_UNIQUE_SYMBOL', 'MPL_ARRAY_API')] ) add_numpy_flags(module) ext_modules.append(module) @@ -1182,6 +1185,7 @@ 'matplotlib._png', deps, include_dirs=numpy_inc_dirs, + define_macros=[('PY_ARRAY_UNIQUE_SYMBOL', 'MPL_ARRAY_API')] ) add_png_flags(module) @@ -1194,7 +1198,6 @@ global BUILT_AGG if BUILT_AGG: return # only build it if you you haven't already - agg = ( 'agg_trans_affine.cpp', 'agg_bezier_arc.cpp', @@ -1204,22 +1207,20 @@ 'agg_image_filters.cpp', ) - deps = ['%s/src/%s'%(AGG_VERSION, name) for name in agg] - deps.extend(('src/_image.cpp', 'src/ft2font.cpp', 'src/mplutils.cpp')) + deps.extend(['src/mplutils.cpp', 'src/agg_py_transforms.cpp']) deps.extend(glob.glob('CXX/*.cxx')) deps.extend(glob.glob('CXX/*.c')) - temp_copy('src/_backend_agg.cpp', 'src/backend_agg.cpp') deps.append('src/backend_agg.cpp') module = Extension( 'matplotlib.backends._backend_agg', deps, include_dirs=numpy_inc_dirs, + define_macros=[('PY_ARRAY_UNIQUE_SYMBOL', 'MPL_ARRAY_API')] ) add_numpy_flags(module) - add_agg_flags(module) add_ft2font_flags(module) ext_modules.append(module) @@ -1242,11 +1243,14 @@ deps.extend(glob.glob('CXX/*.c')) temp_copy('src/_path.cpp', 'src/path.cpp') - deps.extend(['src/path.cpp']) + deps.extend(['src/agg_py_transforms.cpp', + 'src/path_cleanup.cpp', + 'src/path.cpp']) module = Extension( 'matplotlib._path', deps, include_dirs=numpy_inc_dirs, + define_macros=[('PY_ARRAY_UNIQUE_SYMBOL', 'MPL_ARRAY_API')] ) add_numpy_flags(module) @@ -1275,6 +1279,7 @@ 'matplotlib._image', deps, include_dirs=numpy_inc_dirs, + define_macros=[('PY_ARRAY_UNIQUE_SYMBOL', 'MPL_ARRAY_API')] ) add_numpy_flags(module) @@ -1294,7 +1299,9 @@ "delaunay_utils.cpp", "natneighbors.cpp"] sourcefiles = [os.path.join('lib/matplotlib/delaunay',s) for s in sourcefiles] delaunay = Extension('matplotlib._delaunay',sourcefiles, - include_dirs=numpy_inc_dirs) + include_dirs=numpy_inc_dirs, + define_macros=[('PY_ARRAY_UNIQUE_SYMBOL', 'MPL_ARRAY_API')] + ) add_numpy_flags(delaunay) add_base_flags(delaunay) ext_modules.append(delaunay) @@ -1310,6 +1317,7 @@ 'matplotlib._cntr', [ 'src/cntr.c'], include_dirs=numpy_inc_dirs, + define_macros=[('PY_ARRAY_UNIQUE_SYMBOL', 'MPL_ARRAY_API')] ) add_numpy_flags(module) add_base_flags(module) @@ -1325,6 +1333,7 @@ 'matplotlib.nxutils', [ 'src/nxutils.c'], include_dirs=numpy_inc_dirs, + define_macros=[('PY_ARRAY_UNIQUE_SYMBOL', 'MPL_ARRAY_API')] ) add_numpy_flags(module) add_base_flags(module) @@ -1343,6 +1352,7 @@ ['src/backend_gdk.c'], libraries = [], include_dirs=numpy_inc_dirs, + define_macros=[('PY_ARRAY_UNIQUE_SYMBOL', 'MPL_ARRAY_API')] ) add_numpy_flags(module) Modified: trunk/matplotlib/src/_backend_agg.cpp =================================================================== --- trunk/matplotlib/src/_backend_agg.cpp 2009-02-02 16:19:33 UTC (rev 6864) +++ trunk/matplotlib/src/_backend_agg.cpp 2009-02-02 16:29:37 UTC (rev 6865) @@ -37,7 +37,6 @@ #include "swig_runtime.h" #include "MPL_isnan.h" -#define PY_ARRAY_TYPES_PREFIX NumPy #include "numpy/arrayobject.h" #include "agg_py_transforms.h" @@ -253,7 +252,7 @@ Py::Tuple path_and_transform = method.apply(Py::Tuple()); if (path_and_transform[0].ptr() != Py_None) { clippath = path_and_transform[0]; - clippath_trans = py_to_agg_transformation_matrix(path_and_transform[1]); + clippath_trans = py_to_agg_transformation_matrix(path_and_transform[1].ptr()); } } @@ -471,9 +470,9 @@ Py::Object gc_obj = args[0]; Py::Object marker_path_obj = args[1]; - agg::trans_affine marker_trans = py_to_agg_transformation_matrix(args[2]); + agg::trans_affine marker_trans = py_to_agg_transformation_matrix(args[2].ptr()); Py::Object path_obj = args[3]; - agg::trans_affine trans = py_to_agg_transformation_matrix(args[4]); + agg::trans_affine trans = py_to_agg_transformation_matrix(args[4].ptr()); Py::Object face_obj; if (args.size() == 6) face_obj = args[5]; @@ -748,7 +747,7 @@ rendererBase.reset_clipping(true); if (args.size() == 6) { clippath = args[4]; - clippath_trans = py_to_agg_transformation_matrix(args[5], false); + clippath_trans = py_to_agg_transformation_matrix(args[5].ptr(), false); has_clippath = render_clippath(clippath, clippath_trans); } @@ -963,7 +962,7 @@ Py::Object gc_obj = args[0]; Py::Object path_obj = args[1]; - agg::trans_affine trans = py_to_agg_transformation_matrix(args[2]); + agg::trans_affine trans = py_to_agg_transformation_matrix(args[2].ptr()); Py::Object face_obj; if (args.size() == 4) face_obj = args[3]; @@ -1071,7 +1070,7 @@ transforms.reserve(Ntransforms); for (i = 0; i < Ntransforms; ++i) { agg::trans_affine trans = py_to_agg_transformation_matrix - (transforms_obj[i], false); + (transforms_obj[i].ptr(), false); trans *= master_transform; transforms.push_back(trans); @@ -1212,14 +1211,14 @@ args.verify_length(14); //segments, trans, clipbox, colors, linewidths, antialiaseds - agg::trans_affine master_transform = py_to_agg_transformation_matrix(args[0]); + agg::trans_affine master_transform = py_to_agg_transformation_matrix(args[0].ptr()); Py::Object cliprect = args[1]; Py::Object clippath = args[2]; - agg::trans_affine clippath_trans = py_to_agg_transformation_matrix(args[3], false); + agg::trans_affine clippath_trans = py_to_agg_transformation_matrix(args[3].ptr(), false); Py::SeqBase<Py::Object> paths = args[4]; Py::SeqBase<Py::Object> transforms_obj = args[5]; Py::Object offsets_obj = args[6]; - agg::trans_affine offset_trans = py_to_agg_transformation_matrix(args[7]); + agg::trans_affine offset_trans = py_to_agg_transformation_matrix(args[7].ptr()); Py::Object facecolors_obj = args[8]; Py::Object edgecolors_obj = args[9]; Py::SeqBase<Py::Float> linewidths = args[10]; @@ -1328,15 +1327,15 @@ //segments, trans, clipbox, colors, linewidths, antialiaseds - agg::trans_affine master_transform = py_to_agg_transformation_matrix(args[0]); + agg::trans_affine master_transform = py_to_agg_transformation_matrix(args[0].ptr()); Py::Object cliprect = args[1]; Py::Object clippath = args[2]; - agg::trans_affine clippath_trans = py_to_agg_transformation_matrix(args[3], false); + agg::trans_affine clippath_trans = py_to_agg_transformation_matrix(args[3].ptr(), false); size_t mesh_width = Py::Int(args[4]); size_t mesh_height = Py::Int(args[5]); PyObject* coordinates = args[6].ptr(); Py::Object offsets_obj = args[7]; - agg::trans_affine offset_trans = py_to_agg_transformation_matrix(args[8]); + agg::trans_affine offset_trans = py_to_agg_transformation_matrix(args[8].ptr()); Py::Object facecolors_obj = args[9]; bool antialiased = (bool)Py::Int(args[10]); bool showedges = (bool)Py::Int(args[11]); Modified: trunk/matplotlib/src/_backend_gdk.c =================================================================== --- trunk/matplotlib/src/_backend_gdk.c 2009-02-02 16:19:33 UTC (rev 6864) +++ trunk/matplotlib/src/_backend_gdk.c 2009-02-02 16:29:37 UTC (rev 6865) @@ -3,7 +3,6 @@ */ #include "Python.h" -#define PY_ARRAY_TYPES_PREFIX NumPy #include "numpy/arrayobject.h" #include <pygtk/pygtk.h> Modified: trunk/matplotlib/src/_gtkagg.cpp =================================================================== --- trunk/matplotlib/src/_gtkagg.cpp 2009-02-02 16:19:33 UTC (rev 6864) +++ trunk/matplotlib/src/_gtkagg.cpp 2009-02-02 16:29:37 UTC (rev 6865) @@ -10,9 +10,8 @@ #include <fstream> #include "agg_basics.h" -#include "_backend_agg.h" -#define PY_ARRAY_TYPES_PREFIX NumPy #include "numpy/arrayobject.h" +#include "_backend_agg.h" #include "agg_py_transforms.h" // the extension module Modified: trunk/matplotlib/src/_image.cpp =================================================================== --- trunk/matplotlib/src/_image.cpp 2009-02-02 16:19:33 UTC (rev 6864) +++ trunk/matplotlib/src/_image.cpp 2009-02-02 16:29:37 UTC (rev 6865) @@ -11,7 +11,6 @@ #include <cmath> #include <cstdio> -#define PY_ARRAY_TYPES_PREFIX NumPy #include "numpy/arrayobject.h" #include "agg_color_rgba.h" @@ -98,18 +97,7 @@ "\n" "Flip the output image upside down" ; -Py::Object -Image::flipud_out(const Py::Tuple& args) { - _VERBOSE("Image::flipud_out"); - args.verify_length(0); - int stride = rbufOut->stride(); - //std::cout << "flip before: " << rbufOut->stride() << std::endl; - rbufOut->attach(bufferOut, colsOut, rowsOut, -stride); - //std::cout << "flip after: " << rbufOut->stride() << std::endl; - return Py::Object(); -} - char Image::flipud_in__doc__[] = "flipud()\n" "\n" @@ -1756,8 +1744,6 @@ d["ASPECT_FREE"] = Py::Int(Image::ASPECT_FREE); d["ASPECT_PRESERVE"] = Py::Int(Image::ASPECT_PRESERVE); - - } Modified: trunk/matplotlib/src/_image.h =================================================================== --- trunk/matplotlib/src/_image.h 2009-02-02 16:19:33 UTC (rev 6864) +++ trunk/matplotlib/src/_image.h 2009-02-02 16:29:37 UTC (rev 6865) @@ -39,7 +39,15 @@ Py::Object set_interpolation(const Py::Tuple& args); Py::Object set_aspect(const Py::Tuple& args); Py::Object set_bg(const Py::Tuple& args); - Py::Object flipud_out(const Py::Tuple& args); + inline Py::Object flipud_out(const Py::Tuple& args) { + args.verify_length(0); + int stride = rbufOut->stride(); + //std::cout << "flip before: " << rbufOut->stride() << std::endl; + rbufOut->attach(bufferOut, colsOut, rowsOut, -stride); + //std::cout << "flip after: " << rbufOut->stride() << std::endl; + return Py::Object(); + } + Py::Object flipud_in(const Py::Tuple& args); Py::Object set_resample(const Py::Tuple& args); Py::Object get_resample(const Py::Tuple& args); Modified: trunk/matplotlib/src/_path.cpp =================================================================== --- trunk/matplotlib/src/_path.cpp 2009-02-02 16:19:33 UTC (rev 6864) +++ trunk/matplotlib/src/_path.cpp 2009-02-02 16:29:37 UTC (rev 6865) @@ -56,7 +56,10 @@ "convert_path_to_polygons(path, trans, width, height)"); add_varargs_method("cleanup_path", &_path_module::cleanup_path, "cleanup_path(path, trans, remove_nans, clip, quantize, simplify, curves)"); - + /* TEST CODE -- REMOVE LATER */ + add_varargs_method("cleanup_path_test", &_path_module::cleanup_path_test, + "TEST"); + /* **************************************** */ initialize("Helper functions for paths"); } @@ -76,6 +79,8 @@ Py::Object path_intersects_path(const Py::Tuple& args); Py::Object convert_path_to_polygons(const Py::Tuple& args); Py::Object cleanup_path(const Py::Tuple& args); + /* TEST CODE -- REMOVE LATER */ + Py::Object cleanup_path_test(const Py::Tuple& args); }; // @@ -244,7 +249,7 @@ double x = Py::Float(args[0]); double y = Py::Float(args[1]); PathIterator path(args[2]); - agg::trans_affine trans = py_to_agg_transformation_matrix(args[3], false); + agg::trans_affine trans = py_to_agg_transformation_matrix(args[3].ptr(), false); if (::point_in_path(x, y, path, trans)) return Py::Int(1); @@ -259,7 +264,7 @@ double y = Py::Float(args[1]); double r = Py::Float(args[2]); PathIterator path(args[3]); - agg::trans_affine trans = py_to_agg_transformation_matrix(args[4]); + agg::trans_affine trans = py_to_agg_transformation_matrix(args[4].ptr()); if (::point_on_path(x, y, r, path, trans)) return Py::Int(1); @@ -305,7 +310,7 @@ args.verify_length(2); PathIterator path(args[0]); - agg::trans_affine trans = py_to_agg_transformation_matrix(args[1], false); + agg::trans_affine trans = py_to_agg_transformation_matrix(args[1].ptr(), false); npy_intp extent_dims[] = { 2, 2, 0 }; double* extents_data = NULL; @@ -347,7 +352,7 @@ double x0, y0, x1, y1; PathIterator path(args[0]); - agg::trans_affine trans = py_to_agg_transformation_matrix(args[1], false); + agg::trans_affine trans = py_to_agg_transformation_matrix(args[1].ptr(), false); if (!py_convert_bbox(args[2].ptr(), x0, y0, x1, y1)) { throw Py::ValueError("Must pass Bbox object as arg 3 of update_path_extents"); @@ -465,11 +470,11 @@ args.verify_length(5); //segments, trans, clipbox, colors, linewidths, antialiaseds - agg::trans_affine master_transform = py_to_agg_transformation_matrix(args[0]); + agg::trans_affine master_transform = py_to_agg_transformation_matrix(args[0].ptr()); Py::SeqBase<Py::Object> paths = args[1]; Py::SeqBase<Py::Object> transforms_obj = args[2]; Py::Object offsets_obj = args[3]; - agg::trans_affine offset_trans = py_to_agg_transformation_matrix(args[4], false); + agg::trans_affine offset_trans = py_to_agg_transformation_matrix(args[4].ptr(), false); PyArrayObject* offsets = NULL; double x0, y0, x1, y1, xm, ym; @@ -497,7 +502,7 @@ for (i = 0; i < Ntransforms; ++i) { agg::trans_affine trans = py_to_agg_transformation_matrix - (transforms_obj[i], false); + (transforms_obj[i].ptr(), false); trans *= master_transform; transforms.push_back(trans); } @@ -558,11 +563,11 @@ double x = Py::Float(args[0]); double y = Py::Float(args[1]); double radius = Py::Float(args[2]); - agg::trans_affine master_transform = py_to_agg_transformation_matrix(args[3]); + agg::trans_affine master_transform = py_to_agg_transformation_matrix(args[3].ptr()); Py::SeqBase<Py::Object> paths = args[4]; Py::SeqBase<Py::Object> transforms_obj = args[5]; Py::SeqBase<Py::Object> offsets_obj = args[6]; - agg::trans_affine offset_trans = py_to_agg_transformation_matrix(args[7]); + agg::trans_affine offset_trans = py_to_agg_transformation_matrix(args[7].ptr()); bool filled = Py::Int(args[8]); PyArrayObject* offsets = (PyArrayObject*)PyArray_FromObject(offsets_obj.ptr(), PyArray_DOUBLE, 0, 2); @@ -586,7 +591,7 @@ for (i = 0; i < Ntransforms; ++i) { agg::trans_affine trans = py_to_agg_transformation_matrix - (transforms_obj[i], false); + (transforms_obj[i].ptr(), false); trans *= master_transform; transforms.push_back(trans); } @@ -658,9 +663,9 @@ args.verify_length(4); PathIterator a(args[0]); - agg::trans_affine atrans = py_to_agg_transformation_matrix(args[1], false); + agg::trans_affine atrans = py_to_agg_transformation_matrix(args[1].ptr(), false); PathIterator b(args[2]); - agg::trans_affine btrans = py_to_agg_transformation_matrix(args[3], false); + agg::trans_affine btrans = py_to_agg_transformation_matrix(args[3].ptr(), false); return Py::Int(::path_in_path(a, atrans, b, btrans)); } @@ -1153,7 +1158,7 @@ args.verify_length(4); PathIterator path(args[0]); - agg::trans_affine trans = py_to_agg_transformation_matrix(args[1], false); + agg::trans_affine trans = py_to_agg_transformation_matrix(args[1].ptr(), false); double width = Py::Float(args[2]); double height = Py::Float(args[3]); @@ -1256,7 +1261,7 @@ args.verify_length(7); PathIterator path(args[0]); - agg::trans_affine trans = py_to_agg_transformation_matrix(args[1], false); + agg::trans_affine trans = py_to_agg_transformation_matrix(args[1].ptr(), false); bool remove_nans = args[2].isTrue(); Py::Object clip_obj = args[3]; @@ -1349,6 +1354,39 @@ return result; } +/************************************************************/ +/* TEST CODE */ +extern "C" { + void* get_path_iterator( + PyObject* path, PyObject* trans, int remove_nans, int do_clip, + double rect[4], e_quantize_mode quantize_mode, int do_simplify); + + unsigned get_vertex(void* pipeline, double* x, double* y); + + void free_path_iterator(void* pipeline); +} + +Py::Object _path_module::cleanup_path_test(const Py::Tuple& args) +{ + args.verify_length(2); + + double rect[] = { 0.0, 0.0, 640.0, 480.0 }; + + void* iterator = get_path_iterator(args[0].ptr(), args[1].ptr(), 1, 1, rect, QUANTIZE_AUTO, 1); + + unsigned cmd; + double x, y; + while ((cmd = get_vertex(iterator, &x, &y)) != 0 /* STOP */) { + printf("%f %f %d\n", x, y, cmd); + } + + free_path_iterator(iterator); + + return Py::None(); +} +/* END OF TEST CODE */ +/************************************************************/ + extern "C" DL_EXPORT(void) init_path(void) Modified: trunk/matplotlib/src/agg_py_path_iterator.h =================================================================== --- trunk/matplotlib/src/agg_py_path_iterator.h 2009-02-02 16:19:33 UTC (rev 6864) +++ trunk/matplotlib/src/agg_py_path_iterator.h 2009-02-02 16:29:37 UTC (rev 6865) @@ -2,7 +2,6 @@ #define __AGG_PY_PATH_ITERATOR_H__ #include "CXX/Objects.hxx" -#define PY_ARRAY_TYPES_PREFIX NumPy #include "numpy/arrayobject.h" #include "agg_path_storage.h" @@ -39,7 +38,7 @@ public: /* path_obj is an instance of the class Path as defined in path.py */ - PathIterator(const Py::Object& path_obj) : + inline PathIterator(const Py::Object& path_obj) : m_vertices(NULL), m_codes(NULL), m_iterator(0), m_should_simplify(false), m_simplify_threshold(1.0 / 9.0) { Added: trunk/matplotlib/src/agg_py_transforms.cpp =================================================================== --- trunk/matplotlib/src/agg_py_transforms.cpp (rev 0) +++ trunk/matplotlib/src/agg_py_transforms.cpp 2009-02-02 16:29:37 UTC (rev 6865) @@ -0,0 +1,98 @@ +#include <Python.h> + +#define NO_IMPORT_ARRAY +#include "numpy/arrayobject.h" + +#include "CXX/Objects.hxx" +#include "agg_trans_affine.h" + +/** A helper function to convert from a Numpy affine transformation matrix + * to an agg::trans_affine. + */ +agg::trans_affine +py_to_agg_transformation_matrix(PyObject* obj, bool errors = true) +{ + PyArrayObject* matrix = NULL; + + try + { + if (obj == Py_None) + throw std::exception(); + matrix = (PyArrayObject*) PyArray_FromObject(obj, PyArray_DOUBLE, 2, 2); + if (!matrix) + throw std::exception(); + if (PyArray_NDIM(matrix) == 2 || PyArray_DIM(matrix, 0) == 3 || PyArray_DIM(matrix, 1) == 3) + { + size_t stride0 = PyArray_STRIDE(matrix, 0); + size_t stride1 = PyArray_STRIDE(matrix, 1); + char* row0 = PyArray_BYTES(matrix); + char* row1 = row0 + stride0; + + double a = *(double*)(row0); + row0 += stride1; + double c = *(double*)(row0); + row0 += stride1; + double e = *(double*)(row0); + + double b = *(double*)(row1); + row1 += stride1; + double d = *(double*)(row1); + row1 += stride1; + double f = *(double*)(row1); + + Py_XDECREF(matrix); + + return agg::trans_affine(a, b, c, d, e, f); + } + + throw std::exception(); + } + catch (...) + { + if (errors) + { + Py_XDECREF(matrix); + throw Py::TypeError("Invalid affine transformation matrix"); + } + } + + Py_XDECREF(matrix); + return agg::trans_affine(); +} + +bool +py_convert_bbox(PyObject* bbox_obj, double& l, double& b, double& r, double& t) +{ + PyArrayObject* bbox = NULL; + + if (bbox_obj == Py_None) + return false; + + try + { + bbox = (PyArrayObject*) PyArray_FromObject(bbox_obj, PyArray_DOUBLE, 2, 2); + + if (!bbox || PyArray_NDIM(bbox) != 2 || PyArray_DIM(bbox, 0) != 2 || PyArray_DIM(bbox, 1) != 2) + { + throw Py::TypeError + ("Argument 3 to agg_to_gtk_drawable must be a Bbox object."); + } + + l = *(double*)PyArray_GETPTR2(bbox, 0, 0); + b = *(double*)PyArray_GETPTR2(bbox, 0, 1); + r = *(double*)PyArray_GETPTR2(bbox, 1, 0); + t = *(double*)PyArray_GETPTR2(bbox, 1, 1); + + Py_XDECREF(bbox); + bbox = NULL; + return true; + } + catch (...) + { + Py_XDECREF(bbox); + bbox = NULL; + throw; + } + + return false; +} Modified: trunk/matplotlib/src/agg_py_transforms.h =================================================================== --- trunk/matplotlib/src/agg_py_transforms.h 2009-02-02 16:19:33 UTC (rev 6864) +++ trunk/matplotlib/src/agg_py_transforms.h 2009-02-02 16:29:37 UTC (rev 6865) @@ -1,99 +1,15 @@ #ifndef __AGG_PY_TRANSFORMS_H__ #define __AGG_PY_TRANSFORMS_H__ -#define PY_ARRAY_TYPES_PREFIX NumPy -#include "numpy/arrayobject.h" - -#include "CXX/Objects.hxx" #include "agg_trans_affine.h" /** A helper function to convert from a Numpy affine transformation matrix * to an agg::trans_affine. */ -agg::trans_affine py_to_agg_transformation_matrix(const Py::Object& obj, bool errors = true) -{ - PyArrayObject* matrix = NULL; +agg::trans_affine +py_to_agg_transformation_matrix(PyObject* obj, bool errors = true); - try - { - if (obj.ptr() == Py_None) - throw std::exception(); - matrix = (PyArrayObject*) PyArray_FromObject(obj.ptr(), PyArray_DOUBLE, 2, 2); - if (!matrix) - throw std::exception(); - if (PyArray_NDIM(matrix) == 2 || PyArray_DIM(matrix, 0) == 3 || PyArray_DIM(matrix, 1) == 3) - { - size_t stride0 = PyArray_STRIDE(matrix, 0); - size_t stride1 = PyArray_STRIDE(matrix, 1); - char* row0 = PyArray_BYTES(matrix); - char* row1 = row0 + stride0; +bool +py_convert_bbox(PyObject* bbox_obj, double& l, double& b, double& r, double& t); - double a = *(double*)(row0); - row0 += stride1; - double c = *(double*)(row0); - row0 += stride1; - double e = *(double*)(row0); - - double b = *(double*)(row1); - row1 += stride1; - double d = *(double*)(row1); - row1 += stride1; - double f = *(double*)(row1); - - Py_XDECREF(matrix); - - return agg::trans_affine(a, b, c, d, e, f); - } - - throw std::exception(); - } - catch (...) - { - if (errors) - { - Py_XDECREF(matrix); - throw Py::TypeError("Invalid affine transformation matrix"); - } - } - - Py_XDECREF(matrix); - return agg::trans_affine(); -} - -bool py_convert_bbox(PyObject* bbox_obj, double& l, double& b, double& r, double& t) -{ - PyArrayObject* bbox = NULL; - - if (bbox_obj == Py_None) - return false; - - try - { - bbox = (PyArrayObject*) PyArray_FromObject(bbox_obj, PyArray_DOUBLE, 2, 2); - - if (!bbox || PyArray_NDIM(bbox) != 2 || PyArray_DIM(bbox, 0) != 2 || PyArray_DIM(bbox, 1) != 2) - { - throw Py::TypeError - ("Argument 3 to agg_to_gtk_drawable must be a Bbox object."); - } - - l = *(double*)PyArray_GETPTR2(bbox, 0, 0); - b = *(double*)PyArray_GETPTR2(bbox, 0, 1); - r = *(double*)PyArray_GETPTR2(bbox, 1, 0); - t = *(double*)PyArray_GETPTR2(bbox, 1, 1); - - Py_XDECREF(bbox); - bbox = NULL; - return true; - } - catch (...) - { - Py_XDECREF(bbox); - bbox = NULL; - throw; - } - - return false; -} - #endif // __AGG_PY_TRANSFORMS_H__ Modified: trunk/matplotlib/src/ft2font.cpp =================================================================== --- trunk/matplotlib/src/ft2font.cpp 2009-02-02 16:19:33 UTC (rev 6864) +++ trunk/matplotlib/src/ft2font.cpp 2009-02-02 16:29:37 UTC (rev 6865) @@ -2,7 +2,6 @@ #include "mplutils.h" #include <sstream> -#define PY_ARRAY_TYPES_PREFIX NumPy #include "numpy/arrayobject.h" #define FIXED_MAJOR(val) (*((short *) &val+1)) Modified: trunk/matplotlib/src/numerix.h =================================================================== --- trunk/matplotlib/src/numerix.h 2009-02-02 16:19:33 UTC (rev 6864) +++ trunk/matplotlib/src/numerix.h 2009-02-02 16:29:37 UTC (rev 6865) @@ -3,7 +3,6 @@ #ifndef _NUMERIX_H #define _NUMERIX_H -#define PY_ARRAY_TYPES_PREFIX NumPy #include "numpy/arrayobject.h" #if (NDARRAY_VERSION >= 0x00090908) #include "numpy/oldnumeric.h" Added: trunk/matplotlib/src/path_cleanup.cpp =================================================================== --- trunk/matplotlib/src/path_cleanup.cpp (rev 0) +++ trunk/matplotlib/src/path_cleanup.cpp 2009-02-02 16:29:37 UTC (rev 6865) @@ -0,0 +1,84 @@ +#include <Python.h> +#define NO_IMPORT_ARRAY +#include "numpy/arrayobject.h" + +#include "agg_py_path_iterator.h" +#include "agg_conv_transform.h" +#include "agg_py_transforms.h" +#include "path_converters.h" + +class PathCleanupIterator { + typedef agg::conv_transform<PathIterator> transformed_path_t; + typedef PathNanRemover<transformed_path_t> nan_removal_t; + typedef PathClipper<nan_removal_t> clipped_t; + typedef PathQuantizer<clipped_t> quantized_t; + typedef PathSimplifier<quantized_t> simplify_t; + + Py::Object m_path_obj; + PathIterator m_path_iter; + agg::trans_affine m_transform; + transformed_path_t m_transformed; + nan_removal_t m_nan_removed; + clipped_t m_clipped; + quantized_t m_quantized; + simplify_t m_simplify; + +public: + PathCleanupIterator(PyObject* path, agg::trans_affine trans, + bool remove_nans, bool do_clip, + const agg::rect_base<double>& rect, + e_quantize_mode quantize_mode, bool do_simplify) : + m_path_obj(path, true), + m_path_iter(m_path_obj), + m_transform(trans), + m_transformed(m_path_iter, m_transform), + m_nan_removed(m_transformed, remove_nans, m_path_iter.has_curves()), + m_clipped(m_nan_removed, do_clip, rect), + m_quantized(m_clipped, quantize_mode, m_path_iter.total_vertices()), + m_simplify(m_quantized, do_simplify && m_path_iter.should_simplify(), + m_path_iter.simplify_threshold()) + { + Py_INCREF(path); + m_path_iter.rewind(0); + } + + unsigned vertex(double* x, double* y) + { + return m_simplify.vertex(x, y); + } +}; + +extern "C" { + void* + get_path_iterator( + PyObject* path, PyObject* trans, int remove_nans, int do_clip, + double rect[4], e_quantize_mode quantize_mode, int do_simplify) + { + agg::trans_affine agg_trans = py_to_agg_transformation_matrix(trans, false); + agg::rect_base<double> clip_rect(rect[0], rect[1], rect[2], rect[3]); + + PathCleanupIterator* pipeline = new PathCleanupIterator( + path, agg_trans, remove_nans != 0, do_clip != 0, + clip_rect, quantize_mode, do_simplify != 0); + + return (void*)pipeline; + } + + unsigned + get_vertex(void* pipeline, double* x, double* y) + { + PathCleanupIterator* pipeline_iter = (PathCleanupIterator*)pipeline; + + unsigned code = pipeline_iter->vertex(x, y); + return code; + } + + void + free_path_iterator(void* pipeline) + { + PathCleanupIterator* pipeline_iter = (PathCleanupIterator*)pipeline; + + delete pipeline_iter; + } +} + Added: trunk/matplotlib/src/path_cleanup.h =================================================================== --- trunk/matplotlib/src/path_cleanup.h (rev 0) +++ trunk/matplotlib/src/path_cleanup.h 2009-02-02 16:29:37 UTC (rev 6865) @@ -0,0 +1,24 @@ +#ifndef PATH_CLEANUP_H +#define PATH_CLEANUP_H + +#include <Python.h> + +enum e_quantize_mode +{ + QUANTIZE_AUTO, + QUANTIZE_FALSE, + QUANTIZE_TRUE +}; + +void* +get_path_iterator( + PyObject* path, PyObject* trans, int remove_nans, int do_clip, + double rect[4], e_quantize_mode quantize_mode, int do_simplify); + +unsigned +get_vertex(void* pipeline, double* x, double* y); + +void +free_path_iterator(void* pipeline); + +#endif /* PATH_CLEANUP_H */ Modified: trunk/matplotlib/src/path_converters.h =================================================================== --- trunk/matplotlib/src/path_converters.h 2009-02-02 16:19:33 UTC (rev 6864) +++ trunk/matplotlib/src/path_converters.h 2009-02-02 16:29:37 UTC (rev 6865) @@ -2,7 +2,6 @@ #define __PATH_CONVERTERS_H__ #include "CXX/Objects.hxx" -#define PY_ARRAY_TYPES_PREFIX NumPy #include "numpy/arrayobject.h" #include "agg_path_storage.h" #include "agg_clip_liang_barsky.h" This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2009-02-02 17:58:53
|
Revision: 6867 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6867&view=rev Author: mdboom Date: 2009-02-02 17:58:48 +0000 (Mon, 02 Feb 2009) Log Message: ----------- Make resolution of 1 be the default on a polar plot. Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/projections/polar.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009-02-02 17:12:27 UTC (rev 6866) +++ trunk/matplotlib/CHANGELOG 2009-02-02 17:58:48 UTC (rev 6867) @@ -1,3 +1,5 @@ +2009-02-02 Change default resolution on polar plot to 1 - MGD + 2009-02-02 Avoid malloc errors in ttconv for fonts that don't have e.g. PostName (a version of Tahoma triggered this) - JKS Modified: trunk/matplotlib/lib/matplotlib/projections/polar.py =================================================================== --- trunk/matplotlib/lib/matplotlib/projections/polar.py 2009-02-02 17:12:27 UTC (rev 6866) +++ trunk/matplotlib/lib/matplotlib/projections/polar.py 2009-02-02 17:58:48 UTC (rev 6867) @@ -177,7 +177,7 @@ return 0, vmax - RESOLUTION = 75 + RESOLUTION = 1 def __init__(self, *args, **kwargs): """ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jo...@us...> - 2009-02-02 19:35:47
|
Revision: 6868 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6868&view=rev Author: jouni Date: 2009-02-02 19:35:43 +0000 (Mon, 02 Feb 2009) Log Message: ----------- Reduce number of marker objects in pdf output Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009-02-02 17:58:48 UTC (rev 6867) +++ trunk/matplotlib/CHANGELOG 2009-02-02 19:35:43 UTC (rev 6868) @@ -1,3 +1,5 @@ +2009-02-02 Reduce number of marker XObjects in pdf output - JKS + 2009-02-02 Change default resolution on polar plot to 1 - MGD 2009-02-02 Avoid malloc errors in ttconv for fonts that don't have Modified: trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2009-02-02 17:58:48 UTC (rev 6867) +++ trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2009-02-02 19:35:43 UTC (rev 6868) @@ -1109,26 +1109,28 @@ def markerObject(self, path, trans, fillp, lw): """Return name of a marker XObject representing the given path.""" - key = (path, trans, fillp is not None, lw) + pathops = self.pathOperations(path, trans) + key = (tuple(pathops), bool(fillp)) result = self.markers.get(key) if result is None: name = Name('M%d' % len(self.markers)) ob = self.reserveObject('marker %d' % len(self.markers)) - self.markers[key] = (name, ob, path, trans, fillp, lw) + bbox = path.get_extents(trans) + self.markers[key] = [name, ob, bbox, lw] else: + if result[-1] < lw: + result[-1] = lw name = result[0] return name def writeMarkers(self): - for tup in self.markers.values(): - name, object, path, trans, fillp, lw = tup - bbox = path.get_extents(trans) + for (pathops, fillp),(name, ob, bbox, lw) in self.markers.iteritems(): bbox = bbox.padded(lw * 0.5) self.beginStream( - object.id, None, + ob.id, None, {'Type': Name('XObject'), 'Subtype': Name('Form'), 'BBox': list(bbox.extents) }) - self.writePath(path, trans) + self.output(*pathops) if fillp: self.output(Op.fill_stroke) else: @@ -1280,10 +1282,17 @@ def draw_path(self, gc, path, transform, rgbFace=None): self.check_gc(gc, rgbFace) - stream = self.file.writePath(path, transform, rgbFace is None) + self.file.writePath(path, transform, rgbFace is None) self.file.output(self.gc.paint()) def draw_markers(self, gc, marker_path, marker_trans, path, trans, rgbFace=None): + # For simple paths or small numbers of markers, don't bother + # making an XObject + if len(path) * len(marker_path) <= 10: + RendererBase.draw_markers(self, gc, marker_path, marker_trans, + path, trans, rgbFace) + return + self.check_gc(gc, rgbFace) fillp = rgbFace is not None This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2009-02-03 19:52:06
|
Revision: 6871 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6871&view=rev Author: mdboom Date: 2009-02-03 19:52:02 +0000 (Tue, 03 Feb 2009) Log Message: ----------- Change default joinstyle to round Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/backend_bases.py trunk/matplotlib/lib/matplotlib/config/mplconfig.py trunk/matplotlib/lib/matplotlib/config/rcsetup.py trunk/matplotlib/lib/matplotlib/rcsetup.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009-02-03 17:25:49 UTC (rev 6870) +++ trunk/matplotlib/CHANGELOG 2009-02-03 19:52:02 UTC (rev 6871) @@ -1,3 +1,5 @@ +2009-02-03 Change default joinstyle to round - MGD + 2009-02-02 Reduce number of marker XObjects in pdf output - JKS 2009-02-02 Change default resolution on polar plot to 1 - MGD Modified: trunk/matplotlib/lib/matplotlib/backend_bases.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backend_bases.py 2009-02-03 17:25:49 UTC (rev 6870) +++ trunk/matplotlib/lib/matplotlib/backend_bases.py 2009-02-03 19:52:02 UTC (rev 6871) @@ -434,7 +434,7 @@ self._cliprect = None self._clippath = None self._dashes = None, None - self._joinstyle = 'miter' + self._joinstyle = 'round' self._linestyle = 'solid' self._linewidth = 1 self._rgb = (0.0, 0.0, 0.0) Modified: trunk/matplotlib/lib/matplotlib/config/mplconfig.py =================================================================== --- trunk/matplotlib/lib/matplotlib/config/mplconfig.py 2009-02-03 17:25:49 UTC (rev 6870) +++ trunk/matplotlib/lib/matplotlib/config/mplconfig.py 2009-02-03 19:52:02 UTC (rev 6871) @@ -105,9 +105,9 @@ linewidth = T.Float(1.0) linestyle = T.Trait('-','--','-.', ':', 'steps', '', ' ', None) color = T.Trait('blue',mplT.ColorHandler()) - solid_joinstyle = T.Trait('miter', 'miter', 'round', 'bevel') + solid_joinstyle = T.Trait('round', 'miter', 'round', 'bevel') solid_capstyle = T.Trait('butt', 'butt', 'round', 'projecting') - dash_joinstyle = T.Trait('miter', 'miter', 'round', 'bevel') + dash_joinstyle = T.Trait('round', 'miter', 'round', 'bevel') dash_capstyle = T.Trait('butt', 'butt', 'round', 'projecting') marker = T.Trait('None', 'None', 'o', '.', ',', '^', 'v', '<', '>', 's', '+', 'x', 'D','d', '1', '2', '3', '4', 'h', 'H', 'p', Modified: trunk/matplotlib/lib/matplotlib/config/rcsetup.py =================================================================== --- trunk/matplotlib/lib/matplotlib/config/rcsetup.py 2009-02-03 17:25:49 UTC (rev 6870) +++ trunk/matplotlib/lib/matplotlib/config/rcsetup.py 2009-02-03 19:52:02 UTC (rev 6871) @@ -317,8 +317,8 @@ 'lines.markeredgewidth' : [0.5, validate_float], 'lines.markersize' : [6, validate_float], # markersize, in points 'lines.antialiased' : [True, validate_bool], # antialised (no jaggies) - 'lines.dash_joinstyle' : ['miter', validate_joinstyle], - 'lines.solid_joinstyle' : ['miter', validate_joinstyle], + 'lines.dash_joinstyle' : ['round', validate_joinstyle], + 'lines.solid_joinstyle' : ['round', validate_joinstyle], 'lines.dash_capstyle' : ['butt', validate_capstyle], 'lines.solid_capstyle' : ['projecting', validate_capstyle], Modified: trunk/matplotlib/lib/matplotlib/rcsetup.py =================================================================== --- trunk/matplotlib/lib/matplotlib/rcsetup.py 2009-02-03 17:25:49 UTC (rev 6870) +++ trunk/matplotlib/lib/matplotlib/rcsetup.py 2009-02-03 19:52:02 UTC (rev 6871) @@ -343,8 +343,8 @@ 'lines.markeredgewidth' : [0.5, validate_float], 'lines.markersize' : [6, validate_float], # markersize, in points 'lines.antialiased' : [True, validate_bool], # antialised (no jaggies) - 'lines.dash_joinstyle' : ['miter', validate_joinstyle], - 'lines.solid_joinstyle' : ['miter', validate_joinstyle], + 'lines.dash_joinstyle' : ['round', validate_joinstyle], + 'lines.solid_joinstyle' : ['round', validate_joinstyle], 'lines.dash_capstyle' : ['butt', validate_capstyle], 'lines.solid_capstyle' : ['projecting', validate_capstyle], This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2009-02-04 13:37:28
|
Revision: 6874 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6874&view=rev Author: mdboom Date: 2009-02-04 13:37:24 +0000 (Wed, 04 Feb 2009) Log Message: ----------- Merged revisions 6861,6873 via svnmerge from https://matplotlib.svn.sf.net/svnroot/matplotlib/branches/v0_98_5_maint ........ r6861 | mdboom | 2009-01-30 11:31:47 -0500 (Fri, 30 Jan 2009) | 2 lines Document how to find the currently active matplotlibrc file. ........ r6873 | mdboom | 2009-02-04 08:22:35 -0500 (Wed, 04 Feb 2009) | 2 lines Fix bug in mathtext related to \dots and \ldots (Thanks, Fernando Perez) ........ Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/doc/users/customizing.rst trunk/matplotlib/examples/pylab_examples/mathtext_examples.py trunk/matplotlib/lib/matplotlib/_mathtext_data.py trunk/matplotlib/lib/matplotlib/mathtext.py Property Changed: ---------------- trunk/matplotlib/ trunk/matplotlib/doc/pyplots/README trunk/matplotlib/doc/sphinxext/gen_gallery.py trunk/matplotlib/doc/sphinxext/gen_rst.py Property changes on: trunk/matplotlib ___________________________________________________________________ Modified: svnmerge-integrated - /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-6859 + /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-6873 Modified: svn:mergeinfo - /branches/v0_91_maint:5753-5771 /branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859 + /branches/v0_91_maint:5753-5771 /branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873 Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009-02-04 13:22:35 UTC (rev 6873) +++ trunk/matplotlib/CHANGELOG 2009-02-04 13:37:24 UTC (rev 6874) @@ -1,3 +1,5 @@ +2009-02-04 Fix bug in mathtext related to \dots and \ldots - MGD + 2009-02-03 Change default joinstyle to round - MGD 2009-02-02 Reduce number of marker XObjects in pdf output - JKS Property changes on: trunk/matplotlib/doc/pyplots/README ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859 + /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873 Property changes on: trunk/matplotlib/doc/sphinxext/gen_gallery.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859 + /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873 Property changes on: trunk/matplotlib/doc/sphinxext/gen_rst.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859 + /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873 Modified: trunk/matplotlib/doc/users/customizing.rst =================================================================== --- trunk/matplotlib/doc/users/customizing.rst 2009-02-04 13:22:35 UTC (rev 6873) +++ trunk/matplotlib/doc/users/customizing.rst 2009-02-04 13:37:24 UTC (rev 6874) @@ -27,7 +27,13 @@ customizations to be saved, please move this file to you :file:`.matplotlib` directory. +To display where the currently active :file:`matplotlibrc` file was +loaded from, one can do the following:: + >>> import matplotlib + >>> matplotlib.matplotlib_fname() + '/home/foo/.matplotlib/matplotlibrc' + See below for a sample :ref:`matplotlibrc file<matplotlibrc-sample>`. .. _customizing-with-dynamic-rc-settings: Modified: trunk/matplotlib/examples/pylab_examples/mathtext_examples.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/mathtext_examples.py 2009-02-04 13:22:35 UTC (rev 6873) +++ trunk/matplotlib/examples/pylab_examples/mathtext_examples.py 2009-02-04 13:37:24 UTC (rev 6874) @@ -5,6 +5,7 @@ import gc stests = [ + r'$a+b+\dots+\dot{s}+\ldots$', r'$x \doteq y$', r'\$100.00 $\alpha \_$', r'$\frac{\$100.00}{y}$', Modified: trunk/matplotlib/lib/matplotlib/_mathtext_data.py =================================================================== --- trunk/matplotlib/lib/matplotlib/_mathtext_data.py 2009-02-04 13:22:35 UTC (rev 6873) +++ trunk/matplotlib/lib/matplotlib/_mathtext_data.py 2009-02-04 13:37:24 UTC (rev 6874) @@ -1805,7 +1805,7 @@ 'Game': 0x2141, 'hbar': 0x0127, 'hslash': 0x210f, -'ldots': 0x22ef, +'ldots': 0x2026, 'vdots': 0x22ee, 'doteqdot': 0x2251, 'doteq': 8784, @@ -2100,7 +2100,7 @@ 'propto': 8733, 'pi': 960, 'pm': 177, -'dots': 8230, +'dots': 0x2026, 'nrightarrow': 8603, 'textasciiacute': 180, 'Doteq': 8785, Modified: trunk/matplotlib/lib/matplotlib/mathtext.py =================================================================== --- trunk/matplotlib/lib/matplotlib/mathtext.py 2009-02-04 13:22:35 UTC (rev 6873) +++ trunk/matplotlib/lib/matplotlib/mathtext.py 2009-02-04 13:37:24 UTC (rev 6874) @@ -2037,7 +2037,7 @@ \sqsubset \sqsupset \neq \smile \sqsubseteq \sqsupseteq \doteq \frown \in \ni \propto - \vdash \dashv'''.split()) + \vdash \dashv \dots'''.split()) _arrow_symbols = set(r''' \leftarrow \longleftarrow \uparrow @@ -2180,9 +2180,9 @@ + (group | Error("Expected \sqrt{value}")) ).setParseAction(self.sqrt).setName("sqrt") - placeable <<(accent - ^ function + placeable <<(function ^ (c_over_c | symbol) + ^ accent ^ group ^ frac ^ sqrt This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <as...@us...> - 2009-02-04 22:22:11
|
Revision: 6876 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6876&view=rev Author: astraw Date: 2009-02-04 21:43:08 +0000 (Wed, 04 Feb 2009) Log Message: ----------- Add extent keyword arg to hexbin Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/axes.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009-02-04 20:06:17 UTC (rev 6875) +++ trunk/matplotlib/CHANGELOG 2009-02-04 21:43:08 UTC (rev 6876) @@ -1,3 +1,5 @@ +2009-02-04 Add extent keyword arg to hexbin - ADS + 2009-02-04 Fix bug in mathtext related to \dots and \ldots - MGD 2009-02-03 Change default joinstyle to round - MGD Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2009-02-04 20:06:17 UTC (rev 6875) +++ trunk/matplotlib/lib/matplotlib/axes.py 2009-02-04 21:43:08 UTC (rev 6876) @@ -5242,7 +5242,7 @@ scatter.__doc__ = cbook.dedent(scatter.__doc__) % martist.kwdocd def hexbin(self, x, y, C = None, gridsize = 100, bins = None, - xscale = 'linear', yscale = 'linear', + xscale = 'linear', yscale = 'linear', extent = None, cmap=None, norm=None, vmin=None, vmax=None, alpha=1.0, linewidths=None, edgecolors='none', reduce_C_function = np.mean, mincnt=None, marginals=False, @@ -5311,6 +5311,10 @@ colormapped rectagles along the bottom of the x-axis and left of the y-axis + *extent*: [ None | scalars (left, right, bottom, top) ] + The limits of the bins. The default assigns the limits + based on gridsize, x, y, xscale and yscale. + Other keyword arguments controlling color mapping and normalization arguments: @@ -5389,10 +5393,13 @@ x = np.log10(x) if yscale=='log': y = np.log10(y) - xmin = np.amin(x) - xmax = np.amax(x) - ymin = np.amin(y) - ymax = np.amax(y) + if extent is not None: + xmin, xmax, ymin, ymax = extent + else: + xmin = np.amin(x) + xmax = np.amax(x) + ymin = np.amin(y) + ymax = np.amax(y) # In the x-direction, the hexagons exactly cover the region from # xmin to xmax. Need some padding to avoid roundoff errors. padding = 1.e-9 * (xmax - xmin) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <lee...@us...> - 2009-02-05 04:47:35
|
Revision: 6879 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6879&view=rev Author: leejjoon Date: 2009-02-05 04:47:26 +0000 (Thu, 05 Feb 2009) Log Message: ----------- some reorganization of the legend code. Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/legend.py trunk/matplotlib/lib/matplotlib/offsetbox.py Added Paths: ----------- trunk/matplotlib/examples/pylab_examples/anchored_text.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009-02-04 21:48:49 UTC (rev 6878) +++ trunk/matplotlib/CHANGELOG 2009-02-05 04:47:26 UTC (rev 6879) @@ -1,3 +1,6 @@ +2009-02-04 Some reorgnization of the legend code. anchored_text.py + added as an example. - JJL + 2009-02-04 Add extent keyword arg to hexbin - ADS 2009-02-04 Fix bug in mathtext related to \dots and \ldots - MGD Added: trunk/matplotlib/examples/pylab_examples/anchored_text.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/anchored_text.py (rev 0) +++ trunk/matplotlib/examples/pylab_examples/anchored_text.py 2009-02-05 04:47:26 UTC (rev 6879) @@ -0,0 +1,183 @@ +""" +Place a text (or any offsetbox artist) at the corner of the axes, like a lenged. +""" + +from matplotlib.offsetbox import TextArea, OffsetBox, DrawingArea +from matplotlib.transforms import Bbox +from matplotlib.font_manager import FontProperties +from matplotlib import rcParams +from matplotlib.patches import FancyBboxPatch +from matplotlib.patches import Circle + + +class AnchoredOffsetbox(OffsetBox): + def __init__(self, loc, pad=0.4, borderpad=0.5, + child=None, fontsize=None, frameon=True): + + super(AnchoredOffsetbox, self).__init__() + + self.set_child(child) + + self.loc = loc + self.borderpad=borderpad + self.pad = pad + + if fontsize is None: + prop=FontProperties(size=rcParams["legend.fontsize"]) + self._fontsize = prop.get_size_in_points() + else: + self._fontsize = fontsize + + + + self.patch = FancyBboxPatch( + xy=(0.0, 0.0), width=1., height=1., + facecolor='w', edgecolor='k', + mutation_scale=self._fontsize, + snap=True + ) + self.patch.set_boxstyle("square",pad=0) + self._drawFrame = frameon + + def set_child(self, child): + self._child = child + + def get_children(self): + return [self._child] + + def get_child(self): + return self._child + + def get_extent(self, renderer): + w, h, xd, yd = self.get_child().get_extent(renderer) + fontsize = renderer.points_to_pixels(self._fontsize) + pad = self.pad * fontsize + + return w+2*pad, h+2*pad, xd+pad, yd+pad + + def get_window_extent(self, renderer): + ''' + get the bounding box in display space. + ''' + w, h, xd, yd = self.get_extent(renderer) + ox, oy = self.get_offset(w, h, xd, yd) + return Bbox.from_bounds(ox-xd, oy-yd, w, h) + + def draw(self, renderer): + + if not self.get_visible(): return + + fontsize = renderer.points_to_pixels(self._fontsize) + + def _offset(w, h, xd, yd, fontsize=fontsize, self=self): + bbox = Bbox.from_bounds(0, 0, w, h) + borderpad = self.borderpad*fontsize + x0, y0 = self._get_anchored_bbox(self.loc, + bbox, + self.axes.bbox, + borderpad) + return x0+xd, y0+yd + + self.set_offset(_offset) + + if self._drawFrame: + # update the location and size of the legend + bbox = self.get_window_extent(renderer) + self.patch.set_bounds(bbox.x0, bbox.y0, + bbox.width, bbox.height) + + self.patch.set_mutation_scale(fontsize) + + self.patch.draw(renderer) + + + width, height, xdescent, ydescent = self.get_extent(renderer) + + px, py = self.get_offset(width, height, xdescent, ydescent) + + self.get_child().set_offset((px, py)) + self.get_child().draw(renderer) + + + + def _get_anchored_bbox(self, loc, bbox, parentbbox, borderpad): + assert loc in range(1,11) # called only internally + + BEST, UR, UL, LL, LR, R, CL, CR, LC, UC, C = range(11) + + anchor_coefs={UR:"NE", + UL:"NW", + LL:"SW", + LR:"SE", + R:"E", + CL:"W", + CR:"E", + LC:"S", + UC:"N", + C:"C"} + + c = anchor_coefs[loc] + + container = parentbbox.padded(-borderpad) + anchored_box = bbox.anchored(c, container=container) + return anchored_box.x0, anchored_box.y0 + + +class AnchoredText(AnchoredOffsetbox): + def __init__(self, s, loc, pad=0.4, borderpad=0.5, prop=None, frameon=True): + + self.txt = TextArea(s, + minimumdescent=False) + + + if prop is None: + self.prop=FontProperties(size=rcParams["legend.fontsize"]) + else: + self.prop=prop + + + super(AnchoredText, self).__init__(loc, pad=pad, borderpad=borderpad, + child=self.txt, + fontsize=self.prop.get_size_in_points(), + frameon=frameon) + + +class AnchoredDrawingArea(AnchoredOffsetbox): + def __init__(self, width, height, xdescent, ydescent, + loc, pad=0.4, borderpad=0.5, fontsize=None, frameon=True): + + self.da = DrawingArea(width, height, xdescent, ydescent, clip=True) + + super(AnchoredDrawingArea, self).__init__(loc, pad=pad, borderpad=borderpad, + child=self.da, + fontsize=fontsize, + frameon=frameon) + + + +if __name__ == "__main__": + import matplotlib.pyplot as plt + + #ax = plt.subplot(1,1,1) + plt.clf() + plt.cla() + plt.draw() + ax = plt.gca() + #ax.set_aspect(1.) + + at = AnchoredText("Figure 1(a)", loc=2, frameon=False) + ax.add_artist(at) + + ada = AnchoredDrawingArea(20, 20, 0, 0, loc=3, pad=0., frameon=False) + + p = Circle((10, 10), 10) + ada.da.add_artist(p) + ax.add_artist(ada) + + ax.plot([0,1]) + plt.draw() + + plt.show() + + + Modified: trunk/matplotlib/lib/matplotlib/legend.py =================================================================== --- trunk/matplotlib/lib/matplotlib/legend.py 2009-02-04 21:48:49 UTC (rev 6878) +++ trunk/matplotlib/lib/matplotlib/legend.py 2009-02-05 04:47:26 UTC (rev 6879) @@ -34,7 +34,7 @@ from matplotlib.collections import LineCollection, RegularPolyCollection from matplotlib.transforms import Bbox -from matplotlib.offsetbox import HPacker, VPacker, PackerBase, TextArea, DrawingArea +from matplotlib.offsetbox import HPacker, VPacker, TextArea, DrawingArea class Legend(Artist): @@ -138,7 +138,7 @@ ================ ================================================================== The dimensions of pad and spacing are given as a fraction of the -fontsize. Values from rcParams will be used if None. +_fontsize. Values from rcParams will be used if None. """ from matplotlib.axes import Axes # local import only to avoid circularity from matplotlib.figure import Figure # local import only to avoid circularity @@ -149,7 +149,7 @@ self.prop=FontProperties(size=rcParams["legend.fontsize"]) else: self.prop=prop - self.fontsize = self.prop.get_size_in_points() + self._fontsize = self.prop.get_size_in_points() propnames=['numpoints', 'markerscale', 'shadow', "columnspacing", "scatterpoints"] @@ -175,7 +175,7 @@ # conversion factor bbox = parent.bbox - axessize_fontsize = min(bbox.width, bbox.height)/self.fontsize + axessize_fontsize = min(bbox.width, bbox.height)/self._fontsize for k, v in deprecated_kwds.items(): # use deprecated value if not None and if their newer @@ -253,7 +253,7 @@ self.legendPatch = FancyBboxPatch( xy=(0.0, 0.0), width=1., height=1., facecolor='w', edgecolor='k', - mutation_scale=self.fontsize, + mutation_scale=self._fontsize, snap=True ) @@ -276,7 +276,7 @@ # init with null renderer self._init_legend_box(handles, labels) - self._last_fontsize_points = self.fontsize + self._last_fontsize_points = self._fontsize def _set_artist_props(self, a): @@ -313,7 +313,6 @@ "Draw everything that belongs to the legend" if not self.get_visible(): return - self._update_legend_box(renderer) renderer.open_group('legend') @@ -330,7 +329,7 @@ self._legend_box.set_offset(findoffset) - fontsize = renderer.points_to_pixels(self.fontsize) + fontsize = renderer.points_to_pixels(self._fontsize) # if mode == fill, set the width of the legend_box to the # width of the paret (minus pads) @@ -363,9 +362,9 @@ the legend handle. """ if renderer is None: - return self.fontsize + return self._fontsize else: - return renderer.points_to_pixels(self.fontsize) + return renderer.points_to_pixels(self._fontsize) def _init_legend_box(self, handles, labels): @@ -376,7 +375,7 @@ drawing time. """ - fontsize = self.fontsize + fontsize = self._fontsize # legend_box is a HPacker, horizontally packed with # columns. Each column is a VPacker, vertically packed with @@ -415,9 +414,6 @@ # (0, -descent, width, height). And their corrdinates should # be given in the display coordinates. - # NOTE : the coordinates will be updated again in - # _update_legend_box() method. - # The transformation of each handle will be automatically set # to self.get_trasnform(). If the artist does not uses its # default trasnform (eg, Collections), you need to @@ -567,9 +563,9 @@ sep = self.columnspacing*fontsize self._legend_box = HPacker(pad=self.borderpad*fontsize, - sep=sep, align="baseline", - mode=mode, - children=columnbox) + sep=sep, align="baseline", + mode=mode, + children=columnbox) self._legend_box.set_figure(self.figure) @@ -577,97 +573,6 @@ self.legendHandles = handle_list - - - def _update_legend_box(self, renderer): - """ - Update the dimension of the legend_box. This is required - becuase the paddings, the hadle size etc. depends on the dpi - of the renderer. - """ - - # fontsize in points. - fontsize = renderer.points_to_pixels(self.fontsize) - - if self._last_fontsize_points == fontsize: - # no update is needed - return - - # each handle needs to be drawn inside a box of - # (x, y, w, h) = (0, -descent, width, height). - # And their corrdinates should be given in the display coordinates. - - # The approximate height and descent of text. These values are - # only used for plotting the legend handle. - height = self._approx_text_height(renderer) * 0.7 - descent = 0. - - for handle in self.legendHandles: - if isinstance(handle, RegularPolyCollection): - npoints = self.scatterpoints - else: - npoints = self.numpoints - if npoints > 1: - # we put some pad here to compensate the size of the - # marker - xdata = np.linspace(0.3*fontsize, - (self.handlelength-0.3)*fontsize, - npoints) - xdata_marker = xdata - elif npoints == 1: - xdata = np.linspace(0, self.handlelength*fontsize, 2) - xdata_marker = [0.5*self.handlelength*fontsize] - - if isinstance(handle, Line2D): - legline = handle - ydata = ((height-descent)/2.)*np.ones(xdata.shape, float) - legline.set_data(xdata, ydata) - - # if a line collection is added, the legmarker attr is - # not set so we don't need to handle it - if hasattr(handle, "_legmarker"): - legline_marker = legline._legmarker - legline_marker.set_data(xdata_marker, ydata[:len(xdata_marker)]) - - elif isinstance(handle, Patch): - p = handle - p.set_bounds(0., 0., - self.handlelength*fontsize, - (height-descent), - ) - - elif isinstance(handle, RegularPolyCollection): - - p = handle - ydata = height*self._scatteryoffsets - p.set_offsets(zip(xdata_marker,ydata)) - - - # correction factor - cor = fontsize / self._last_fontsize_points - - # helper function to iterate over all children - def all_children(parent): - yield parent - for c in parent.get_children(): - for cc in all_children(c): yield cc - - - #now update paddings - for box in all_children(self._legend_box): - if isinstance(box, PackerBase): - box.pad = box.pad * cor - box.sep = box.sep * cor - - elif isinstance(box, DrawingArea): - box.width = self.handlelength*fontsize - box.height = height - box.xdescent = 0. - box.ydescent=descent - - self._last_fontsize_points = fontsize - - def _auto_legend_data(self): """ Returns list of vertices and extents covered by the plot. @@ -769,7 +674,7 @@ c = anchor_coefs[loc] - fontsize = renderer.points_to_pixels(self.fontsize) + fontsize = renderer.points_to_pixels(self._fontsize) container = parentbbox.padded(-(self.borderaxespad) * fontsize) anchored_box = bbox.anchored(c, container=container) return anchored_box.x0, anchored_box.y0 Modified: trunk/matplotlib/lib/matplotlib/offsetbox.py =================================================================== --- trunk/matplotlib/lib/matplotlib/offsetbox.py 2009-02-04 21:48:49 UTC (rev 6878) +++ trunk/matplotlib/lib/matplotlib/offsetbox.py 2009-02-05 04:47:26 UTC (rev 6879) @@ -38,7 +38,7 @@ total width and the x-offset positions of each items according to *mode*. xdescent is analagous to the usual descent, but along the x-direction. xdescent values are currently ignored. - + *wd_list* : list of (width, xdescent) of boxes to be packed. *sep* : spacing between boxes *total* : Intended total length. None if not used. @@ -47,14 +47,14 @@ w_list, d_list = zip(*wd_list) # d_list is currently not used. - + if mode == "fixed": offsets_ = np.add.accumulate([0]+[w + sep for w in w_list]) offsets = offsets_[:-1] if total is None: total = offsets_[-1] - sep - + return total, offsets elif mode == "expand": @@ -86,7 +86,7 @@ total width and the offset positions of each items according to *mode*. xdescent is analagous to the usual descent, but along the x-direction. xdescent values are currently ignored. - + *hd_list* : list of (width, xdescent) of boxes to be aligned. *sep* : spacing between boxes *height* : Intended total length. None if not used. @@ -120,13 +120,13 @@ class OffsetBox(martist.Artist): """ The OffsetBox is a simple container artist. The child artist are meant - to be drawn at a relative position to its parent. + to be drawn at a relative position to its parent. """ def __init__(self, *args, **kwargs): super(OffsetBox, self).__init__(*args, **kwargs) - - self._children = [] + + self._children = [] self._offset = (0, 0) def set_figure(self, fig): @@ -138,7 +138,7 @@ martist.Artist.set_figure(self, fig) for c in self.get_children(): c.set_figure(fig) - + def set_offset(self, xy): """ Set the offset @@ -173,7 +173,7 @@ accepts float """ self.height = height - + def get_children(self): """ Return a list of artists it contains. @@ -213,8 +213,8 @@ c.draw(renderer) bbox_artist(self, renderer, fill=False, props=dict(pad=0.)) - + class PackerBase(OffsetBox): def __init__(self, pad=None, sep=None, width=None, height=None, align=None, mode=None, @@ -224,8 +224,14 @@ *sep* : spacing between items *width*, *height* : width and height of the container box. calculated if None. - *align* : alignment of boxes + *align* : alignment of boxes. Can be one of 'top', 'bottom', + 'left', 'right', 'center' and 'baseline' *mode* : packing mode + + .. note:: + *pad* and *sep* need to given in points and will be + scale with the renderer dpi, while *width* and *hight* + need to be in pixels. """ super(PackerBase, self).__init__() @@ -254,9 +260,14 @@ calculated if None. *align* : alignment of boxes *mode* : packing mode + + .. note:: + *pad* and *sep* need to given in points and will be + scale with the renderer dpi, while *width* and *hight* + need to be in pixels. """ super(VPacker, self).__init__(pad, sep, width, height, - align, mode, + align, mode, children) @@ -266,6 +277,10 @@ update offset of childrens and return the extents of the box """ + dpicor = renderer.points_to_pixels(1.) + pad = self.pad * dpicor + sep = self.sep * dpicor + whd_list = [c.get_extent(renderer) for c in self.get_children()] whd_list = [(w, h, xd, (h-yd)) for w, h, xd, yd in whd_list] @@ -277,8 +292,8 @@ pack_list = [(h, yd) for w,h,xd,yd in whd_list] height, yoffsets_ = _get_packed_offsets(pack_list, self.height, - self.sep, self.mode) - + sep, self.mode) + yoffsets = yoffsets_ + [yd for w,h,xd,yd in whd_list] ydescent = height - yoffsets[0] yoffsets = height - yoffsets @@ -286,8 +301,9 @@ #w, h, xd, h_yd = whd_list[-1] yoffsets = yoffsets - ydescent - return width + 2*self.pad, height + 2*self.pad, \ - xdescent+self.pad, ydescent+self.pad, \ + + return width + 2*pad, height + 2*pad, \ + xdescent+pad, ydescent+pad, \ zip(xoffsets, yoffsets) @@ -296,7 +312,7 @@ The HPacker has its children packed horizontally. It automatically adjust the relative postisions of children in the drawing time. """ - def __init__(self, pad=None, sep=None, width=None, height=None, + def __init__(self, pad=None, sep=None, width=None, height=None, align="baseline", mode="fixed", children=None): """ @@ -306,6 +322,11 @@ calculated if None. *align* : alignment of boxes *mode* : packing mode + + .. note:: + *pad* and *sep* need to given in points and will be + scale with the renderer dpi, while *width* and *hight* + need to be in pixels. """ super(HPacker, self).__init__(pad, sep, width, height, align, mode, children) @@ -316,14 +337,18 @@ update offset of childrens and return the extents of the box """ + dpicor = renderer.points_to_pixels(1.) + pad = self.pad * dpicor + sep = self.sep * dpicor + whd_list = [c.get_extent(renderer) for c in self.get_children()] if self.height is None: - height_descent = max([h-yd for w,h,xd,yd in whd_list]) + height_descent = max([h-yd for w,h,xd,yd in whd_list]) ydescent = max([yd for w,h,xd,yd in whd_list]) height = height_descent + ydescent else: - height = self.height - 2*self._pad # width w/o pad + height = self.height - 2*pad # width w/o pad hd_list = [(h, yd) for w, h, xd, yd in whd_list] height, ydescent, yoffsets = _get_aligned_offsets(hd_list, @@ -333,26 +358,26 @@ pack_list = [(w, xd) for w,h,xd,yd in whd_list] width, xoffsets_ = _get_packed_offsets(pack_list, self.width, - self.sep, self.mode) + sep, self.mode) xoffsets = xoffsets_ + [xd for w,h,xd,yd in whd_list] xdescent=whd_list[0][2] xoffsets = xoffsets - xdescent - - return width + 2*self.pad, height + 2*self.pad, \ - xdescent + self.pad, ydescent + self.pad, \ + + return width + 2*pad, height + 2*pad, \ + xdescent + pad, ydescent + pad, \ zip(xoffsets, yoffsets) - + class DrawingArea(OffsetBox): """ The DrawingArea can contain any Artist as a child. The DrawingArea has a fixed width and height. The position of children relative to the parent is fixed. """ - + def __init__(self, width, height, xdescent=0., ydescent=0., clip=True): """ @@ -371,13 +396,16 @@ self.offset_transform.clear() self.offset_transform.translate(0, 0) + self.dpi_transform = mtransforms.Affine2D() + + def get_transform(self): """ Return the :class:`~matplotlib.transforms.Transform` applied to the children """ - return self.offset_transform + return self.dpi_transform + self.offset_transform def set_transform(self, t): """ @@ -404,7 +432,7 @@ """ return self._offset - + def get_window_extent(self, renderer): ''' get the bounding box in display space. @@ -418,10 +446,13 @@ """ Return with, height, xdescent, ydescent of box """ - return self.width, self.height, self.xdescent, self.ydescent + dpi_cor = renderer.points_to_pixels(1.) + return self.width*dpi_cor, self.height*dpi_cor, \ + self.xdescent*dpi_cor, self.ydescent*dpi_cor + def add_artist(self, a): 'Add any :class:`~matplotlib.artist.Artist` to the container box' self._children.append(a) @@ -433,6 +464,10 @@ Draw the children """ + dpi_cor = renderer.points_to_pixels(1.) + self.dpi_transform.clear() + self.dpi_transform.scale(dpi_cor, dpi_cor) + for c in self._children: c.draw(renderer) @@ -448,7 +483,7 @@ """ - + def __init__(self, s, textprops=None, multilinebaseline=None, @@ -473,8 +508,8 @@ OffsetBox.__init__(self) self._children = [self._text] - + self.offset_transform = mtransforms.Affine2D() self.offset_transform.clear() self.offset_transform.translate(0, 0) @@ -483,8 +518,8 @@ self._multilinebaseline = multilinebaseline self._minimumdescent = minimumdescent - + def set_multilinebaseline(self, t): """ Set multilinebaseline . @@ -507,7 +542,7 @@ """ Set minimumdescent . - If True, extent of the single line text is adjusted so that + If True, extent of the single line text is adjusted so that it has minimum descent of "p" """ self._minimumdescent = t @@ -545,7 +580,7 @@ """ return self._offset - + def get_window_extent(self, renderer): ''' get the bounding box in display space. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2009-02-05 16:01:02
|
Revision: 6882 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6882&view=rev Author: mdboom Date: 2009-02-05 16:00:51 +0000 (Thu, 05 Feb 2009) Log Message: ----------- Speed up nan-handling on curves. Add test case for this. Modified Paths: -------------- trunk/matplotlib/examples/pylab_examples/simplification_clipping_test.py trunk/matplotlib/src/path_converters.h Modified: trunk/matplotlib/examples/pylab_examples/simplification_clipping_test.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/simplification_clipping_test.py 2009-02-05 15:35:24 UTC (rev 6881) +++ trunk/matplotlib/examples/pylab_examples/simplification_clipping_test.py 2009-02-05 16:00:51 UTC (rev 6882) @@ -1,5 +1,8 @@ from pylab import * import numpy as np +from matplotlib import patches, path +nan = np.nan +Path = path.Path t = arange(0.0, 2.0, 0.01) s = sin(2*pi*t) @@ -55,4 +58,15 @@ title("Original length: %d, simplified length: %d" % (len(path.vertices), len(simplified))) +figure() +pp1 = patches.PathPatch( + Path([(0, 0), (1, 0), (1, 1), (nan, 1), (0, 0), (2, 0), (2, 2), (0, 0)], + [Path.MOVETO, Path.CURVE3, Path.CURVE3, Path.CURVE3, Path.CURVE3, Path.CURVE3, Path.CURVE3, Path.CLOSEPOLY]), + fc="none") + +gca().add_patch(pp1) +gca().set_xlim((0, 2)) +gca().set_ylim((0, 2)) +title("Should be one line with two curves below it") + show() Modified: trunk/matplotlib/src/path_converters.h =================================================================== --- trunk/matplotlib/src/path_converters.h 2009-02-05 15:35:24 UTC (rev 6881) +++ trunk/matplotlib/src/path_converters.h 2009-02-05 16:00:51 UTC (rev 6882) @@ -149,7 +149,7 @@ return code; } - bool skipped = false; + bool needs_move_to = false; while (true) { code = m_source->vertex(x, y); if (code == agg::path_cmd_stop || @@ -158,38 +158,38 @@ return code; } + if (needs_move_to) { + queue_push(agg::path_cmd_move_to, *x, *y); + } + size_t num_extra_points = num_extra_points_map[code & 0xF]; bool has_nan = (MPL_notisfinite64(*x) || MPL_notisfinite64(*y)); - double xc[2], yc[2]; + queue_push(code, *x, *y); /* Note: this test can not be short-circuited, since we need to advance through the entire curve no matter what */ for (size_t i = 0; i < num_extra_points; ++i) { - m_source->vertex(&xc[i], &yc[i]); - has_nan |= (MPL_notisfinite64(xc[i]) || MPL_notisfinite64(yc[i])); + m_source->vertex(x, y); + has_nan |= (MPL_notisfinite64(*x) || MPL_notisfinite64(*y)); + queue_push(code, *x, *y); } - if (has_nan) + if (!has_nan) { - skipped = true; + break; } - else - { - if (skipped) - { - queue_push(agg::path_cmd_move_to, *x, *y); - } - if (!skipped || code != agg::path_cmd_line_to) { - queue_push(code, *x, *y); - for (size_t i = 0; i < num_extra_points; ++i) - { - queue_push(code, xc[i], yc[i]); - } - } + queue_clear(); - break; + if (!(MPL_notisfinite64(*x) || MPL_notisfinite64(*y))) + { + queue_push(agg::path_cmd_move_to, *x, *y); + needs_move_to = false; } + else + { + needs_move_to = true; + } } if (queue_flush(&code, x, y)) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ry...@us...> - 2009-02-05 18:00:56
|
Revision: 6885 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6885&view=rev Author: ryanmay Date: 2009-02-05 18:00:52 +0000 (Thu, 05 Feb 2009) Log Message: ----------- Merged revisions 6883-6884 via svnmerge from https://matplotlib.svn.sourceforge.net/svnroot/matplotlib/branches/v0_98_5_maint ........ r6883 | ryanmay | 2009-02-05 11:48:37 -0600 (Thu, 05 Feb 2009) | 1 line Backport doc typo fixes from trunk. ........ r6884 | ryanmay | 2009-02-05 11:55:51 -0600 (Thu, 05 Feb 2009) | 1 line Add an example that displays all of the colormaps available. This is based on code in the scipy.org cookbook. This should make a nice addition to the gallery. ........ Added Paths: ----------- trunk/matplotlib/examples/pylab_examples/show_colormaps.py Property Changed: ---------------- trunk/matplotlib/ trunk/matplotlib/doc/pyplots/README trunk/matplotlib/doc/sphinxext/gen_gallery.py trunk/matplotlib/doc/sphinxext/gen_rst.py Property changes on: trunk/matplotlib ___________________________________________________________________ Modified: svnmerge-integrated - /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-6873 + /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-6884 Modified: svn:mergeinfo - /branches/v0_91_maint:5753-5771 /branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873 + /branches/v0_91_maint:5753-5771 /branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884 Property changes on: trunk/matplotlib/doc/pyplots/README ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873 + /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884 Property changes on: trunk/matplotlib/doc/sphinxext/gen_gallery.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873 + /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884 Property changes on: trunk/matplotlib/doc/sphinxext/gen_rst.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873 + /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884 Copied: trunk/matplotlib/examples/pylab_examples/show_colormaps.py (from rev 6884, branches/v0_98_5_maint/examples/pylab_examples/show_colormaps.py) =================================================================== --- trunk/matplotlib/examples/pylab_examples/show_colormaps.py (rev 0) +++ trunk/matplotlib/examples/pylab_examples/show_colormaps.py 2009-02-05 18:00:52 UTC (rev 6885) @@ -0,0 +1,25 @@ +# This example comes from the Cookbook on www.scipy.org. According to the +# history, Andrew Straw did the conversion from an old page, but it is +# unclear who the original author is. +import numpy as np +import matplotlib.pyplot as plt + +a = np.linspace(0, 1, 256).reshape(1,-1) +a = np.vstack((a,a)) + +# Get a list of the colormaps in matplotlib. Ignore the ones that end with +# '_r' because these are simply reversed versions of ones that don't end +# with '_r' +maps = sorted(m for m in plt.cm.datad if not m.endswith("_r")) +nmaps = len(maps) + 1 + +fig = plt.figure(figsize=(5,10)) +fig.subplots_adjust(top=0.99, bottom=0.01, left=0.2, right=0.99) +for i,m in enumerate(maps): + ax = plt.subplot(nmaps, 1, i+1) + plt.axis("off") + plt.imshow(a, aspect='auto', cmap=plt.get_cmap(m), origin='lower') + pos = list(ax.get_position().bounds) + fig.text(pos[0] - 0.01, pos[1], m, fontsize=10, horizontalalignment='right') + +plt.show() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ry...@us...> - 2009-02-06 02:51:28
|
Revision: 6887 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6887&view=rev Author: ryanmay Date: 2009-02-06 02:51:24 +0000 (Fri, 06 Feb 2009) Log Message: ----------- Merged revisions 6886 via svnmerge from https://matplotlib.svn.sourceforge.net/svnroot/matplotlib/branches/v0_98_5_maint ........ r6886 | ryanmay | 2009-02-05 20:48:19 -0600 (Thu, 05 Feb 2009) | 1 line Fix missing colon in reference to patches. Thanks to Sandro Tosi. ........ Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/__init__.py Property Changed: ---------------- trunk/matplotlib/ trunk/matplotlib/doc/pyplots/README trunk/matplotlib/doc/sphinxext/gen_gallery.py trunk/matplotlib/doc/sphinxext/gen_rst.py Property changes on: trunk/matplotlib ___________________________________________________________________ Modified: svnmerge-integrated - /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-6884 + /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-6886 Modified: svn:mergeinfo - /branches/v0_91_maint:5753-5771 /branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884 + /branches/v0_91_maint:5753-5771 /branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886 Property changes on: trunk/matplotlib/doc/pyplots/README ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884 + /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886 Property changes on: trunk/matplotlib/doc/sphinxext/gen_gallery.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884 + /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886 Property changes on: trunk/matplotlib/doc/sphinxext/gen_rst.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884 + /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886 Modified: trunk/matplotlib/lib/matplotlib/__init__.py =================================================================== --- trunk/matplotlib/lib/matplotlib/__init__.py 2009-02-06 02:48:19 UTC (rev 6886) +++ trunk/matplotlib/lib/matplotlib/__init__.py 2009-02-06 02:51:24 UTC (rev 6887) @@ -36,7 +36,7 @@ defines the :class:`~matplotlib.lines.Line2D` class for drawing lines and markers - :mod`matplotlib.patches` + :mod:`matplotlib.patches` defines classes for drawing polygons :mod:`matplotlib.text` This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ef...@us...> - 2009-02-07 21:19:16
|
Revision: 6889 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6889&view=rev Author: efiring Date: 2009-02-07 21:19:11 +0000 (Sat, 07 Feb 2009) Log Message: ----------- Restore interpolation in polar_bar plot, and update docstring in pyplot Modified Paths: -------------- trunk/matplotlib/examples/pylab_examples/polar_bar.py trunk/matplotlib/lib/matplotlib/pyplot.py Modified: trunk/matplotlib/examples/pylab_examples/polar_bar.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/polar_bar.py 2009-02-06 13:12:38 UTC (rev 6888) +++ trunk/matplotlib/examples/pylab_examples/polar_bar.py 2009-02-07 21:19:11 UTC (rev 6889) @@ -7,7 +7,7 @@ # force square figure and square axes looks better for polar, IMO fig = figure(figsize=(8,8)) -ax = fig.add_axes([0.1, 0.1, 0.8, 0.8], polar=True) +ax = fig.add_axes([0.1, 0.1, 0.8, 0.8], polar=True, resolution=50) N = 20 theta = np.arange(0.0, 2*np.pi, 2*np.pi/N) Modified: trunk/matplotlib/lib/matplotlib/pyplot.py =================================================================== --- trunk/matplotlib/lib/matplotlib/pyplot.py 2009-02-06 13:12:38 UTC (rev 6888) +++ trunk/matplotlib/lib/matplotlib/pyplot.py 2009-02-07 21:19:11 UTC (rev 6889) @@ -1418,8 +1418,8 @@ with format strings, as in :func:`~matplotlib.pyplot.plot`. An optional kwarg *resolution* sets the number of vertices to - interpolate between each pair of points. Set to 1 to disable - interpolation. + interpolate between each pair of points. The default is 1, + which disables interpolation. """ resolution = kwargs.pop('resolution', None) ax = gca(polar=True, resolution=resolution) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2009-02-09 13:32:37
|
Revision: 6893 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6893&view=rev Author: mdboom Date: 2009-02-09 13:32:34 +0000 (Mon, 09 Feb 2009) Log Message: ----------- Merged revisions 6890-6891 via svnmerge from https://matplotlib.svn.sf.net/svnroot/matplotlib/branches/v0_98_5_maint ........ r6890 | jdh2358 | 2009-02-08 15:29:42 -0500 (Sun, 08 Feb 2009) | 1 line bumped the version number for bugfix release ........ r6891 | mdboom | 2009-02-09 08:15:45 -0500 (Mon, 09 Feb 2009) | 2 lines Fix URLs in matplotlibrc.template (thanks, Sandro Tosi) ........ Modified Paths: -------------- trunk/matplotlib/matplotlibrc.template Property Changed: ---------------- trunk/matplotlib/ trunk/matplotlib/doc/pyplots/README trunk/matplotlib/doc/sphinxext/gen_gallery.py trunk/matplotlib/doc/sphinxext/gen_rst.py Property changes on: trunk/matplotlib ___________________________________________________________________ Modified: svnmerge-integrated - /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-6886 + /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-6892 Modified: svn:mergeinfo - /branches/v0_91_maint:5753-5771 /branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886 + /branches/v0_91_maint:5753-5771 /branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891 Property changes on: trunk/matplotlib/doc/pyplots/README ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886 + /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891 Property changes on: trunk/matplotlib/doc/sphinxext/gen_gallery.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886 + /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891 Property changes on: trunk/matplotlib/doc/sphinxext/gen_rst.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886 + /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891 Modified: trunk/matplotlib/matplotlibrc.template =================================================================== --- trunk/matplotlib/matplotlibrc.template 2009-02-09 13:31:18 UTC (rev 6892) +++ trunk/matplotlib/matplotlibrc.template 2009-02-09 13:32:34 UTC (rev 6893) @@ -35,7 +35,7 @@ # you if backend_fallback is True #backend_fallback: True numerix : %(numerix)s # numpy, Numeric or numarray -#interactive : False # see http://matplotlib.sourceforge.net/interactive.html +#interactive : False #toolbar : toolbar2 # None | classic | toolbar2 #timezone : UTC # a pytz timezone string, eg US/Central or Europe/Paris @@ -45,7 +45,7 @@ ### LINES -# See http://matplotlib.sourceforge.net/matplotlib.lines.html for more +# See http://matplotlib.sourceforge.net/api/artist_api.html#module-matplotlib.lines for more # information on line properties. #lines.linewidth : 1.0 # line width in points #lines.linestyle : - # solid line @@ -62,7 +62,7 @@ ### PATCHES # Patches are graphical objects that fill 2D space, like polygons or # circles. See -# http://matplotlib.sourceforge.net/matplotlib.patches.html for more +# http://matplotlib.sourceforge.net/api/artist_api.html#module-matplotlib.patches # information on patch properties #patch.linewidth : 1.0 # edge width in points #patch.facecolor : blue @@ -72,7 +72,7 @@ ### FONT # # font properties used by text.Text. See -# http://matplotlib.sourceforge.net/matplotlib.font_manager.html for more +# http://matplotlib.sourceforge.net/api/font_manager_api.html for more # information on font properties. The 6 font properties used for font # matching are given below with their default values. # @@ -123,7 +123,7 @@ ### TEXT # text properties used by text.Text. See -# http://matplotlib.sourceforge.net/matplotlib.text.html for more +# http://matplotlib.sourceforge.net/api/artist_api.html#module-matplotlib.text for more # information on text properties #text.color : black @@ -193,7 +193,7 @@ ### AXES # default face and edge color, default tick sizes, # default fontsizes for ticklabels, and so on. See -# http://matplotlib.sourceforge.net/matplotlib.axes.html#Axes +# http://matplotlib.sourceforge.net/api/axes_api.html#module-matplotlib.axes #axes.hold : True # whether to clear the axes by default on #axes.facecolor : white # axes background color #axes.edgecolor : black # axes edge color @@ -213,7 +213,7 @@ #polaraxes.grid : True # display grid on polar axes ### TICKS -# see http://matplotlib.sourceforge.net/matplotlib.axis.html#Ticks +# see http://matplotlib.sourceforge.net/api/axis_api.html#matplotlib.axis.Tick #xtick.major.size : 4 # major tick size in points #xtick.minor.size : 2 # minor tick size in points #xtick.major.pad : 4 # distance to major tick label in points @@ -253,7 +253,7 @@ #legend.shadow : False ### FIGURE -# See http://matplotlib.sourceforge.net/matplotlib.figure.html#Figure +# See http://matplotlib.sourceforge.net/api/figure_api.html#matplotlib.figure.Figure #figure.figsize : 8, 6 # figure size in inches #figure.dpi : 80 # figure dots per inch #figure.facecolor : 0.75 # figure facecolor; 0.75 is scalar gray This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <as...@us...> - 2009-02-10 04:43:27
|
Revision: 6899 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6899&view=rev Author: astraw Date: 2009-02-10 04:43:23 +0000 (Tue, 10 Feb 2009) Log Message: ----------- Add imsave() to matplotlib.image, pyplot, and pylab. Patch from Gary Ruben. Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/doc/_templates/index.html trunk/matplotlib/doc/api/api_changes.rst trunk/matplotlib/lib/matplotlib/image.py trunk/matplotlib/lib/matplotlib/pylab.py trunk/matplotlib/lib/matplotlib/pyplot.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009-02-09 23:05:22 UTC (rev 6898) +++ trunk/matplotlib/CHANGELOG 2009-02-10 04:43:23 UTC (rev 6899) @@ -1,3 +1,6 @@ +2009-02-08 Added a new imsave function to image.py and exposed it in + the pyplot interface - GR + 2009-02-04 Some reorgnization of the legend code. anchored_text.py added as an example. - JJL Modified: trunk/matplotlib/doc/_templates/index.html =================================================================== --- trunk/matplotlib/doc/_templates/index.html 2009-02-09 23:05:22 UTC (rev 6898) +++ trunk/matplotlib/doc/_templates/index.html 2009-02-10 04:43:23 UTC (rev 6899) @@ -567,6 +567,17 @@ </tr> <tr> <th align="left"> + <a href="api/pyplot_api.html#matplotlib.pyplot.imsave">imsave</a> + + </th> + + <td align="left"> + save array as an image file + </td> + + </tr> + <tr> + <th align="left"> <a href="api/pyplot_api.html#matplotlib.pyplot.imshow">imshow</a> </th> Modified: trunk/matplotlib/doc/api/api_changes.rst =================================================================== --- trunk/matplotlib/doc/api/api_changes.rst 2009-02-09 23:05:22 UTC (rev 6898) +++ trunk/matplotlib/doc/api/api_changes.rst 2009-02-10 04:43:23 UTC (rev 6899) @@ -19,6 +19,9 @@ Changes for 0.98.x ================== +* Added new :func:`matplotlib.image.imsave` and exposed it to the + :mod:`matplotlib.pyplot` interface. + * Remove support for pyExcelerator in exceltools -- use xlwt instead Modified: trunk/matplotlib/lib/matplotlib/image.py =================================================================== --- trunk/matplotlib/lib/matplotlib/image.py 2009-02-09 23:05:22 UTC (rev 6898) +++ trunk/matplotlib/lib/matplotlib/image.py 2009-02-10 04:43:23 UTC (rev 6899) @@ -747,7 +747,43 @@ return handler(fname) +def imsave(fname, arr, vmin=None, vmax=None, cmap=None, format=None, origin=None): + """ + Saves a 2D :class:`numpy.array` as an image with one pixel per element. + The output formats available depend on the backend being used. + Arguments: + *fname*: + A string containing a path to a filename, or a Python file-like object. + If *format* is *None* and *fname* is a string, the output + format is deduced from the extension of the filename. + *arr*: + A 2D array. + Keyword arguments: + *vmin*/*vmax*: [ None | scalar ] + *vmin* and *vmax* set the color scaling for the image by fixing the + values that map to the colormap color limits. If either *vmin* or *vmax* + is None, that limit is determined from the *arr* min/max value. + *cmap*: + cmap is a colors.Colormap instance, eg cm.jet. + If None, default to the rc image.cmap value. + *format*: + One of the file extensions supported by the active + backend. Most backends support png, pdf, ps, eps and svg. + *origin* + [ 'upper' | 'lower' ] Indicates where the [0,0] index of + the array is in the upper left or lower left corner of + the axes. Defaults to the rc image.origin value. + """ + from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas + from matplotlib.figure import Figure + + fig = Figure(figsize=arr.shape[::-1], dpi=1, frameon=False) + canvas = FigureCanvas(fig) + fig.figimage(arr, cmap=cmap, vmin=vmin, vmax=vmax, origin=origin) + fig.savefig(fname, dpi=1, format=format) + + def pil_to_array( pilImage ): """ load a PIL image and return it as a numpy array of uint8. For Modified: trunk/matplotlib/lib/matplotlib/pylab.py =================================================================== --- trunk/matplotlib/lib/matplotlib/pylab.py 2009-02-09 23:05:22 UTC (rev 6898) +++ trunk/matplotlib/lib/matplotlib/pylab.py 2009-02-10 04:43:23 UTC (rev 6899) @@ -50,6 +50,7 @@ ion - turn interaction mode on isinteractive - return True if interaction mode is on imread - load image file into array + imsave - save array as an image file imshow - plot image data ishold - return the hold state of the current axes legend - make an axes legend Modified: trunk/matplotlib/lib/matplotlib/pyplot.py =================================================================== --- trunk/matplotlib/lib/matplotlib/pyplot.py 2009-02-09 23:05:22 UTC (rev 6898) +++ trunk/matplotlib/lib/matplotlib/pyplot.py 2009-02-10 04:43:23 UTC (rev 6899) @@ -6,6 +6,7 @@ from matplotlib.figure import Figure, figaspect from matplotlib.backend_bases import FigureCanvasBase from matplotlib.image import imread as _imread +from matplotlib.image import imsave as _imsave from matplotlib import rcParams, rcParamsDefault, get_backend from matplotlib.rcsetup import interactive_bk as _interactive_bk from matplotlib.artist import getp, get, Artist @@ -1181,6 +1182,7 @@ legend add a legend to the axes loglog a log log plot imread load image file into array + imsave save array as an image file imshow plot image data matshow display a matrix in a new figure preserving aspect pcolor make a pseudocolor plot @@ -1230,7 +1232,7 @@ def get_plot_commands(): return ( 'axes', 'axis', 'bar', 'boxplot', 'cla', 'clf', 'close', 'colorbar', 'cohere', 'csd', 'draw', 'errorbar', 'figlegend', 'figtext', 'figimage', 'figure', 'fill', 'gca', - 'gcf', 'gci', 'get', 'gray', 'barh', 'jet', 'hist', 'hold', 'imread', + 'gcf', 'gci', 'get', 'gray', 'barh', 'jet', 'hist', 'hold', 'imread', 'imsave', 'imshow', 'legend', 'loglog', 'quiver', 'rc', 'pcolor', 'pcolormesh', 'plot', 'psd', 'savefig', 'scatter', 'set', 'semilogx', 'semilogy', 'show', 'specgram', 'stem', 'subplot', 'table', 'text', 'title', 'xlabel', @@ -1370,6 +1372,11 @@ if _imread.__doc__ is not None: imread.__doc__ = dedent(_imread.__doc__) +def imsave(*args, **kwargs): + return _imsave(*args, **kwargs) +if _imsave.__doc__ is not None: + imsave.__doc__ = dedent(_imsave.__doc__) + def matshow(A, fignum=None, **kw): """ Display an array as a matrix in a new figure window. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jo...@us...> - 2009-02-10 23:02:15
|
Revision: 6904 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6904&view=rev Author: jouni Date: 2009-02-10 22:16:35 +0000 (Tue, 10 Feb 2009) Log Message: ----------- Commit Nicolas Grilly's use14corefonts patch Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py Added Paths: ----------- trunk/matplotlib/unit/test_pdf_use14corefonts.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009-02-10 16:09:38 UTC (rev 6903) +++ trunk/matplotlib/CHANGELOG 2009-02-10 22:16:35 UTC (rev 6904) @@ -1,3 +1,7 @@ +2009-02-10 Fixed a bug in backend_pdf so it doesn't break when the setting + pdf.use14corefonts=True is used. Added test case in + unit/test_pdf_use14corefonts.py. - NGR + 2009-02-08 Added a new imsave function to image.py and exposed it in the pyplot interface - GR Modified: trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2009-02-10 16:09:38 UTC (rev 6903) +++ trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2009-02-10 22:16:35 UTC (rev 6904) @@ -1465,7 +1465,7 @@ self.draw_path(boxgc, path, mytrans, gc._rgb) def encode_string(self, s, fonttype): - if fonttype == 3: + if fonttype in (1, 3): return s.encode('cp1252', 'replace') return s.encode('utf-16be', 'replace') @@ -1492,7 +1492,7 @@ font = self._get_font_afm(prop) l, b, w, h = font.get_str_bbox(s) descent = -b * fontsize / 1000 - fonttype = 42 + fonttype = 1 else: font = self._get_font_ttf(prop) self.track_characters(font, s) @@ -1627,9 +1627,9 @@ font = self._get_font_afm(prop) l, b, w, h, d = font.get_str_bbox_and_descent(s) scale = prop.get_size_in_points() - w *= scale - h *= scale - d *= scale + w *= scale / 1000 + h *= scale / 1000 + d *= scale / 1000 else: font = self._get_font_ttf(prop) font.set_text(s, 0.0, flags=LOAD_NO_HINTING) Added: trunk/matplotlib/unit/test_pdf_use14corefonts.py =================================================================== --- trunk/matplotlib/unit/test_pdf_use14corefonts.py (rev 0) +++ trunk/matplotlib/unit/test_pdf_use14corefonts.py 2009-02-10 22:16:35 UTC (rev 6904) @@ -0,0 +1,25 @@ +# encoding: utf-8 + +import matplotlib +matplotlib.use('PDF') + +from matplotlib import rcParams +import pylab + +rcParams['pdf.use14corefonts'] = True +rcParams['font.family'] = 'sans-serif' +rcParams['font.size'] = 8 +rcParams['font.sans-serif'] = ['Helvetica'] + +title = u'Test PDF backend with option use14corefonts=True' + +text = u'''A three-line text positioned just above a blue line +and containing some French characters and the euro symbol: +"Merci pépé pour les 10 €"''' + +pylab.figure(figsize=(6, 4)) +pylab.title(title) +pylab.text(0.5, 0.5, text, horizontalalignment='center') +pylab.axhline(0.5, linewidth=0.5) +pylab.savefig('test_pdf_use14corefonts.pdf') +pylab.close() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ry...@us...> - 2009-02-12 21:24:39
|
Revision: 6910 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6910&view=rev Author: ryanmay Date: 2009-02-12 21:24:36 +0000 (Thu, 12 Feb 2009) Log Message: ----------- Merged revisions 6906-6907,6909 via svnmerge from https://matplotlib.svn.sourceforge.net/svnroot/matplotlib/branches/v0_98_5_maint ........ r6906 | ryanmay | 2009-02-12 14:05:10 -0600 (Thu, 12 Feb 2009) | 1 line Add a demo for getting notified of an Axes' change in view limits. ........ r6907 | ryanmay | 2009-02-12 14:06:50 -0600 (Thu, 12 Feb 2009) | 1 line Remove trailing whitespace. ........ r6909 | ryanmay | 2009-02-12 15:20:09 -0600 (Thu, 12 Feb 2009) | 1 line Make viewlims demo more interesting by using events to regenerate a fractal. ........ Modified Paths: -------------- trunk/matplotlib/doc/users/event_handling.rst Added Paths: ----------- trunk/matplotlib/examples/event_handling/viewlims.py Property Changed: ---------------- trunk/matplotlib/ Property changes on: trunk/matplotlib ___________________________________________________________________ Modified: svnmerge-integrated - /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-6892 + /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-6909 Modified: svn:mergeinfo - /branches/v0_91_maint:5753-5771 /branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891 + /branches/v0_91_maint:5753-5771 /branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909 Modified: trunk/matplotlib/doc/users/event_handling.rst =================================================================== --- trunk/matplotlib/doc/users/event_handling.rst 2009-02-12 21:20:09 UTC (rev 6909) +++ trunk/matplotlib/doc/users/event_handling.rst 2009-02-12 21:24:36 UTC (rev 6910) @@ -552,11 +552,4 @@ fig.canvas.mpl_connect('pick_event', onpick) - plt.show() - - - - - - - + plt.show() Copied: trunk/matplotlib/examples/event_handling/viewlims.py (from rev 6909, branches/v0_98_5_maint/examples/event_handling/viewlims.py) =================================================================== --- trunk/matplotlib/examples/event_handling/viewlims.py (rev 0) +++ trunk/matplotlib/examples/event_handling/viewlims.py 2009-02-12 21:24:36 UTC (rev 6910) @@ -0,0 +1,79 @@ +# Creates two identical panels. Zooming in on the right panel will show +# a rectangle in the first panel, denoting the zoomed region. +import numpy as np +import matplotlib.pyplot as plt +from matplotlib.patches import Rectangle + +# We just subclass Rectangle so that it can be called with an Axes +# instance, causing the rectangle to update its shape to match the +# bounds of the Axes +class UpdatingRect(Rectangle): + def __call__(self, ax): + self.set_bounds(*ax.viewLim.bounds) + ax.figure.canvas.draw_idle() + +# A class that will regenerate a fractal set as we zoom in, so that you +# can actually see the increasing detail. A box in the left panel will show +# the area to which we are zoomed. +class MandlebrotDisplay(object): + def __init__(self, h=500, w=500, niter=50, radius=2., power=2): + self.height = h + self.width = w + self.niter = niter + self.radius = radius + self.power = power + + def __call__(self, xstart, xend, ystart, yend): + self.x = np.linspace(xstart, xend, self.width) + self.y = np.linspace(ystart, yend, self.height).reshape(-1,1) + c = self.x + 1.0j * self.y + threshold_time = np.zeros((self.height, self.width)) + z = np.zeros(threshold_time.shape, dtype=np.complex) + mask = np.ones(threshold_time.shape, dtype=np.bool) + for i in xrange(self.niter): + z[mask] = z[mask]**self.power + c[mask] + mask = (np.abs(z) < self.radius) + threshold_time += mask + return threshold_time + + def ax_update(self, ax): + ax.set_autoscale_on(False) # Otherwise, infinite loop + + #Get the number of points from the number of pixels in the window + dims = ax.axesFrame.get_window_extent().bounds + self.width = int(dims[2] + 0.5) + self.height = int(dims[2] + 0.5) + + #Get the range for the new area + xstart,ystart,xdelta,ydelta = ax.viewLim.bounds + xend = xstart + xdelta + yend = ystart + ydelta + + # Update the image object with our new data and extent + im = ax.images[-1] + im.set_data(self.__call__(xstart, xend, ystart, yend)) + im.set_extent((xstart, xend, ystart, yend)) + ax.figure.canvas.draw_idle() + +md = MandlebrotDisplay() +Z = md(-2., 0.5, -1.25, 1.25) + +fig = plt.figure() +ax1 = fig.add_subplot(1, 2, 1) +ax1.imshow(Z, origin='lower', extent=(md.x.min(), md.x.max(), md.y.min(), md.y.max())) + +ax2 = fig.add_subplot(1, 2, 2) +ax2.imshow(Z, origin='lower', extent=(md.x.min(), md.x.max(), md.y.min(), md.y.max())) + +rect = UpdatingRect([0, 0], 0, 0, facecolor='None', edgecolor='black') +rect.set_bounds(*ax2.viewLim.bounds) +ax1.add_patch(rect) + +# Connect for changing the view limits +ax2.callbacks.connect('xlim_changed', rect) +ax2.callbacks.connect('ylim_changed', rect) + +ax2.callbacks.connect('xlim_changed', md.ax_update) +ax2.callbacks.connect('ylim_changed', md.ax_update) + +plt.show() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ry...@us...> - 2009-02-13 18:21:41
|
Revision: 6913 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6913&view=rev Author: ryanmay Date: 2009-02-13 18:21:37 +0000 (Fri, 13 Feb 2009) Log Message: ----------- Merged revisions 6911-6912 via svnmerge from https://matplotlib.svn.sourceforge.net/svnroot/matplotlib/branches/v0_98_5_maint ........ r6911 | ryanmay | 2009-02-13 11:54:52 -0600 (Fri, 13 Feb 2009) | 1 line Backport fix for infinite recursion when finding the appropriate converter for a string. A lot of users seem to be hitting this. ........ r6912 | ryanmay | 2009-02-13 12:17:31 -0600 (Fri, 13 Feb 2009) | 1 line Typo in docstring ........ Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/axes.py Property Changed: ---------------- trunk/matplotlib/ trunk/matplotlib/doc/pyplots/README trunk/matplotlib/doc/sphinxext/gen_gallery.py trunk/matplotlib/doc/sphinxext/gen_rst.py Property changes on: trunk/matplotlib ___________________________________________________________________ Modified: svnmerge-integrated - /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-6909 + /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-6912 Modified: svn:mergeinfo - /branches/v0_91_maint:5753-5771 /branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909 + /branches/v0_91_maint:5753-5771 /branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912 Property changes on: trunk/matplotlib/doc/pyplots/README ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891 + /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912 Property changes on: trunk/matplotlib/doc/sphinxext/gen_gallery.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891 + /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912 Property changes on: trunk/matplotlib/doc/sphinxext/gen_rst.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891 + /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912 Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2009-02-13 18:17:31 UTC (rev 6912) +++ trunk/matplotlib/lib/matplotlib/axes.py 2009-02-13 18:21:37 UTC (rev 6913) @@ -5933,7 +5933,7 @@ corner of the axes. If *None*, default to rc ``image.origin``. *extent*: [ None | scalars (left, right, bottom, top) ] - Eata values of the axes. The default assigns zero-based row, + Data limits for the axes. The default assigns zero-based row, column indices to the *x*, *y* centers of the pixels. *shape*: [ None | scalars (columns, rows) ] This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <lee...@us...> - 2009-02-15 00:12:33
|
Revision: 6914 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6914&view=rev Author: leejjoon Date: 2009-02-15 00:12:19 +0000 (Sun, 15 Feb 2009) Log Message: ----------- Legend title support Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/examples/pylab_examples/legend_demo3.py trunk/matplotlib/lib/matplotlib/legend.py trunk/matplotlib/lib/matplotlib/offsetbox.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009-02-13 18:21:37 UTC (rev 6913) +++ trunk/matplotlib/CHANGELOG 2009-02-15 00:12:19 UTC (rev 6914) @@ -1,3 +1,5 @@ +2009-02-14 Added the legend title support - JJL + 2009-02-10 Fixed a bug in backend_pdf so it doesn't break when the setting pdf.use14corefonts=True is used. Added test case in unit/test_pdf_use14corefonts.py. - NGR Modified: trunk/matplotlib/examples/pylab_examples/legend_demo3.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/legend_demo3.py 2009-02-13 18:21:37 UTC (rev 6913) +++ trunk/matplotlib/examples/pylab_examples/legend_demo3.py 2009-02-15 00:12:19 UTC (rev 6914) @@ -18,9 +18,9 @@ ax2 = plt.subplot(3,1,2) myplot(ax2) -ax2.legend(loc=1, ncol=2, shadow=True) +ax2.legend(loc=1, ncol=2, shadow=True, title="Legend") +ax2.get_legend().get_title().set_color("red") - ax3 = plt.subplot(3,1,3) myplot(ax3) ax3.legend(loc=1, ncol=4, mode="expand", shadow=True) Modified: trunk/matplotlib/lib/matplotlib/legend.py =================================================================== --- trunk/matplotlib/lib/matplotlib/legend.py 2009-02-13 18:21:37 UTC (rev 6913) +++ trunk/matplotlib/lib/matplotlib/legend.py 2009-02-15 00:12:19 UTC (rev 6914) @@ -110,7 +110,8 @@ mode=None, # mode for horizontal distribution of columns. None, "expand" fancybox=None, # True use a fancy box, false use a rounded box, none use rc - shadow = None, + shadow = None, + title = None, # set a title for the legend ): """ - *parent* : the artist that contains the legend @@ -135,6 +136,7 @@ handletextpad the pad between the legend handle and text borderaxespad the pad between the axes and legend border columnspacing the spacing between columns + title the legend title ================ ================================================================== The dimensions of pad and spacing are given as a fraction of the @@ -276,6 +278,8 @@ # init with null renderer self._init_legend_box(handles, labels) + self.set_title(title) + self._last_fontsize_points = self._fontsize @@ -316,6 +320,7 @@ renderer.open_group('legend') + # find_offset function will be provided to _legend_box and # _legend_box will draw itself at the location of the return # value of the find_offset. @@ -562,11 +567,19 @@ sep = self.columnspacing*fontsize - self._legend_box = HPacker(pad=self.borderpad*fontsize, - sep=sep, align="baseline", - mode=mode, - children=columnbox) + self._legend_handle_box = HPacker(pad=0, + sep=sep, align="baseline", + mode=mode, + children=columnbox) + self._legend_title_box = TextArea("") + + self._legend_box = VPacker(pad=self.borderpad*fontsize, + sep=self.labelspacing*fontsize, + align="center", + children=[self._legend_title_box, + self._legend_handle_box]) + self._legend_box.set_figure(self.figure) self.texts = text_list @@ -640,6 +653,19 @@ 'return a list of text.Text instance in the legend' return silent_list('Text', self.texts) + def set_title(self, title): + 'set the legend title' + self._legend_title_box._text.set_text(title) + + if title: + self._legend_title_box.set_visible(True) + else: + self._legend_title_box.set_visible(False) + + def get_title(self): + 'return Text instance for the legend title' + return self._legend_title_box._text + def get_window_extent(self): 'return a extent of the the legend' return self.legendPatch.get_window_extent() Modified: trunk/matplotlib/lib/matplotlib/offsetbox.py =================================================================== --- trunk/matplotlib/lib/matplotlib/offsetbox.py 2009-02-13 18:21:37 UTC (rev 6913) +++ trunk/matplotlib/lib/matplotlib/offsetbox.py 2009-02-15 00:12:19 UTC (rev 6914) @@ -174,6 +174,12 @@ """ self.height = height + def get_visible_children(self): + """ + Return a list of visible artists it contains. + """ + return [c for c in self._children if c.get_visible()] + def get_children(self): """ Return a list of artists it contains. @@ -208,7 +214,7 @@ px, py = self.get_offset(width, height, xdescent, ydescent) - for c, (ox, oy) in zip(self.get_children(), offsets): + for c, (ox, oy) in zip(self.get_visible_children(), offsets): c.set_offset((px+ox, py+oy)) c.draw(renderer) @@ -281,7 +287,12 @@ pad = self.pad * dpicor sep = self.sep * dpicor - whd_list = [c.get_extent(renderer) for c in self.get_children()] + if self.width is not None: + for c in self.get_visible_children(): + if isinstance(c, PackerBase) and c.mode == "expand": + c.set_width(self.width) + + whd_list = [c.get_extent(renderer) for c in self.get_visible_children()] whd_list = [(w, h, xd, (h-yd)) for w, h, xd, yd in whd_list] @@ -341,7 +352,7 @@ pad = self.pad * dpicor sep = self.sep * dpicor - whd_list = [c.get_extent(renderer) for c in self.get_children()] + whd_list = [c.get_extent(renderer) for c in self.get_visible_children()] if self.height is None: height_descent = max([h-yd for w,h,xd,yd in whd_list]) @@ -520,6 +531,14 @@ self._minimumdescent = minimumdescent + def set_text(self, s): + "set text" + self._text.set_text(s) + + def get_text(self): + "get text" + return self._text.get_text() + def set_multilinebaseline(self, t): """ Set multilinebaseline . This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2009-02-16 14:24:59
|
Revision: 6917 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6917&view=rev Author: mdboom Date: 2009-02-16 14:24:56 +0000 (Mon, 16 Feb 2009) Log Message: ----------- Merged revisions 6915-6916 via svnmerge from https://matplotlib.svn.sf.net/svnroot/matplotlib/branches/v0_98_5_maint ........ r6915 | mdboom | 2009-02-16 09:12:13 -0500 (Mon, 16 Feb 2009) | 2 lines Move the mathmpl Sphinx extension to the installed tree so that other projects can take advantage of it. ........ r6916 | mdboom | 2009-02-16 09:18:36 -0500 (Mon, 16 Feb 2009) | 1 line Update CHANGELOG ........ Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/doc/conf.py trunk/matplotlib/lib/matplotlib/sphinxext/__init__.py trunk/matplotlib/lib/matplotlib/sphinxext/mathmpl.py trunk/matplotlib/lib/matplotlib/sphinxext/only_directives.py trunk/matplotlib/setup.py Added Paths: ----------- trunk/matplotlib/lib/matplotlib/sphinxext/ Removed Paths: ------------- trunk/matplotlib/doc/sphinxext/mathmpl.py trunk/matplotlib/doc/sphinxext/only_directives.py Property Changed: ---------------- trunk/matplotlib/ trunk/matplotlib/doc/pyplots/README trunk/matplotlib/doc/sphinxext/gen_gallery.py trunk/matplotlib/doc/sphinxext/gen_rst.py Property changes on: trunk/matplotlib ___________________________________________________________________ Modified: svnmerge-integrated - /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-6912 + /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-6916 Modified: svn:mergeinfo - /branches/v0_91_maint:5753-5771 /branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912 + /branches/v0_91_maint:5753-5771 /branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912,6915-6916 Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009-02-16 14:18:36 UTC (rev 6916) +++ trunk/matplotlib/CHANGELOG 2009-02-16 14:24:56 UTC (rev 6917) @@ -1,3 +1,6 @@ +2009-02-16 Move mathmpl.py to the installed source tree so it is + available to other projects. - MGD + 2009-02-14 Added the legend title support - JJL 2009-02-10 Fixed a bug in backend_pdf so it doesn't break when the setting Modified: trunk/matplotlib/doc/conf.py =================================================================== --- trunk/matplotlib/doc/conf.py 2009-02-16 14:18:36 UTC (rev 6916) +++ trunk/matplotlib/doc/conf.py 2009-02-16 14:24:56 UTC (rev 6917) @@ -27,9 +27,9 @@ # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['mathmpl', 'math_symbol_table', 'sphinx.ext.autodoc', - 'only_directives', 'plot_directive', 'inheritance_diagram', - 'gen_gallery', 'gen_rst'] +extensions = ['matplotlib.sphinxext.mathmpl', 'math_symbol_table', + 'sphinx.ext.autodoc', 'matplotlib.sphinxext.only_directives', + 'plot_directive', 'inheritance_diagram', 'gen_gallery', 'gen_rst'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] Property changes on: trunk/matplotlib/doc/pyplots/README ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912 + /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916 Property changes on: trunk/matplotlib/doc/sphinxext/gen_gallery.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912 + /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916 Property changes on: trunk/matplotlib/doc/sphinxext/gen_rst.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912 + /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916 Deleted: trunk/matplotlib/doc/sphinxext/mathmpl.py =================================================================== --- trunk/matplotlib/doc/sphinxext/mathmpl.py 2009-02-16 14:18:36 UTC (rev 6916) +++ trunk/matplotlib/doc/sphinxext/mathmpl.py 2009-02-16 14:24:56 UTC (rev 6917) @@ -1,141 +0,0 @@ -"""matplotlib-based directive for math rendering in reST using sphinx. - -To use this extension, add ``mathmpl`` to the list of extensions in -:file:`conf.py`. - -Note: - -Current SVN versions of Sphinx now include built-in support for math. -There are two flavors: - - - pngmath: uses dvipng to render the equation - - - jsmath: renders the math in the browser using Javascript - -To use these extensions instead of the code in this module, add -``sphinx.ext.pngmath`` or ``sphinx.ext.jsmath`` to the list of extensions in -:file:`conf.py` instead of ``mathmpl``. - -All three of these options for math are designed to behave in the same -way. -""" - -import os -import sys -try: - from hashlib import md5 -except ImportError: - from md5 import md5 - -from docutils import nodes -from docutils.parsers.rst import directives -import warnings - -from matplotlib import rcParams -from matplotlib.mathtext import MathTextParser -rcParams['mathtext.fontset'] = 'cm' -mathtext_parser = MathTextParser("Bitmap") - -# Define LaTeX math node: -class latex_math(nodes.General, nodes.Element): - pass - -def fontset_choice(arg): - return directives.choice(arg, ['cm', 'stix', 'stixsans']) - -options_spec = {'fontset': fontset_choice} - -def math_role(role, rawtext, text, lineno, inliner, - options={}, content=[]): - i = rawtext.find('`') - latex = rawtext[i+1:-1] - node = latex_math(rawtext) - node['latex'] = latex - node['fontset'] = options.get('fontset', 'cm') - return [node], [] -math_role.options = options_spec - -def math_directive(name, arguments, options, content, lineno, - content_offset, block_text, state, state_machine): - latex = ''.join(content) - node = latex_math(block_text) - node['latex'] = latex - node['fontset'] = options.get('fontset', 'cm') - return [node] - -# This uses mathtext to render the expression -def latex2png(latex, filename, fontset='cm'): - latex = "$%s$" % latex - orig_fontset = rcParams['mathtext.fontset'] - rcParams['mathtext.fontset'] = fontset - if os.path.exists(filename): - depth = mathtext_parser.get_depth(latex, dpi=100) - else: - try: - depth = mathtext_parser.to_png(filename, latex, dpi=100) - except: - warnings.warn("Could not render math expression %s" % latex, - Warning) - depth = 0 - rcParams['mathtext.fontset'] = orig_fontset - sys.stdout.write("#") - sys.stdout.flush() - return depth - -# LaTeX to HTML translation stuff: -def latex2html(node, source): - inline = isinstance(node.parent, nodes.TextElement) - latex = node['latex'] - name = 'math-%s' % md5(latex).hexdigest()[-10:] - - destdir = os.path.join(setup.app.builder.outdir, '_images', 'mathmpl') - if not os.path.exists(destdir): - os.makedirs(destdir) - dest = os.path.join(destdir, '%s.png' % name) - path = os.path.join(setup.app.builder.imgpath, 'mathmpl') - - depth = latex2png(latex, dest, node['fontset']) - - if inline: - cls = '' - else: - cls = 'class="center" ' - if inline and depth != 0: - style = 'style="position: relative; bottom: -%dpx"' % (depth + 1) - else: - style = '' - - return '<img src="%s/%s.png" %s%s/>' % (path, name, cls, style) - -def setup(app): - setup.app = app - - app.add_node(latex_math) - app.add_role('math', math_role) - - # Add visit/depart methods to HTML-Translator: - def visit_latex_math_html(self, node): - source = self.document.attributes['source'] - self.body.append(latex2html(node, source)) - def depart_latex_math_html(self, node): - pass - - # Add visit/depart methods to LaTeX-Translator: - def visit_latex_math_latex(self, node): - inline = isinstance(node.parent, nodes.TextElement) - if inline: - self.body.append('$%s$' % node['latex']) - else: - self.body.extend(['\\begin{equation}', - node['latex'], - '\\end{equation}']) - def depart_latex_math_latex(self, node): - pass - - app.add_node(latex_math, html=(visit_latex_math_html, - depart_latex_math_html)) - app.add_node(latex_math, latex=(visit_latex_math_latex, - depart_latex_math_latex)) - app.add_role('math', math_role) - app.add_directive('math', math_directive, - True, (0, 0, 0), **options_spec) Deleted: trunk/matplotlib/doc/sphinxext/only_directives.py =================================================================== --- trunk/matplotlib/doc/sphinxext/only_directives.py 2009-02-16 14:18:36 UTC (rev 6916) +++ trunk/matplotlib/doc/sphinxext/only_directives.py 2009-02-16 14:24:56 UTC (rev 6917) @@ -1,67 +0,0 @@ -"""Sphinx directives for selective inclusion of contents. - -A pair of directives for inserting content that will only appear in -either html or latex. -""" - -# Required modules -from docutils.nodes import Body, Element -from docutils.parsers.rst import directives - - -# Code begins -class only_base(Body, Element): - def dont_traverse(self, *args, **kwargs): - return [] - -class html_only(only_base): - pass - -class latex_only(only_base): - pass - -def run(content, node_class, state, content_offset): - text = '\n'.join(content) - node = node_class(text) - state.nested_parse(content, content_offset, node) - return [node] - -def html_only_directive(name, arguments, options, content, lineno, - content_offset, block_text, state, state_machine): - return run(content, html_only, state, content_offset) - -def latex_only_directive(name, arguments, options, content, lineno, - content_offset, block_text, state, state_machine): - return run(content, latex_only, state, content_offset) - -def builder_inited(app): - if app.builder.name == 'html': - latex_only.traverse = only_base.dont_traverse - else: - html_only.traverse = only_base.dont_traverse - -def setup(app): - app.add_directive('htmlonly', html_only_directive, True, (0, 0, 0)) - app.add_directive('latexonly', latex_only_directive, True, (0, 0, 0)) - app.add_node(html_only) - app.add_node(latex_only) - - # This will *really* never see the light of day As it turns out, - # this results in "broken" image nodes since they never get - # processed, so best not to do this. - # app.connect('builder-inited', builder_inited) - - # Add visit/depart methods to HTML-Translator: - def visit_perform(self, node): - pass - def depart_perform(self, node): - pass - def visit_ignore(self, node): - node.children = [] - def depart_ignore(self, node): - node.children = [] - - app.add_node(html_only, html=(visit_perform, depart_perform)) - app.add_node(html_only, latex=(visit_ignore, depart_ignore)) - app.add_node(latex_only, latex=(visit_perform, depart_perform)) - app.add_node(latex_only, html=(visit_ignore, depart_ignore)) Modified: trunk/matplotlib/setup.py =================================================================== --- trunk/matplotlib/setup.py 2009-02-16 14:18:36 UTC (rev 6916) +++ trunk/matplotlib/setup.py 2009-02-16 14:24:56 UTC (rev 6917) @@ -58,7 +58,8 @@ 'matplotlib.numerix.npyma', 'matplotlib.numerix.linear_algebra', 'matplotlib.numerix.random_array', - 'matplotlib.numerix.fft' + 'matplotlib.numerix.fft', + 'matplotlib.sphinxext' ] py_modules = ['pylab'] This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2009-02-16 15:31:16
|
Revision: 6919 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6919&view=rev Author: mdboom Date: 2009-02-16 15:31:13 +0000 (Mon, 16 Feb 2009) Log Message: ----------- Merged revisions 6918 via svnmerge from https://matplotlib.svn.sf.net/svnroot/matplotlib/branches/v0_98_5_maint ........ r6918 | mdboom | 2009-02-16 10:23:25 -0500 (Mon, 16 Feb 2009) | 2 lines Move plot_directive to installed source tree. Add support for inline code. ........ Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/doc/conf.py Added Paths: ----------- trunk/matplotlib/lib/matplotlib/sphinxext/plot_directive.py Removed Paths: ------------- trunk/matplotlib/doc/sphinxext/plot_directive.py Property Changed: ---------------- trunk/matplotlib/ trunk/matplotlib/doc/pyplots/README trunk/matplotlib/doc/sphinxext/gen_gallery.py trunk/matplotlib/doc/sphinxext/gen_rst.py Property changes on: trunk/matplotlib ___________________________________________________________________ Modified: svnmerge-integrated - /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-6916 + /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-6918 Modified: svn:mergeinfo - /branches/v0_91_maint:5753-5771 /branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912,6915-6916 + /branches/v0_91_maint:5753-5771 /branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912,6915-6916,6918 Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009-02-16 15:23:25 UTC (rev 6918) +++ trunk/matplotlib/CHANGELOG 2009-02-16 15:31:13 UTC (rev 6919) @@ -1,3 +1,6 @@ +2009-02-16 Move plot_directive.py to the installed source tree. Add + support for inline code content - MGD + 2009-02-16 Move mathmpl.py to the installed source tree so it is available to other projects. - MGD Modified: trunk/matplotlib/doc/conf.py =================================================================== --- trunk/matplotlib/doc/conf.py 2009-02-16 15:23:25 UTC (rev 6918) +++ trunk/matplotlib/doc/conf.py 2009-02-16 15:31:13 UTC (rev 6919) @@ -28,8 +28,9 @@ # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ['matplotlib.sphinxext.mathmpl', 'math_symbol_table', - 'sphinx.ext.autodoc', 'matplotlib.sphinxext.only_directives', - 'plot_directive', 'inheritance_diagram', 'gen_gallery', 'gen_rst'] + 'sphinx.ext.autodoc', # 'matplotlib.sphinxext.only_directives', + 'matplotlib.sphinxext.plot_directive', 'inheritance_diagram', + 'gen_gallery', 'gen_rst'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] Property changes on: trunk/matplotlib/doc/pyplots/README ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916 + /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918 Property changes on: trunk/matplotlib/doc/sphinxext/gen_gallery.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916 + /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918 Property changes on: trunk/matplotlib/doc/sphinxext/gen_rst.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916 + /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918 Deleted: trunk/matplotlib/doc/sphinxext/plot_directive.py =================================================================== --- trunk/matplotlib/doc/sphinxext/plot_directive.py 2009-02-16 15:23:25 UTC (rev 6918) +++ trunk/matplotlib/doc/sphinxext/plot_directive.py 2009-02-16 15:31:13 UTC (rev 6919) @@ -1,303 +0,0 @@ -"""A special directive for including a matplotlib plot. - -Given a path to a .py file, it includes the source code inline, then: - -- On HTML, will include a .png with a link to a high-res .png. - -- On LaTeX, will include a .pdf - -This directive supports all of the options of the `image` directive, -except for `target` (since plot will add its own target). - -Additionally, if the :include-source: option is provided, the literal -source will be included inline, as well as a link to the source. - -The set of file formats to generate can be specified with the -plot_formats configuration variable. -""" - -import sys, os, glob, shutil, imp, warnings, cStringIO -from docutils.parsers.rst import directives -try: - # docutils 0.4 - from docutils.parsers.rst.directives.images import align -except ImportError: - # docutils 0.5 - from docutils.parsers.rst.directives.images import Image - align = Image.align -from docutils import nodes - -import matplotlib -import matplotlib.cbook as cbook -matplotlib.use('Agg') -import matplotlib.pyplot as plt -import matplotlib.image as image -from matplotlib import _pylab_helpers - -if hasattr(os.path, 'relpath'): - relpath = os.path.relpath -else: - def relpath(target, base=os.curdir): - """ - Return a relative path to the target from either the current dir or an optional base dir. - Base can be a directory specified either as absolute or relative to current dir. - """ - - if not os.path.exists(target): - raise OSError, 'Target does not exist: '+target - - if not os.path.isdir(base): - raise OSError, 'Base is not a directory or does not exist: '+base - - base_list = (os.path.abspath(base)).split(os.sep) - target_list = (os.path.abspath(target)).split(os.sep) - - # On the windows platform the target may be on a completely different drive from the base. - if os.name in ['nt','dos','os2'] and base_list[0] <> target_list[0]: - raise OSError, 'Target is on a different drive to base. Target: '+target_list[0].upper()+', base: '+base_list[0].upper() - - # Starting from the filepath root, work out how much of the filepath is - # shared by base and target. - for i in range(min(len(base_list), len(target_list))): - if base_list[i] <> target_list[i]: break - else: - # If we broke out of the loop, i is pointing to the first differing path elements. - # If we didn't break out of the loop, i is pointing to identical path elements. - # Increment i so that in all cases it points to the first differing path elements. - i+=1 - - rel_list = [os.pardir] * (len(base_list)-i) + target_list[i:] - return os.path.join(*rel_list) - -def write_char(s): - sys.stdout.write(s) - sys.stdout.flush() - -options = {'alt': directives.unchanged, - 'height': directives.length_or_unitless, - 'width': directives.length_or_percentage_or_unitless, - 'scale': directives.nonnegative_int, - 'align': align, - 'class': directives.class_option, - 'include-source': directives.flag } - -template = """ -.. htmlonly:: - - [%(links)s] - - .. image:: %(tmpdir)s/%(outname)s.png - %(options)s - -.. latexonly:: - .. image:: %(tmpdir)s/%(outname)s.pdf - %(options)s -""" - -exception_template = """ -.. htmlonly:: - - [`source code <%(linkdir)s/%(basename)s.py>`__] - -Exception occurred rendering plot. - -""" - -def out_of_date(original, derived): - """ - Returns True if derivative is out-of-date wrt original, - both of which are full file paths. - """ - return (not os.path.exists(derived)) - # or os.stat(derived).st_mtime < os.stat(original).st_mtime) - -def runfile(fullpath): - """ - Import a Python module from a path. - """ - # Change the working directory to the directory of the example, so - # it can get at its data files, if any. - pwd = os.getcwd() - path, fname = os.path.split(fullpath) - sys.path.insert(0, os.path.abspath(path)) - stdout = sys.stdout - sys.stdout = cStringIO.StringIO() - os.chdir(path) - try: - fd = open(fname) - module = imp.load_module("__main__", fd, fname, ('py', 'r', imp.PY_SOURCE)) - except: - raise - finally: - del sys.path[0] - os.chdir(pwd) - sys.stdout = stdout - return module - -def makefig(fullpath, outdir): - """ - run a pyplot script and save the low and high res PNGs and a PDF in _static - """ - formats = [('png', 80), ('hires.png', 200), ('pdf', 50)] - - fullpath = str(fullpath) # todo, why is unicode breaking this - - basedir, fname = os.path.split(fullpath) - basename, ext = os.path.splitext(fname) - all_exists = True - - # Look for single-figure output files first - for format, dpi in formats: - outname = os.path.join(outdir, '%s.%s' % (basename, format)) - if out_of_date(fullpath, outname): - all_exists = False - break - - if all_exists: - write_char('.' * len(formats)) - return 1 - - # Then look for multi-figure output files, assuming - # if we have some we have all... - i = 0 - while True: - all_exists = True - for format, dpi in formats: - outname = os.path.join(outdir, '%s_%02d.%s' % (basename, i, format)) - if out_of_date(fullpath, outname): - all_exists = False - break - if all_exists: - i += 1 - else: - break - - if i != 0: - write_char('.' * i * len(formats)) - return i - - # We didn't find the files, so build them - - plt.close('all') # we need to clear between runs - matplotlib.rcdefaults() - # Set a figure size that doesn't overflow typical browser windows - matplotlib.rcParams['figure.figsize'] = (5.5, 4.5) - - try: - runfile(fullpath) - except: - s = cbook.exception_to_str("Exception running plot %s" % fullpath) - warnings.warn(s) - return 0 - - fig_managers = _pylab_helpers.Gcf.get_all_fig_managers() - for i, figman in enumerate(fig_managers): - for format, dpi in formats: - if len(fig_managers) == 1: - outname = basename - else: - outname = "%s_%02d" % (basename, i) - outpath = os.path.join(outdir, '%s.%s' % (outname, format)) - try: - figman.canvas.figure.savefig(outpath, dpi=dpi) - except: - s = cbook.exception_to_str("Exception running plot %s" % fullpath) - warnings.warn(s) - return 0 - - write_char('*') - - return len(fig_managers) - -def plot_directive(name, arguments, options, content, lineno, - content_offset, block_text, state, state_machine): - """ - Handle the plot directive. - """ - formats = setup.config.plot_formats - if type(formats) == str: - formats = eval(formats) - - reference = directives.uri(arguments[0]) - basedir, fname = os.path.split(reference) - basename, ext = os.path.splitext(fname) - basedir = relpath(basedir, setup.app.builder.srcdir) - - # Get the directory of the rst file, and determine the relative - # path from the resulting html file to the plot_directive links - # (linkdir). This relative path is used for html links *only*, - # and not the embedded image. That is given an absolute path to - # the temporary directory, and then sphinx moves the file to - # build/html/_images for us later. - rstdir, rstfile = os.path.split(state_machine.document.attributes['source']) - reldir = rstdir[len(setup.confdir)+1:] - relparts = [p for p in os.path.split(reldir) if p.strip()] - nparts = len(relparts) - outdir = os.path.join('plot_directive', basedir) - linkdir = ('../' * nparts) + outdir - - # tmpdir is where we build all the output files. This way the - # plots won't have to be redone when generating latex after html. - tmpdir = os.path.abspath(os.path.join('build', outdir)) - if not os.path.exists(tmpdir): - cbook.mkdirs(tmpdir) - - # destdir is the directory within the output to store files - # that we'll be linking to -- not the embedded images. - destdir = os.path.abspath(os.path.join(setup.app.builder.outdir, outdir)) - if not os.path.exists(destdir): - cbook.mkdirs(destdir) - - # Generate the figures, and return the number of them - num_figs = makefig(reference, tmpdir) - - if options.has_key('include-source'): - contents = open(reference, 'r').read() - lines = ['::', ''] + [' %s'%row.rstrip() for row in contents.split('\n')] - del options['include-source'] - else: - lines = [] - - if num_figs > 0: - options = [' :%s: %s' % (key, val) for key, val in - options.items()] - options = "\n".join(options) - shutil.copyfile(reference, os.path.join(destdir, fname)) - - for i in range(num_figs): - if num_figs == 1: - outname = basename - else: - outname = "%s_%02d" % (basename, i) - - # Copy the linked-to files to the destination within the build tree, - # and add a link for them - links = ['`source code <%(linkdir)s/%(basename)s.py>`__'] - for format in formats[1:]: - shutil.copyfile(os.path.join(tmpdir, outname + "." + format), - os.path.join(destdir, outname + "." + format)) - links.append('`%s <%s/%s.%s>`__' % (format, linkdir, outname, format)) - links = ', '.join(links) % locals() - - # Output the resulting reST - lines.extend((template % locals()).split('\n')) - else: - lines.extend((exception_template % locals()).split('\n')) - - if len(lines): - state_machine.insert_input( - lines, state_machine.input_lines.source(0)) - - return [] - -def setup(app): - setup.app = app - setup.config = app.config - setup.confdir = app.confdir - - app.add_directive('plot', plot_directive, False, (1, 0, 1), **options) - app.add_config_value( - 'plot_formats', - ['png', 'hires.png', 'pdf'], - True) - Copied: trunk/matplotlib/lib/matplotlib/sphinxext/plot_directive.py (from rev 6918, branches/v0_98_5_maint/lib/matplotlib/sphinxext/plot_directive.py) =================================================================== --- trunk/matplotlib/lib/matplotlib/sphinxext/plot_directive.py (rev 0) +++ trunk/matplotlib/lib/matplotlib/sphinxext/plot_directive.py 2009-02-16 15:31:13 UTC (rev 6919) @@ -0,0 +1,331 @@ +"""A special directive for including a matplotlib plot. + +Given a path to a .py file, it includes the source code inline, then: + +- On HTML, will include a .png with a link to a high-res .png. + +- On LaTeX, will include a .pdf + +This directive supports all of the options of the `image` directive, +except for `target` (since plot will add its own target). + +Additionally, if the :include-source: option is provided, the literal +source will be included inline, as well as a link to the source. + +The set of file formats to generate can be specified with the +plot_formats configuration variable. +""" + +import sys, os, glob, shutil, hashlib, imp, warnings, cStringIO +try: + from hashlib import md5 +except ImportError: + from md5 import md5 +from docutils.parsers.rst import directives +try: + # docutils 0.4 + from docutils.parsers.rst.directives.images import align +except ImportError: + # docutils 0.5 + from docutils.parsers.rst.directives.images import Image + align = Image.align +from docutils import nodes + +import matplotlib +import matplotlib.cbook as cbook +matplotlib.use('Agg') +import matplotlib.pyplot as plt +import matplotlib.image as image +from matplotlib import _pylab_helpers + +import only_directives + +if hasattr(os.path, 'relpath'): + relpath = os.path.relpath +else: + def relpath(target, base=os.curdir): + """ + Return a relative path to the target from either the current dir or an optional base dir. + Base can be a directory specified either as absolute or relative to current dir. + """ + + if not os.path.exists(target): + raise OSError, 'Target does not exist: '+target + + if not os.path.isdir(base): + raise OSError, 'Base is not a directory or does not exist: '+base + + base_list = (os.path.abspath(base)).split(os.sep) + target_list = (os.path.abspath(target)).split(os.sep) + + # On the windows platform the target may be on a completely different drive from the base. + if os.name in ['nt','dos','os2'] and base_list[0] <> target_list[0]: + raise OSError, 'Target is on a different drive to base. Target: '+target_list[0].upper()+', base: '+base_list[0].upper() + + # Starting from the filepath root, work out how much of the filepath is + # shared by base and target. + for i in range(min(len(base_list), len(target_list))): + if base_list[i] <> target_list[i]: break + else: + # If we broke out of the loop, i is pointing to the first differing path elements. + # If we didn't break out of the loop, i is pointing to identical path elements. + # Increment i so that in all cases it points to the first differing path elements. + i+=1 + + rel_list = [os.pardir] * (len(base_list)-i) + target_list[i:] + return os.path.join(*rel_list) + +def write_char(s): + sys.stdout.write(s) + sys.stdout.flush() + +options = {'alt': directives.unchanged, + 'height': directives.length_or_unitless, + 'width': directives.length_or_percentage_or_unitless, + 'scale': directives.nonnegative_int, + 'align': align, + 'class': directives.class_option, + 'include-source': directives.flag } + +template = """ +.. htmlonly:: + + [%(links)s] + + .. image:: %(tmpdir)s/%(outname)s.png + %(options)s + +.. latexonly:: + .. image:: %(tmpdir)s/%(outname)s.pdf + %(options)s +""" + +exception_template = """ +.. htmlonly:: + + [`source code <%(linkdir)s/%(basename)s.py>`__] + +Exception occurred rendering plot. + +""" + +def out_of_date(original, derived): + """ + Returns True if derivative is out-of-date wrt original, + both of which are full file paths. + """ + return (not os.path.exists(derived)) + # or os.stat(derived).st_mtime < os.stat(original).st_mtime) + +def runfile(fullpath): + """ + Import a Python module from a path. + """ + # Change the working directory to the directory of the example, so + # it can get at its data files, if any. + pwd = os.getcwd() + path, fname = os.path.split(fullpath) + sys.path.insert(0, os.path.abspath(path)) + stdout = sys.stdout + sys.stdout = cStringIO.StringIO() + os.chdir(path) + try: + fd = open(fname) + module = imp.load_module("__main__", fd, fname, ('py', 'r', imp.PY_SOURCE)) + except: + raise + finally: + del sys.path[0] + os.chdir(pwd) + sys.stdout = stdout + return module + +def makefig(fullpath, code, outdir): + """ + run a pyplot script and save the low and high res PNGs and a PDF in _static + """ + formats = [('png', 80), ('hires.png', 200), ('pdf', 50)] + + fullpath = str(fullpath) # todo, why is unicode breaking this + basedir, fname = os.path.split(fullpath) + basename, ext = os.path.splitext(fname) + + if str(basename) == "None": + import pdb + pdb.set_trace() + + all_exists = True + + # Look for single-figure output files first + for format, dpi in formats: + outname = os.path.join(outdir, '%s.%s' % (basename, format)) + if out_of_date(fullpath, outname): + all_exists = False + break + + if all_exists: + write_char('.' * len(formats)) + return 1 + + # Then look for multi-figure output files, assuming + # if we have some we have all... + i = 0 + while True: + all_exists = True + for format, dpi in formats: + outname = os.path.join(outdir, '%s_%02d.%s' % (basename, i, format)) + if out_of_date(fullpath, outname): + all_exists = False + break + if all_exists: + i += 1 + else: + break + + if i != 0: + write_char('.' * i * len(formats)) + return i + + # We didn't find the files, so build them + + plt.close('all') # we need to clear between runs + matplotlib.rcdefaults() + # Set a figure size that doesn't overflow typical browser windows + matplotlib.rcParams['figure.figsize'] = (5.5, 4.5) + + if code is not None: + exec(code) + else: + try: + runfile(fullpath) + except: + s = cbook.exception_to_str("Exception running plot %s" % fullpath) + warnings.warn(s) + return 0 + + fig_managers = _pylab_helpers.Gcf.get_all_fig_managers() + for i, figman in enumerate(fig_managers): + for format, dpi in formats: + if len(fig_managers) == 1: + outname = basename + else: + outname = "%s_%02d" % (basename, i) + outpath = os.path.join(outdir, '%s.%s' % (outname, format)) + try: + figman.canvas.figure.savefig(outpath, dpi=dpi) + except: + s = cbook.exception_to_str("Exception running plot %s" % fullpath) + warnings.warn(s) + return 0 + + write_char('*') + + return len(fig_managers) + +def plot_directive(name, arguments, options, content, lineno, + content_offset, block_text, state, state_machine): + """ + Handle the plot directive. + """ + formats = setup.config.plot_formats + if type(formats) == str: + formats = eval(formats) + + # The user may provide a filename *or* Python code content, but not both + if len(arguments) == 1: + reference = directives.uri(arguments[0]) + basedir, fname = os.path.split(reference) + basename, ext = os.path.splitext(fname) + basedir = relpath(basedir, setup.app.builder.srcdir) + if len(content): + raise ValueError("plot directive may not specify both a filename and inline content") + content = None + else: + basedir = "inline" + content = '\n'.join(content) + # Since we don't have a filename, use a hash based on the content + reference = basename = md5(content).hexdigest()[-10:] + fname = None + + # Get the directory of the rst file, and determine the relative + # path from the resulting html file to the plot_directive links + # (linkdir). This relative path is used for html links *only*, + # and not the embedded image. That is given an absolute path to + # the temporary directory, and then sphinx moves the file to + # build/html/_images for us later. + rstdir, rstfile = os.path.split(state_machine.document.attributes['source']) + reldir = rstdir[len(setup.confdir)+1:] + relparts = [p for p in os.path.split(reldir) if p.strip()] + nparts = len(relparts) + outdir = os.path.join('plot_directive', basedir) + linkdir = ('../' * nparts) + outdir + + # tmpdir is where we build all the output files. This way the + # plots won't have to be redone when generating latex after html. + tmpdir = os.path.abspath(os.path.join('build', outdir)) + if not os.path.exists(tmpdir): + cbook.mkdirs(tmpdir) + + # destdir is the directory within the output to store files + # that we'll be linking to -- not the embedded images. + destdir = os.path.abspath(os.path.join(setup.app.builder.outdir, outdir)) + if not os.path.exists(destdir): + cbook.mkdirs(destdir) + + # Generate the figures, and return the number of them + num_figs = makefig(reference, content, tmpdir) + + if options.has_key('include-source'): + if content is None: + content = open(reference, 'r').read() + lines = ['::', ''] + [' %s'%row.rstrip() for row in content.split('\n')] + del options['include-source'] + else: + lines = [] + + if num_figs > 0: + options = [' :%s: %s' % (key, val) for key, val in + options.items()] + options = "\n".join(options) + if fname is not None: + shutil.copyfile(reference, os.path.join(destdir, fname)) + + for i in range(num_figs): + if num_figs == 1: + outname = basename + else: + outname = "%s_%02d" % (basename, i) + + # Copy the linked-to files to the destination within the build tree, + # and add a link for them + links = [] + if fname is not None: + links.append('`source code <%(linkdir)s/%(basename)s.py>`__') + for format in formats[1:]: + shutil.copyfile(os.path.join(tmpdir, outname + "." + format), + os.path.join(destdir, outname + "." + format)) + links.append('`%s <%s/%s.%s>`__' % (format, linkdir, outname, format)) + links = ', '.join(links) % locals() + + # Output the resulting reST + lines.extend((template % locals()).split('\n')) + else: + lines.extend((exception_template % locals()).split('\n')) + + if len(lines): + state_machine.insert_input( + lines, state_machine.input_lines.source(0)) + + return [] + +def setup(app): + setup.app = app + setup.config = app.config + setup.confdir = app.confdir + + app.add_directive('plot', plot_directive, True, (0, 1, 0), **options) + app.add_config_value( + 'plot_formats', + ['png', 'hires.png', 'pdf'], + True) + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jr...@us...> - 2009-02-18 19:44:32
|
Revision: 6922 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6922&view=rev Author: jrevans Date: 2009-02-18 19:44:29 +0000 (Wed, 18 Feb 2009) Log Message: ----------- Unit-Test harness initial check-in. Added Paths: ----------- trunk/matplotlib/test/ trunk/matplotlib/test/README.txt trunk/matplotlib/test/mplTest/ trunk/matplotlib/test/mplTest/MplNosePlugin.py trunk/matplotlib/test/mplTest/MplTestCase.py trunk/matplotlib/test/mplTest/TestTEMPLATE.py trunk/matplotlib/test/mplTest/__init__.py trunk/matplotlib/test/mplTest/compare.py trunk/matplotlib/test/mplTest/directories.py trunk/matplotlib/test/mplTest/path_utils.py trunk/matplotlib/test/mplTest/units/ trunk/matplotlib/test/mplTest/units/Duration.py trunk/matplotlib/test/mplTest/units/Epoch.py trunk/matplotlib/test/mplTest/units/EpochConverter.py trunk/matplotlib/test/mplTest/units/StrConverter.py trunk/matplotlib/test/mplTest/units/UnitDbl.py trunk/matplotlib/test/mplTest/units/UnitDblConverter.py trunk/matplotlib/test/mplTest/units/UnitDblFormatter.py trunk/matplotlib/test/mplTest/units/__init__.py trunk/matplotlib/test/run-mpl-test.py trunk/matplotlib/test/test_artists/ trunk/matplotlib/test/test_backends/ trunk/matplotlib/test/test_backends/TestAgg.py trunk/matplotlib/test/test_basemap/ trunk/matplotlib/test/test_cxx/ trunk/matplotlib/test/test_mathtext/ trunk/matplotlib/test/test_matplotlib/ trunk/matplotlib/test/test_matplotlib/TestAxes.py trunk/matplotlib/test/test_matplotlib/TestCookbook.py trunk/matplotlib/test/test_matplotlib/TestTickers.py trunk/matplotlib/test/test_matplotlib/baseline/ trunk/matplotlib/test/test_matplotlib/baseline/TestAxes/ trunk/matplotlib/test/test_matplotlib/baseline/TestAxes/default_datetime.png trunk/matplotlib/test/test_matplotlib/baseline/TestAxes/empty_datetime.png trunk/matplotlib/test/test_matplotlib/baseline/TestAxes/formatter_ticker_001.png trunk/matplotlib/test/test_matplotlib/baseline/TestAxes/formatter_ticker_002.png trunk/matplotlib/test/test_matplotlib/baseline/TestAxes/formatter_ticker_003.png trunk/matplotlib/test/test_matplotlib/baseline/TestAxes/formatter_ticker_004.png trunk/matplotlib/test/test_matplotlib/baseline/TestAxes/formatter_ticker_005.png trunk/matplotlib/test/test_matplotlib/baseline/TestTickers/ trunk/matplotlib/test/test_matplotlib/baseline/TestTickers/DateFormatter_fractionalSeconds.png trunk/matplotlib/test/test_matplotlib/baseline/TestTickers/RRuleLocator_bounds.png trunk/matplotlib/test/test_numerix/ trunk/matplotlib/test/test_plots/ trunk/matplotlib/test/test_plots/TestAnnotation.py trunk/matplotlib/test/test_plots/TestPlot.py trunk/matplotlib/test/test_plots/TestPolar.py trunk/matplotlib/test/test_plots/TestSpan.py trunk/matplotlib/test/test_plots/baseline/ trunk/matplotlib/test/test_plots/baseline/TestAnnotation/ trunk/matplotlib/test/test_plots/baseline/TestAnnotation/offset_points.png trunk/matplotlib/test/test_plots/baseline/TestAnnotation/polar_axes.png trunk/matplotlib/test/test_plots/baseline/TestAnnotation/polar_coords.png trunk/matplotlib/test/test_plots/baseline/TestPlot/ trunk/matplotlib/test/test_plots/baseline/TestPlot/const_xy.png trunk/matplotlib/test/test_plots/baseline/TestPlot/shaped_data.png trunk/matplotlib/test/test_plots/baseline/TestPlot/single_date.png trunk/matplotlib/test/test_plots/baseline/TestPlot/single_point.png trunk/matplotlib/test/test_plots/baseline/TestPolar/ trunk/matplotlib/test/test_plots/baseline/TestPolar/polar_units.png trunk/matplotlib/test/test_plots/baseline/TestPolar/polar_wrap_180.png trunk/matplotlib/test/test_plots/baseline/TestPolar/polar_wrap_360.png trunk/matplotlib/test/test_plots/baseline/TestSpan/ trunk/matplotlib/test/test_plots/baseline/TestSpan/axhspan_epoch.png trunk/matplotlib/test/test_plots/baseline/TestSpan/axvspan_epoch.png trunk/matplotlib/test/test_pylab/ trunk/matplotlib/test/test_transforms/ Added: trunk/matplotlib/test/README.txt =================================================================== --- trunk/matplotlib/test/README.txt (rev 0) +++ trunk/matplotlib/test/README.txt 2009-02-18 19:44:29 UTC (rev 6922) @@ -0,0 +1,290 @@ +======================================================================== + matplotlib test structure +======================================================================== + +===== How To Use + += Running + +Run the 'run-mpl-test.py' script to execute the test harness. This must +be run with the version of python that you wish to test matplotlib with. +This means that it must have nose installed (and PIL if image comparison +is to be done). By default this will pick up whatever python is on your +path, so make sure it is the correct one. + +- Command-Line Options +In addition to the standard nose command-line options, there are several +specific to the matplotlib test harness. They are as follows: + + -t TAG, --with-tag=TAG + Will only run test cases that have the specified tag. + Each test case should have a 'tag' attribute (if a + case does not have one, then it is assumed to be an + empty list). The 'tag' attribute is a list of + strings, where each value is a representative propery + of the test case. Example tags are 'qt' or 'units'. + This can be specified multiple times. + --without-tag=TAG This will run those test cases that do not have the + specified tags. + --clean This will remove all output files and saved results. + If this is specified, no other processing will be + performed. + --all This will runn all test programs regardless of working + directory. + --keep Keep any generated output files in a directory called + 'saved-results'. This directory will be created if it + doesn't already exist. This directory is in the same + location as the test case whose results are being + saved. + --keep-failed This acts just like '--keep' except will only keeps + the results from tests that error or fail. + --make-test=testName + Creates a template test case file in the current + directory with the name TestFoo. Where 'Foo' is the + provided test name. + + +- Running Specific Tests +In order to can specify the exact test case you want to run use the +standard nose mechanism. For example, if you have the following setup: + +TestFoo.py + def test_func(): + ... + + class TestFoo: + def test_bar( self ): + ... + def test_bug( self ): + ... + +Then to test everything in TestFoo.py do the following: +$> run-mpl-test.py TestFoo.py + +To run all tests in the test class TestFoo do this: +$> run-mpl-test.py TestFoo.py:TestFoo + +To run the specific 'test_bar' methodd do the following: +$> run-mpl-test.py TestFoo.py:TestFoo.test_bar + + += Detecting Test Cases + +When running the matplotlib test script it will search for all tests +in the current working directory and below (unless '--all' is specified). +This is provided that the current working directory is a sub-directory +of the matplotlib test directory. In the event that it is not, then the +matplotlib root test directory will be used and all appropriate test cases +will be run. + +This will not search outside of the test structure and will not look in +the mplTest module. This will only search for test cases in the root +test directory and any of its sub-directories. + += Saving Results + +When using the keep flag any generated files in the 'output' directory +are copied to the 'saved-results/<classname>' directory, where <classname> +is the name of the unit-test class. This means that for each test case +within a given test class, all output files should have unique names. + +The 'saved-results' directory will always contain the results from the +last test run. This is considered a volatile directory since running +the test cases without the '--keep' flag will remove any existing +'saved-results' directory. This is to ensure the integrity of the +saved results, they will always match the last test run. + += Filtering Tests + +In the case of filtering via tags, a unit-test cane have multiple tags. +When running the test program if any tags are specified as 'skip' then +this will take precedence over any tags that might say 'process'. For +example, if a test case has both the 'gui' and 'qt' tag, but the command- +line is specified with the following flags: + '--with-tag=gui --without-tag=qt' +then the example test case will not be run because it matches the skip +tag. + + +===== Directory Structure + +There are several directories in the matplotlib test structure. The first +directory is the 'mplTest' directory. This is the matplotlib test module +and contains the various python scripts that the test harness needs to +run. The remaining directories are as follows and contain the various test +cases for matplotlib. + +mplTest + This directory does not contain any test cases, rather it is the location + of the matplotlib specific utilities for performing unit tests. + +test_artists + This directory contains tests that focus on the rendering aspects of + the various artists. Essentially the artist derived functionality. + +test_backends + This directory contains various tests that focus on making sure the + various backend targets work. + +test_basemap + This directory contains test cases that excercise the basemap add-on + module. + +test_cxx + This directoy contains tests that focus on testing the interface of + the compiled code contained in matplotlib. + +test_mathtext + This directory contains tests that focus on excercising the mathtext + sub-system. + +test_numerix + This directory contains tests that focus on validating the numerix + component. + +test_plots + This directory contains tests that validate the various plot funtions. + +test_pylab + This directory has pylab specific test cases. + +test_transforms + This directory has test cases that focus on testing the various + transformation and projection functions. + +test_matplotlib + This directory has all other test cases. This contins test that focus + on making sure that Axis, Axes, Figure, etc are all acting properly. This + has test cases that are general to the overall funtionality of matplotlib. + + +===== Writing Test Cases + += The Test Case + +As per the nose implementation, a test case is ultimately any function that +has the phrase 'test' in its name. The matplotlib cases however are grouped +into directories, by what is being tested, and from there are grouped into +classes (one class per file), by similarity. + +It is desireable that all matplotlib tests follow the same structure to +not only facilitate the writing of test cases, but to make things easier +for maintaining them and keeping things uniform. + +There is a class 'MplTestCase' provided to be the base class for all matplotlib +test classes. This class provides some extra functionality in the form of +verification functions and test data management. + += Comparison Functions + +There are several methods provided for testing whether or not a particular +test case should fail or succeed. The following methods are provided by +the base matplotlib test class: + +- MplTestCase.checkEq( expected, actual, msg = "" ) + Fail if the values are not equal, with the given message. + +- MplTestCase.checkNeq( expected, actual, msg = "" ) + Fail if the values are equal, with the given message. + +- MplTestCase.checkClose( expected, actual, relTol=None, absTol=None, msg="" ) + Fail if the floating point values are not close enough, with the given message. + You can specify a relative tolerance, absolute tolerance, or both. + +- MplTestCase.checkImage( filename, tol = 1.0e-3, msg = "" ) + Check to see if the image is similair to the one stored in the baseline + directory. filename can be a fully qualified name (via the 'outFile' method), + or it can be the name of the file (to be passed into the 'outFile' method). + The default tolerance is typically fine, but might need to be adjusted in some + cases (see the 'compareImages' function for more details). Fails with + the specified message. + +Note that several of the tests will perform image comparison for validation +of a specific plot. Though not 100% accurate it at least flags potential +failures and signals a human to come and take a closer look. If an image has +changed and after a human deems the change is acceptable, then updating the +baseline image with the appropriate image from the 'saved-results' directory +(when using the '--keep' or '--keep-failed' command-line arguments) will make +the test pass properly. + +Image comparison depends on the python imaging library (PIL) being installed. +If PIL is not installed, then any test cases that rely on it will not +pass. To not run these test cases, then pass the '--without-tag=PIL' +option on the command-line. + += Directories + +Input data files for a given test case should be place in a directory +called 'inputs' with the test case that uses it. A convienence function +is provided with each test class for accessing input files. + +For example if a test case has an input file of the name 'inputs.txt' +you can get the path to the file by calling 'self.inFile("inputs.txt")'. +This is to allow for a uniform convention that all test cases can follow. + +Output files are handled just like input files with the exception that +they are written to the 'output' directory and the path name can be +had by calling 'self.outFile'. It is more important to use this mechanism +for getting the pathname for an output file because it allows for the +management of cleaning up and saving generated output files (It also +significantly reduces the probability of typo errors when specifying +where to place the files). + +A Third and final directory used by the test cases is the 'baseline' +directory. This is where data files used for verifying test results +are stored. The path name can be had by using the 'self.baseFile' +method. + +Accessing these directories can be made simple (and reduce the chance of a +typo) via the following MplTestCase methods: + +- MplTestCase.inFile( filename ) + Returns the full pathname of filename in the input data directory. + +- MplTestCase.outFile( filename ) + Returns the full pathname of filename in the output data directory. + +- MplTestCase.baseFile( filename ) + Returns the full pathname of filename in the baseline data directory. + += Units + +Located in the mplTest directory is a set of unit classes. These classes +are provided for testing the various unitized data interfaces that matplotlib +supports (ie unit conversion). These are used because they provide a very +strict enforcement of unitized data which will test the entire spectrum of how +unitized data might be used (it is not always meaningful to convert to +a float without specific units given). This allows us to test for cases that +might accidentally be performing operations that really do not make sense +physically for unitized data. + +The provided classes are as follows: +- UnitDbl + UnitDbl is essentially a unitized floating point number. It has a + minimal set of supported units (enough for testing purposes). All + of the mathematical operation are provided to fully test any behaviour + that might occur with unitized data. Remeber that unitized data has + rules as to how it can be applied to one another (a value of distance + cannot be added to a value of time). Thus we need to guard against any + accidental "default" conversion that will strip away the meaning of the + data and render it neutered. + +- Epoch + Epoch is different than a UnitDbl of time. Time is something that can be + measured where an Epoch is a specific moment in time. Epochs are typically + referenced as an offset from some predetermined epoch. Conceptally an Epoch + is like saying 'January 1, 2000 at 12:00 UTC'. It is a specific + time, but more importantly it is a time with a frame. In the example + the frame is 'UTC'. This class is provided to test the functionality of + matplotlib's various routines and mechanisms for dealing with datetimes. + +- Duration + A difference of two epochs is a Duration. The distinction between a + Duration and a UnitDbl of time is made because an Epoch can have different + frames (or units). In the case of our test Epoch class the two allowed + frames are 'UTC' and 'ET' (Note that these are rough estimates provided for + testing purposes and should not be used in production code where accuracy + of time frames is desired). As such a Duration also has a frame of + reference and therefore needs to be called out as different that a simple + measurement of time since a delta-t in one frame may not be the same in another. + Property changes on: trunk/matplotlib/test/README.txt ___________________________________________________________________ Added: svn:eol-style + LF Added: trunk/matplotlib/test/mplTest/MplNosePlugin.py =================================================================== --- trunk/matplotlib/test/mplTest/MplNosePlugin.py (rev 0) +++ trunk/matplotlib/test/mplTest/MplNosePlugin.py 2009-02-18 19:44:29 UTC (rev 6922) @@ -0,0 +1,836 @@ +#======================================================================= + +import os +import sys +import shutil +import os.path +import optparse + +import nose.case +from nose.plugins import Plugin + +from path_utils import * +import directories as dirs +from MplTestCase import MplTestCase + +#======================================================================= + +__all__ = [ 'MplNosePlugin' ] + +#======================================================================= +def getInstance( test ): + """Given a nose test case, will return the actual unit test instance. + + We do this with a function call in case the method for getting the + actual unit test instance needs to change. + """ + assert isinstance( test, nose.case.Test ) + + if isinstance( test.test, nose.case.MethodTestCase ): + return test.test.inst + elif isinstance( test.test, nose.case.FunctionTestCase ): + return test.test.test + # elif isinstance( test.test, unittest.TestCase ): + else: + return test.test + + +#======================================================================= +class MplNosePlugin( Plugin ): + + enabled = True + name = "MplNosePlugin" + score = 0 + + KEEP_NONE = 0 + KEEP_FAIL = 1 + KEEP_ALL = 2 + + TEST_ERRORED = -1 + TEST_FAILED = 0 + TEST_PASSED = 1 + + #-------------------------------------------------------------------- + # Some 'property' functions + def getRootDir( self ): + # The bottom directory of the stack is the root directory. + return self.dirStack[0] + + def getInputDir( self ): + return os.path.join( self.currentDir, dirs.inputDirName ) + + def getOutputDir( self ): + return os.path.join( self.currentDir, dirs.outputDirName ) + + def getBaselineRootDir( self ): + return os.path.join( self.currentDir, dirs.baselineDirName ) + + def getSaveRootDir( self ): + return os.path.join( self.currentDir, dirs.saveDirName ) + + rootDir = property( getRootDir ) + inputDir = property( getInputDir ) + outputDir = property( getOutputDir ) + baselineRootDir = property( getBaselineRootDir ) + saveRootDir = property( getSaveRootDir ) + + def getBaselineDir( self, test ): + t = getInstance( test ) + return os.path.join( self.baselineRootDir, t.__class__.__name__ ) + + def getSaveDir( self, test ): + t = getInstance( test ) + return os.path.join( self.saveRootDir, t.__class__.__name__ ) + + #-------------------------------------------------------------------- + def saveResults( self, test ): + """Save the output directory for the gived test.""" + saveDir = self.getSaveDir( test ) + if not os.path.exists( saveDir ): + mkdir( saveDir, recursive = True ) + + outDir = getInstance( test ).outputDir + + for fname in walk( outDir ): + if os.path.isdir( fname ): + shutil.copytree( fname, saveDir ) + else: + shutil.copy( fname, saveDir ) + + #-------------------------------------------------------------------- + def filterTestItem( self, item ): + """Return true if you want the main test selector to collect tests from + this class, false if you don't, and None if you don't care. + + Parameters: + item : An instance of the testable item that has a 'tag' attribute. + """ + + reallyWant = False + reallyDontWant = False + + if hasattr( item, 'tags' ): + itemTags = item.tags + else: + itemTags = [] + + for tag in self.skipTags: + if tag in itemTags: + reallyDontWant = True + break + + for tag in self.includeTags: + if tag in itemTags: + reallyWant = True + else: + reallyDontWant = True + break + + if self.includeTags and not itemTags: + reallyDontWant = True + + if reallyDontWant: + return False + if reallyWant: + return True + + return None + + #-------------------------------------------------------------------- + def addError( self, test, err ): + """Called when a test raises an uncaught exception. DO NOT return a value + unless you want to stop other plugins from seeing that the test has + raised an error. + + Parameters: + test : nose.case.Test + the test case + err : 3-tuple + sys.exc_info() tuple + """ + self.testResults.append( (test, self.TEST_ERRORED, err) ) + + #-------------------------------------------------------------------- + def addFailure( self, test, err ): + """Called when a test fails. DO NOT return a value unless you want to + stop other plugins from seeing that the test has failed. + + Parameters: + test : nose.case.Test + the test case + err : 3-tuple + sys.exc_info() tuple + """ + self.testResults.append( (test, self.TEST_FAILED, err) ) + + #-------------------------------------------------------------------- + def addSuccess( self, test ): + """Called when a test passes. DO NOT return a value unless you want to + stop other plugins from seeing the passing test. + + Parameters: + test : nose.case.Test + the test case + """ + self.testResults.append( (test, self.TEST_PASSED, None) ) + + #-------------------------------------------------------------------- + def afterContext( self ): + """Called after a context (generally a module) has been lazy-loaded, + imported, setup, had its tests loaded and executed, and torn down. + """ + return None + + #-------------------------------------------------------------------- + def afterDirectory( self, path ): + """Called after all tests have been loaded from directory at path and run. + + Parameters: + path : string + the directory that has finished processing + """ + # Set the current directory to the previous directory + self.currentDir = self.dirStack.pop() + chdir( self.currentDir ) + return None + + #-------------------------------------------------------------------- + def afterImport( self, filename, module ): + """Called after module is imported from filename. afterImport is called + even if the import failed. + + Parameters: + filename : string + The file that was loaded + module : string + The name of the module + """ + return None + + #-------------------------------------------------------------------- + def afterTest( self, test ): + """Called after the test has been run and the result recorded + (after stopTest). + + Parameters: + test : nose.case.Test + the test case + """ + return None + + #-------------------------------------------------------------------- + def beforeContext( self ): + """Called before a context (generally a module) is examined. Since the + context is not yet loaded, plugins don't get to know what the + context is; so any context operations should use a stack that is + pushed in beforeContext and popped in afterContext to ensure they + operate symmetrically. + + beforeContext and afterContext are mainly useful for tracking and + restoring global state around possible changes from within a + context, whatever the context may be. If you need to operate on + contexts themselves, see startContext and stopContext, which are + passed the context in question, but are called after it has been + loaded (imported in the module case). + """ + return None + + #-------------------------------------------------------------------- + def beforeDirectory( self, path ): + """Called before tests are loaded from directory at path. + + Parameters: + path : string + the directory that is about to be processed + """ + # Save the cuurent directory and set to the new directory. + self.dirStack.append( self.currentDir ) + self.currentDir = path + chdir( self.currentDir ) + + # Remove any existing 'saved-results' directory + #NOTE: We must do this after setting 'self.currentDir' + rmdir( self.saveRootDir ) + + return None + + #-------------------------------------------------------------------- + def beforeImport( self, filename, module ): + """Called before module is imported from filename. + + Parameters: + filename : string + The file that will be loaded + module : string + The name of the module found in file + """ + return None + + #-------------------------------------------------------------------- + def beforeTest( self, test ): + """Called before the test is run (before startTest). + + Parameters: + test : nose.case.Test + the test case + """ + return None + + #-------------------------------------------------------------------- + def begin( self ): + """Called before any tests are collected or run. Use this to perform + any setup needed before testing begins. + """ + return None + + #-------------------------------------------------------------------- + def configure( self, options, conf ): + """Called after the command line has been parsed, with the parsed + options and the config container. Here, implement any config + storage or changes to state or operation that are set by command + line options. + + Do not return a value from this method unless you want to stop all + other plugins from being configured. + """ + self.includeTags = [ t for t in options.mpl_process_tags ] + self.skipTags = [ t for t in options.mpl_skip_tags ] + self.keepLevel = options.mpl_keep + + self.currentDir = os.getcwd() + self.dirStack = [] + + self.testResults = [] + + #-------------------------------------------------------------------- + def describeTest( self, test ): + """Return a test description. Called by nose.case.Test.shortDescription. + + Parameters: + test : nose.case.Test + the test case + """ + return None + + #-------------------------------------------------------------------- + def finalize( self, result ): + """Called after all report output, including output from all plugins, + has been sent to the stream. Use this to print final test results + or perform final cleanup. Return None to allow other plugins to + continue printing, any other value to stop them. + + Note + When tests are run under a test runner other than + nose.core.TextTestRunner, for example when tests are run via + 'python setup.py test', this method may be called before the default + report output is sent. + """ + return None + + #-------------------------------------------------------------------- + def formatError( self, test, err ): + """Called in result.addError, before plugin.addError. If you want to + replace or modify the error tuple, return a new error tuple. + + Parameters: + test : nose.case.Test + the test case + err : 3-tuple + sys.exc_info() tuple + """ + return err + + #-------------------------------------------------------------------- + def formatFailure( self, test, err ): + """Called in result.addFailure, before plugin.addFailure. If you want to + replace or modify the error tuple, return a new error tuple. Since + this method is chainable, you must return the test as well, so you + you'll return something like: + return (test, err) + + Parameters: + test : nose.case.Test + the test case + err : 3-tuple + sys.exc_info() tuple + """ + return None + + #-------------------------------------------------------------------- + def handleError( self, test, err ): + """Called on addError. To handle the error yourself and prevent normal + error processing, return a true value. + + Parameters: + test : nose.case.Test + the test case + err : 3-tuple + sys.exc_info() tuple + """ + if (self.keepLevel == self.KEEP_FAIL) or (self.keepLevel == self.KEEP_ALL): + self.saveResults( test ) + + return None + + #-------------------------------------------------------------------- + def handleFailure( self, test, err ): + """Called on addFailure. To handle the failure yourself and prevent + normal failure processing, return a true value. + + Parameters: + test : nose.case.Test + the test case + err : 3-tuple + sys.exc_info() tuple + """ + if (self.keepLevel == self.KEEP_FAIL) or (self.keepLevel == self.KEEP_ALL): + self.saveResults( test ) + + return None + + #-------------------------------------------------------------------- + def loadTestsFromDir( self, path ): + """Return iterable of tests from a directory. May be a generator. + Each item returned must be a runnable unittest.TestCase + (or subclass) instance or suite instance. Return None if your + plugin cannot collect any tests from directory. + + Parameters: + path : string + The path to the directory. + """ + return None + + #-------------------------------------------------------------------- + def loadTestsFromFile( self, filename ): + """Return tests in this file. Return None if you are not interested in + loading any tests, or an iterable if you are and can load some. May + be a generator. If you are interested in loading tests from the file + and encounter no errors, but find no tests, yield False or + return [False]. + + Parameters: + filename : string + The full path to the file or directory. + """ + return None + + #-------------------------------------------------------------------- + def loadTestsFromModule( self, module ): + """Return iterable of tests in a module. May be a generator. Each + item returned must be a runnable unittest.TestCase (or subclass) + instance. Return None if your plugin cannot collect any tests + from module. + + Parameters: + module : python module + The module object + """ + return None + + #-------------------------------------------------------------------- + def loadTestsFromName( self, name, module=None, importPath=None ): + """Return tests in this file or module. Return None if you are not able + to load any tests, or an iterable if you are. May be a generator. + + Parameters: + name : string + The test name. May be a file or module name plus a test + callable. Use split_test_name to split into parts. Or it might + be some crazy name of your own devising, in which case, do + whatever you want. + module : python module + Module from which the name is to be loaded + """ + return None + + #-------------------------------------------------------------------- + def loadTestsFromNames( self, names, module=None ): + """Return a tuple of (tests loaded, remaining names). Return None if you + are not able to load any tests. Multiple plugins may implement + loadTestsFromNames; the remaining name list from each will be passed + to the next as input. + + Parameters: + names : iterable + List of test names. + module : python module + Module from which the names are to be loaded + """ + return None + + #-------------------------------------------------------------------- + def loadTestsFromTestCase( self, cls ): + """Return tests in this test case class. Return None if you are not able + to load any tests, or an iterable if you are. May be a generator. + + Parameters: + cls : class + The test case class. Must be subclass of unittest.TestCase. + """ + return None + + #-------------------------------------------------------------------- + def loadTestsFromTestClass( self, cls ): + """Return tests in this test class. Class will not be a unittest.TestCase + subclass. Return None if you are not able to load any tests, an + iterable if you are. May be a generator. + + Parameters: + cls : class + The test class. Must NOT be subclass of unittest.TestCase. + """ + return None + + #-------------------------------------------------------------------- + def makeTest( self, obj, parent ): + """Given an object and its parent, return or yield one or more test + cases. Each test must be a unittest.TestCase (or subclass) instance. + This is called before default test loading to allow plugins to load + an alternate test case or cases for an object. May be a generator. + + Parameters: + obj : any object + The object to be made into a test + parent : class, module or other object + The parent of obj (eg, for a method, the class) + """ + return None + + #-------------------------------------------------------------------- + def options( self, parser, env = os.environ ): + """Called to allow plugin to register command line options with the parser. + + Do not return a value from this method unless you want to stop all other + plugins from setting their options. + + NOTE: By default, parser is a Python optparse.OptionParser instance. + """ + helpMsg = "The following are options specific to the matplotlib test harness" + group = optparse.OptionGroup( parser, "Matplotlib Options", helpMsg ) + + # Options to handle tags + helpMsg = "Will only run test cases that have the specified tag. Each " + helpMsg += "test case should have a 'tag' attribute (if a case does not h" + helpMsg += "ave one, then it is assumed to be an empty list). The 'tag' " + helpMsg += "attribute is a list of strings, where each value is a " + helpMsg += "representative propery of the test case. Example tags are " + helpMsg += "'qt' or 'units'. This can be specified multiple times." + group.add_option( '-t', '--with-tag', + action = 'append', type = 'string', dest = 'mpl_process_tags', + default = [], metavar = 'TAG', help = helpMsg ) + + helpMsg = "This will run those test cases that do not have the specified tags." + group.add_option( '--without-tag', + action = 'append', type = 'string', dest = 'mpl_skip_tags', + default = [], metavar = 'TAG', help = helpMsg ) + + + # Some Miscellaneous options + helpMsg = "This will remove all output files, saved results, and .pyc files. " + helpMsg += "If this is specified, no other processing will be performed." + group.add_option( '--clean', + action = "store_true", dest = "mpl_clean", + default = False, help = helpMsg ) + + helpMsg = "This will run all test programs regardless of working directory." + group.add_option( '--all', + action = "store_true", dest = "mpl_all", + default = False, help = helpMsg ) + + + # Options to handle generated data files + helpMsg = "Keep any generated output files in a directory called " + helpMsg += "'saved-results'. This directory will be created if it " + helpMsg += "doesn't already exist. This directory is in the same " + helpMsg += "location as the test case whose results are being saved." + group.add_option( '--keep', + action = "store_const", dest = "mpl_keep", + default = self.KEEP_NONE, const = self.KEEP_ALL, help = helpMsg ) + + helpMsg = "This acts just like '--keep' except will only keeps the results " + helpMsg += "from tests that error or fail." + group.add_option( '--keep-failed', + action = "store_const", dest = "mpl_keep", + default = self.KEEP_NONE, const = self.KEEP_FAIL, help = helpMsg ) + + + # Options to create a test case file + helpMsg = "Creates a template test case file in the current directory " + helpMsg += "with the name TestFoo. Where 'Foo' is the provided test name." + group.add_option( '--make-test', + action = 'store', dest = 'mpl_make_test', + default = False, metavar = 'testName', help = helpMsg ) + + + parser.add_option_group( group ) + + #-------------------------------------------------------------------- + def prepareTest( self, test ): + """Called before the test is run by the test runner. Please note the + article the in the previous sentence: prepareTest is called only once, + and is passed the test case or test suite that the test runner will + execute. It is not called for each individual test case. If you return + a non-None value, that return value will be run as the test. Use this + hook to wrap or decorate the test with another function. If you need + to modify or wrap individual test cases, use prepareTestCase instead. + + Parameters: + test : nose.case.Test + the test case + """ + return None + + #-------------------------------------------------------------------- + def prepareTestCase( self, test ): + """Prepare or wrap an individual test case. Called before execution of + the test. The test passed here is a nose.case.Test instance; the case + to be executed is in the test attribute of the passed case. To modify + the test to be run, you should return a callable that takes one + argument (the test result object) -- it is recommended that you do not + side-effect the nose.case.Test instance you have been passed. + + Keep in mind that when you replace the test callable you are replacing + the run() method of the test case -- including the exception handling + and result calls, etc. + + Parameters: + test : nose.case.Test + the test case + """ + # Save the dir names in the test class instance to make it available + # to the individual test cases. + t = getInstance( test ) + t.inputDir = self.inputDir + t.outputDir = self.outputDir + t.baselineDir = self.getBaselineDir( test ) + t.workingDir = self.currentDir + + return None + + #-------------------------------------------------------------------- + def prepareTestLoader( self, loader ): + """Called before tests are loaded. To replace the test loader, return a + test loader. To allow other plugins to process the test loader, + return None. Only one plugin may replace the test loader. Only valid + when using nose.TestProgram. + + Parameters: + loader : nose.loader.TestLoader or other loader instance + the test loader + """ + return None + + #-------------------------------------------------------------------- + def prepareTestResult( self, result ): + """Called before the first test is run. To use a different test result + handler for all tests than the given result, return a test result + handler. NOTE however that this handler will only be seen by tests, + that is, inside of the result proxy system. The TestRunner and + TestProgram -- whether nose's or other -- will continue to see the + original result handler. For this reason, it is usually better to + monkeypatch the result (for instance, if you want to handle some + exceptions in a unique way). Only one plugin may replace the result, + but many may monkeypatch it. If you want to monkeypatch and stop + other plugins from doing so, monkeypatch and return the patched result. + + Parameters: + result : nose.result.TextTestResult or other result instance + the test result + """ + return None + + #-------------------------------------------------------------------- + def prepareTestRunner( self, runner ): + """Called before tests are run. To replace the test runner, return a + test runner. To allow other plugins to process the test runner, + return None. Only valid when using nose.TestProgram. + + Parameters: + runner : nose.core.TextTestRunner or other runner instance + the test runner + """ + return None + + #-------------------------------------------------------------------- + def report( self, stream ): + """Called after all error output has been printed. Print your plugin's + report to the provided stream. Return None to allow other plugins to + print reports, any other value to stop them. + + Parameters: + stream : file-like object + stream object; send your output here + """ + return None + + #-------------------------------------------------------------------- + def setOutputStream( self, stream ): + """Called before test output begins. To direct test output to a new + stream, return a stream object, which must implement a write(msg) + method. If you only want to note the stream, not capture or redirect + it, then return None. + + Parameters: + stream : file-like object + the original output stream + """ + return None + + #-------------------------------------------------------------------- + def startContext( self, context ): + """Called before context setup and the running of tests in the context. + Note that tests have already been loaded from the context before this call. + + Parameters: + context : module, class or other object + the context about to be setup. May be a module or class, or + any other object that contains tests. + """ + return None + + #-------------------------------------------------------------------- + def startTest( self, test ): + """Called before each test is run. DO NOT return a value unless you want + to stop other plugins from seeing the test start. + + Parameters: + test : nose.case.Test + the test case + """ + # make sure there is a fresh output directory to use. + rmdir( self.outputDir ) + mkdir( self.outputDir, recursive = True ) + + # sys.stdout.write( "%s\n %s \n" % (test.id(), test.shortDescription()) ) + print "%s" % (test.id()) + print " %s" % (test.shortDescription()) + + #-------------------------------------------------------------------- + def stopContext( self, context ): + """Called after the tests in a context have run and the context has been + torn down. + + Parameters: + context : module, class or other object + the context that has just been torn down. + """ + return None + + #-------------------------------------------------------------------- + def stopTest( self, test ): + """Called after each test is run. DO NOT return a value unless you want + to stop other plugins from seeing that the test has stopped. + + Parameters: + test : nose.case.Test + the test case + """ + assert test == self.testResults[-1][0] + + if self.keepLevel == self.KEEP_ALL: + self.saveResults( test ) + + # KEEP_FAIL is handled by the 'handleError' and 'handleFailed' methods. + + rmdir( self.outputDir ) + + #-------------------------------------------------------------------- + def testName( self, test ): + """Return a short test name. Called by nose.case.Test.__str__. + + Parameters: + test : nose.case.Test + the test case + """ + return None + + #-------------------------------------------------------------------- + def wantClass( self, cls ): + """Return true if you want the main test selector to collect tests from + this class, false if you don't, and None if you don't care. + + Parameters: + cls : class + The class being examined by the selector + """ + # Filter out classes that do not inherit from MplTestCase + if not issubclass( cls, MplTestCase ): + return False + + return self.filterTestItem( cls ) + + #-------------------------------------------------------------------- + def wantDirectory( self, dirname ): + """Return true if you want test collection to descend into this + directory, false if you do not, and None if you don't care. + + Parameters: + dirname : string + Full path to directory being examined by the selector + """ + # Skip the unit-test utility module. + if dirname == os.path.join( self.rootDir, 'mplTest' ): + return False + + return None + + #-------------------------------------------------------------------- + def wantFile( self, file ): + """Return true if you want to collect tests from this file, false if + you do not and None if you don't care. + + Parameters: + file : string + Full path to file being examined by the selector + """ + # Skip anything not under the root test directory + if self.rootDir not in file: + return False + + return None + + #-------------------------------------------------------------------- + def wantFunction( self, function ): + """Return true to collect this function as a test, false to prevent it + from being collected, and None if you don't care. + + Parameters: + function : function + The function object being examined by the selector + """ + #TODO: Filter out functions that exist outside of the test-structure + name = function.__name__.lower() + if "disabled" in name: return False + return self.filterTestItem( function ) + + #-------------------------------------------------------------------- + def wantMethod( self, method ): + """Return true to collect this method as a test, false to prevent it + from being collected, and None if you don't care. + + Parameters: + method : unbound method + The method object being examined by the selector + """ + #TODO: Filter out methods that exist outside of the test-structure + name = method.__name__.lower() + if "disabled" in name: return False + return self.filterTestItem( method ) + + #-------------------------------------------------------------------- + def wantModule( self, module ): + """Return true if you want to collection to descend into this module, + false to prevent the collector from descending into the module, and + None if you don't care. + + Parameters: + module : python module + The module object being examined by the selector + """ + #TODO: Filter out modules that exist outside of the test-structure + name = module.__name__.lower() + if "disabled" in name: return False + return self.filterTestItem( module ) + + Added: trunk/matplotlib/test/mplTest/MplTestCase.py =================================================================== --- trunk/matplotlib/test/mplTest/MplTestCase.py (rev 0) +++ trunk/matplotlib/test/mplTest/MplTestCase.py 2009-02-18 19:44:29 UTC (rev 6922) @@ -0,0 +1,117 @@ +#======================================================================= +"""Defines the base matplotlib test-case.""" +#======================================================================= + +import os +import os.path +import unittest + +import compare +import path_utils + +#======================================================================= + +__all__ = [ 'MplTestCase' ] + +#======================================================================= +class MplTestCase( unittest.TestCase ): + """This is the base class for the matplotlib unit-tests. + + It provides a few utility functions for accessing managed directories: + - inputs - All input files for the test case are stored here. + - outputs - All output files for the test case are written here. + - baseline - All baseline files (those used for verifying results) for + athe test case are stored here. + """ + #-------------------------------------------------------------------- + def inFile( self, fname ): + """Returns the pathname of the specified input file.""" + return os.path.join( self.inputDir, fname ) + + def outFile( self, fname ): + """Returns the pathname of the specified output file.""" + return os.path.join( self.outputDir, fname ) + + def baseFile( self, fname ): + """Returns the pathname of the specified basline file.""" + return os.path.join( self.baselineDir, fname ) + + #-------------------------------------------------------------------- + def checkImage( self, outfname, tol = 1.0e-3, msg = "" ): + """Check to see if the image is similair to one stored in the + baseline directory. + """ + if self.outputDir in outfname: + # We are passed the path name and just want the file name. + actualImage = outfname + basename = path_utils.name( outfname ) + else: + basename = outfname + actualImage = self.outFile( basename ) + + baselineImage = self.baseFile( basename ) + + errorMessage = compare.compareImages( baselineImage, actualImage, tol ) + + if errorMessage: + self.fail( msg + "\n" + errorMessage ) + + #-------------------------------------------------------------------- + def checkEq( expected, actual, msg = "" ): + """Fail if the values are not equal, with the given message.""" + if not expected == actual: + expectedStr = str( expected ) + actualStr = str( actual ) + isMultiLine = ( "\n" in expectedStr or "\n" in actualStr or + len( expectedStr ) > 70 or len( actualStr ) > 70 ) + + if isMultiLine: + if msg: + msg += "\n\n" + msg += "Expected:\n" + msg += expectedStr + "\n\n" + msg += "Actual:\n" + msg += actualStr + "\n" + else: + if msg: + msg += "\n" + msg += " Expected: " + expectedStr + "\n" + msg += " Actual: " + actualStr + "\n" + + self.fail( msg ) + + #-------------------------------------------------------------------- + def checkNeq( expected, actual, msg = "" ): + """Fail is the values are equal, with the given message.""" + if expected == actual: + expectedStr = str( expected ) + isMultiLine = ( "\n" in expectedStr or len( expectedStr ) > 55 ) + + if isMultiLine: + if msg: + msg += "\n\n" + msg += "Expected and actual should not be equal.\n" + msg += "Expected and actual:\n" + msg += expectedStr + "\n" + else: + if msg: + msg += "\n" + msg += " Expected and actual should not be equal.\n" + msg += " Expected and actual: " + expectedStr + "\n" + + self.fail( msg ) + + #-------------------------------------------------------------------- + def checkClose( expected, actual, relTol = None, absTol = None, msg = "" ): + """Fail if the floating point values are not close enough, with + the givem message. + + You can specify a relative tolerance, absolute tolerance, or both. + """ + errorMessage = compare.compareFloat( expected, actual, relTol, absTol ) + + if errorMessage: + self.fail( msg + "\n" + errorMessage ) + + #-------------------------------------------------------------------- + Added: trunk/matplotlib/test/mplTest/TestTEMPLATE.py =================================================================== --- trunk/matplotlib/test/mplTest/TestTEMPLATE.py (rev 0) +++ trunk/matplotlib/test/mplTest/TestTEMPLATE.py 2009-02-18 19:44:29 UTC (rev 6922) @@ -0,0 +1,62 @@ +#======================================================================= +"""The UNITTEST unit-test class implementation.""" +#======================================================================= + +from mplTest import * + +#======================================================================= +# Add import modules below. +import matplotlib +matplotlib.use( "Agg", warn = False ) + +import pylab +import numpy as npy +# +#======================================================================= + +#======================================================================= +class TestUNITTEST( MplTestCase ): + """UNITTEST unit test class.""" + + # Uncomment any appropriate tags + tags = [ + # 'gui', # requires the creation of a gui window + # 'agg', # uses agg in the backend + # 'agg-only', # uses only agg in the backend + # 'wx', # uses wx in the backend + # 'qt', # uses qt in the backend + # 'ps', # uses the postscript backend + # 'pdf', # uses the PDF backend + # 'units', # uses units in the test + # 'PIL', # uses PIL for image comparison + ] + + #-------------------------------------------------------------------- + def setUp( self ): + """Setup any data needed for the unit test.""" + #TODO: Put set-up code here + pass + + #-------------------------------------------------------------------- + def tearDown( self ): + """Clean-up any generated files here.""" + #TODO: Put clean-up code here + pass + + #-------------------------------------------------------------------- + def test_case_001( self ): + """TODO: A very brief description of the test case.""" + #TODO: Put test-case code here + + fname = self.outFile( "test_case_001a" ) + fout = open( fname, 'w' ) + fout.write( "A UNITTEST.test_case_001 output file.\n" ) + fout.close() + + fname = self.outFile( "test_case_001b" ) + fout = open( fname, 'w' ) + fout.write( "Another UNITTEST.test_case_001 output file.\n" ) + fout.close() + + pass + Added: trunk/matplotlib/test/mplTest/__init__.py =================================================================== --- trunk/matplotlib/test/mplTest/__init__.py (rev 0) +++ trunk/matplotlib/test/mplTest/__init__.py 2009-02-18 19:44:29 UTC (rev 6922) @@ -0,0 +1,13 @@ + +""" +A matplotlib unit test module. This module provides several utilities for +performing unit-tests on matplotlib. Theis module depends on a properly +installed version of 'nose'. +""" + +from directories import * + +from mplTest.MplNosePlugin import MplNosePlugin +from mplTest.MplTestCase import MplTestCase + +import mplTest.units as units Added: trunk/matplotlib/test/mplTest/compare.py =================================================================== --- trunk/matplotlib/test/mplTest/compare.py (rev 0) +++ trunk/matplotlib/test/mplTest/compare.py 2009-02-18 19:44:29 UTC (rev 6922) @@ -0,0 +1,121 @@ +#======================================================================= +""" A set of utilities for comparing results. +""" +#======================================================================= + +import math +import operator + +#======================================================================= + +__all__ = [ + 'compareFloat', + 'compareImages', + ] + +#----------------------------------------------------------------------- +def compareFloat( expected, actual, relTol = None, absTol = None ): + """Fail if the floating point values are not close enough, with + the givem message. + + You can specify a relative tolerance, absolute tolerance, or both. + """ + if relTol is None and absTol is None: + exMsg = "You haven't specified a 'relTol' relative tolerance " + exMsg += "or a 'absTol' absolute tolerance function argument. " + exMsg += "You must specify one." + raise ValueError, exMsg + + msg = "" + + if absTol is not None: + absDiff = abs( expected - actual ) + if absTol < absDiff: + expectedStr = str( expected ) + actualStr = str( actual ) + absDiffStr = str( absDiff ) + absTolStr = str( absTol ) + + msg += "\n" + msg += " Expected: " + expectedStr + "\n" + msg += " Actual: " + actualStr + "\n" + msg += " Abs Diff: " + absDiffStr + "\n" + msg += " Abs Tol: " + absTolStr + "\n" + + if relTol is not None: + # The relative difference of the two values. If the expected value is + # zero, then return the absolute value of the difference. + relDiff = abs( expected - actual ) + if expected: + relDiff = relDiff / abs( expected ) + + if relTol < relDiff: + + # The relative difference is a ratio, so it's always unitless. + relDiffStr = str( relDiff ) + relTolStr = str( relTol ) + + expectedStr = str( expected ) + actualStr = str( actual ) + + msg += "\n" + msg += " Expected: " + expectedStr + "\n" + msg += " Actual: " + actualStr + "\n" + msg += " Rel Diff: " + relDiffStr + "\n" + msg += " Rel Tol: " + relTolStr + "\n" + + if msg: + return msg + else: + return None + +#----------------------------------------------------------------------- +def compareImages( expected, ac... [truncated message content] |
From: <ef...@us...> - 2009-02-21 19:07:03
|
Revision: 6923 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6923&view=rev Author: efiring Date: 2009-02-21 19:06:58 +0000 (Sat, 21 Feb 2009) Log Message: ----------- Improve scatter argument handling Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/axes.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009-02-18 19:44:29 UTC (rev 6922) +++ trunk/matplotlib/CHANGELOG 2009-02-21 19:06:58 UTC (rev 6923) @@ -1,3 +1,6 @@ +2009-02-21 Improve scatter argument handling; add an early error + message, allow inputs to have more than one dimension. - EF + 2009-02-16 Move plot_directive.py to the installed source tree. Add support for inline code content - MGD Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2009-02-18 19:44:29 UTC (rev 6922) +++ trunk/matplotlib/lib/matplotlib/axes.py 2009-02-21 19:06:58 UTC (rev 6923) @@ -4949,8 +4949,8 @@ vmin=None, vmax=None, alpha=1.0, linewidths=None, verts=None, **kwargs) - Make a scatter plot of *x* versus *y*, where *x*, *y* are 1-D - sequences of the same length, *N*. + Make a scatter plot of *x* versus *y*, where *x*, *y* are + converted to 1-D sequences which must be of the same length, *N*. Keyword arguments: @@ -5088,24 +5088,35 @@ x = self.convert_xunits(x) y = self.convert_yunits(y) + # np.ma.ravel yields an ndarray, not a masked array, + # unless its argument is a masked array. + x = np.ma.ravel(x) + y = np.ma.ravel(y) + if x.size != y.size: + raise ValueError("x and y must be the same size") + + s = np.ma.ravel(s) # This doesn't have to match x, y in size. + + c_is_stringy = is_string_like(c) or cbook.is_sequence_of_strings(c) + if not c_is_stringy: + c = np.asanyarray(c) + if c.size == x.size: + c = np.ma.ravel(c) + x, y, s, c = cbook.delete_masked_points(x, y, s, c) + scales = s # Renamed for readability below. - if is_string_like(c) or cbook.is_sequence_of_strings(c): + if c_is_stringy: colors = mcolors.colorConverter.to_rgba_array(c, alpha) else: - sh = np.shape(c) # The inherent ambiguity is resolved in favor of color # mapping, not interpretation as rgb or rgba: - if len(sh) == 1 and sh[0] == len(x): + if c.size == x.size: colors = None # use cmap, norm after collection is created else: colors = mcolors.colorConverter.to_rgba_array(c, alpha) - if not iterable(s): - scales = (s,) - else: - scales = s if faceted: edgecolors = None This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |