You can subscribe to this list here.
2007 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(115) |
Aug
(120) |
Sep
(137) |
Oct
(170) |
Nov
(461) |
Dec
(263) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2008 |
Jan
(120) |
Feb
(74) |
Mar
(35) |
Apr
(74) |
May
(245) |
Jun
(356) |
Jul
(240) |
Aug
(115) |
Sep
(78) |
Oct
(225) |
Nov
(98) |
Dec
(271) |
2009 |
Jan
(132) |
Feb
(84) |
Mar
(74) |
Apr
(56) |
May
(90) |
Jun
(79) |
Jul
(83) |
Aug
(296) |
Sep
(214) |
Oct
(76) |
Nov
(82) |
Dec
(66) |
2010 |
Jan
(46) |
Feb
(58) |
Mar
(51) |
Apr
(77) |
May
(58) |
Jun
(126) |
Jul
(128) |
Aug
(64) |
Sep
(50) |
Oct
(44) |
Nov
(48) |
Dec
(54) |
2011 |
Jan
(68) |
Feb
(52) |
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(1) |
2018 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
S | M | T | W | T | F | S |
---|---|---|---|---|---|---|
|
|
1
(3) |
2
|
3
|
4
(1) |
5
|
6
(1) |
7
(2) |
8
(22) |
9
(8) |
10
(24) |
11
(3) |
12
(4) |
13
|
14
(3) |
15
(3) |
16
(1) |
17
(2) |
18
(6) |
19
|
20
|
21
(3) |
22
(2) |
23
(8) |
24
(1) |
25
|
26
(6) |
27
(1) |
28
(3) |
29
(4) |
30
|
31
(9) |
|
|
Revision: 4867 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4867&view=rev Author: mdboom Date: 2008年01月14日 05:15:17 -0800 (2008年1月14日) Log Message: ----------- Merged revisions 4856-4866 via svnmerge from https://matplotlib.svn.sourceforge.net/svnroot/matplotlib/branches/v0_91_maint ........ r4866 | mdboom | 2008年01月14日 08:11:16 -0500 (2008年1月14日) | 3 lines Fix SVG glyphs for use with Qt (which doesn't look forward for the glyph definitions). ........ Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/backends/backend_svg.py Property Changed: ---------------- trunk/matplotlib/ Property changes on: trunk/matplotlib ___________________________________________________________________ Name: svnmerge-integrated - /branches/v0_91_maint:1-4855 + /branches/v0_91_maint:1-4866 Modified: trunk/matplotlib/lib/matplotlib/backends/backend_svg.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_svg.py 2008年01月14日 13:11:16 UTC (rev 4866) +++ trunk/matplotlib/lib/matplotlib/backends/backend_svg.py 2008年01月14日 13:15:17 UTC (rev 4867) @@ -294,8 +294,20 @@ fontsize = prop.get_size_in_points() color = rgb2hex(gc.get_rgb()[:3]) + write = self._svgwriter.write if rcParams['svg.embed_char_paths']: + new_chars = [] + for c in s: + path = self._add_char_def(prop, c) + if path is not None: + new_chars.append(path) + if len(new_chars): + write('<defs>\n') + for path in new_chars: + write(path) + write('</defs>\n') + svg = ['<g style="fill: %s; opacity: %s" transform="' % (color, gc.get_alpha())] if angle != 0: svg.append('translate(%s,%s)rotate(%1.1f)' % (x,y,-angle)) @@ -307,7 +319,7 @@ lastgind = None currx = 0 for c in s: - charid = self._add_char_def(prop, c) + charnum = self._get_char_def_id(prop, c) ccode = ord(c) gind = cmap.get(ccode) if gind is None: @@ -322,7 +334,7 @@ lastgind = gind currx += kern/64.0 - svg.append('<use xlink:href="#%s"' % charid) + svg.append('<use xlink:href="#%s"' % charnum) if currx != 0: svg.append(' x="%s"' % (currx * (self.FONT_SCALE / fontsize))) @@ -346,7 +358,7 @@ svg = """\ <text style="%(style)s" x="%(x)s" y="%(y)s" %(transform)s>%(thetext)s</text> """ % locals() - self._svgwriter.write (svg) + write(svg) def _add_char_def(self, prop, char): if isinstance(prop, FontProperties): @@ -357,9 +369,9 @@ font.set_size(self.FONT_SCALE, 72) ps_name = font.get_sfnt()[(1,0,0,6)] char_id = urllib.quote('%s-%d' % (ps_name, ord(char))) - char_num, path = self._char_defs.get(char_id, (None, None)) + char_num = self._char_defs.get(char_id, None) if char_num is not None: - return char_num + return None path_data = [] glyph = font.load_char(ord(char), flags=LOAD_NO_HINTING) @@ -388,9 +400,20 @@ currx, curry = step[-2], -step[-1] char_num = 'c%x' % len(self._char_defs) path_element = '<path id="%s" d="%s"/>\n' % (char_num, ''.join(path_data)) - self._char_defs[char_id] = (char_num, path_element) - return char_num + self._char_defs[char_id] = char_num + return path_element + def _get_char_def_id(self, prop, char): + if isinstance(prop, FontProperties): + newprop = prop.copy() + font = self._get_font(newprop) + else: + font = prop + font.set_size(self.FONT_SCALE, 72) + ps_name = font.get_sfnt()[(1,0,0,6)] + char_id = urllib.quote('%s-%d' % (ps_name, ord(char))) + return self._char_defs[char_id] + def _draw_mathtext(self, gc, x, y, s, prop, angle): """ Draw math text using matplotlib.mathtext @@ -400,12 +423,22 @@ svg_glyphs = svg_elements.svg_glyphs svg_rects = svg_elements.svg_rects color = rgb2hex(gc.get_rgb()[:3]) + write = self._svgwriter.write - self.open_group("mathtext") - style = "fill: %s" % color if rcParams['svg.embed_char_paths']: + new_chars = [] + for font, fontsize, thetext, new_x, new_y_mtc, metrics in svg_glyphs: + path = self._add_char_def(font, thetext) + if path is not None: + new_chars.append(path) + if len(new_chars): + write('<defs>\n') + for path in new_chars: + write(path) + write('</defs>\n') + svg = ['<g style="%s" transform="' % style] if angle != 0: svg.append('translate(%s,%s)rotate(%1.1f)' @@ -415,7 +448,7 @@ svg.append('">\n') for font, fontsize, thetext, new_x, new_y_mtc, metrics in svg_glyphs: - charid = self._add_char_def(font, thetext) + charid = self._get_char_def_id(font, thetext) svg.append('<use xlink:href="#%s" transform="translate(%s,%s)scale(%s)"/>\n' % (charid, new_x, -new_y_mtc, fontsize / self.FONT_SCALE)) @@ -469,16 +502,12 @@ svg.append('<rect x="%s" y="%s" width="%s" height="%s" fill="black" stroke="none" />' % (x, -y + height, width, height)) svg.append("</g>") - self._svgwriter.write (''.join(svg)) + self.open_group("mathtext") + write (''.join(svg)) self.close_group("mathtext") def finalize(self): write = self._svgwriter.write - if len(self._char_defs): - write('<defs id="fontpaths">\n') - for char_num, path in self._char_defs.values(): - write(path) - write('</defs>\n') write('</svg>\n') def flipy(self): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 4866 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4866&view=rev Author: mdboom Date: 2008年01月14日 05:11:16 -0800 (2008年1月14日) Log Message: ----------- Fix SVG glyphs for use with Qt (which doesn't look forward for the glyph definitions). Modified Paths: -------------- branches/v0_91_maint/lib/matplotlib/backends/backend_svg.py Modified: branches/v0_91_maint/lib/matplotlib/backends/backend_svg.py =================================================================== --- branches/v0_91_maint/lib/matplotlib/backends/backend_svg.py 2008年01月12日 13:36:24 UTC (rev 4865) +++ branches/v0_91_maint/lib/matplotlib/backends/backend_svg.py 2008年01月14日 13:11:16 UTC (rev 4866) @@ -284,8 +284,20 @@ fontsize = prop.get_size_in_points() color = rgb2hex(gc.get_rgb()) + write = self._svgwriter.write if rcParams['svg.embed_char_paths']: + new_chars = [] + for c in s: + path = self._add_char_def(prop, c) + if path is not None: + new_chars.append(path) + if len(new_chars): + write('<defs>\n') + for path in new_chars: + write(path) + write('</defs>\n') + svg = ['<g style="fill: %s; opacity: %s" transform="' % (color, gc.get_alpha())] if angle != 0: svg.append('translate(%s,%s)rotate(%1.1f)' % (x,y,-angle)) @@ -297,7 +309,7 @@ lastgind = None currx = 0 for c in s: - charid = self._add_char_def(prop, c) + charnum = self._get_char_def_id(prop, c) ccode = ord(c) gind = cmap.get(ccode) if gind is None: @@ -312,7 +324,7 @@ lastgind = gind currx += kern/64.0 - svg.append('<use xlink:href="#%s"' % charid) + svg.append('<use xlink:href="#%s"' % charnum) if currx != 0: svg.append(' transform="translate(%s)"' % (currx * (self.FONT_SCALE / fontsize))) @@ -336,7 +348,7 @@ svg = """\ <text style="%(style)s" x="%(x)s" y="%(y)s" %(transform)s>%(thetext)s</text> """ % locals() - self._svgwriter.write (svg) + write(svg) def _add_char_def(self, prop, char): if isinstance(prop, FontProperties): @@ -347,9 +359,9 @@ font.set_size(self.FONT_SCALE, 72) ps_name = font.get_sfnt()[(1,0,0,6)] char_id = urllib.quote('%s-%d' % (ps_name, ord(char))) - char_num, path = self._char_defs.get(char_id, (None, None)) + char_num = self._char_defs.get(char_id, None) if char_num is not None: - return char_num + return None path_data = [] glyph = font.load_char(ord(char), flags=LOAD_NO_HINTING) @@ -378,9 +390,20 @@ currx, curry = step[-2], -step[-1] char_num = 'c_%x' % len(self._char_defs) path_element = '<path id="%s" d="%s"/>\n' % (char_num, ''.join(path_data)) - self._char_defs[char_id] = (char_num, path_element) - return char_num + self._char_defs[char_id] = char_num + return path_element + def _get_char_def_id(self, prop, char): + if isinstance(prop, FontProperties): + newprop = prop.copy() + font = self._get_font(newprop) + else: + font = prop + font.set_size(self.FONT_SCALE, 72) + ps_name = font.get_sfnt()[(1,0,0,6)] + char_id = urllib.quote('%s-%d' % (ps_name, ord(char))) + return self._char_defs[char_id] + def _draw_mathtext(self, gc, x, y, s, prop, angle): """ Draw math text using matplotlib.mathtext @@ -390,12 +413,22 @@ svg_glyphs = svg_elements.svg_glyphs svg_rects = svg_elements.svg_rects color = rgb2hex(gc.get_rgb()) + write = self._svgwriter.write - self.open_group("mathtext") - style = "fill: %s" % color if rcParams['svg.embed_char_paths']: + new_chars = [] + for font, fontsize, thetext, new_x, new_y_mtc, metrics in svg_glyphs: + path = self._add_char_def(font, thetext) + if path is not None: + new_chars.append(path) + if len(new_chars): + write('<defs>\n') + for path in new_chars: + write(path) + write('</defs>\n') + svg = ['<g style="%s" transform="' % style] if angle != 0: svg.append('translate(%s,%s)rotate(%1.1f)' @@ -405,7 +438,7 @@ svg.append('">\n') for font, fontsize, thetext, new_x, new_y_mtc, metrics in svg_glyphs: - charid = self._add_char_def(font, thetext) + charid = self._get_char_def_id(font, thetext) svg.append('<use xlink:href="#%s" transform="translate(%s,%s)scale(%s)"/>\n' % (charid, new_x, -new_y_mtc, fontsize / self.FONT_SCALE)) @@ -459,16 +492,12 @@ svg.append('<rect x="%s" y="%s" width="%s" height="%s" fill="black" stroke="none" />' % (x, -y + height, width, height)) svg.append("</g>") - self._svgwriter.write (''.join(svg)) + self.open_group("mathtext") + write (''.join(svg)) self.close_group("mathtext") def finish(self): write = self._svgwriter.write - if len(self._char_defs): - write('<defs id="fontpaths">\n') - for char_num, path in self._char_defs.values(): - write(path) - write('</defs>\n') write('</svg>\n') def flipy(self): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 4865 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4865&view=rev Author: jswhit Date: 2008年01月12日 05:36:24 -0800 (2008年1月12日) Log Message: ----------- update download instructions Modified Paths: -------------- trunk/toolkits/basemap/README Modified: trunk/toolkits/basemap/README =================================================================== --- trunk/toolkits/basemap/README 2008年01月12日 13:32:31 UTC (rev 4864) +++ trunk/toolkits/basemap/README 2008年01月12日 13:36:24 UTC (rev 4865) @@ -68,8 +68,11 @@ 0) Install pre-requisite python modules numpy and matplotlib. -1) Then download basemap-X.Y.Z.tar.gz from +1) Then download basemap-X.Y.Z.tar.gz (approx 32 mb) from the sourceforge download site, unpack and cd to basemap-X.Y.Z. +If you want the full-resolution coastline dataset (useful if you +will be making maps of very small regions), get +basemap-fullresdata-X.Y.Z.tar.gz (approx. 100 mb). 2) Install the GEOS library. If you already have it on your system, just set the environment variable GEOS_DIR to point to the location This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 4864 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4864&view=rev Author: jswhit Date: 2008年01月12日 05:32:31 -0800 (2008年1月12日) Log Message: ----------- obsolete Removed Paths: ------------- trunk/toolkits/basemap/MANIFEST-data Deleted: trunk/toolkits/basemap/MANIFEST-data =================================================================== --- trunk/toolkits/basemap/MANIFEST-data 2008年01月12日 00:12:10 UTC (rev 4863) +++ trunk/toolkits/basemap/MANIFEST-data 2008年01月12日 13:32:31 UTC (rev 4864) @@ -1,13 +0,0 @@ -MANIFEST-data -LICENSE_data -README -setup-data.py -lib/matplotlib/toolkits/basemap/data/__init__.py -lib/matplotlib/toolkits/basemap/data/countries_f.dat -lib/matplotlib/toolkits/basemap/data/countriesmeta_f.dat -lib/matplotlib/toolkits/basemap/data/gshhs_f.dat -lib/matplotlib/toolkits/basemap/data/gshhsmeta_f.dat -lib/matplotlib/toolkits/basemap/data/rivers_f.dat -lib/matplotlib/toolkits/basemap/data/riversmeta_f.dat -lib/matplotlib/toolkits/basemap/data/states_f.dat -lib/matplotlib/toolkits/basemap/data/statesmeta_f.dat This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 4863 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4863&view=rev Author: jswhit Date: 2008年01月11日 16:12:10 -0800 (2008年1月11日) Log Message: ----------- not needed Removed Paths: ------------- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/__init__.py Deleted: trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/__init__.py =================================================================== This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 4862 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4862&view=rev Author: jswhit Date: 2008年01月11日 16:00:22 -0800 (2008年1月11日) Log Message: ----------- update install instructions. Modified Paths: -------------- trunk/toolkits/basemap/README Modified: trunk/toolkits/basemap/README =================================================================== --- trunk/toolkits/basemap/README 2008年01月11日 23:59:04 UTC (rev 4861) +++ trunk/toolkits/basemap/README 2008年01月12日 00:00:22 UTC (rev 4862) @@ -89,19 +89,9 @@ run the usual 'python setup.py install'. 4) To test, cd to the examples directory and run 'python simpletest.py'. -On linux, if you get an import error (with a message about not -finding libgeos.so) you may need to set the LD_LIBRARY_PATH environment -to include $GEOS_DIR/lib. To run all the examples (except those that -have extra dependenices or require an internet connection), execute -'python run_all.py'. +To run all the examples (except those that have extra dependencies +or require an internet connection), execute 'python run_all.py'. -5) if you want the full-resolution coastlines, download -basemap-data-fullres-X.Y.Z.tar.gz (about 70 mb), untar -it, cd into basemap-data-fullres-X.Y.Z and -run 'python setup-data.py install'. The fullres dataset does not -change with every basemap release, so you may need to look back -a couple of releases on the download page to find it. - **Contact** Jeff Whitaker <jef...@no...> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 4861 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4861&view=rev Author: jswhit Date: 2008年01月11日 15:59:04 -0800 (2008年1月11日) Log Message: ----------- remove separate data package (won't work unless nested namespace packages are used anyway) Modified Paths: -------------- trunk/toolkits/basemap/MANIFEST.in Removed Paths: ------------- trunk/toolkits/basemap/setup-data.py trunk/toolkits/basemap/setupegg-data.py Modified: trunk/toolkits/basemap/MANIFEST.in =================================================================== --- trunk/toolkits/basemap/MANIFEST.in 2008年01月11日 23:32:10 UTC (rev 4860) +++ trunk/toolkits/basemap/MANIFEST.in 2008年01月11日 23:59:04 UTC (rev 4861) @@ -84,54 +84,4 @@ recursive-include lib/httplib2 * recursive-include lib/dbflib * recursive-include lib/shapelib * -include lib/mpl_toolkits/basemap/data/5minmask.bin -include lib/mpl_toolkits/basemap/data/GL27 -include lib/mpl_toolkits/basemap/data/countries_c.dat -include lib/mpl_toolkits/basemap/data/countries_h.dat -include lib/mpl_toolkits/basemap/data/countries_i.dat -include lib/mpl_toolkits/basemap/data/countries_l.dat -include lib/mpl_toolkits/basemap/data/countriesmeta_c.dat -include lib/mpl_toolkits/basemap/data/countriesmeta_h.dat -include lib/mpl_toolkits/basemap/data/countriesmeta_i.dat -include lib/mpl_toolkits/basemap/data/countriesmeta_l.dat -include lib/mpl_toolkits/basemap/data/epsg -include lib/mpl_toolkits/basemap/data/esri -include lib/mpl_toolkits/basemap/data/esri.extra -include lib/mpl_toolkits/basemap/data/gshhs_c.dat -include lib/mpl_toolkits/basemap/data/gshhs_h.dat -include lib/mpl_toolkits/basemap/data/gshhs_i.dat -include lib/mpl_toolkits/basemap/data/gshhs_l.dat -include lib/mpl_toolkits/basemap/data/gshhsmeta_c.dat -include lib/mpl_toolkits/basemap/data/gshhsmeta_h.dat -include lib/mpl_toolkits/basemap/data/gshhsmeta_i.dat -include lib/mpl_toolkits/basemap/data/gshhsmeta_l.dat -include lib/mpl_toolkits/basemap/data/nad.lst -include lib/mpl_toolkits/basemap/data/nad27 -include lib/mpl_toolkits/basemap/data/nad83 -include lib/mpl_toolkits/basemap/data/ntv2_out.dist -include lib/mpl_toolkits/basemap/data/other.extra -include lib/mpl_toolkits/basemap/data/pj_out27.dist -include lib/mpl_toolkits/basemap/data/pj_out83.dist -include lib/mpl_toolkits/basemap/data/proj_def.dat -include lib/mpl_toolkits/basemap/data/rivers_c.dat -include lib/mpl_toolkits/basemap/data/rivers_h.dat -include lib/mpl_toolkits/basemap/data/rivers_i.dat -include lib/mpl_toolkits/basemap/data/rivers_l.dat -include lib/mpl_toolkits/basemap/data/riversmeta_c.dat -include lib/mpl_toolkits/basemap/data/riversmeta_h.dat -include lib/mpl_toolkits/basemap/data/riversmeta_i.dat -include lib/mpl_toolkits/basemap/data/riversmeta_l.dat -include lib/mpl_toolkits/basemap/data/states_c.dat -include lib/mpl_toolkits/basemap/data/states_h.dat -include lib/mpl_toolkits/basemap/data/states_i.dat -include lib/mpl_toolkits/basemap/data/states_l.dat -include lib/mpl_toolkits/basemap/data/statesmeta_c.dat -include lib/mpl_toolkits/basemap/data/statesmeta_h.dat -include lib/mpl_toolkits/basemap/data/statesmeta_i.dat -include lib/mpl_toolkits/basemap/data/statesmeta_l.dat -include lib/mpl_toolkits/basemap/data/td_out.dist -include lib/mpl_toolkits/basemap/data/test27 -include lib/mpl_toolkits/basemap/data/test83 -include lib/mpl_toolkits/basemap/data/testntv2 -include lib/mpl_toolkits/basemap/data/testvarious -include lib/mpl_toolkits/basemap/data/world +recursive-include lib/mpl_toolkits/basemap/data * Deleted: trunk/toolkits/basemap/setup-data.py =================================================================== --- trunk/toolkits/basemap/setup-data.py 2008年01月11日 23:32:10 UTC (rev 4860) +++ trunk/toolkits/basemap/setup-data.py 2008年01月11日 23:59:04 UTC (rev 4861) @@ -1,41 +0,0 @@ -import sys, glob, os -major, minor1, minor2, s, tmp = sys.version_info -if major==2 and minor1<=3: - # setuptools monkeypatches distutils.core.Distribution to support - # package_data - try: import setuptools - except ImportError: - raise SystemExit(""" -matplotlib requires setuptools for installation. Please download -http://peak.telecommunity.com/dist/ez_setup.py and run it (as su if -you are doing a system wide install) to install the proper version of -setuptools for your system""") - raise SystemExit("""The basemap toolkit requires python 2.4.""") -from distutils.core import setup - -packages = ['mpl_toolkits.basemap.data'] -package_dirs = {'':'lib'} -boundaryfiles = glob.glob("lib/matplotlib/toolkits/basemap/data/*_f.dat") -basemap_datafiles = [os.path.basename(bfile) for bfile in boundaryfiles] -package_data = {'mpl_toolkits.basemap.data':basemap_datafiles} -setup( - name = "basemap-data-fullres", - version = "0.9.7", - description = "full-resolution boundary data for basemap", - url = "http://matplotlib.sourceforge.net/toolkits.html", - download_url = "http://sourceforge.net/projects/matplotlib", - author = "Jeff Whitaker", - author_email = "jef...@no...", - platforms = ["any"], - license = "OSI Approved", - keywords = ["python","plotting","plots","graphs","charts","GIS","mapping","map projections","maps"], - classifiers = ["Development Status :: 4 - Beta", - "Intended Audience :: Science/Research", - "License :: OSI Approved", - "Topic :: Scientific/Engineering :: Visualization", - "Topic :: Software Development :: Libraries :: Python Modules", - "Operating System :: OS Independent"], - packages = packages, - package_dir = package_dirs, - package_data = package_data - ) Deleted: trunk/toolkits/basemap/setupegg-data.py =================================================================== --- trunk/toolkits/basemap/setupegg-data.py 2008年01月11日 23:32:10 UTC (rev 4860) +++ trunk/toolkits/basemap/setupegg-data.py 2008年01月11日 23:59:04 UTC (rev 4861) @@ -1,8 +0,0 @@ -""" -Poor man's setuptools script... -""" - -from setuptools import setup -execfile('setup-data.py', - {'additional_params' : - {'namespace_packages' : ['mpl_toolkits']}}) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 4860 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4860&view=rev Author: jswhit Date: 2008年01月11日 15:32:10 -0800 (2008年1月11日) Log Message: ----------- fixed installation of fullres data for new mpl_toolkits namespace Modified Paths: -------------- trunk/toolkits/basemap/setup-data.py trunk/toolkits/basemap/setupegg-data.py Modified: trunk/toolkits/basemap/setup-data.py =================================================================== --- trunk/toolkits/basemap/setup-data.py 2008年01月11日 21:08:45 UTC (rev 4859) +++ trunk/toolkits/basemap/setup-data.py 2008年01月11日 23:32:10 UTC (rev 4860) @@ -3,21 +3,21 @@ if major==2 and minor1<=3: # setuptools monkeypatches distutils.core.Distribution to support # package_data - #try: import setuptools - #except ImportError: - # raise SystemExit(""" -#matplotlib requires setuptools for installation. Please download -#http://peak.telecommunity.com/dist/ez_setup.py and run it (as su if -#you are doing a system wide install) to install the proper version of -#setuptools for your system""") + try: import setuptools + except ImportError: + raise SystemExit(""" +matplotlib requires setuptools for installation. Please download +http://peak.telecommunity.com/dist/ez_setup.py and run it (as su if +you are doing a system wide install) to install the proper version of +setuptools for your system""") raise SystemExit("""The basemap toolkit requires python 2.4.""") from distutils.core import setup -packages = ['matplotlib.toolkits.basemap.data'] +packages = ['mpl_toolkits.basemap.data'] package_dirs = {'':'lib'} boundaryfiles = glob.glob("lib/matplotlib/toolkits/basemap/data/*_f.dat") basemap_datafiles = [os.path.basename(bfile) for bfile in boundaryfiles] -package_data = {'matplotlib.toolkits.basemap.data':basemap_datafiles} +package_data = {'mpl_toolkits.basemap.data':basemap_datafiles} setup( name = "basemap-data-fullres", version = "0.9.7", Modified: trunk/toolkits/basemap/setupegg-data.py =================================================================== --- trunk/toolkits/basemap/setupegg-data.py 2008年01月11日 21:08:45 UTC (rev 4859) +++ trunk/toolkits/basemap/setupegg-data.py 2008年01月11日 23:32:10 UTC (rev 4860) @@ -3,4 +3,6 @@ """ from setuptools import setup -execfile('setup-data.py') +execfile('setup-data.py', + {'additional_params' : + {'namespace_packages' : ['mpl_toolkits']}}) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 4859 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4859&view=rev Author: cmoad Date: 2008年01月11日 13:08:45 -0800 (2008年1月11日) Log Message: ----------- added explicit compiler flag to win32 build notes Modified Paths: -------------- trunk/matplotlib/setupext.py Modified: trunk/matplotlib/setupext.py =================================================================== --- trunk/matplotlib/setupext.py 2008年01月10日 19:32:16 UTC (rev 4858) +++ trunk/matplotlib/setupext.py 2008年01月11日 21:08:45 UTC (rev 4859) @@ -37,7 +37,7 @@ http://matplotlib.sourceforge.net/win32_static_vs.tar.gz and see the README in that dir - > python setup.py build bdist_wininst + > python setup.py build --compiler=msvc bdist_wininst """ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 4858 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4858&view=rev Author: jswhit Date: 2008年01月10日 11:32:16 -0800 (2008年1月10日) Log Message: ----------- remove duplicate data files, change import to mpl_toolkits. Modified Paths: -------------- trunk/htdocs/screenshots/contour_shot.py trunk/htdocs/screenshots/plotmap.py Removed Paths: ------------- trunk/htdocs/screenshots/etopo20data.gz trunk/htdocs/screenshots/etopo20lats.gz trunk/htdocs/screenshots/etopo20lons.gz Modified: trunk/htdocs/screenshots/contour_shot.py =================================================================== --- trunk/htdocs/screenshots/contour_shot.py 2008年01月10日 18:38:56 UTC (rev 4857) +++ trunk/htdocs/screenshots/contour_shot.py 2008年01月10日 19:32:16 UTC (rev 4858) @@ -1,17 +1,14 @@ -from matplotlib.toolkits.basemap import Basemap, interp +from mpl_toolkits.basemap import Basemap, interp from pylab import * -import cPickle # read in data on lat/lon grid. -hgt = array(load('data/500hgtdata.gz'),'d') -lons = array(load('data/500hgtlons.gz'),'d') -lats = array(load('data/500hgtlats.gz'),'d') +hgt = load('data/500hgtdata.gz') +lons = load('data/500hgtlons.gz') +lats = load('data/500hgtlats.gz') lons, lats = meshgrid(lons,lats) # set up map projection (lambert azimuthal equal area). -m = Basemap(-135.,-20.,45.,-20., - resolution='c',area_thresh=10000.,projection='laea', - lat_0=90.,lon_0=-90.) +m = Basemap(projection='nplaea',lon_0=-90,boundinglat=15.,resolution='c') cmap = cm.jet fig = figure(figsize=(6,6)) @@ -19,8 +16,8 @@ ax = fig.add_axes([0.1, 0.1, 0.8, 0.8]) x,y = m(lons, lats) -cs = contour(x,y,hgt,15,linewidths=0.5,colors='k') -cs = contourf(x,y,hgt,15,cmap=cmap,colors=None) +cs = m.contour(x,y,hgt,15,linewidths=0.5,colors='k') +cs = m.contourf(x,y,hgt,15,cmap=cm.jet) # draw map. m.drawcoastlines() Deleted: trunk/htdocs/screenshots/etopo20data.gz =================================================================== (Binary files differ) Deleted: trunk/htdocs/screenshots/etopo20lats.gz =================================================================== (Binary files differ) Deleted: trunk/htdocs/screenshots/etopo20lons.gz =================================================================== (Binary files differ) Modified: trunk/htdocs/screenshots/plotmap.py =================================================================== --- trunk/htdocs/screenshots/plotmap.py 2008年01月10日 18:38:56 UTC (rev 4857) +++ trunk/htdocs/screenshots/plotmap.py 2008年01月10日 19:32:16 UTC (rev 4858) @@ -4,15 +4,15 @@ # the data is interpolated to the native projection grid. -from matplotlib.toolkits.basemap import Basemap, shiftgrid +from mpl_toolkits.basemap import Basemap, shiftgrid from pylab import title, colorbar, show, axes, cm, load, arange, figure, \ text # read in topo data (on a regular lat/lon grid) # longitudes go from 20 to 380. -topoin = load('etopo20data.gz') -lons = load('etopo20lons.gz') -lats = load('etopo20lats.gz') +topoin = load('data/etopo20data.gz') +lons = load('data/etopo20lons.gz') +lats = load('data/etopo20lats.gz') # shift data so lons go from -180 to 180 instead of 20 to 380. topoin,lons = shiftgrid(180.,topoin,lons,start=False) @@ -32,7 +32,11 @@ # plot image over map with imshow. im = m.imshow(topodat,cm.jet) # setup colorbar axes instance. -l,b,w,h = ax.get_position() +# for matplotlib 0.91 and earlier, could do l,b,w,h = ax.get_position() +# for post 0.91, pos = ax.get_position(); l,b,w,h = pos.bounds +# this works for both. +pos = ax.get_position() +l, b, w, h = getattr(pos, 'bounds', pos) cax = axes([l+w+0.075, b, 0.05, h]) colorbar(cax=cax) # draw colorbar axes(ax) # make the original axes current again This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 4857 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4857&view=rev Author: jswhit Date: 2008年01月10日 10:38:56 -0800 (2008年1月10日) Log Message: ----------- toolkits moved to mpl_toolkits Modified Paths: -------------- trunk/htdocs/hthelpers.py Modified: trunk/htdocs/hthelpers.py =================================================================== --- trunk/htdocs/hthelpers.py 2008年01月10日 16:42:31 UTC (rev 4856) +++ trunk/htdocs/hthelpers.py 2008年01月10日 18:38:56 UTC (rev 4857) @@ -46,7 +46,7 @@ 'matplotlib.texmanager', 'matplotlib.text', 'matplotlib.ticker', - 'matplotlib.toolkits.basemap.basemap', + 'mpl_toolkits.basemap.basemap', 'matplotlib.transforms', 'matplotlib.type1font', 'matplotlib.units', This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 4856 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4856&view=rev Author: mdboom Date: 2008年01月10日 08:42:31 -0800 (2008年1月10日) Log Message: ----------- Merged revisions 4844-4855 via svnmerge from https://matplotlib.svn.sourceforge.net/svnroot/matplotlib/branches/v0_91_maint ........ r4846 | mdboom | 2008年01月10日 08:38:37 -0500 (2008年1月10日) | 3 lines Merge Darren's win32 build changes to the maintenance branch (since they'll be handy there also). ........ r4854 | mdboom | 2008年01月10日 11:37:18 -0500 (2008年1月10日) | 2 lines Fix display of '[' and ']' in mathtext. ........ r4855 | mdboom | 2008年01月10日 11:40:54 -0500 (2008年1月10日) | 2 lines Update changelog. ........ Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/mathtext.py Property Changed: ---------------- trunk/matplotlib/ Property changes on: trunk/matplotlib ___________________________________________________________________ Name: svnmerge-integrated - /branches/v0_91_maint:1-4843 + /branches/v0_91_maint:1-4855 Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2008年01月10日 16:40:54 UTC (rev 4855) +++ trunk/matplotlib/CHANGELOG 2008年01月10日 16:42:31 UTC (rev 4856) @@ -4,6 +4,15 @@ 2008年01月10日 Use setup.cfg to set the default parameters (tkagg, numpy) when building windows installers - DSD +2008年01月10日 Fix bug displaying [ and ] in mathtext - MGD + +2008年01月10日 Fix bug when displaying a tick value offset with scientific + notation. (Manifests itself as a warning that the \times + symbol can not be found). - MGD + +2008年01月10日 Use setup.cfg to set the default parameters (tkagg, + numpy) when building windows installers - DSD + =============================================================== 2008年01月06日 Released 0.91.2 at revision 4802 Modified: trunk/matplotlib/lib/matplotlib/mathtext.py =================================================================== --- trunk/matplotlib/lib/matplotlib/mathtext.py 2008年01月10日 16:40:54 UTC (rev 4855) +++ trunk/matplotlib/lib/matplotlib/mathtext.py 2008年01月10日 16:42:31 UTC (rev 4856) @@ -2057,7 +2057,7 @@ ).setParseAction(self.customspace).setName('customspace') unicode_range = u"\U00000080-\U0001ffff" - symbol =(Regex(UR"([a-zA-Z0-9 +\-*/<>=:,.;!'@()|%s])|(\\[%%${}\[\]_|])" % unicode_range) + symbol =(Regex(UR"([a-zA-Z0-9 +\-*/<>=:,.;!'@()\[\]|%s])|(\\[%%${}\[\]_|])" % unicode_range) | Combine( bslash + oneOf(tex2uni.keys()) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 4855 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4855&view=rev Author: mdboom Date: 2008年01月10日 08:40:54 -0800 (2008年1月10日) Log Message: ----------- Update changelog. Modified Paths: -------------- branches/v0_91_maint/CHANGELOG Modified: branches/v0_91_maint/CHANGELOG =================================================================== --- branches/v0_91_maint/CHANGELOG 2008年01月10日 16:37:18 UTC (rev 4854) +++ branches/v0_91_maint/CHANGELOG 2008年01月10日 16:40:54 UTC (rev 4855) @@ -1,3 +1,5 @@ +2008年01月10日 Fix bug displaying [ and ] in mathtext - MGD + 2008年01月10日 Fix bug when displaying a tick value offset with scientific notation. (Manifests itself as a warning that the \times symbol can not be found). - MGD This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 4854 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4854&view=rev Author: mdboom Date: 2008年01月10日 08:37:18 -0800 (2008年1月10日) Log Message: ----------- Fix display of '[' and ']' in mathtext. Modified Paths: -------------- branches/v0_91_maint/lib/matplotlib/mathtext.py Modified: branches/v0_91_maint/lib/matplotlib/mathtext.py =================================================================== --- branches/v0_91_maint/lib/matplotlib/mathtext.py 2008年01月10日 16:01:02 UTC (rev 4853) +++ branches/v0_91_maint/lib/matplotlib/mathtext.py 2008年01月10日 16:37:18 UTC (rev 4854) @@ -2058,7 +2058,7 @@ ).setParseAction(self.customspace).setName('customspace') unicode_range = u"\U00000080-\U0001ffff" - symbol =(Regex(UR"([a-zA-Z0-9 +\-*/<>=:,.;!'@()|%s])|(\\[%%${}\[\]_|])" % unicode_range) + symbol =(Regex(UR"([a-zA-Z0-9 +\-*/<>=:,.;!'@()\[\]|%s])|(\\[%%${}\[\]_|])" % unicode_range) | Combine( bslash + oneOf(tex2uni.keys()) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 4853 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4853&view=rev Author: jswhit Date: 2008年01月10日 08:01:02 -0800 (2008年1月10日) Log Message: ----------- include setupegg.py Modified Paths: -------------- trunk/toolkits/basemap/MANIFEST.in Modified: trunk/toolkits/basemap/MANIFEST.in =================================================================== --- trunk/toolkits/basemap/MANIFEST.in 2008年01月10日 15:57:28 UTC (rev 4852) +++ trunk/toolkits/basemap/MANIFEST.in 2008年01月10日 16:01:02 UTC (rev 4853) @@ -8,6 +8,7 @@ include KNOWN_BUGS include Changelog include setup.py +include setupegg.py include src/* include examples/simpletest.py include examples/hires.py This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 4852 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4852&view=rev Author: jswhit Date: 2008年01月10日 07:57:28 -0800 (2008年1月10日) Log Message: ----------- add missing files Added Paths: ----------- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdftime.py trunk/toolkits/basemap/lib/mpl_toolkits/basemap/proj.py trunk/toolkits/basemap/lib/mpl_toolkits/basemap/pupynere.py trunk/toolkits/basemap/lib/mpl_toolkits/basemap/pyproj.py Added: trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdftime.py =================================================================== --- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdftime.py (rev 0) +++ trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdftime.py 2008年01月10日 15:57:28 UTC (rev 4852) @@ -0,0 +1,853 @@ +""" +Performs conversions of netCDF time coordinate data to/from datetime objects. +""" +import math, numpy, re, time +from datetime import datetime as real_datetime + +_units = ['days','hours','minutes','seconds','day','hour','minute','second'] +_calendars = ['standard','gregorian','proleptic_gregorian','noleap','julian','all_leap','365_day','366_day','360_day'] + +__version__ = '0.6' + +class datetime: + """ +Phony datetime object which mimics the python datetime object, +but allows for dates that don't exist in the proleptic gregorian calendar. +Doesn't do timedelta operations, doesn't overload + and -. + +Has strftime, timetuple and __repr__ methods. The format +of the string produced by __repr__ is controlled by self.format +(default %Y-%m-%d %H:%M:%S). + +Instance variables are year,month,day,hour,minute,second,dayofwk,dayofyr +and format. + """ + def __init__(self,year,month,day,hour=0,minute=0,second=0,dayofwk=-1,dayofyr=1): + """dayofyr set to 1 by default - otherwise time.strftime will complain""" + self.year=year + self.month=month + self.day=day + self.hour=hour + self.minute=minute + self.dayofwk=dayofwk + self.dayofyr=dayofyr + self.second=second + self.format='%Y-%m-%d %H:%M:%S' + def strftime(self,format=None): + if format is None: + format = self.format + return _strftime(self,format) + def timetuple(self): + return (self.year,self.month,self.day,self.hour,self.minute,self.second,self.dayofwk,self.dayofyr,-1) + def __repr__(self): + return self.strftime(self.format) + +def JulianDayFromDate(date,calendar='standard'): + + """ + +creates a Julian Day from a 'datetime-like' object. Returns the fractional +Julian Day (resolution 1 second). + +if calendar='standard' or 'gregorian' (default), Julian day follows Julian +Calendar on and before 1582年10月5日, Gregorian calendar after 1582年10月15日. + +if calendar='proleptic_gregorian', Julian Day follows gregorian calendar. + +if calendar='julian', Julian Day follows julian calendar. + +Algorithm: + +Meeus, Jean (1998) Astronomical Algorithms (2nd Edition). Willmann-Bell, +Virginia. p. 63 + + """ + + # based on redate.py by David Finlayson. + + year=date.year; month=date.month; day=date.day + hour=date.hour; minute=date.minute; second=date.second + # Convert time to fractions of a day + day = day + hour/24.0 + minute/1440.0 + second/86400.0 + + # Start Meeus algorithm (variables are in his notation) + if (month < 3): + month = month + 12 + year = year - 1 + + A = int(year/100) + + jd = int(365.25 * (year + 4716)) + int(30.6001 * (month + 1)) + \ + day - 1524.5 + + # optionally adjust the jd for the switch from + # the Julian to Gregorian Calendar + # here assumed to have occurred the day after 1582 October 4 + if calendar in ['standard','gregorian']: + if jd >= 2299170.5: + # 1582 October 15 (Gregorian Calendar) + B = 2 - A + int(A/4) + elif jd < 2299160.5: + # 1582 October 5 (Julian Calendar) + B = 0 + else: + raise ValueError, 'impossible date (falls in gap between end of Julian calendar and beginning of Gregorian calendar' + elif calendar == 'proleptic_gregorian': + B = 2 - A + int(A/4) + elif calendar == 'julian': + B = 0 + else: + raise ValueError, 'unknown calendar, must be one of julian,standard,gregorian,proleptic_gregorian, got %s' % calendar + + # adjust for Julian calendar if necessary + jd = jd + B + + return jd + +def _NoLeapDayFromDate(date): + + """ + +creates a Julian Day for a calendar with no leap years from a datetime +instance. Returns the fractional Julian Day (resolution 1 second). + + """ + + year=date.year; month=date.month; day=date.day + hour=date.hour; minute=date.minute; second=date.second + # Convert time to fractions of a day + day = day + hour/24.0 + minute/1440.0 + second/86400.0 + + # Start Meeus algorithm (variables are in his notation) + if (month < 3): + month = month + 12 + year = year - 1 + + jd = int(365. * (year + 4716)) + int(30.6001 * (month + 1)) + \ + day - 1524.5 + + return jd + +def _AllLeapFromDate(date): + + """ + +creates a Julian Day for a calendar where all years have 366 days from +a 'datetime-like' object. +Returns the fractional Julian Day (resolution 1 second). + + """ + + year=date.year; month=date.month; day=date.day + hour=date.hour; minute=date.minute; second=date.second + # Convert time to fractions of a day + day = day + hour/24.0 + minute/1440.0 + second/86400.0 + + # Start Meeus algorithm (variables are in his notation) + if (month < 3): + month = month + 12 + year = year - 1 + + jd = int(366. * (year + 4716)) + int(30.6001 * (month + 1)) + \ + day - 1524.5 + + return jd + +def _360DayFromDate(date): + + """ + +creates a Julian Day for a calendar where all months have 30 daysfrom +a 'datetime-like' object. +Returns the fractional Julian Day (resolution 1 second). + + """ + + year=date.year; month=date.month; day=date.day + hour=date.hour; minute=date.minute; second=date.second + # Convert time to fractions of a day + day = day + hour/24.0 + minute/1440.0 + second/86400.0 + + jd = int(360. * (year + 4716)) + int(30. * (month - 1)) + day + + return jd + +def DateFromJulianDay(JD,calendar='standard'): + """ + +returns a 'datetime-like' object given Julian Day. Julian Day is a +fractional day with a resolution of 1 second. + +if calendar='standard' or 'gregorian' (default), Julian day follows Julian +Calendar on and before 1582年10月5日, Gregorian calendar after 1582年10月15日. + +if calendar='proleptic_gregorian', Julian Day follows gregorian calendar. + +if calendar='julian', Julian Day follows julian calendar. + +The datetime object is a 'real' datetime object if the date falls in +the Gregorian calendar (i.e. calendar='proleptic_gregorian', or +calendar = 'standard'/'gregorian' and the date is after 1582年10月15日). +Otherwise, it's a 'phony' datetime object which is actually an instance +of netcdftime.datetime. + + +Algorithm: + +Meeus, Jean (1998) Astronomical Algorithms (2nd Edition). Willmann-Bell, +Virginia. p. 63 + + """ + + # based on redate.py by David Finlayson. + + if JD < 0: + raise ValueError, 'Julian Day must be positive' + + dayofwk = int(math.fmod(int(JD + 1.5),7)) + (F, Z) = math.modf(JD + 0.5) + Z = int(Z) + if calendar in ['standard','gregorian']: + if JD < 2299160.5: + A = Z + else: + alpha = int((Z - 1867216.25)/36524.25) + A = Z + 1 + alpha - int(alpha/4) + + elif calendar == 'proleptic_gregorian': + alpha = int((Z - 1867216.25)/36524.25) + A = Z + 1 + alpha - int(alpha/4) + elif calendar == 'julian': + A = Z + else: + raise ValueError, 'unknown calendar, must be one of julian,standard,gregorian,proleptic_gregorian, got %s' % calendar + + B = A + 1524 + C = int((B - 122.1)/365.25) + D = int(365.25 * C) + E = int((B - D)/30.6001) + + # Convert to date + day = B - D - int(30.6001 * E) + F + nday = B-D-123 + if nday <= 305: + dayofyr = nday+60 + else: + dayofyr = nday-305 + if E < 14: + month = E - 1 + else: + month = E - 13 + + if month > 2: + year = C - 4716 + else: + year = C - 4715 + + # a leap year? + leap = 0 + if year % 4 == 0: + leap = 1 + if calendar == 'proleptic_gregorian' or \ + (calendar in ['standard','gregorian'] and JD >= 2299160.5): + if year % 100 == 0 and year % 400 != 0: + print year % 100, year % 400 + leap = 0 + if leap and month > 2: + dayofyr = dayofyr + leap + + # Convert fractions of a day to time + (dfrac, days) = math.modf(day/1.0) + (hfrac, hours) = math.modf(dfrac * 24.0) + (mfrac, minutes) = math.modf(hfrac * 60.0) + seconds = round(mfrac * 60.0) # seconds are rounded + + if seconds > 59: + seconds = 0 + minutes = minutes + 1 + if minutes > 59: + minutes = 0 + hours = hours + 1 + if hours > 23: + hours = 0 + days = days + 1 + + # return a 'real' datetime instance if calendar is gregorian. + if calendar == 'proleptic_gregorian' or \ + (calendar in ['standard','gregorian'] and JD >= 2299160.5): + return real_datetime(year,month,int(days),int(hours),int(minutes),int(seconds)) + else: + # or else, return a 'datetime-like' instance. + return datetime(year,month,int(days),int(hours),int(minutes),int(seconds),dayofwk,dayofyr) + +def _DateFromNoLeapDay(JD): + """ + +returns a 'datetime-like' object given Julian Day for a calendar with no leap +days. Julian Day is a fractional day with a resolution of 1 second. + + """ + + # based on redate.py by David Finlayson. + + if JD < 0: + raise ValueError, 'Julian Day must be positive' + + dayofwk = int(math.fmod(int(JD + 1.5),7)) + (F, Z) = math.modf(JD + 0.5) + Z = int(Z) + A = Z + B = A + 1524 + C = int((B - 122.1)/365.) + D = int(365. * C) + E = int((B - D)/30.6001) + + # Convert to date + day = B - D - int(30.6001 * E) + F + nday = B-D-123 + if nday <= 305: + dayofyr = nday+60 + else: + dayofyr = nday-305 + if E < 14: + month = E - 1 + else: + month = E - 13 + + if month > 2: + year = C - 4716 + else: + year = C - 4715 + + # Convert fractions of a day to time + (dfrac, days) = math.modf(day/1.0) + (hfrac, hours) = math.modf(dfrac * 24.0) + (mfrac, minutes) = math.modf(hfrac * 60.0) + seconds = round(mfrac * 60.0) # seconds are rounded + + if seconds > 59: + seconds = 0 + minutes = minutes + 1 + if minutes > 59: + minutes = 0 + hours = hours + 1 + if hours > 23: + hours = 0 + days = days + 1 + + return datetime(year,month,int(days),int(hours),int(minutes),int(seconds), dayofwk, dayofyr) + +def _DateFromAllLeap(JD): + """ + +returns a 'datetime-like' object given Julian Day for a calendar where all +years have 366 days. +Julian Day is a fractional day with a resolution of 1 second. + + """ + + # based on redate.py by David Finlayson. + + if JD < 0: + raise ValueError, 'Julian Day must be positive' + + dayofwk = int(math.fmod(int(JD + 1.5),7)) + (F, Z) = math.modf(JD + 0.5) + Z = int(Z) + A = Z + B = A + 1524 + C = int((B - 122.1)/366.) + D = int(366. * C) + E = int((B - D)/30.6001) + + # Convert to date + day = B - D - int(30.6001 * E) + F + nday = B-D-123 + if nday <= 305: + dayofyr = nday+60 + else: + dayofyr = nday-305 + if E < 14: + month = E - 1 + else: + month = E - 13 + if month > 2: + dayofyr = dayofyr+1 + + if month > 2: + year = C - 4716 + else: + year = C - 4715 + + # Convert fractions of a day to time + (dfrac, days) = math.modf(day/1.0) + (hfrac, hours) = math.modf(dfrac * 24.0) + (mfrac, minutes) = math.modf(hfrac * 60.0) + seconds = round(mfrac * 60.0) # seconds are rounded + + if seconds > 59: + seconds = 0 + minutes = minutes + 1 + if minutes > 59: + minutes = 0 + hours = hours + 1 + if hours > 23: + hours = 0 + days = days + 1 + + return datetime(year,month,int(days),int(hours),int(minutes),int(seconds), dayofwk, dayofyr) + +def _DateFrom360Day(JD): + """ + +returns a 'datetime-like' object given Julian Day for a calendar where all +months have 30 days. +Julian Day is a fractional day with a resolution of 1 second. + + """ + + if JD < 0: + raise ValueError, 'Julian Day must be positive' + + #jd = int(360. * (year + 4716)) + int(30. * (month - 1)) + day + (F, Z) = math.modf(JD) + year = int((Z-0.5)/360.) - 4716 + dayofyr = JD - (year+4716)*360 + month = int((dayofyr-0.5)/30)+1 + day = dayofyr - (month-1)*30 + F + + # Convert fractions of a day to time + (dfrac, days) = math.modf(day/1.0) + (hfrac, hours) = math.modf(dfrac * 24.0) + (mfrac, minutes) = math.modf(hfrac * 60.0) + seconds = round(mfrac * 60.0) # seconds are rounded + + if seconds > 59: + seconds = 0 + minutes = minutes + 1 + if minutes > 59: + minutes = 0 + hours = hours + 1 + if hours > 23: + hours = 0 + days = days + 1 + + return datetime(year,month,int(days),int(hours),int(minutes),int(seconds),-1, int(dayofyr)) + +def _dateparse(timestr): + """parse a string of the form time-units since yyyy-mm-dd hh:mm:ss + return a tuple (units, datetimeinstance)""" + timestr_split = timestr.split() + units = timestr_split[0].lower() + if units not in _units: + raise ValueError,"units must be one of 'seconds', 'minutes', 'hours' or 'days' (or singular version of these), got '%s'" % units + if timestr_split[1].lower() != 'since': + raise ValueError,"no 'since' in unit_string" + # parse the date string. + n = timestr.find('since')+6 + year,month,day,hour,minute,second,utc_offset = _parse_date(timestr[n:]) + return units, utc_offset, datetime(year, month, day, hour, minute, second) + +class utime: + """ +Performs conversions of netCDF time coordinate +data to/from datetime objects. + +To initialize: C{t = utime(unit_string,calendar='standard')} + +where + +B{C{unit_string}} is a string of the form +C{'time-units since <time-origin>'} defining the time units. + +Valid time-units are days, hours, minutes and seconds (the singular forms +are also accepted). An example unit_string would be C{'hours +since 0001年01月01日 00:00:00'}. + +The B{C{calendar}} keyword describes the calendar used in the time calculations. +All the values currently defined in the U{CF metadata convention +<http://www.cgd.ucar.edu/cms/eaton/cf-metadata/CF-1.0.html#time>} are +accepted. The default is C{'standard'}, which corresponds to the mixed +Gregorian/Julian calendar used by the C{udunits library}. Valid calendars +are: + +C{'gregorian'} or C{'standard'} (default): + +Mixed Gregorian/Julian calendar as defined by udunits. + +C{'proleptic_gregorian'}: + +A Gregorian calendar extended to dates before 1582年10月15日. That is, a year +is a leap year if either (i) it is divisible by 4 but not by 100 or (ii) +it is divisible by 400. + +C{'noleap'} or C{'365_day'}: + +Gregorian calendar without leap years, i.e., all years are 365 days long. +all_leap or 366_day Gregorian calendar with every year being a leap year, +i.e., all years are 366 days long. + +C{'360_day'}: + +All years are 360 days divided into 30 day months. + +C{'julian'}: + +Proleptic Julian calendar, extended to dates after 1582年10月5日. A year is a +leap year if it is divisible by 4. + +The C{L{num2date}} and C{L{date2num}} class methods can used to convert datetime +instances to/from the specified time units using the specified calendar. + +The datetime instances returned by C{num2date} are 'real' python datetime +objects if the date falls in the Gregorian calendar (i.e. +C{calendar='proleptic_gregorian', 'standard'} or C{'gregorian'} and +the date is after 1582年10月15日). Otherwise, they are 'phony' datetime +objects which are actually instances of C{L{netcdftime.datetime}}. This is +because the python datetime module cannot handle the weird dates in some +calendars (such as C{'360_day'} and C{'all_leap'}) which don't exist in any real +world calendar. + + +Example usage: + +>>> from netcdftime import utime +>>> from datetime import datetime +>>> cdftime = utime('hours since 0001年01月01日 00:00:00') +>>> date = datetime.now() +>>> print date +2006年03月17日 16:04:02.561678 +>>> +>>> t = cdftime.date2num(date) +>>> print t +17577328.0672 +>>> +>>> date = cdftime.num2date(t) +>>> print date +2006年03月17日 16:04:02 +>>> + +The resolution of the transformation operation is 1 second. + +Warning: Dates between 1582年10月5日 and 1582年10月15日 do not exist in the +C{'standard'} or C{'gregorian'} calendars. An exception will be raised if you pass +a 'datetime-like' object in that range to the C{L{date2num}} class method. + +Words of Wisdom from the British MetOffice concerning reference dates +U{http://www.metoffice.com/research/hadleycentre/models/GDT/ch26.html}: + +"udunits implements the mixed Gregorian/Julian calendar system, as +followed in England, in which dates prior to 1582年10月15日 are assumed to use +the Julian calendar. Other software cannot be relied upon to handle the +change of calendar in the same way, so for robustness it is recommended +that the reference date be later than 1582. If earlier dates must be used, +it should be noted that udunits treats 0 AD as identical to 1 AD." + +@ivar origin: datetime instance defining the origin of the netCDF time variable. +@ivar calendar: the calendar used (as specified by the C{calendar} keyword). +@ivar unit_string: a string defining the the netCDF time variable. +@ivar units: the units part of C{unit_string} (i.e. 'days', 'hours', 'seconds'). + """ + def __init__(self,unit_string,calendar='standard'): + """ +@param unit_string: a string of the form +C{'time-units since <time-origin>'} defining the time units. + +Valid time-units are days, hours, minutes and seconds (the singular forms +are also accepted). An example unit_string would be C{'hours +since 0001年01月01日 00:00:00'}. + +@keyword calendar: describes the calendar used in the time calculations. +All the values currently defined in the U{CF metadata convention +<http://www.cgd.ucar.edu/cms/eaton/cf-metadata/CF-1.0.html#time>} are +accepted. The default is C{'standard'}, which corresponds to the mixed +Gregorian/Julian calendar used by the C{udunits library}. Valid calendars +are: + - C{'gregorian'} or C{'standard'} (default): + Mixed Gregorian/Julian calendar as defined by udunits. + - C{'proleptic_gregorian'}: + A Gregorian calendar extended to dates before 1582年10月15日. That is, a year + is a leap year if either (i) it is divisible by 4 but not by 100 or (ii) + it is divisible by 400. + - C{'noleap'} or C{'365_day'}: + Gregorian calendar without leap years, i.e., all years are 365 days long. + - C{'all_leap'} or C{'366_day'}: + Gregorian calendar with every year being a leap year, i.e., + all years are 366 days long. + -C{'360_day'}: + All years are 360 days divided into 30 day months. + -C{'julian'}: + Proleptic Julian calendar, extended to dates after 1582年10月5日. A year is a + leap year if it is divisible by 4. + +@returns: A class instance which may be used for converting times from netCDF +units to datetime objects. + """ + if calendar in _calendars: + self.calendar = calendar + else: + raise ValueError, "calendar must be one of %s, got '%s'" % (str(_calendars),calendar) + units, tzoffset, self.origin = _dateparse(unit_string) + self.tzoffset = tzoffset # time zone offset in minutes + self.units = units + self.unit_string = unit_string + if self.calendar in ['noleap','365_day'] and self.origin.month == 2 and self.origin.day == 29: + raise ValueError, 'cannot specify a leap day as the reference time with the noleap calendar' + if self.calendar == '360_day' and self.origin.day > 30: + raise ValueError, 'there are only 30 days in every month with the 360_day calendar' + if self.calendar in ['noleap','365_day']: + self._jd0 = _NoLeapDayFromDate(self.origin) + elif self.calendar in ['all_leap','366_day']: + self._jd0 = _AllLeapFromDate(self.origin) + elif self.calendar == '360_day': + self._jd0 = _360DayFromDate(self.origin) + else: + self._jd0 = JulianDayFromDate(self.origin,calendar=self.calendar) + + def date2num(self,date): + """ +Returns C{time_value} in units described by L{unit_string}, using +the specified L{calendar}, given a 'datetime-like' object. + +The datetime object must represent UTC with no time-zone offset. +If there is a time-zone offset implied by L{unit_string}, it will +be applied to the returned numeric values. + +Resolution is 1 second. + +If C{calendar = 'standard'} or C{'gregorian'} (indicating +that the mixed Julian/Gregorian calendar is to be used), an +exception will be raised if the 'datetime-like' object describes +a date between 1582年10月5日 and 1582年10月15日. + +Works for scalars, sequences and numpy arrays. +Returns a scalar if input is a scalar, else returns a numpy array. + """ + isscalar = False + try: + date[0] + except: + isscalar = True + if not isscalar: + date = numpy.array(date) + shape = date.shape + if self.calendar in ['julian','standard','gregorian','proleptic_gregorian']: + if isscalar: + jdelta = JulianDayFromDate(date,self.calendar)-self._jd0 + else: + jdelta = [JulianDayFromDate(d,self.calendar)-self._jd0 for d in date.flat] + elif self.calendar in ['noleap','365_day']: + if date.month == 2 and date.day == 29: + raise ValueError, 'there is no leap day in the noleap calendar' + if isscalar: + jdelta = _NoLeapDayFromDate(date) - self._jd0 + else: + jdelta = [_NoLeapDayFromDate(d)-self._jd0 for d in date.flat] + elif self.calendar in ['all_leap','366_day']: + if isscalar: + jdelta = _AllLeapFromDate(date) - self._jd0 + else: + jdelta = [_AllLeapFromDate(d)-self._jd0 for d in date.flat] + elif self.calendar == '360_day': + if self.calendar == '360_day' and date.day > 30: + raise ValueError, 'there are only 30 days in every month with the 360_day calendar' + if isscalar: + jdelta = _360DayFromDate(date) - self._jd0 + else: + jdelta = [_360DayFromDate(d)-self._jd0 for d in date.flat] + if not isscalar: + jdelta = numpy.array(jdelta) + # convert to desired units, add time zone offset. + if self.units in ['second','seconds']: + jdelta = jdelta*86400. + self.tzoffset*60. + elif self.units in ['minute','minutes']: + jdelta = jdelta*1440. + self.tzoffset + elif self.units in ['hour','hours']: + jdelta = jdelta*24. + self.tzoffset/60. + elif self.units in ['day','days']: + jdelta = jdelta + self.tzoffset/1440. + if isscalar: + return jdelta + else: + return numpy.reshape(jdelta,shape) + + def num2date(self,time_value): + """ +Return a 'datetime-like' object given a C{time_value} in units +described by L{unit_string}, using L{calendar}. + +dates are in UTC with no offset, even if L{unit_string} contains +a time zone offset from UTC. + +Resolution is 1 second. + +Works for scalars, sequences and numpy arrays. +Returns a scalar if input is a scalar, else returns a numpy array. + +The datetime instances returned by C{num2date} are 'real' python datetime +objects if the date falls in the Gregorian calendar (i.e. +C{calendar='proleptic_gregorian'}, or C{calendar = 'standard'/'gregorian'} and +the date is after 1582年10月15日). Otherwise, they are 'phony' datetime +objects which are actually instances of netcdftime.datetime. This is +because the python datetime module cannot handle the weird dates in some +calendars (such as C{'360_day'} and C{'all_leap'}) which +do not exist in any real world calendar. + """ + isscalar = False + try: + time_value[0] + except: + isscalar = True + if not isscalar: + time_value = numpy.array(time_value) + shape = time_value.shape + # convert to desired units, remove time zone offset. + if self.units in ['second','seconds']: + jdelta = time_value/86400. - self.tzoffset/1440. + elif self.units in ['minute','minutes']: + jdelta = time_value/1440. - self.tzoffset/1440. + elif self.units in ['hour','hours']: + jdelta = time_value/24. - self.tzoffset/1440. + elif self.units in ['day','days']: + jdelta = time_value - self.tzoffset/1440. + jd = self._jd0 + jdelta + if self.calendar in ['julian','standard','gregorian','proleptic_gregorian']: + if not isscalar: + date = [DateFromJulianDay(j,self.calendar) for j in jd.flat] + else: + date = DateFromJulianDay(jd,self.calendar) + elif self.calendar in ['noleap','365_day']: + if not isscalar: + date = [_DateFromNoLeapDay(j) for j in jd.flat] + else: + date = _DateFromNoLeapDay(jd) + elif self.calendar in ['all_leap','366_day']: + if not isscalar: + date = [_DateFromAllLeap(j) for j in jd.flat] + else: + date = _DateFromAllLeap(jd) + elif self.calendar == '360_day': + if not isscalar: + date = [_DateFrom360Day(j) for j in jd.flat] + else: + date = _DateFrom360Day(jd) + if isscalar: + return date + else: + return numpy.reshape(numpy.array(date),shape) + +def _parse_date(origin): + """Parses a date string and returns a tuple + (year,month,day,hour,minute,second,utc_offset). + utc_offset is in minutes. + + This function parses the 'origin' part of the time unit. It should be + something like:: + + 2004年11月03日 14:42:27.0 +2:00 + + Lots of things are optional; just the date is mandatory. + + by Roberto De Almeida + + excerpted from coards.py - http://cheeseshop.python.org/pypi/coards/ + """ + # yyyy-mm-dd [hh:mm:ss[.s][ [+-]hh[:][mm]]] + p = re.compile( r'''(?P<year>\d{1,4}) # yyyy + - # + (?P<month>\d{1,2}) # mm or m + - # + (?P<day>\d{1,2}) # dd or d + # + (?: # [optional time and timezone] + \s # + (?P<hour>\d{1,2}) # hh or h + : # + (?P<min>\d{1,2}) # mm or m + (?: + \: + (?P<sec>\d{1,2}) # ss or s (optional) + )? + # + (?: # [optional decisecond] + \. # . + (?P<dsec>\d) # s + )? # + (?: # [optional timezone] + \s # + (?P<ho>[+-]? # [+ or -] + \d{1,2}) # hh or h + :? # [:] + (?P<mo>\d{2})? # [mm] + )? # + )? # + $ # EOL + ''', re.VERBOSE) + + m = p.match(origin.strip()) + if m: + c = m.groupdict(0) + # UTC offset. + offset = int(c['ho'])*60 + int(c['mo']) + return int(c['year']),int(c['month']),int(c['day']),int(c['hour']),int(c['min']),int(c['sec']),offset + + raise Exception('Invalid date origin: %s' % origin) + +# remove the unsupposed "%s" command. But don't +# do it if there's an even number of %s before the s +# because those are all escaped. Can't simply +# remove the s because the result of +# %sY +# should be %Y if %s isn't supported, not the +# 4 digit year. +_illegal_s = re.compile(r"((^|[^%])(%%)*%s)") + +def _findall(text, substr): + # Also finds overlaps + sites = [] + i = 0 + while 1: + j = text.find(substr, i) + if j == -1: + break + sites.append(j) + i=j+1 + return sites + +# Every 28 years the calendar repeats, except through century leap +# years where it's 6 years. But only if you're using the Gregorian +# calendar. ;) + +def _strftime(dt, fmt): + if _illegal_s.search(fmt): + raise TypeError("This strftime implementation does not handle %s") + # don't use strftime method at all. + #if dt.year > 1900: + # return dt.strftime(fmt) + + year = dt.year + # For every non-leap year century, advance by + # 6 years to get into the 28-year repeat cycle + delta = 2000 - year + off = 6*(delta // 100 + delta // 400) + year = year + off + + # Move to around the year 2000 + year = year + ((2000 - year)//28)*28 + timetuple = dt.timetuple() + s1 = time.strftime(fmt, (year,) + timetuple[1:]) + sites1 = _findall(s1, str(year)) + + s2 = time.strftime(fmt, (year+28,) + timetuple[1:]) + sites2 = _findall(s2, str(year+28)) + + sites = [] + for site in sites1: + if site in sites2: + sites.append(site) + + s = s1 + syear = "%4d" % (dt.year,) + for site in sites: + s = s[:site] + syear + s[site+4:] + return s Added: trunk/toolkits/basemap/lib/mpl_toolkits/basemap/proj.py =================================================================== --- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/proj.py (rev 0) +++ trunk/toolkits/basemap/lib/mpl_toolkits/basemap/proj.py 2008年01月10日 15:57:28 UTC (rev 4852) @@ -0,0 +1,343 @@ +import numpy as npy +import pyproj +import math + +__version__ = '1.2.2' +_dg2rad = math.radians(1.) +_rad2dg = math.degrees(1.) + +_upper_right_out_of_bounds = ( + 'the upper right corner of the plot is not in the map projection region') + +_lower_left_out_of_bounds = ( + 'the lower left corner of the plot is not in the map projection region') + + +class Proj(object): + """ + peforms cartographic transformations (converts from longitude,latitude + to native map projection x,y coordinates and vice versa) using proj + (http://proj.maptools.org/) + Uses a pyrex generated C-interface to libproj. + + __init__ method sets up projection information. + __call__ method compute transformations. + See docstrings for __init__ and __call__ for details. + + Contact: Jeff Whitaker <jef...@no...> + """ + + def __init__(self,projparams,llcrnrlon,llcrnrlat, + urcrnrlon,urcrnrlat,urcrnrislatlon=True): + """ + initialize a Proj class instance. + + Input 'projparams' is a dictionary containing proj map + projection control parameter key/value pairs. + See the proj documentation (http://www.remotesensing.org/proj/) + for details. + + llcrnrlon,llcrnrlat are lon and lat (in degrees) of lower + left hand corner of projection region. + + urcrnrlon,urcrnrlat are lon and lat (in degrees) of upper + right hand corner of projection region if urcrnrislatlon=True + (default). Otherwise, urcrnrlon,urcrnrlat are x,y in projection + coordinates (units meters), assuming the lower left corner is x=0,y=0. + """ + self.projparams = projparams + self.projection = projparams['proj'] + # rmajor is the semi-major axis. + # rminor is the semi-minor axis. + # esq is eccentricity squared. + try: + self.rmajor = projparams['a'] + self.rminor = projparams['b'] + except: + try: + self.rmajor = projparams['R'] + except: + self.rmajor = projparams['bR_a'] + self.rminor = self.rmajor + if self.rmajor == self.rminor: + self.ellipsoid = False + else: + self.ellipsoid = True + self.flattening = (self.rmajor-self.rminor)/self.rmajor + self.esq = (self.rmajor**2 - self.rminor**2)/self.rmajor**2 + self.llcrnrlon = llcrnrlon + self.llcrnrlat = llcrnrlat + if self.projection not in ['cyl','ortho','geos','moll','robin','sinu']: + self._proj4 = pyproj.Proj(projparams) + llcrnrx, llcrnry = self(llcrnrlon,llcrnrlat) + elif self.projection == 'cyl': + llcrnrx = llcrnrlon + llcrnry = llcrnrlat + elif self.projection == 'ortho': + if (llcrnrlon == -180 and llcrnrlat == -90 and + urcrnrlon == 180 and urcrnrlat == 90): + self._fulldisk = True + self._proj4 = pyproj.Proj(projparams) + llcrnrx = -self.rmajor + llcrnry = -self.rmajor + urcrnrx = -llcrnrx + urcrnry = -llcrnry + else: + self._fulldisk = False + self._proj4 = pyproj.Proj(projparams) + llcrnrx, llcrnry = self(llcrnrlon,llcrnrlat) + if llcrnrx > 1.e20 or llcrnry > 1.e20: + raise ValueError(_lower_left_out_of_bounds) + elif self.projection == 'geos': + self._proj4 = pyproj.Proj(projparams) + # find major and minor axes of ellipse defining map proj region. + delta = 0.01 + lats = npy.arange(0,90,delta) + lon_0 = projparams['lon_0'] + lons = lon_0*npy.ones(len(lats),'d') + x, y = self._proj4(lons, lats) + yi = (y > 1.e20).tolist() + ny = yi.index(1)-1 + height = y[ny] + lons = npy.arange(lon_0,lon_0+90,delta) + lats = npy.zeros(len(lons),'d') + x, y = self(lons, lats) + xi = (x > 1.e20).tolist() + nx = xi.index(1)-1 + width = x[nx] + self._height = height + self._width = width + if (llcrnrlon == -180 and llcrnrlat == -90 and + urcrnrlon == 180 and urcrnrlat == 90): + self._fulldisk = True + llcrnrx = -width + llcrnry = -height + urcrnrx = -llcrnrx + urcrnry = -llcrnry + else: + self._fulldisk = False + llcrnrx, llcrnry = self(llcrnrlon,llcrnrlat) + if llcrnrx > 1.e20 or llcrnry > 1.e20: + raise ValueError(_lower_left_out_of_bounds) + elif self.projection in ['moll','robin','sinu']: + self._proj4 = pyproj.Proj(projparams) + xtmp,urcrnry = self(projparams['lon_0'],90.) + urcrnrx,xtmp = self(projparams['lon_0']+180.,0) + llcrnrx = -urcrnrx + llcrnry = -urcrnry + # compute x_0, y_0 so ll corner of domain is x=0,y=0. + # note that for 'cyl' x,y == lon,lat + self.projparams['x_0']=-llcrnrx + self.projparams['y_0']=-llcrnry + # reset with x_0, y_0. + if self.projection != 'cyl': + self._proj4 = pyproj.Proj(projparams) + llcrnry = 0. + llcrnrx = 0. + else: + llcrnrx = llcrnrlon + llcrnry = llcrnrlat + if urcrnrislatlon: + self.urcrnrlon = urcrnrlon + self.urcrnrlat = urcrnrlat + if self.projection not in ['ortho','geos','moll','robin','sinu']: + urcrnrx,urcrnry = self(urcrnrlon,urcrnrlat) + elif self.projection == 'ortho': + if self._fulldisk: + urcrnrx = 2.*self.rmajor + urcrnry = 2.*self.rmajor + else: + urcrnrx,urcrnry = self(urcrnrlon,urcrnrlat) + if urcrnrx > 1.e20 or urcrnry > 1.e20: + raise ValueError(_upper_right_out_of_bounds) + elif self.projection == 'geos': + if self._fulldisk: + urcrnrx = 2.*self._width + urcrnry = 2.*self._height + else: + urcrnrx,urcrnry = self(urcrnrlon,urcrnrlat) + if urcrnrx > 1.e20 or urcrnry > 1.e20: + raise ValueError(_upper_right_out_of_bounds) + elif self.projection in ['moll','robin','sinu']: + xtmp,urcrnry = self(projparams['lon_0'],90.) + urcrnrx,xtmp = self(projparams['lon_0']+180.,0) + else: + urcrnrx = urcrnrlon + urcrnry = urcrnrlat + urcrnrlon, urcrnrlat = self(urcrnrx, urcrnry, inverse=True) + self.urcrnrlon = urcrnrlon + self.urcrnrlat = urcrnrlat + # corners of domain. + self.llcrnrx = llcrnrx + self.llcrnry = llcrnry + self.urcrnrx = urcrnrx + self.urcrnry = urcrnry + if urcrnrx > llcrnrx: + self.xmin = llcrnrx + self.xmax = urcrnrx + else: + self.xmax = llcrnrx + self.xmin = urcrnrx + if urcrnry > llcrnry: + self.ymin = llcrnry + self.ymax = urcrnry + else: + self.ymax = llcrnry + self.ymin = urcrnry + + def __call__(self, *args, **kw): + # x,y,inverse=False): + """ + Calling a Proj class instance with the arguments lon, lat will + convert lon/lat (in degrees) to x/y native map projection + coordinates (in meters). If optional keyword 'inverse' is + True (default is False), the inverse transformation from x/y + to lon/lat is performed. + + For cylindrical equidistant projection ('cyl'), this + does nothing (i.e. x,y == lon,lat). + + lon,lat can be either scalar floats or N arrays. + """ + if len(args) == 1: + xy = args[0] + onearray = True + else: + x,y = args + onearray = False + if self.projection == 'cyl': # for cyl x,y == lon,lat + if onearray: + return xy + else: + return x,y + inverse = kw.get('inverse', False) + if onearray: + outxy = self._proj4(xy, inverse=inverse) + else: + outx,outy = self._proj4(x, y, inverse=inverse) + if inverse: + if self.projection in ['merc','mill']: + if self.projection == 'merc': + coslat = math.cos(math.radians(self.projparams['lat_ts'])) + sinlat = math.sin(math.radians(self.projparams['lat_ts'])) + else: + coslat = 1. + sinlat = 0. + # radius of curvature of the ellipse perpendicular to + # the plane of the meridian. + rcurv = self.rmajor*coslat/math.sqrt(1.-self.esq*sinlat**2) + if onearray: + outxy[:,0] = _rad2dg*(xy[:,0]/rcurv) + self.llcrnrlon + else: + try: # x a scalar or an array + outx = _rad2dg*(x/rcurv) + self.llcrnrlon + except: # x a sequence + outx = [_rad2dg*(xi/rcurv) + self.llcrnrlon for xi in x] + else: + if self.projection in ['merc','mill']: + if self.projection == 'merc': + coslat = math.cos(math.radians(self.projparams['lat_ts'])) + sinlat = math.sin(math.radians(self.projparams['lat_ts'])) + else: + coslat = 1. + sinlat = 0. + # radius of curvature of the ellipse perpendicular to + # the plane of the meridian. + rcurv = self.rmajor*coslat/math.sqrt(1.-self.esq*sinlat**2) + if onearray: + outxy[:,0] = rcurv*_dg2rad*(xy[:,0]-self.llcrnrlon) + else: + try: # x is a scalar or an array + outx = rcurv*_dg2rad*(x-self.llcrnrlon) + except: # x is a sequence. + outx = [rcurv*_dg2rad*(xi-self.llcrnrlon) for xi in x] + if onearray: + return outxy + else: + return outx, outy + + def makegrid(self,nx,ny,returnxy=False): + """ + return arrays of shape (ny,nx) containing lon,lat coordinates of + an equally spaced native projection grid. + if returnxy=True, the x,y values of the grid are returned also. + """ + dx = (self.urcrnrx-self.llcrnrx)/(nx-1) + dy = (self.urcrnry-self.llcrnry)/(ny-1) + x = self.llcrnrx+dx*npy.indices((ny,nx),npy.float32)[1,:,:] + y = self.llcrnry+dy*npy.indices((ny,nx),npy.float32)[0,:,:] + lons, lats = self(x, y, inverse=True) + if returnxy: + return lons, lats, x, y + else: + return lons, lats + + def makegrid3d(self,nx,ny,returnxy=False): + """ + return array of shape (ny,nx, 2) containing lon,lat coordinates of + an equally spaced native projection grid. + if returnxy=True, the x,y values of the grid are returned also. + """ + dx = (self.urcrnrx-self.llcrnrx)/(nx-1) + dy = (self.urcrnry-self.llcrnry)/(ny-1) + xy = npy.empty((ny,nx,2), npy.float64) + xy[...,0] = self.llcrnrx+dx*npy.indices((ny,nx),npy.float32)[1,:,:] + xy[...,1] = self.llcrnry+dy*npy.indices((ny,nx),npy.float32)[0,:,:] + lonlat = self(xy, inverse=True) + if returnxy: + return lonlat, xy + else: + return lonlat + + +if __name__ == "__main__": + + params = {} + params['proj'] = 'lcc' + params['R'] = 6371200 + params['lat_1'] = 50 + params['lat_2'] = 50 + params['lon_0'] = -107 + nx = 349; ny = 277; dx = 32463.41; dy = dx + awips221 = Proj(params,-145.5,1.0,(nx-1)*dx,(ny-1)*dy,urcrnrislatlon=False) + # AWIPS grid 221 parameters + # (from http://www.nco.ncep.noaa.gov/pmb/docs/on388/tableb.html) + llcornerx, llcornery = awips221(-145.5,1.) + # find 4 lon/lat corners of AWIPS grid 221. + llcornerx = 0.; llcornery = 0. + lrcornerx = dx*(nx-1); lrcornery = 0. + ulcornerx = 0.; ulcornery = dy*(ny-1) + urcornerx = dx*(nx-1); urcornery = dy*(ny-1) + llcornerlon, llcornerlat = awips221(llcornerx, llcornery, inverse=True) + lrcornerlon, lrcornerlat = awips221(lrcornerx, lrcornery, inverse=True) + urcornerlon, urcornerlat = awips221(urcornerx, urcornery, inverse=True) + ulcornerlon, ulcornerlat = awips221(ulcornerx, ulcornery, inverse=True) + print '4 corners of AWIPS grid 221:' + print llcornerlon, llcornerlat + print lrcornerlon, lrcornerlat + print urcornerlon, urcornerlat + print ulcornerlon, ulcornerlat + print 'from GRIB docs' + print '(see http://www.nco.ncep.noaa.gov/pmb/docs/on388/tableb.html)' + print ' -145.5 1.0' + print ' -68.318 0.897' + print ' -2.566 46.352' + print ' 148.639 46.635' + # compute lons and lats for the whole AWIPS grid 221 (377x249). + import time; t1 = time.clock() + lons, lats = awips221.makegrid(nx,ny) + t2 = time.clock() + print 'compute lats/lons for all points on AWIPS 221 grid (%sx%s)' %(nx,ny) + print 'max/min lons' + print min(npy.ravel(lons)),max(npy.ravel(lons)) + print 'max/min lats' + print min(npy.ravel(lats)),max(npy.ravel(lats)) + print 'took',t2-t1,'secs' + print 'Same thing but with a single 3-D array' + t1 = time.clock() + lonlat, xy = awips221.makegrid3d(nx,ny, returnxy=True) + t2 = time.clock() + print 'took',t2-t1,'secs' + + assert (lons==lonlat[...,0]).all(), "The longitudes are different" + assert (lats==lonlat[...,1]).all(), "The latitudes are different" Added: trunk/toolkits/basemap/lib/mpl_toolkits/basemap/pupynere.py =================================================================== --- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/pupynere.py (rev 0) +++ trunk/toolkits/basemap/lib/mpl_toolkits/basemap/pupynere.py 2008年01月10日 15:57:28 UTC (rev 4852) @@ -0,0 +1,432 @@ +"""NetCDF reader. + +Pupynere implements a PUre PYthon NEtcdf REader. + +Copyright (c) 2003-2006 Roberto De Almeida <ro...@py...> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject +to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +""" + +__author__ = "Roberto De Almeida <ro...@py...>" + + +import struct +import itertools +import mmap + +from numpy import ndarray, empty, array, ma, squeeze, zeros +import numpy + +from dap.client import open as open_remote +from dap.dtypes import ArrayType, GridType, typemap + +has_pynio = True +try: + from PyNGL import nio +except ImportError: + has_pynio = False + +ABSENT = '\x00' * 8 +ZERO = '\x00' * 4 +NC_BYTE = '\x00\x00\x00\x01' +NC_CHAR = '\x00\x00\x00\x02' +NC_SHORT = '\x00\x00\x00\x03' +NC_INT = '\x00\x00\x00\x04' +NC_FLOAT = '\x00\x00\x00\x05' +NC_DOUBLE = '\x00\x00\x00\x06' +NC_DIMENSION = '\x00\x00\x00\n' +NC_VARIABLE = '\x00\x00\x00\x0b' +NC_ATTRIBUTE = '\x00\x00\x00\x0c' + +_typecodes = dict([[_v,_k] for _k,_v in typemap.items()]) +# default _FillValue for netcdf types (apply also to corresponding +# DAP types). +_default_fillvals = {'c':'0円', + 'S':"", + 'b':-127, + 'B':-127, + 'h':-32767, + 'H':65535, + 'i':-2147483647L, + 'L':4294967295L, + 'q':-2147483647L, + 'f':9.9692099683868690e+36, + 'd':9.9692099683868690e+36} + +def NetCDFFile(file, maskandscale=True): + """NetCDF File reader. API is the same as Scientific.IO.NetCDF. + If 'file' is a URL that starts with 'http', it is assumed + to be a remote OPenDAP dataset, and the python dap client is used + to retrieve the data. Only the OPenDAP Array and Grid data + types are recognized. If file does not start with 'http', it + is assumed to be a local file. If possible, the file will be read + with a pure python NetCDF reader, otherwise PyNIO + (http://www.pyngl.ucar.edu/Nio.shtml) will be used (if it is installed). + PyNIO supports NetCDF version 4, GRIB1, GRIB2, HDF4 and HDFEOS2 files. + Data read from OPenDAP and NetCDF version 3 datasets will + automatically be converted to masked arrays if the variable has either + a 'missing_value' or '_FillValue' attribute, and some data points + are equal to the value specified by that attribute. In addition, + variables stored as integers that have the 'scale_factor' and + 'add_offset' attribute will automatically be rescaled to floats when + read. If PyNIO is used, neither of the automatic conversions will + be performed. To suppress these automatic conversions, set the + maskandscale keyword to False. + """ + if file.startswith('http'): + return _RemoteFile(file,maskandscale) + else: + # use pynio if it is installed and the file cannot + # be read with the pure python netCDF reader. This allows + # netCDF version 4, GRIB1, GRIB2, HDF4 and HDFEOS files + # to be read. + if has_pynio: + try: + f = _LocalFile(file,maskandscale) + except: + f = nio.open_file(file) + # otherwise, use the pupynere netCDF 3 pure python reader. + # (will fail if file is not a netCDF version 3 file). + else: + f = _LocalFile(file,maskandscale) + return f + +def _maskandscale(var,datout): + totalmask = zeros(datout.shape,numpy.bool) + fillval = None + if hasattr(var, 'missing_value') and (datout == var.missing_value).any(): + fillval = var.missing_value + totalmask = totalmask + datout==fillval + if hasattr(var, '_FillValue') and (datout == var._FillValue).any(): + if fillval is None: + fillval = var._FillValue + totalmask = totalmask + datout==var._FillValue + elif (datout == _default_fillvals[var.typecode()]).any(): + if fillval is None: + fillval = _default_fillvals[var.typecode()] + totalmask = totalmask + datout==_default_fillvals[var.dtype] + if fillval is not None: + datout = ma.masked_array(datout,mask=totalmask,fill_value=fillval) + try: + datout = var.scale_factor*datout + var.add_offset + except: + pass + return datout + +class _RemoteFile(object): + """A NetCDF file reader. API is the same as Scientific.IO.NetCDF.""" + + def __init__(self, file, maskandscale): + self._buffer = open_remote(file) + self._maskandscale = maskandscale + self._parse() + + def read(self, size=-1): + """Alias for reading the file buffer.""" + return self._buffer.read(size) + + def _parse(self): + """Initial parsing of the header.""" + # Read header info. + self._dim_array() + self._gatt_array() + self._var_array() + + def _dim_array(self): + """Read a dict with dimensions names and sizes.""" + self.dimensions = {} + self._dims = [] + for k,d in self._buffer.iteritems(): + if (isinstance(d, ArrayType) or isinstance(d, GridType)) and len(d.shape) == 1 and k == d.dimensions[0]: + name = k + length = len(d) + self.dimensions[name] = length + self._dims.append(name) # preserve dim order + + def _gatt_array(self): + """Read global attributes.""" + self.__dict__.update(self._buffer.attributes) + + def _var_array(self): + """Read all variables.""" + # Read variables. + self.variables = {} + for k,d in self._buffer.iteritems(): + if isinstance(d, GridType) or isinstance(d, ArrayType): + name = k + self.variables[name] = _RemoteVariable(d,self._maskandscale) + + def close(self): + # this is a no-op provided for compatibility + pass + + +class _RemoteVariable(object): + def __init__(self, var, maskandscale): + self._var = var + self._maskandscale = maskandscale + self.dtype = var.type + self.shape = var.shape + self.dimensions = var.dimensions + self.__dict__.update(var.attributes) + + def __getitem__(self, index): + datout = squeeze(self._var.__getitem__(index)) + # automatically + # - remove singleton dimensions + # - create a masked array using missing_value or _FillValue attribute + # - apply scale_factor and add_offset to packed integer data + if self._maskandscale: + return _maskandscale(self,datout) + else: + return datout + + def typecode(self): + return _typecodes[self.dtype] + + +class _LocalFile(object): + """A NetCDF file reader. API is the same as Scientific.IO.NetCDF.""" + + def __init__(self, file, maskandscale): + self._buffer = open(file, 'rb') + self._maskandscale = maskandscale + self._parse() + + def read(self, size=-1): + """Alias for reading the file buffer.""" + return self._buffer.read(size) + + def _parse(self): + """Initial parsing of the header.""" + # Check magic bytes. + assert self.read(3) == 'CDF' + + # Read version byte. + byte = self.read(1) + self.version_byte = struct.unpack('>b', byte)[0] + + # Read header info. + self._numrecs() + self._dim_array() + self._gatt_array() + self._var_array() + + def _numrecs(self): + """Read number of records.""" + self._nrecs = self._unpack_int() + + def _dim_array(self): + """Read a dict with dimensions names and sizes.""" + assert self.read(4) in [ZERO, NC_DIMENSION] + count = self._unpack_int() + + self.dimensions = {} + self._dims = [] + for dim in range(count): + name = self._read_string() + length = self._unpack_int() + if length == 0: length = None # record dimension + self.dimensions[name] = length + self._dims.append(name) # preserve dim order + + def _gatt_array(self): + """Read global attributes.""" + self.attributes = self._att_array() + + # Update __dict__ for compatibility with S.IO.N + self.__dict__.update(self.attributes) + + def _att_array(self): + """Read a dict with attributes.""" + assert self.read(4) in [ZERO, NC_ATTRIBUTE] + count = self._unpack_int() + + # Read attributes. + attributes = {} + for attribute in range(count): + name = self._read_string() + nc_type = self._unpack_int() + n = self._unpack_int() + + # Read value for attributes. + attributes[name] = self._read_values(n, nc_type) + + return attributes + + def _var_array(self): + """Read all variables.""" + assert self.read(4) in [ZERO, NC_VARIABLE] + + # Read size of each record, in bytes. + self._read_recsize() + + # Read variables. + self.variables = {} + count = self._unpack_int() + for variable in range(count): + name = self._read_string() + self.variables[name] = self._read_var() + + def _read_recsize(self): + """Read all variables and compute record bytes.""" + pos = self._buffer.tell() + + recsize = 0 + count = self._unpack_int() + for variable in range(count): + name = self._read_string() + n = self._unpack_int() + isrec = False + for i in range(n): + dimid = self._unpack_int() + name = self._dims[dimid] + dim = self.dimensions[name] + if dim is None and i == 0: + isrec = True + attributes = self._att_array() + nc_type = self._unpack_int() + vsize = self._unpack_int() + begin = [self._unpack_int, self._unpack_int64][self.version_byte-1]() + + if isrec: recsize += vsize + + self._recsize = recsize + self._buffer.seek(pos) + + def _read_var(self): + dimensions = [] + shape = [] + n = self._unpack_int() + isrec = False + for i in range(n): + dimid = self._unpack_int() + name = self._dims[dimid] + dimensions.append(name) + dim = self.dimensions[name] + if dim is None and i == 0: + dim = self._nrecs + isrec = True + shape.append(dim) + dimensions = tuple(dimensions) + shape = tuple(shape) + + attributes = self._att_array() + nc_type = self._unpack_int() + vsize = self._unpack_int() + + # Read offset. + begin = [self._unpack_int, self._unpack_int64][self.version_byte-1]() + + return _LocalVariable(self._buffer.fileno(), nc_type, vsize, begin, shape, dimensions, attributes, isrec, self._recsize, maskandscale=self._maskandscale) + + def _read_values(self, n, nc_type): + bytes = [1, 1, 2, 4, 4, 8] + typecodes = ['b', 'c', 'h', 'i', 'f', 'd'] + + count = n * bytes[nc_type-1] + values = self.read(count) + padding = self.read((4 - (count % 4)) % 4) + + typecode = typecodes[nc_type-1] + if nc_type != 2: # not char + values = struct.unpack('>%s' % (typecode * n), values) + values = array(values, dtype=typecode) + else: + # Remove EOL terminator. + if values.endswith('\x00'): values = values[:-1] + + return values + + def _unpack_int(self): + return struct.unpack('>i', self.read(4))[0] + _unpack_int32 = _unpack_int + + def _unpack_int64(self): + return struct.unpack('>q', self.read(8))[0] + + def _read_string(self): + count = struct.unpack('>i', self.read(4))[0] + s = self.read(count) + # Remove EOL terminator. + if s.endswith('\x00'): s = s[:-1] + padding = self.read((4 - (count % 4)) % 4) + return s + + def close(self): + self._buffer.close() + + +class _LocalVariable(object): + def __init__(self, fileno, nc_type, vsize, begin, shape, dimensions, attributes, isrec=False, recsize=0, maskandscale=True): + self._nc_type = nc_type + self._vsize = vsize + self._begin = begin + self.shape = shape + self.dimensions = dimensions + self.attributes = attributes # for ``dap.plugins.netcdf`` + self.__dict__.update(attributes) + self._is_record = isrec + self._maskandscale = maskandscale + + # Number of bytes and type. + self._bytes = [1, 1, 2, 4, 4, 8][self._nc_type-1] + type_ = ['i', 'S', 'i', 'i', 'f', 'f'][self._nc_type-1] + dtype = '>%s%d' % (type_, self._bytes) + bytes = self._begin + self._vsize + + if isrec: + # Record variables are not stored contiguosly on disk, so we + # need to create a separate array for each record. + self.__array_data__ = empty(shape, dtype) + bytes += (shape[0] - 1) * recsize + for n in range(shape[0]): + offset = self._begin + (n * recsize) + mm = mmap.mmap(fileno, bytes, access=mmap.ACCESS_READ) + self.__array_data__[n] = ndarray.__new__(ndarray, shape[1:], dtype=dtype, buffer=mm, offset=offset, order=0) + else: + # Create buffer and data. + mm = mmap.mmap(fileno, bytes, access=mmap.ACCESS_READ) + self.__array_data__ = ndarray.__new__(ndarray, shape, dtype=dtype, buffer=mm, offset=self._begin, order=0) + + # N-D array interface + self.__array_interface__ = {'shape' : shape, + 'typestr': dtype, + ... [truncated message content]
Revision: 4851 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4851&view=rev Author: jswhit Date: 2008年01月10日 06:31:37 -0800 (2008年1月10日) Log Message: ----------- re-enable python 2.3 support Modified Paths: -------------- trunk/toolkits/basemap/Changelog trunk/toolkits/basemap/README Modified: trunk/toolkits/basemap/Changelog =================================================================== --- trunk/toolkits/basemap/Changelog 2008年01月10日 14:05:56 UTC (rev 4850) +++ trunk/toolkits/basemap/Changelog 2008年01月10日 14:31:37 UTC (rev 4851) @@ -1,10 +1,11 @@ -version 0.9.9.2 +version 0.99 * Now lives in mpl_toolkits.basemap. Instead of 'from matplotlib.toolkits.basemap import Basemap', use 'from mpl_toolkits.basemap import Basemap'. All examples changed. Uses matplotlib mpl_toolkits namespace package, so basemap can now be installed - if matplotlib is installed as an egg. + if matplotlib is installed as an egg. Python 2.3 + support re-enabled. version 0.9.9.1 (svn revision 4808) * require python 2.4 (really only needed for building). Once namespace packages are re-enabled in matplotlib, Modified: trunk/toolkits/basemap/README =================================================================== --- trunk/toolkits/basemap/README 2008年01月10日 14:05:56 UTC (rev 4850) +++ trunk/toolkits/basemap/README 2008年01月10日 14:31:37 UTC (rev 4851) @@ -5,9 +5,9 @@ **Requirements** -python 2.4 (or higher) +python 2.3 (or higher) -matplotlib 0.90 (or higher) +matplotlib 0.98 (or higher) numpy 1.0 (or higher) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 4850 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4850&view=rev Author: jswhit Date: 2008年01月10日 06:05:56 -0800 (2008年1月10日) Log Message: ----------- move to mpl_toolkits Modified Paths: -------------- trunk/toolkits/basemap/MANIFEST.in Modified: trunk/toolkits/basemap/MANIFEST.in =================================================================== --- trunk/toolkits/basemap/MANIFEST.in 2008年01月10日 14:05:09 UTC (rev 4849) +++ trunk/toolkits/basemap/MANIFEST.in 2008年01月10日 14:05:56 UTC (rev 4850) @@ -65,13 +65,14 @@ include examples/plotprecip.py include examples/nws_precip_conus_20061222.nc include examples/README -include lib/matplotlib/toolkits/basemap/__init__.py -include lib/matplotlib/toolkits/basemap/basemap.py -include lib/matplotlib/toolkits/basemap/proj.py -include lib/matplotlib/toolkits/basemap/pyproj.py -include lib/matplotlib/toolkits/basemap/cm.py -include lib/matplotlib/toolkits/basemap/pupynere.py -include lib/matplotlib/toolkits/basemap/netcdftime.py +include lib/mpl_toolkits/__init__.py +include lib/mpl_toolkits/basemap/__init__.py +include lib/mpl_toolkits/basemap/basemap.py +include lib/mpl_toolkits/basemap/proj.py +include lib/mpl_toolkits/basemap/pyproj.py +include lib/mpl_toolkits/basemap/cm.py +include lib/mpl_toolkits/basemap/pupynere.py +include lib/mpl_toolkits/basemap/netcdftime.py include pyshapelib/README pyshapelib/COPYING pyshapelib/ChangeLog pyshapelib/NEWS include pyshapelib/*.i pyshapelib/*.c pyshapelib/*.py pyshapelib/*.h include pyshapelib/*.shp pyshapelib/*.shx pyshapelib/*.dbf @@ -82,54 +83,54 @@ recursive-include lib/httplib2 * recursive-include lib/dbflib * recursive-include lib/shapelib * -include lib/matplotlib/toolkits/basemap/data/5minmask.bin -include lib/matplotlib/toolkits/basemap/data/GL27 -include lib/matplotlib/toolkits/basemap/data/countries_c.dat -include lib/matplotlib/toolkits/basemap/data/countries_h.dat -include lib/matplotlib/toolkits/basemap/data/countries_i.dat -include lib/matplotlib/toolkits/basemap/data/countries_l.dat -include lib/matplotlib/toolkits/basemap/data/countriesmeta_c.dat -include lib/matplotlib/toolkits/basemap/data/countriesmeta_h.dat -include lib/matplotlib/toolkits/basemap/data/countriesmeta_i.dat -include lib/matplotlib/toolkits/basemap/data/countriesmeta_l.dat -include lib/matplotlib/toolkits/basemap/data/epsg -include lib/matplotlib/toolkits/basemap/data/esri -include lib/matplotlib/toolkits/basemap/data/esri.extra -include lib/matplotlib/toolkits/basemap/data/gshhs_c.dat -include lib/matplotlib/toolkits/basemap/data/gshhs_h.dat -include lib/matplotlib/toolkits/basemap/data/gshhs_i.dat -include lib/matplotlib/toolkits/basemap/data/gshhs_l.dat -include lib/matplotlib/toolkits/basemap/data/gshhsmeta_c.dat -include lib/matplotlib/toolkits/basemap/data/gshhsmeta_h.dat -include lib/matplotlib/toolkits/basemap/data/gshhsmeta_i.dat -include lib/matplotlib/toolkits/basemap/data/gshhsmeta_l.dat -include lib/matplotlib/toolkits/basemap/data/nad.lst -include lib/matplotlib/toolkits/basemap/data/nad27 -include lib/matplotlib/toolkits/basemap/data/nad83 -include lib/matplotlib/toolkits/basemap/data/ntv2_out.dist -include lib/matplotlib/toolkits/basemap/data/other.extra -include lib/matplotlib/toolkits/basemap/data/pj_out27.dist -include lib/matplotlib/toolkits/basemap/data/pj_out83.dist -include lib/matplotlib/toolkits/basemap/data/proj_def.dat -include lib/matplotlib/toolkits/basemap/data/rivers_c.dat -include lib/matplotlib/toolkits/basemap/data/rivers_h.dat -include lib/matplotlib/toolkits/basemap/data/rivers_i.dat -include lib/matplotlib/toolkits/basemap/data/rivers_l.dat -include lib/matplotlib/toolkits/basemap/data/riversmeta_c.dat -include lib/matplotlib/toolkits/basemap/data/riversmeta_h.dat -include lib/matplotlib/toolkits/basemap/data/riversmeta_i.dat -include lib/matplotlib/toolkits/basemap/data/riversmeta_l.dat -include lib/matplotlib/toolkits/basemap/data/states_c.dat -include lib/matplotlib/toolkits/basemap/data/states_h.dat -include lib/matplotlib/toolkits/basemap/data/states_i.dat -include lib/matplotlib/toolkits/basemap/data/states_l.dat -include lib/matplotlib/toolkits/basemap/data/statesmeta_c.dat -include lib/matplotlib/toolkits/basemap/data/statesmeta_h.dat -include lib/matplotlib/toolkits/basemap/data/statesmeta_i.dat -include lib/matplotlib/toolkits/basemap/data/statesmeta_l.dat -include lib/matplotlib/toolkits/basemap/data/td_out.dist -include lib/matplotlib/toolkits/basemap/data/test27 -include lib/matplotlib/toolkits/basemap/data/test83 -include lib/matplotlib/toolkits/basemap/data/testntv2 -include lib/matplotlib/toolkits/basemap/data/testvarious -include lib/matplotlib/toolkits/basemap/data/world +include lib/mpl_toolkits/basemap/data/5minmask.bin +include lib/mpl_toolkits/basemap/data/GL27 +include lib/mpl_toolkits/basemap/data/countries_c.dat +include lib/mpl_toolkits/basemap/data/countries_h.dat +include lib/mpl_toolkits/basemap/data/countries_i.dat +include lib/mpl_toolkits/basemap/data/countries_l.dat +include lib/mpl_toolkits/basemap/data/countriesmeta_c.dat +include lib/mpl_toolkits/basemap/data/countriesmeta_h.dat +include lib/mpl_toolkits/basemap/data/countriesmeta_i.dat +include lib/mpl_toolkits/basemap/data/countriesmeta_l.dat +include lib/mpl_toolkits/basemap/data/epsg +include lib/mpl_toolkits/basemap/data/esri +include lib/mpl_toolkits/basemap/data/esri.extra +include lib/mpl_toolkits/basemap/data/gshhs_c.dat +include lib/mpl_toolkits/basemap/data/gshhs_h.dat +include lib/mpl_toolkits/basemap/data/gshhs_i.dat +include lib/mpl_toolkits/basemap/data/gshhs_l.dat +include lib/mpl_toolkits/basemap/data/gshhsmeta_c.dat +include lib/mpl_toolkits/basemap/data/gshhsmeta_h.dat +include lib/mpl_toolkits/basemap/data/gshhsmeta_i.dat +include lib/mpl_toolkits/basemap/data/gshhsmeta_l.dat +include lib/mpl_toolkits/basemap/data/nad.lst +include lib/mpl_toolkits/basemap/data/nad27 +include lib/mpl_toolkits/basemap/data/nad83 +include lib/mpl_toolkits/basemap/data/ntv2_out.dist +include lib/mpl_toolkits/basemap/data/other.extra +include lib/mpl_toolkits/basemap/data/pj_out27.dist +include lib/mpl_toolkits/basemap/data/pj_out83.dist +include lib/mpl_toolkits/basemap/data/proj_def.dat +include lib/mpl_toolkits/basemap/data/rivers_c.dat +include lib/mpl_toolkits/basemap/data/rivers_h.dat +include lib/mpl_toolkits/basemap/data/rivers_i.dat +include lib/mpl_toolkits/basemap/data/rivers_l.dat +include lib/mpl_toolkits/basemap/data/riversmeta_c.dat +include lib/mpl_toolkits/basemap/data/riversmeta_h.dat +include lib/mpl_toolkits/basemap/data/riversmeta_i.dat +include lib/mpl_toolkits/basemap/data/riversmeta_l.dat +include lib/mpl_toolkits/basemap/data/states_c.dat +include lib/mpl_toolkits/basemap/data/states_h.dat +include lib/mpl_toolkits/basemap/data/states_i.dat +include lib/mpl_toolkits/basemap/data/states_l.dat +include lib/mpl_toolkits/basemap/data/statesmeta_c.dat +include lib/mpl_toolkits/basemap/data/statesmeta_h.dat +include lib/mpl_toolkits/basemap/data/statesmeta_i.dat +include lib/mpl_toolkits/basemap/data/statesmeta_l.dat +include lib/mpl_toolkits/basemap/data/td_out.dist +include lib/mpl_toolkits/basemap/data/test27 +include lib/mpl_toolkits/basemap/data/test83 +include lib/mpl_toolkits/basemap/data/testntv2 +include lib/mpl_toolkits/basemap/data/testvarious +include lib/mpl_toolkits/basemap/data/world This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 4849 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4849&view=rev Author: jswhit Date: 2008年01月10日 06:05:09 -0800 (2008年1月10日) Log Message: ----------- remove unintentional commit Removed Paths: ------------- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/_geod.so Deleted: trunk/toolkits/basemap/lib/mpl_toolkits/basemap/_geod.so =================================================================== (Binary files differ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 4848 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4848&view=rev Author: jswhit Date: 2008年01月10日 06:04:44 -0800 (2008年1月10日) Log Message: ----------- remove unintentional commit Removed Paths: ------------- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/_proj.so Deleted: trunk/toolkits/basemap/lib/mpl_toolkits/basemap/_proj.so =================================================================== (Binary files differ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 4847 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4847&view=rev Author: jswhit Date: 2008年01月10日 05:59:29 -0800 (2008年1月10日) Log Message: ----------- move matplotlit/toolkits to mpl_toolkits Modified Paths: -------------- trunk/toolkits/basemap/API_CHANGES trunk/toolkits/basemap/Changelog trunk/toolkits/basemap/setup.py trunk/toolkits/basemap/setupegg.py Added Paths: ----------- trunk/toolkits/basemap/lib/mpl_toolkits/ trunk/toolkits/basemap/lib/mpl_toolkits/__init__.py trunk/toolkits/basemap/lib/mpl_toolkits/basemap/ trunk/toolkits/basemap/lib/mpl_toolkits/basemap/__init__.py trunk/toolkits/basemap/lib/mpl_toolkits/basemap/_geod.so trunk/toolkits/basemap/lib/mpl_toolkits/basemap/_proj.so trunk/toolkits/basemap/lib/mpl_toolkits/basemap/basemap.py trunk/toolkits/basemap/lib/mpl_toolkits/basemap/cm.py trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/ trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/5minmask.bin trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/GL27 trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/README trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/__init__.py trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/countries_c.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/countries_f.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/countries_h.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/countries_i.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/countries_l.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/countriesmeta_c.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/countriesmeta_f.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/countriesmeta_h.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/countriesmeta_i.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/countriesmeta_l.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/epsg trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/esri trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/esri.extra trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/gshhs_c.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/gshhs_f.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/gshhs_h.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/gshhs_i.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/gshhs_l.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/gshhsmeta_c.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/gshhsmeta_f.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/gshhsmeta_h.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/gshhsmeta_i.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/gshhsmeta_l.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/nad.lst trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/nad27 trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/nad83 trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/ntv2_out.dist trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/other.extra trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/pj_out27.dist trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/pj_out83.dist trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/proj_def.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/rivers_c.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/rivers_f.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/rivers_h.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/rivers_i.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/rivers_l.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/riversmeta_c.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/riversmeta_f.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/riversmeta_h.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/riversmeta_i.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/riversmeta_l.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/states_c.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/states_f.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/states_h.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/states_i.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/states_l.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/statesmeta_c.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/statesmeta_f.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/statesmeta_h.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/statesmeta_i.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/statesmeta_l.dat trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/td_out.dist trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/test27 trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/test83 trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/testntv2 trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/testvarious trunk/toolkits/basemap/lib/mpl_toolkits/basemap/data/world Removed Paths: ------------- trunk/toolkits/basemap/lib/matplotlib/ Modified: trunk/toolkits/basemap/API_CHANGES =================================================================== --- trunk/toolkits/basemap/API_CHANGES 2008年01月10日 13:38:37 UTC (rev 4846) +++ trunk/toolkits/basemap/API_CHANGES 2008年01月10日 13:59:29 UTC (rev 4847) @@ -1,3 +1,5 @@ +version 0.99: now must be imported as mpl_toolkits.basemap instead + of matplotlib.toolkits.basemap. version 0.9.8: remove linestyle kwarg from drawparallels and drawmeridians. add fill_color kwarg to drawmapboundary. version 0.9.7: added lake_color kwarg to fillcontinents. Modified: trunk/toolkits/basemap/Changelog =================================================================== --- trunk/toolkits/basemap/Changelog 2008年01月10日 13:38:37 UTC (rev 4846) +++ trunk/toolkits/basemap/Changelog 2008年01月10日 13:59:29 UTC (rev 4847) @@ -1,3 +1,10 @@ +version 0.9.9.2 + * Now lives in mpl_toolkits.basemap. Instead + of 'from matplotlib.toolkits.basemap import Basemap', + use 'from mpl_toolkits.basemap import Basemap'. + All examples changed. Uses matplotlib mpl_toolkits + namespace package, so basemap can now be installed + if matplotlib is installed as an egg. version 0.9.9.1 (svn revision 4808) * require python 2.4 (really only needed for building). Once namespace packages are re-enabled in matplotlib, Added: trunk/toolkits/basemap/lib/mpl_toolkits/__init__.py =================================================================== --- trunk/toolkits/basemap/lib/mpl_toolkits/__init__.py (rev 0) +++ trunk/toolkits/basemap/lib/mpl_toolkits/__init__.py 2008年01月10日 13:59:29 UTC (rev 4847) @@ -0,0 +1,4 @@ +try: + __import__('pkg_resources').declare_namespace(__name__) +except ImportError: + pass # must not have setuptools Added: trunk/toolkits/basemap/lib/mpl_toolkits/basemap/__init__.py =================================================================== --- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/__init__.py (rev 0) +++ trunk/toolkits/basemap/lib/mpl_toolkits/basemap/__init__.py 2008年01月10日 13:59:29 UTC (rev 4847) @@ -0,0 +1,2 @@ +from basemap import __doc__, __version__ +from basemap import * Added: trunk/toolkits/basemap/lib/mpl_toolkits/basemap/_geod.so =================================================================== (Binary files differ) Property changes on: trunk/toolkits/basemap/lib/mpl_toolkits/basemap/_geod.so ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/toolkits/basemap/lib/mpl_toolkits/basemap/_proj.so =================================================================== (Binary files differ) Property changes on: trunk/toolkits/basemap/lib/mpl_toolkits/basemap/_proj.so ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/toolkits/basemap/lib/mpl_toolkits/basemap/basemap.py =================================================================== --- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/basemap.py (rev 0) +++ trunk/toolkits/basemap/lib/mpl_toolkits/basemap/basemap.py 2008年01月10日 13:59:29 UTC (rev 4847) @@ -0,0 +1,2981 @@ +""" +Module for plotting data on maps with matplotlib. + +Contains the Basemap class (which does most of the +heavy lifting), and the following functions: + +NetCDFFile: Read local and remote NetCDF datasets. + +interp: bilinear interpolation between rectilinear grids. + +shiftgrid: shifts global lat/lon grids east or west. + +addcyclic: Add cyclic (wraparound) point in longitude. + +num2date: convert from a numeric time value to a datetime object. + +date2num: convert from a datetime object to a numeric time value. +""" +from matplotlib import __version__ as _matplotlib_version +from matplotlib.cbook import is_scalar, dedent +# check to make sure matplotlib is not too old. +_mpl_required_version = '0.98' +if _matplotlib_version < _mpl_required_version: + msg = dedent(""" + your matplotlib is too old - basemap requires version %s or + higher, you have version %s""" % + (_mpl_required_version,_matplotlib_version)) + raise ImportError(msg) +from matplotlib import rcParams, is_interactive, _pylab_helpers +from matplotlib.collections import LineCollection +from matplotlib.patches import Ellipse, Circle, Polygon +from matplotlib.lines import Line2D +import pyproj, sys, os, math, dbflib +from proj import Proj +import numpy as npy +from numpy import linspace, squeeze, ma +from shapelib import ShapeFile +import _geos, pupynere, netcdftime + +# basemap data files now installed in lib/matplotlib/toolkits/basemap/data +basemap_datadir = os.sep.join([os.path.dirname(__file__), 'data']) + +__version__ = '0.99' + +# supported map projections. +_projnames = {'cyl' : 'Cylindrical Equidistant', + 'merc' : 'Mercator', + 'tmerc' : 'Transverse Mercator', + 'omerc' : 'Oblique Mercator', + 'mill' : 'Miller Cylindrical', + 'lcc' : 'Lambert Conformal', + 'laea' : 'Lambert Azimuthal Equal Area', + 'nplaea' : 'North-Polar Lambert Azimuthal', + 'splaea' : 'South-Polar Lambert Azimuthal', + 'eqdc' : 'Equidistant Conic', + 'aeqd' : 'Azimuthal Equidistant', + 'npaeqd' : 'North-Polar Azimuthal Equidistant', + 'spaeqd' : 'South-Polar Azimuthal Equidistant', + 'aea' : 'Albers Equal Area', + 'stere' : 'Stereographic', + 'npstere' : 'North-Polar Stereographic', + 'spstere' : 'South-Polar Stereographic', + 'cass' : 'Cassini-Soldner', + 'poly' : 'Polyconic', + 'ortho' : 'Orthographic', + 'geos' : 'Geostationary', + 'sinu' : 'Sinusoidal', + 'moll' : 'Mollweide', + 'robin' : 'Robinson', + 'gnom' : 'Gnomonic', + } +supported_projections = [] +for _items in _projnames.iteritems(): + supported_projections.append("'%s' = %s\n" % (_items)) +supported_projections = ''.join(supported_projections) + +# projection specific parameters. +projection_params = {'cyl' : 'corners only (no width/height)', + 'merc' : 'corners plus lat_ts (no width/height)', + 'tmerc' : 'lon_0,lat_0', + 'omerc' : 'lon_0,lat_0,lat_1,lat_2,lon_1,lon_2,no width/height', + 'mill' : 'corners only (no width/height)', + 'lcc' : 'lon_0,lat_0,lat_1,lat_2', + 'laea' : 'lon_0,lat_0', + 'nplaea' : 'bounding_lat,lon_0,lat_0,no corners or width/height', + 'splaea' : 'bounding_lat,lon_0,lat_0,no corners or width/height', + 'eqdc' : 'lon_0,lat_0,lat_1,lat_2', + 'aeqd' : 'lon_0,lat_0', + 'npaeqd' : 'bounding_lat,lon_0,lat_0,no corners or width/height', + 'spaeqd' : 'bounding_lat,lon_0,lat_0,no corners or width/height', + 'aea' : 'lon_0,lat_0,lat_1', + 'stere' : 'lon_0,lat_0,lat_ts', + 'npstere' : 'bounding_lat,lon_0,lat_0,no corners or width/height', + 'spstere' : 'bounding_lat,lon_0,lat_0,no corners or width/height', + 'cass' : 'lon_0,lat_0', + 'poly' : 'lon_0,lat_0', + 'ortho' : 'lon_0,lat_0', + 'geos' : 'lon_0,lat_0,satellite_height', + 'sinu' : 'lon_0,lat_0,no corners or width/height', + 'moll' : 'lon_0,lat_0,no corners or width/height', + 'robin' : 'lon_0,lat_0,no corners or width/height', + 'gnom' : 'lon_0,lat_0', + } + +# The __init__ docstring is pulled out here because it is so long; +# Having it in the usual place makes it hard to get from the +# __init__ argument list to the code that uses the arguments. +_Basemap_init_doc = """ + create a Basemap instance. + + This sets up a basemap with specified map projection. + and creates the coastline data structures in native map projection + coordinates. + + arguments: + + projection - map projection. Supported projections are: +%(supported_projections)s + Default is 'cyl'. + + For most map projections, the map projection region can either be + specified by setting these keywords: + + llcrnrlon - longitude of lower left hand corner of the desired map domain (degrees). + llcrnrlat - latitude of lower left hand corner of the desired map domain (degrees). + urcrnrlon - longitude of upper right hand corner of the desired map domain (degrees). + urcrnrlat - latitude of upper right hand corner of the desired map domain (degrees). + + or these keywords: + + width - width of desired map domain in projection coordinates (meters). + height - height of desired map domain in projection coordinates (meters). + lon_0 - center of desired map domain (in degrees). + lat_0 - center of desired map domain (in degrees). + + For 'sinu', 'moll', 'npstere', 'spstere', 'nplaea', 'splaea', 'nplaea', + 'splaea', 'npaeqd', 'spaeqd' or 'robin', the values of + llcrnrlon,llcrnrlat,urcrnrlon,urcrnrlat,width and height are ignored + (because either they are computed internally, or entire globe is + always plotted). For the cylindrical projections + ('cyl','merc' and 'mill'), the default is to use + llcrnrlon=-180,llcrnrlat=-90, urcrnrlon=180 and urcrnrlat=90). For all other + projections except 'ortho' and 'geos', either the lat/lon values of the + corners or width and height must be specified by the user. + For 'ortho' and 'geos', the lat/lon values of the corners may be specified, + but if they are not, the entire globe is plotted. + + resolution - resolution of boundary database to use. Can be 'c' (crude), + 'l' (low), 'i' (intermediate), 'h' (high), 'f' (full) or None. + If None, no boundary data will be read in (and class methods + such as drawcoastlines will raise an exception if invoked). + Resolution drops off by roughly 80%% + between datasets. Higher res datasets are much slower to draw. + Default 'c'. Coastline data is from the GSHHS + (http://www.soest.hawaii.edu/wessel/gshhs/gshhs.html). + State, country and river datasets from the Generic Mapping + Tools (http://gmt.soest.hawaii.edu). + + area_thresh - coastline or lake with an area smaller than area_thresh + in km^2 will not be plotted. Default 10000,1000,100,10,1 for resolution + 'c','l','i','h','f'. + + rsphere - radius of the sphere used to define map projection (default + 6370997 meters, close to the arithmetic mean radius of the earth). If + given as a sequence, the first two elements are interpreted as + the the radii of the major and minor axes of an ellipsoid. Note: sometimes + an ellipsoid is specified by the major axis and an 'inverse flattening + parameter' (if). The minor axis (b) can be computed from the major axis (a) + and the inverse flattening parameter using the formula if = a/(a-b). + + suppress_ticks - suppress automatic drawing of axis ticks and labels + in map projection coordinates. Default False, so parallels and meridians + can be labelled instead. If parallel or meridian labelling is requested + (using drawparallels and drawmeridians methods), automatic tick labelling + will be supressed even is suppress_ticks=False. suppress_ticks=False + is useful if you want to use your own custom tick formatter, or + if you want to let matplotlib label the axes in meters + using native map projection coordinates + + anchor - determines how map is placed in axes rectangle (passed to + axes.set_aspect). Default is 'C', which means map is centered. + Allowed values are ['C', 'SW', 'S', 'SE', 'E', 'NE', 'N', 'NW', 'W']. + + ax - set default axes instance (default None - pylab.gca() may be used + to get the current axes instance). If you don't want pylab to be imported, + you can either set this to a pre-defined axes instance, or use the 'ax' + keyword in each Basemap method call that does drawing. In the first case, + all Basemap method calls will draw to the same axes instance. In the + second case, you can draw to different axes with the same Basemap instance. + You can also use the 'ax' keyword in individual method calls to + selectively override the default axes instance. + + The following parameters are map projection parameters which all default to + None. Not all parameters are used by all projections, some are ignored. + The module variable 'projection_params' is a dictionary which + lists which parameters apply to which projections. + + lat_ts - latitude of true scale for mercator projection, optional + for stereographic projection. + lat_1 - first standard parallel for lambert conformal, albers + equal area projection and equidistant conic projections. Latitude of one + of the two points on the projection centerline for oblique mercator. + If lat_1 is not given, but lat_0 is, lat_1 is set to lat_0 for + lambert conformal, albers equal area and equidistant conic. + lat_2 - second standard parallel for lambert conformal, albers + equal area projection and equidistant conic projections. Latitude of one + of the two points on the projection centerline for oblique mercator. + If lat_2 is not given, it is set to lat_1 for + lambert conformal, albers equal area and equidistant conic. + lon_1 - longitude of one of the two points on the projection centerline + for oblique mercator. + lon_2 - longitude of one of the two points on the projection centerline + for oblique mercator. + lat_0 - central latitude (y-axis origin) - used by all projections, + Must be equator for mercator projection. + lon_0 - central meridian (x-axis origin) - used by all projections, + boundinglat - bounding latitude for pole-centered projections (npstere,spstere, + nplaea,splaea,npaeqd,spaeqd). These projections are square regions centered + on the north or south pole. The longitude lon_0 is at 6-o'clock, and the + latitude circle boundinglat is tangent to the edge of the map at lon_0. + satellite_height - height of satellite (in m) above equator - + only relevant for geostationary projections ('geos'). Default 35,786 km. + + Here are the most commonly used class methods (see the docstring + for each for more details): + + To draw a graticule grid (labelled latitude and longitude lines) + use the drawparallels and drawmeridians methods. + + To draw coastline, rivers and political boundaries, use the + the drawcontinents, drawrivers, drawcountries and drawstates methods. + + To fill the continents and inland lakes, use the fillcontinents method. + + To draw the boundary of the map projection region, and fill the + interior a certain color, use the drawmapboundary method. + + The contour, contourf, pcolor, pcolormesh, plot, scatter + quiver and imshow methods use the corresponding matplotlib axes + methods to draw on the map. + + The transform_scalar method can be used to interpolate regular + lat/lon grids of scalar data to native map projection grids. + + The transform_vector method can be used to interpolate and rotate + regular lat/lon grids of vector data to native map projection grids. + + The rotate_vector method rotates a vector field from lat/lon + coordinates into map projections coordinates, without doing any + interpolation. + + The readshapefile method can be used to read in data from ESRI + shapefiles. + + The drawgreatcircle method draws great circles on the map. +""" % locals() + +# unsupported projection error message. +_unsupported_projection = ["'%s' is an unsupported projection.\n"] +_unsupported_projection.append("The supported projections are:\n") +_unsupported_projection.append(supported_projections) +_unsupported_projection = ''.join(_unsupported_projection) + +def _validated_ll(param, name, minval, maxval): + param = float(param) + if param > maxval or param < minval: + raise ValueError('%s must be between %f and %f degrees' % + (name, minval, maxval)) + return param + +def _insert_validated(d, param, name, minval, maxval): + if param is not None: + d[name] = _validated_ll(param, name, minval, maxval) + +class Basemap(object): + """ + Class for plotting data on map projections with matplotlib. + See __init__ docstring for details on how to create a class + instance for a given map projection. + + Useful instance variables: + + projection - map projection. Print the module variable + "supported_projections" to see a list. + aspect - map aspect ratio (size of y dimension / size of x dimension). + llcrnrlon - longitude of lower left hand corner of the desired map domain. + llcrnrlon - latitude of lower left hand corner of the desired map domain. + urcrnrlon - longitude of upper right hand corner of the desired map domain. + urcrnrlon - latitude of upper right hand corner of the desired map domain. + llcrnrx,llcrnry,urcrnrx,urcrnry - corners of map domain in projection coordinates. + rmajor,rminor - equatorial and polar radii of ellipsoid used (in meters). + resolution - resolution of boundary dataset being used ('c' for crude, + 'l' for low, etc.). If None, no boundary dataset is associated with the + Basemap instance. + srs - a string representing the 'spatial reference system' for the map + projection as defined by PROJ.4. + + Example Usage: + + >>> from mpl_toolkits.basemap import Basemap + >>> from pylab import load, meshgrid, title, arange, show + >>> # read in topo data (on a regular lat/lon grid) + >>> etopo = load('etopo20data.gz') + >>> lons = load('etopo20lons.gz') + >>> lats = load('etopo20lats.gz') + >>> # create Basemap instance for Robinson projection. + >>> m = Basemap(projection='robin',lon_0=0.5*(lons[0]+lons[-1])) + >>> # compute native map projection coordinates for lat/lon grid. + >>> x, y = m(*meshgrid(lons,lats)) + >>> # make filled contour plot. + >>> cs = m.contourf(x,y,etopo,30,cmap=cm.jet) + >>> m.drawcoastlines() # draw coastlines + >>> m.drawmapboundary() # draw a line around the map region + >>> m.drawparallels(arange(-90.,120.,30.),labels=[1,0,0,0]) # draw parallels + >>> m.drawmeridians(arange(0.,420.,60.),labels=[0,0,0,1]) # draw meridians + >>> title('Robinson Projection') # add a title + >>> show() + + [this example (simpletest.py) plus many others can be found in the + examples directory of source distribution. The "OO" version of this + example (which does not use pylab) is called "simpletest_oo.py".] + """ + + def __init__(self, llcrnrlon=None, llcrnrlat=None, + urcrnrlon=None, urcrnrlat=None, + width=None, height=None, + projection='cyl', resolution='c', + area_thresh=None, rsphere=6370997.0, + lat_ts=None, + lat_1=None, lat_2=None, + lat_0=None, lon_0=None, + lon_1=None, lon_2=None, + suppress_ticks=True, + satellite_height=35786000, + boundinglat=None, + anchor='C', + ax=None): + # docstring is added after __init__ method definition + + # where to put plot in figure (default is 'C' or center) + self.anchor = anchor + # map projection. + self.projection = projection + + # set up projection parameter dict. + projparams = {} + projparams['proj'] = projection + try: + if rsphere[0] > rsphere[1]: + projparams['a'] = rsphere[0] + projparams['b'] = rsphere[1] + else: + projparams['a'] = rsphere[1] + projparams['b'] = rsphere[0] + except: + if projection == 'tmerc': + # use bR_a instead of R because of obscure bug + # in proj4 for tmerc projection. + projparams['bR_a'] = rsphere + else: + projparams['R'] = rsphere + # set units to meters. + projparams['units']='m' + # check for sane values of lon_0, lat_0, lat_ts, lat_1, lat_2 + _insert_validated(projparams, lat_0, 'lat_0', -90, 90) + _insert_validated(projparams, lat_1, 'lat_1', -90, 90) + _insert_validated(projparams, lat_2, 'lat_2', -90, 90) + _insert_validated(projparams, lat_ts, 'lat_ts', -90, 90) + _insert_validated(projparams, lon_0, 'lon_0', -360, 720) + _insert_validated(projparams, lon_1, 'lon_1', -360, 720) + _insert_validated(projparams, lon_2, 'lon_2', -360, 720) + if projection == 'geos': + projparams['h'] = satellite_height + # check for sane values of projection corners. + using_corners = (None not in [llcrnrlon,llcrnrlat,urcrnrlon,urcrnrlat]) + if using_corners: + self.llcrnrlon = _validated_ll(llcrnrlon, 'llcrnrlon', -360, 720) + self.urcrnrlon = _validated_ll(urcrnrlon, 'urcrnrlon', -360, 720) + self.llcrnrlat = _validated_ll(llcrnrlat, 'llcrnrlat', -90, 90) + self.urcrnrlat = _validated_ll(urcrnrlat, 'urcrnrlat', -90, 90) + + # for each of the supported projections, + # compute lat/lon of domain corners + # and set values in projparams dict as needed. + + if projection in ['lcc', 'eqdc', 'aea']: + # if lat_0 is given, but not lat_1, + # set lat_1=lat_0 + if lat_1 is None and lat_0 is not None: + lat_1 = lat_0 + projparams['lat_1'] = lat_1 + if lat_1 is None or lon_0 is None: + raise ValueError('must specify lat_1 or lat_0 and lon_0 for %s basemap (lat_2 is optional)' % _projnames[projection]) + if lat_2 is None: + projparams['lat_2'] = lat_1 + if not using_corners: + if width is None or height is None: + raise ValueError, 'must either specify lat/lon values of corners (llcrnrlon,llcrnrlat,ucrnrlon,urcrnrlat) in degrees or width and height in meters' + if lon_0 is None or lat_0 is None: + raise ValueError, 'must specify lon_0 and lat_0 when using width, height to specify projection region' + llcrnrlon,llcrnrlat,urcrnrlon,urcrnrlat = _choosecorners(width,height,**projparams) + self.llcrnrlon = llcrnrlon; self.llcrnrlat = llcrnrlat + self.urcrnrlon = urcrnrlon; self.urcrnrlat = urcrnrlat + elif projection == 'stere': + if lat_0 is None or lon_0 is None: + raise ValueError, 'must specify lat_0 and lon_0 for Stereographic basemap (lat_ts is optional)' + if not using_corners: + if width is None or height is None: + raise ValueError, 'must either specify lat/lon values of corners (llcrnrlon,llcrnrlat,ucrnrlon,urcrnrlat) in degrees or width and height in meters' + if lon_0 is None or lat_0 is None: + raise ValueError, 'must specify lon_0 and lat_0 when using width, height to specify projection region' + llcrnrlon,llcrnrlat,urcrnrlon,urcrnrlat = _choosecorners(width,height,**projparams) + self.llcrnrlon = llcrnrlon; self.llcrnrlat = llcrnrlat + self.urcrnrlon = urcrnrlon; self.urcrnrlat = urcrnrlat + elif projection in ['spstere', 'npstere', + 'splaea', 'nplaea', + 'spaeqd', 'npaeqd']: + if boundinglat is None or lon_0 is None: + raise ValueError('must specify boundinglat and lon_0 for %s basemap' % _projnames[projection]) + if projection[0] == 's': + sgn = -1 + else: + sgn = 1 + rootproj = projection[2:] + projparams['proj'] = rootproj + if rootproj == 'stere': + projparams['lat_ts'] = sgn * 90. + projparams['lat_0'] = sgn * 90. + self.llcrnrlon = lon_0 - sgn*45. + self.urcrnrlon = lon_0 + sgn*135. + proj = pyproj.Proj(projparams) + x,y = proj(lon_0,boundinglat) + lon,self.llcrnrlat = proj(math.sqrt(2.)*y,0.,inverse=True) + self.urcrnrlat = self.llcrnrlat + if width is not None or height is not None: + print 'warning: width and height keywords ignored for %s projection' % _projnames[projection] + elif projection == 'laea': + if lat_0 is None or lon_0 is None: + raise ValueError, 'must specify lat_0 and lon_0 for Lambert Azimuthal basemap' + if not using_corners: + if width is None or height is None: + raise ValueError, 'must either specify lat/lon values of corners (llcrnrlon,llcrnrlat,ucrnrlon,urcrnrlat) in degrees or width and height in meters' + if lon_0 is None or lat_0 is None: + raise ValueError, 'must specify lon_0 and lat_0 when using width, height to specify projection region' + llcrnrlon,llcrnrlat,urcrnrlon,urcrnrlat = _choosecorners(width,height,**projparams) + self.llcrnrlon = llcrnrlon; self.llcrnrlat = llcrnrlat + self.urcrnrlon = urcrnrlon; self.urcrnrlat = urcrnrlat + elif projection == 'merc': + if lat_ts is None: + raise ValueError, 'must specify lat_ts for Mercator basemap' + # clip plot region to be within -89.99S to 89.99N + # (mercator is singular at poles) + if not using_corners: + llcrnrlon = -180. + llcrnrlat = -90. + urcrnrlon = 180 + urcrnrlat = 90. + if llcrnrlat < -89.99: llcrnrlat = -89.99 + if llcrnrlat > 89.99: llcrnrlat = 89.99 + if urcrnrlat < -89.99: urcrnrlat = -89.99 + if urcrnrlat > 89.99: urcrnrlat = 89.99 + self.llcrnrlon = llcrnrlon; self.llcrnrlat = llcrnrlat + self.urcrnrlon = urcrnrlon; self.urcrnrlat = urcrnrlat + if width is not None or height is not None: + print 'warning: width and height keywords ignored for %s projection' % self.projection + elif projection in ['tmerc','gnom','cass','poly'] : + if lat_0 is None or lon_0 is None: + raise ValueError, 'must specify lat_0 and lon_0 for Transverse Mercator, Gnomonic, Cassini-Soldnerr Polyconic basemap' + if not using_corners: + if width is None or height is None: + raise ValueError, 'must either specify lat/lon values of corners (llcrnrlon,llcrnrlat,ucrnrlon,urcrnrlat) in degrees or width and height in meters' + if lon_0 is None or lat_0 is None: + raise ValueError, 'must specify lon_0 and lat_0 when using width, height to specify projection region' + llcrnrlon,llcrnrlat,urcrnrlon,urcrnrlat = _choosecorners(width,height,**projparams) + self.llcrnrlon = llcrnrlon; self.llcrnrlat = llcrnrlat + self.urcrnrlon = urcrnrlon; self.urcrnrlat = urcrnrlat + elif projection == 'ortho': + if not projparams.has_key('R'): + raise ValueError, 'orthographic projection only works for perfect spheres - not ellipsoids' + if lat_0 is None or lon_0 is None: + raise ValueError, 'must specify lat_0 and lon_0 for Orthographic basemap' + if width is not None or height is not None: + print 'warning: width and height keywords ignored for %s projection' % self.projection + if not using_corners: + llcrnrlon = -180. + llcrnrlat = -90. + urcrnrlon = 180 + urcrnrlat = 90. + self._fulldisk = True + else: + self._fulldisk = False + self.llcrnrlon = llcrnrlon; self.llcrnrlat = llcrnrlat + self.urcrnrlon = urcrnrlon; self.urcrnrlat = urcrnrlat + # FIXME: won't work for points exactly on equator?? + if npy.abs(lat_0) < 1.e-2: lat_0 = 1.e-2 + projparams['lat_0'] = lat_0 + elif projection == 'geos': + if lon_0 is None: + raise ValueError, 'must specify lon_0 for Geostationary basemap' + if width is not None or height is not None: + print 'warning: width and height keywords ignored for %s projection' % self.projection + if not using_corners: + llcrnrlon = -180. + llcrnrlat = -90. + urcrnrlon = 180 + urcrnrlat = 90. + self._fulldisk = True + else: + self._fulldisk = False + self.llcrnrlon = llcrnrlon; self.llcrnrlat = llcrnrlat + self.urcrnrlon = urcrnrlon; self.urcrnrlat = urcrnrlat + elif projection in ['moll','robin','sinu']: + if lon_0 is None: + raise ValueError, 'must specify lon_0 for Robinson, Mollweide, or Sinusoidal basemap' + if width is not None or height is not None: + print 'warning: width and height keywords ignored for %s projection' % self.projection + llcrnrlon = -180. + llcrnrlat = -90. + urcrnrlon = 180 + urcrnrlat = 90. + self.llcrnrlon = llcrnrlon; self.llcrnrlat = llcrnrlat + self.urcrnrlon = urcrnrlon; self.urcrnrlat = urcrnrlat + elif projection == 'omerc': + if lat_1 is None or lon_1 is None or lat_2 is None or lon_2 is None: + raise ValueError, 'must specify lat_1,lon_1 and lat_2,lon_2 for Oblique Mercator basemap' + projparams['lat_1'] = lat_1 + projparams['lon_1'] = lon_1 + projparams['lat_2'] = lat_2 + projparams['lon_2'] = lon_2 + if not using_corners: + raise ValueError, 'cannot specify map region with width and height keywords for this projection, please specify lat/lon values of corners' + elif projection == 'aeqd': + if lat_0 is None or lon_0 is None: + raise ValueError, 'must specify lat_0 and lon_0 for Azimuthal Equidistant basemap' + if not using_corners: + if width is None or height is None: + raise ValueError, 'must either specify lat/lon values of corners (llcrnrlon,llcrnrlat,ucrnrlon,urcrnrlat) in degrees or width and height in meters' + if lon_0 is None or lat_0 is None: + raise ValueError, 'must specify lon_0 and lat_0 when using width, height to specify projection region' + llcrnrlon,llcrnrlat,urcrnrlon,urcrnrlat = _choosecorners(width,height,**projparams) + self.llcrnrlon = llcrnrlon; self.llcrnrlat = llcrnrlat + self.urcrnrlon = urcrnrlon; self.urcrnrlat = urcrnrlat + elif projection == 'mill': + if not using_corners: + llcrnrlon = -180. + llcrnrlat = -90. + urcrnrlon = 180 + urcrnrlat = 90. + self.llcrnrlon = llcrnrlon; self.llcrnrlat = llcrnrlat + self.urcrnrlon = urcrnrlon; self.urcrnrlat = urcrnrlat + if width is not None or height is not None: + print 'warning: width and height keywords ignored for %s projection' % self.projection + elif projection == 'cyl': + if not using_corners: + llcrnrlon = -180. + llcrnrlat = -90. + urcrnrlon = 180 + urcrnrlat = 90. + self.llcrnrlon = llcrnrlon; self.llcrnrlat = llcrnrlat + self.urcrnrlon = urcrnrlon; self.urcrnrlat = urcrnrlat + if width is not None or height is not None: + print 'warning: width and height keywords ignored for %s projection' % self.projection + else: + raise ValueError(_unsupported_projection % projection) + + # initialize proj4 + proj = Proj(projparams,self.llcrnrlon,self.llcrnrlat,self.urcrnrlon,self.urcrnrlat) + + # make sure axis ticks are suppressed. + self.noticks = suppress_ticks + + # make Proj instance a Basemap instance variable. + self.projtran = proj + # copy some Proj attributes. + atts = ['rmajor','rminor','esq','flattening','ellipsoid','projparams'] + for att in atts: + self.__dict__[att] = proj.__dict__[att] + # these only exist for geostationary projection. + if hasattr(proj,'_width'): + self.__dict__['_width'] = proj.__dict__['_width'] + if hasattr(proj,'_height'): + self.__dict__['_height'] = proj.__dict__['_height'] + # spatial reference string (useful for georeferencing output + # images with gdal_translate). + if hasattr(self,'_proj4'): + self.srs = proj._proj4.srs + else: + pjargs = [] + for key,value in self.projparams.iteritems(): + # 'cyl' projection translates to 'eqc' in PROJ.4 + if projection == 'cyl' and key == 'proj': + value = 'eqc' + # ignore x_0 and y_0 settings for 'cyl' projection + # (they are not consistent with what PROJ.4 uses) + elif projection == 'cyl' and key in ['x_0','y_0']: + continue + pjargs.append('+'+key+"="+str(value)+' ') + self.srs = ''.join(pjargs) + # set instance variables defining map region. + self.xmin = proj.xmin + self.xmax = proj.xmax + self.ymin = proj.ymin + self.ymax = proj.ymax + if projection == 'cyl': + self.aspect = (self.urcrnrlat-self.llcrnrlat)/(self.urcrnrlon-self.llcrnrlon) + else: + self.aspect = (proj.ymax-proj.ymin)/(proj.xmax-proj.xmin) + self.llcrnrx = proj.llcrnrx + self.llcrnry = proj.llcrnry + self.urcrnrx = proj.urcrnrx + self.urcrnry = proj.urcrnry + + # set min/max lats for projection domain. + if projection in ['mill','cyl','merc']: + self.latmin = self.llcrnrlat + self.latmax = self.urcrnrlat + elif projection in ['ortho','geos','moll','robin','sinu']: + self.latmin = -90. + self.latmax = 90. + else: + lons, lats = self.makegrid(101,101) + self.latmin = lats.min() + self.latmax = lats.max() + + # if ax == None, pylab.gca may be used. + self.ax = ax + self.lsmask = None + + # set defaults for area_thresh. + self.resolution = resolution + if area_thresh is None and resolution is not None: + if resolution == 'c': + area_thresh = 10000. + elif resolution == 'l': + area_thresh = 1000. + elif resolution == 'i': + area_thresh = 100. + elif resolution == 'h': + area_thresh = 10. + elif resolution == 'f': + area_thresh = 1. + else: + raise ValueError, "boundary resolution must be one of 'c','l','i','h' or 'f'" + self.area_thresh = area_thresh + # define map boundary polygon (in lat/lon coordinates) + self._boundarypolyll, self._boundarypolyxy = self._getmapboundary() + # read in coastline polygons, only keeping those that + # intersect map boundary polygon. + if self.resolution is not None: + self.coastsegs, self.coastpolygontypes = self._readboundarydata('gshhs') + # reformat for use in matplotlib.patches.Polygon. + self.coastpolygons = [] + # also, split coastline segments that jump across entire plot. + coastsegs = [] + for seg in self.coastsegs: + x, y = zip(*seg) + self.coastpolygons.append((x,y)) + x = npy.array(x,npy.float64); y = npy.array(y,npy.float64) + xd = (x[1:]-x[0:-1])**2 + yd = (y[1:]-y[0:-1])**2 + dist = npy.sqrt(xd+yd) + split = dist > 5000000. + if npy.sum(split) and self.projection not in ['merc','cyl','mill']: + ind = (npy.compress(split,squeeze(split*npy.indices(xd.shape)))+1).tolist() + iprev = 0 + ind.append(len(xd)) + for i in ind: + # don't add empty lists. + if len(range(iprev,i)): + coastsegs.append(zip(x[iprev:i],y[iprev:i])) + iprev = i + else: + coastsegs.append(seg) + self.coastsegs = coastsegs + # set __init__'s docstring + __init__.__doc__ = _Basemap_init_doc + + def __call__(self,x,y,inverse=False): + """ + Calling a Basemap class instance with the arguments lon, lat will + convert lon/lat (in degrees) to x/y native map projection + coordinates (in meters). If optional keyword 'inverse' is + True (default is False), the inverse transformation from x/y + to lon/lat is performed. + + For cylindrical equidistant projection ('cyl'), this + does nothing (i.e. x,y == lon,lat). + + For non-cylindrical projections, the inverse transformation + always returns longitudes between -180 and 180 degrees. For + cylindrical projections (self.projection == 'cyl','mill' or 'merc') + the inverse transformation will return longitudes between + self.llcrnrlon and self.llcrnrlat. + + input arguments lon, lat can be either scalar floats or N arrays. + """ + return self.projtran(x,y,inverse=inverse) + + def makegrid(self,nx,ny,returnxy=False): + """ + return arrays of shape (ny,nx) containing lon,lat coordinates of + an equally spaced native projection grid. + if returnxy = True, the x,y values of the grid are returned also. + """ + return self.projtran.makegrid(nx,ny,returnxy=returnxy) + + def _readboundarydata(self,name): + """ + read boundary data, clip to map projection region. + """ + msg = dedent(""" + Unable to open boundary dataset file. Only the 'crude', 'low', + 'intermediate' and 'high' resolution datasets are installed by default. + If you are requesting a 'full' resolution dataset, you may need to + download and install those files separately + (see the basemap README for details).""") + try: + bdatfile = open(os.path.join(basemap_datadir,name+'_'+self.resolution+'.dat'),'rb') + bdatmetafile = open(os.path.join(basemap_datadir,name+'meta_'+self.resolution+'.dat'),'r') + except: + raise IOError, msg + polygons = [] + polygon_types = [] + # coastlines are polygons, other boundaries are line segments. + if name == 'gshhs': + Shape = _geos.Polygon + else: + Shape = _geos.LineString + # see if map projection region polygon contains a pole. + NPole = _geos.Point(self(0.,90.)) + SPole = _geos.Point(self(0.,-90.)) + boundarypolyxy = self._boundarypolyxy + boundarypolyll = self._boundarypolyll + hasNP = NPole.within(boundarypolyxy) + hasSP = SPole.within(boundarypolyxy) + containsPole = hasNP or hasSP + # these projections cannot cross pole. + if containsPole and\ + self.projection in ['tmerc','cass','omerc','merc','mill','cyl','robin','moll','sinu','geos']: + raise ValueError('%s projection cannot cross pole'%(self.projection)) + # make sure orthographic projection has containsPole=True + # we will compute the intersections in stereographic + # coordinates, then transform to orthographic. + if self.projection == 'ortho' and name == 'gshhs': + containsPole = True + lon_0=self.projparams['lon_0'] + lat_0=self.projparams['lat_0'] + re = self.projparams['R'] + # center of stereographic projection restricted to be + # nearest one of 6 points on the sphere (every 90 deg lat/lon). + lon0 = 90.*(npy.around(lon_0/90.)) + lat0 = 90.*(npy.around(lat_0/90.)) + if npy.abs(int(lat0)) == 90: lon0=0. + maptran = pyproj.Proj(proj='stere',lon_0=lon0,lat_0=lat0,R=re) + # boundary polygon for orthographic projection + # in stereographic coorindates. + b = self._boundarypolyll.boundary + blons = b[:,0]; blats = b[:,1] + b[:,0], b[:,1] = maptran(blons, blats) + boundarypolyxy = _geos.Polygon(b) + for line in bdatmetafile: + linesplit = line.split() + area = float(linesplit[1]) + south = float(linesplit[3]) + north = float(linesplit[4]) + if area < 0.: area = 1.e30 + useit = self.latmax>=south and self.latmin<=north and area>self.area_thresh + if useit: + type = int(linesplit[0]) + npts = int(linesplit[2]) + offsetbytes = int(linesplit[5]) + bytecount = int(linesplit[6]) + bdatfile.seek(offsetbytes,0) + # read in binary string convert into an npts by 2 + # numpy array (first column is lons, second is lats). + polystring = bdatfile.read(bytecount) + # binary data is little endian. + b = npy.array(npy.fromstring(polystring,dtype='<f4'),'f8') + b.shape = (npts,2) + b2 = b.copy() + # if map boundary polygon is a valid one in lat/lon + # coordinates (i.e. it does not contain either pole), + # the intersections of the boundary geometries + # and the map projection region can be computed before + # transforming the boundary geometry to map projection + # coordinates (this saves time, especially for small map + # regions and high-resolution boundary geometries). + if not containsPole: + # close Antarctica. + if name == 'gshhs' and south < -68 and area > 10000: + lons = b[:,0] + lats = b[:,1] + lons2 = lons[:-2][::-1] + lats2 = lats[:-2][::-1] + lons1 = lons2 - 360. + lons3 = lons2 + 360. + lons = lons1.tolist()+lons2.tolist()+lons3.tolist() + lats = lats2.tolist()+lats2.tolist()+lats2.tolist() + lonstart,latstart = lons[0], lats[0] + lonend,latend = lons[-1], lats[-1] + lons.insert(0,lonstart) + lats.insert(0,-90.) + lons.append(lonend) + lats.append(-90.) + b = npy.empty((len(lons),2),npy.float64) + b[:,0] = lons; b[:,1] = lats + poly = _geos.Polygon(b) + antart = True + else: + poly = Shape(b) + antart = False + # create duplicate polygons shifted by -360 and +360 + # (so as to properly treat polygons that cross + # Greenwich meridian). + if not antart: + b2[:,0] = b[:,0]-360 + poly1 = Shape(b2) + b2[:,0] = b[:,0]+360 + poly2 = Shape(b2) + polys = [poly1,poly,poly2] + else: # Antartica already extends from -360 to +720. + polys = [poly] + for poly in polys: + # if polygon instersects map projection + # region, process it. + if poly.intersects(boundarypolyll): + # if geometry intersection calculation fails, + # just move on. + try: + geoms = poly.intersection(boundarypolyll) + except: + continue + # iterate over geometries in intersection. + for psub in geoms: + # only coastlines are polygons, + # which have a 'boundary' attribute. + # otherwise, use 'coords' attribute + # to extract coordinates. + b = psub.boundary + blons = b[:,0]; blats = b[:,1] + # transformation from lat/lon to + # map projection coordinates. + bx, by = self(blons, blats) + polygons.append(zip(bx,by)) + polygon_types.append(type) + # if map boundary polygon is not valid in lat/lon + # coordinates, compute intersection between map + # projection region and boundary geometries in map + # projection coordinates. + else: + # transform coordinates from lat/lon + # to map projection coordinates. + # special case for ortho, compute coastline polygon + # vertices in stereographic coords. + if name == 'gshhs' and self.projection == 'ortho': + b[:,0], b[:,1] = maptran(b[:,0], b[:,1]) + else: + b[:,0], b[:,1] = self(b[:,0], b[:,1]) + goodmask = npy.logical_and(b[:,0]<1.e20,b[:,1]<1.e20) + # if less than two points are valid in + # map proj coords, skip this geometry. + if npy.sum(goodmask) <= 1: continue + if name != 'gshhs': + # if not a polygon, + # just remove parts of geometry that are undefined + # in this map projection. + bx = npy.compress(goodmask, b[:,0]) + by = npy.compress(goodmask, b[:,1]) + # for orthographic projection, all points + # outside map projection region are eliminated + # with the above step, so we're done. + if self.projection == 'ortho': + polygons.append(zip(bx,by)) + polygon_types.append(type) + continue + # create a GEOS geometry object. + poly = Shape(b) + # if geometry instersects map projection + # region, and doesn't have any invalid points, process it. + if goodmask.all() and poly.intersects(boundarypolyxy): + # if geometry intersection calculation fails, + # just move on. + try: + geoms = poly.intersection(boundarypolyxy) + except: + continue + # iterate over geometries in intersection. + for psub in geoms: + b = psub.boundary + # if projection == 'ortho', + # transform polygon from stereographic + # to orthographic coordinates. + if self.projection == 'ortho': + # if coastline polygon covers more than 99% + # of map region for fulldisk projection, + # it's probably bogus, so skip it. + areafrac = psub.area()/boundarypolyxy.area() + if name == 'gshhs' and\ + self._fulldisk and\ + areafrac > 0.99: continue + # inverse transform from stereographic + # to lat/lon. + b[:,0], b[:,1] = maptran(b[:,0], b[:,1], inverse=True) + # orthographic. + b[:,0], b[:,1]= self(b[:,0], b[:,1]) + polygons.append(zip(b[:,0],b[:,1])) + polygon_types.append(type) + return polygons, polygon_types + + def _getmapboundary(self): + """ + create map boundary polygon (in lat/lon and x/y coordinates) + """ + nx = 100 + ny = 100 + maptran = self + if self.projection in ['ortho','geos']: + # circular region. + thetas = linspace(0.,2.*npy.pi,2*nx*ny)[:-1] + if self.projection == 'ortho': + rminor = self.rmajor + rmajor = self.rmajor + else: + rminor = self._height + rmajor = self._width + x = rmajor*npy.cos(thetas) + rmajor + y = rminor*npy.sin(thetas) + rminor + b = npy.empty((len(x),2),npy.float64) + b[:,0]=x; b[:,1]=y + boundaryxy = _geos.Polygon(b) + # compute proj instance for full disk, if necessary. + if not self._fulldisk: + projparms = self.projparams + del projparms['x_0'] + del projparms['y_0'] + if self.projection == 'ortho': + llcrnrx = -self.rmajor + llcrnry = -self.rmajor + urcrnrx = -llcrnrx + urcrnry = -llcrnry + else: + llcrnrx = -self._width + llcrnry = -self._height + urcrnrx = -llcrnrx + urcrnry = -llcrnry + projparms['x_0']=-llcrnrx + projparms['y_0']=-llcrnry + maptran = pyproj.Proj(projparms) + elif self.projection in ['moll','robin','sinu']: + # quasi-elliptical region. + lon_0 = self.projparams['lon_0'] + # left side + lats1 = linspace(-89.9,89.9,ny).tolist() + lons1 = len(lats1)*[lon_0-179.9] + # top. + lons2 = linspace(lon_0-179.9,lon_0+179.9,nx).tolist() + lats2 = len(lons2)*[89.9] + # right side + lats3 = linspace(89.9,-89.9,ny).tolist() + lons3 = len(lats3)*[lon_0+179.9] + # bottom. + lons4 = linspace(lon_0+179.9,lon_0-179.9,nx).tolist() + lats4 = len(lons4)*[-89.9] + lons = npy.array(lons1+lons2+lons3+lons4,npy.float64) + lats = npy.array(lats1+lats2+lats3+lats4,npy.float64) + x, y = maptran(lons,lats) + b = npy.empty((len(x),2),npy.float64) + b[:,0]=x; b[:,1]=y + boundaryxy = _geos.Polygon(b) + else: # all other projections are rectangular. + # left side (x = xmin, ymin <= y <= ymax) + yy = linspace(self.ymin, self.ymax, ny)[:-1] + x = len(yy)*[self.xmin]; y = yy.tolist() + # top (y = ymax, xmin <= x <= xmax) + xx = npy.linspace(self.xmin, self.xmax, nx)[:-1] + x = x + xx.tolist() + y = y + len(xx)*[self.ymax] + # right side (x = xmax, ymin <= y <= ymax) + yy = linspace(self.ymax, self.ymin, ny)[:-1] + x = x + len(yy)*[self.xmax]; y = y + yy.tolist() + # bottom (y = ymin, xmin <= x <= xmax) + xx = linspace(self.xmax, self.xmin, nx)[:-1] + x = x + xx.tolist() + y = y + len(xx)*[self.ymin] + x = npy.array(x,npy.float64) + y = npy.array(y,npy.float64) + b = npy.empty((4,2),npy.float64) + b[:,0]=[self.xmin,self.xmin,self.xmax,self.xmax] + b[:,1]=[self.ymin,self.ymax,self.ymax,self.ymin] + boundaryxy = _geos.Polygon(b) + if self.projection in ['mill','merc','cyl']: + # make sure map boundary doesn't quite include pole. + if self.urcrnrlat > 89.9999: + urcrnrlat = 89.9999 + else: + urcrnrlat = self.urcrnrlat + if self.llcrnrlat < -89.9999: + llcrnrlat = -89.9999 + else: + llcrnrlat = self.llcrnrlat + lons = [self.llcrnrlon, self.llcrnrlon, self.urcrnrlon, self.urcrnrlon] + lats = [llcrnrlat, urcrnrlat, urcrnrlat, llcrnrlat] + x, y = self(lons, lats) + b = npy.empty((len(x),2),npy.float64) + b[:,0]=x; b[:,1]=y + boundaryxy = _geos.Polygon(b) + else: + if self.projection not in ['moll','robin','sinu']: + lons, lats = maptran(x,y,inverse=True) + # fix lons so there are no jumps. + n = 1 + lonprev = lons[0] + for lon,lat in zip(lons[1:],lats[1:]): + if npy.abs(lon-lonprev) > 90.: + if lonprev < 0: + lon = lon - 360. + else: + lon = lon + 360 + lons[n] = lon + lonprev = lon + n = n + 1 + b = npy.empty((len(lons),2),npy.float64) + b[:,0]=lons; b[:,1]=lats + boundaryll = _geos.Polygon(b) + return boundaryll, boundaryxy + + + def drawmapboundary(self,color='k',linewidth=1.0,fill_color=None,\ + zorder=None,ax=None): + """ + draw boundary around map projection region, optionally + filling interior of region. + + linewidth - line width for boundary (default 1.) + color - color of boundary line (default black) + fill_color - fill the map region background with this + color (default is no fill or fill with axis background color). + zorder - sets the zorder for filling map background + (default 0). + ax - axes instance to use (default None, use default axes + instance). + """ + # get current axes instance (if none specified). + if ax is None and... [truncated message content]
Revision: 4846 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4846&view=rev Author: mdboom Date: 2008年01月10日 05:38:37 -0800 (2008年1月10日) Log Message: ----------- Merge Darren's win32 build changes to the maintenance branch (since they'll be handy there also). Modified Paths: -------------- branches/v0_91_maint/CHANGELOG branches/v0_91_maint/setup.py Modified: branches/v0_91_maint/CHANGELOG =================================================================== --- branches/v0_91_maint/CHANGELOG 2008年01月10日 13:38:31 UTC (rev 4845) +++ branches/v0_91_maint/CHANGELOG 2008年01月10日 13:38:37 UTC (rev 4846) @@ -1,3 +1,10 @@ +2008年01月10日 Fix bug when displaying a tick value offset with scientific + notation. (Manifests itself as a warning that the \times + symbol can not be found). - MGD + +2008年01月10日 Use setup.cfg to set the default parameters (tkagg, + numpy) when building windows installers - DSD + =============================================================== 2008年01月06日 Released 0.91.2 at revision 4802 Modified: branches/v0_91_maint/setup.py =================================================================== --- branches/v0_91_maint/setup.py 2008年01月10日 13:38:31 UTC (rev 4845) +++ branches/v0_91_maint/setup.py 2008年01月10日 13:38:37 UTC (rev 4846) @@ -8,7 +8,7 @@ """ # This dict will be updated as we try to select the best option during -# the build process. However, values in setup.cfg will be used, if +# the build process. However, values in setup.cfg will be used, if # defined. rc = {'backend':'Agg', 'numerix':'numpy'} @@ -36,7 +36,7 @@ if major==2 and minor1<3 or major<2: raise SystemExit("""matplotlib requires Python 2.3 or later.""") - + import glob from distutils.core import setup from setupext import build_agg, build_gtkagg, build_tkagg, build_wxagg,\ @@ -112,7 +112,7 @@ subprocess_dir = os.path.dirname(subprocess.__file__) if subprocess_dir.endswith('.egg/subprocess'): havesubprocess = False - + if not havesubprocess: packages.append('subprocess') if sys.platform == 'win32': @@ -120,7 +120,7 @@ if not check_for_freetype(): sys.exit(1) - + build_ft2font(ext_modules, packages) build_ttconv(ext_modules, packages) build_contour(ext_modules, packages) @@ -145,7 +145,7 @@ build_windowing(ext_modules, packages) # the options can be True, False, or 'auto'. If True, try to build -# regardless of the lack of dependencies. If auto, silently skip +# regardless of the lack of dependencies. If auto, silently skip # when dependencies are missing. if options['build_tkagg']: if check_for_tk() or (options['build_tkagg'] is True): @@ -188,12 +188,12 @@ if hasdatetime: # dates require python23 datetime # only install pytz and dateutil if the user hasn't got them - + def add_pytz(): packages.append('pytz') resources = ['zone.tab', 'locales/pytz.pot'] # install pytz subdirs - for dirpath, dirname, filenames in os.walk(os.path.join('lib', 'pytz', + for dirpath, dirname, filenames in os.walk(os.path.join('lib', 'pytz', 'zoneinfo')): if '.svn' not in dirpath: # remove the 'lib/pytz' part of the path @@ -237,12 +237,8 @@ print_line() # Write the default matplotlibrc file -if sys.platform=='win32': - rc['backend'] = 'TkAgg' - rc['numerix'] = 'numpy' -else: - if options['backend']: rc['backend'] = options['backend'] - if options['numerix']: rc['numerix'] = options['numerix'] +if options['backend']: rc['backend'] = options['backend'] +if options['numerix']: rc['numerix'] = options['numerix'] template = file('matplotlibrc.template').read() file('lib/matplotlib/mpl-data/matplotlibrc', 'w').write(template%rc) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 4845 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4845&view=rev Author: jswhit Date: 2008年01月10日 05:38:31 -0800 (2008年1月10日) Log Message: ----------- moved into mpl_toolkits Modified Paths: -------------- trunk/toolkits/mplsizer/demo/demo_basic.py trunk/toolkits/mplsizer/demo/demo_gridsizer.py trunk/toolkits/mplsizer/demo/demo_gridsizer2.py trunk/toolkits/mplsizer/demo/demo_minsize.py trunk/toolkits/mplsizer/setup.py Added Paths: ----------- trunk/toolkits/mplsizer/mpl_toolkits/ trunk/toolkits/mplsizer/mpl_toolkits/__init__.py trunk/toolkits/mplsizer/mpl_toolkits/mplsizer/ trunk/toolkits/mplsizer/mpl_toolkits/mplsizer/__init__.py trunk/toolkits/mplsizer/mpl_toolkits/mplsizer/mplsizer.py Removed Paths: ------------- trunk/toolkits/mplsizer/matplotlib/ Modified: trunk/toolkits/mplsizer/demo/demo_basic.py =================================================================== --- trunk/toolkits/mplsizer/demo/demo_basic.py 2008年01月10日 13:33:03 UTC (rev 4844) +++ trunk/toolkits/mplsizer/demo/demo_basic.py 2008年01月10日 13:38:31 UTC (rev 4845) @@ -63,7 +63,7 @@ if 1: # Now perform the mplsizer stuff - import matplotlib.toolkits.mplsizer as mplsizer + import mpl_toolkits.mplsizer as mplsizer frame = mplsizer.MplSizerFrame( fig ) sizer = mplsizer.MplBoxSizer() Modified: trunk/toolkits/mplsizer/demo/demo_gridsizer.py =================================================================== --- trunk/toolkits/mplsizer/demo/demo_gridsizer.py 2008年01月10日 13:33:03 UTC (rev 4844) +++ trunk/toolkits/mplsizer/demo/demo_gridsizer.py 2008年01月10日 13:38:31 UTC (rev 4845) @@ -47,7 +47,7 @@ if 1: # Now perform the mplsizer stuff - import matplotlib.toolkits.mplsizer as mplsizer + import mpl_toolkits.mplsizer as mplsizer frame = mplsizer.MplSizerFrame( fig ) sizer = mplsizer.MplBoxSizer()#orientation='horizontal') Modified: trunk/toolkits/mplsizer/demo/demo_gridsizer2.py =================================================================== --- trunk/toolkits/mplsizer/demo/demo_gridsizer2.py 2008年01月10日 13:33:03 UTC (rev 4844) +++ trunk/toolkits/mplsizer/demo/demo_gridsizer2.py 2008年01月10日 13:38:31 UTC (rev 4845) @@ -16,7 +16,7 @@ # simply return a previous Axes instance with the same bounding box, # assign a different label to each Axes instance. -import matplotlib.toolkits.mplsizer as mplsizer +import mpl_toolkits.mplsizer as mplsizer frame = mplsizer.MplSizerFrame( fig ) sizer = mplsizer.MplBoxSizer()#orientation='horizontal') Modified: trunk/toolkits/mplsizer/demo/demo_minsize.py =================================================================== --- trunk/toolkits/mplsizer/demo/demo_minsize.py 2008年01月10日 13:33:03 UTC (rev 4844) +++ trunk/toolkits/mplsizer/demo/demo_minsize.py 2008年01月10日 13:38:31 UTC (rev 4845) @@ -1,5 +1,5 @@ import pylab -import matplotlib.toolkits.mplsizer as mplsizer +import mpl_toolkits.mplsizer as mplsizer # Demonstration of minsize use. Added: trunk/toolkits/mplsizer/mpl_toolkits/__init__.py =================================================================== --- trunk/toolkits/mplsizer/mpl_toolkits/__init__.py (rev 0) +++ trunk/toolkits/mplsizer/mpl_toolkits/__init__.py 2008年01月10日 13:38:31 UTC (rev 4845) @@ -0,0 +1,4 @@ +try: + __import__('pkg_resources').declare_namespace(__name__) +except ImportError: + pass # must not have setuptools Added: trunk/toolkits/mplsizer/mpl_toolkits/mplsizer/__init__.py =================================================================== --- trunk/toolkits/mplsizer/mpl_toolkits/mplsizer/__init__.py (rev 0) +++ trunk/toolkits/mplsizer/mpl_toolkits/mplsizer/__init__.py 2008年01月10日 13:38:31 UTC (rev 4845) @@ -0,0 +1 @@ +from mplsizer import * Added: trunk/toolkits/mplsizer/mpl_toolkits/mplsizer/mplsizer.py =================================================================== --- trunk/toolkits/mplsizer/mpl_toolkits/mplsizer/mplsizer.py (rev 0) +++ trunk/toolkits/mplsizer/mpl_toolkits/mplsizer/mplsizer.py 2008年01月10日 13:38:31 UTC (rev 4845) @@ -0,0 +1,500 @@ +from __future__ import division +import math +import matplotlib.numerix as nx +from matplotlib.axes import Axes + +_axes_sizer_elements = {} +_sizer_flags = ['left','right','bottom','top','all', + 'expand', + 'align_centre', + 'align_centre_vertical', + 'align_centre_horizontal', + 'align_right', + 'align_bottom', + ] + +def as_sizer_element(ax,**kwargs): + if ax in _axes_sizer_elements: + el = _axes_sizer_elements[ax] + return el + + if isinstance(ax,Axes): + el = MplAxesSizerElement(ax,**kwargs) + _axes_sizer_elements[ax] = el # allow warning when adding twice + return el + + else: + raise ValueError("") + +class MplSizerElement: + """encapsulates anything that can be an element in a sizer""" + def __init__(self,**kwargs): + self.option = 0 # "weight" along sizer direction + self.flag = {} + self.border = 0 # in inches + self.minsize = (1.0,1.0) # width, height in inches + self.name = '' + self._border_rect = None + self._rect = None + self._update_sizer_element_kwargs(**kwargs) + def _update_sizer_element_kwargs(self,**kwargs): + for key,value in kwargs.iteritems(): + if key in ['option','border','minsize','name']: + setattr(self,key,value) + elif key in _sizer_flags: + self.flag[key]=value + else: + raise ValueError('key "%s" is not understood'%key) # hint: try centre instead of center + self.Update() # update self.minsize and self.minsize_bordered + + def _show_contents(self,indent=0): + buf = (' '*indent)+'MplSizerElement\n' + return buf + + def Update(self): + # updates self.minsize and self.minsize_bordered + + left = self.flag.get('left',False) or self.flag.get('all',False) + right = self.flag.get('right',False) or self.flag.get('all',False) + bottom = self.flag.get('bottom',False) or self.flag.get('all',False) + top = self.flag.get('top',False) or self.flag.get('all',False) + + hborder = 0 + vborder = 0 + if left: hborder += self.border + if right: hborder += self.border + if bottom: vborder += self.border + if top: vborder += self.border + + # self.minsize already set + self.minsize_bordered = [self.minsize[0]+hborder, + self.minsize[1]+vborder] + + if 0: + print self.name,'MplSizerElement.Update() setting minsize_bordered',self.minsize_bordered + print self.name,'MplSizerElement.Update() setting minsize',self.minsize + print + return + + def _layout(self,lbrt_inch,fig_w_inch,fig_h_inch,eps=1e-10): + #print 'MplSizerElement._layout',self,self.name,lbrt_inch + + # check if we have to request larger size + # check size allocation, which must include room for this element's borders + request_w_inch = None + request_h_inch = None + if self.minsize_bordered[0]-eps > (lbrt_inch[2]-lbrt_inch[0]): + request_w_inch = self.minsize_bordered[0] +## print 'self.minsize_bordered[0]',repr(self.minsize_bordered[0]) +## print '(lbrt_inch[2]-lbrt_inch[0])',repr((lbrt_inch[2]-lbrt_inch[0])) +## print 'requesting width increase',self,self.name,request_w_inch +## print + if self.minsize_bordered[1]-eps > (lbrt_inch[3]-lbrt_inch[1]): + request_h_inch = self.minsize_bordered[1] +# print 'requesting height increase',self,self.name,request_h_inch + if (request_w_inch is not None) or (request_h_inch is not None): + return request_w_inch, request_h_inch + + w_inch = lbrt_inch[2]-lbrt_inch[0] + h_inch = lbrt_inch[3]-lbrt_inch[1] + self._border_rect = (lbrt_inch[0]/fig_w_inch, lbrt_inch[1]/fig_h_inch, + w_inch/fig_w_inch, h_inch/fig_h_inch ) + + # remove border sizes + l,b,r,t = lbrt_inch + left = self.flag.get('left',False) or self.flag.get('all',False) + right = self.flag.get('right',False) or self.flag.get('all',False) + bottom = self.flag.get('bottom',False) or self.flag.get('all',False) + top = self.flag.get('top',False) or self.flag.get('all',False) + if left: l+=self.border + if bottom: b+=self.border + if right: r-=self.border + if top: t-=self.border + lbrt_inch = l,b,r,t + + # calculate MPL coords + w_inch = lbrt_inch[2]-lbrt_inch[0] + h_inch = lbrt_inch[3]-lbrt_inch[1] + self._rect = (lbrt_inch[0]/fig_w_inch, lbrt_inch[1]/fig_h_inch, + w_inch/fig_w_inch, h_inch/fig_h_inch ) + + # call derived class layout_core (where the action is) + return self._layout_core(lbrt_inch,fig_w_inch,fig_h_inch) + + def _layout_core(self,lbrt_inch,fig_w_inch,fig_h_inch): + # does nothing in this base class -- override for interesting behavior + return None,None + +class MplAxesSizerElement( MplSizerElement ): + def __init__(self,ax,**kwargs): + self.ax = ax + MplSizerElement.__init__(self,**kwargs) + def _show_contents(self,indent=0): + buf = (' '*indent)+'MplAxesSizerElement: %s\n'%repr(self.ax) + return buf + def _layout_core(self,lbrt_inch,fig_w_inch,fig_h_inch): + if self.ax is not None: + self.ax.set_position(self._rect) +## if 1: +## print 'assigning "%s" to MPL'%self.name,self.ax,'(%.2f,%.2f,%.2f,%.2f)'%self._rect +## print ' from:',lbrt_inch,fig_w_inch,fig_h_inch +## print + return None,None + +class MplSizer( MplSizerElement ): + """abstract sizer class that holds elements""" + def __init__(self): + self.elements = [] + MplSizerElement.__init__(self) + def Add(self, element, **kwargs): + if not isinstance(element,MplSizerElement): + element = as_sizer_element(element,**kwargs) + else: + element._update_sizer_element_kwargs(**kwargs) + if element in self.elements: + raise ValueError("element already in MplSizer") + # update + self.elements.append( element ) + self.Update() + def _show_contents(self,indent=0): + buf = (' '*indent)+'MplSizer:\n' + for el in self.elements: + buf += el._show_contents(indent=indent+2) + return buf + +class MplBoxSizer( MplSizer ): + """vertical or horizontal sizer""" + def __init__(self,orientation=None): + if orientation is None: + orientation='vertical' + if orientation not in ['vertical','horizontal']: + raise ValueError("only horizontal and vertical orientations allowed") + self.orientation = orientation + MplSizer.__init__(self) + def _show_contents(self,indent=0): + buf = (' '*indent)+'MplBoxSizer:\n' + buf += MplSizer._show_contents(self,indent+2) + return buf + + def Update(self): + # calculate minsize based on minsize_bordered of children + if self.orientation.startswith('v'): + vertical=True + elif self.orientation.startswith('h'): + vertical=False + else: ValueError("only vertical and horizontal supported") + + if vertical: + dir_idx=1 + other_idx=0 + else: + dir_idx=0 + other_idx=1 + + minsize = [0,0] + for el in self.elements: + el.Update() # updates minsize, may not be necessary + dir_minsize = el.minsize_bordered[dir_idx] + other_minsize = el.minsize_bordered[other_idx] + + minsize[dir_idx] = minsize[dir_idx] + dir_minsize + minsize[other_idx] = max(minsize[other_idx],other_minsize) + + self.minsize = minsize + #print self.name,'MplBoxSizer.Update() setting minsize',self.minsize + MplSizer.Update(self) # call base class (sets self.minsize_bordered) + + def _layout_core(self,lbrt_inch,fig_w_inch,fig_h_inch): + #print 'MplBoxSizer._layout_core',self,self.name,lbrt_inch + + if self.orientation.startswith('v'): + vertical=True + elif self.orientation.startswith('h'): + vertical=False + else: ValueError("only vertical and horizontal supported") + + if vertical: + dir_idx = 1 + sizer_width_inch = lbrt_inch[2]-lbrt_inch[0] + else: + dir_idx = 0 + sizer_height_inch = lbrt_inch[3]-lbrt_inch[1] + + start = lbrt_inch[dir_idx+0] + stop = lbrt_inch[dir_idx+2] + dist_avail = stop-start + total_weight = 0 + + # first iteration -- find inches remaining after borders and minsizes allocated + optioned_minimum = 0 + for el in self.elements: + if el.option == 0: + dist_avail -= el.minsize_bordered[dir_idx] + else: + # make sure we don't give less than requested + optioned_minimum += el.minsize_bordered[dir_idx] + total_weight += el.option + + use_option = False + if dist_avail > optioned_minimum: + # OK, we can allocate using expansion options + use_option = True + if total_weight > 0: + dist_inc = dist_avail/total_weight + else: + dist_inc = None + + if vertical: + # go top to bottom + current_location_inch = lbrt_inch[3] + dir = -1 + else: + # go left to right + current_location_inch = lbrt_inch[0] + dir = 1 + + req_w_inch = None + req_h_inch = None + + for el in self.elements: + #print 'self, el, el.flag',self, el, el.flag + # calculate the bordered region and call element's ._layout() + # the element itself must deal with removing the border + el_lt = current_location_inch + if (el.option > 0) and use_option: + current_location_inch += dir*dist_inc*el.option + #print 'boxsizer',self.name,'el %s dir=%f dist_inc=%f option=%f'%(el.name, + # dir, + # dist_inc, + # el.option) + else: + current_location_inch += dir*el.minsize_bordered[dir_idx] + el_rb = current_location_inch + + if vertical: + el_bottom = el_rb + el_top = el_lt + #print 'vert boxsizer',self.name,'el',el.name + #print 'vert boxsizer',self.name,'el top',el_top + #print 'vert boxsizer',self.name,'el bottom',el_bottom + if el.flag.get('expand',False): + # expand horizontally + el_lbrt_inch = (lbrt_inch[0], el_bottom, + lbrt_inch[2], el_top) + else: + minwidth = el.minsize_bordered[0] + if (el.flag.get('align_centre_horizontal',False) or + el.flag.get('align_centre',False)): + w0 = sizer_width_inch/2-minwidth/2 + w1 = sizer_width_inch/2+minwidth/2 + el_lbrt_inch = (lbrt_inch[0]+w0, el_bottom, + lbrt_inch[0]+w1, el_top) + elif el.flag.get('align_right',False): + #print 'aligning right!' + el_lbrt_inch = (lbrt_inch[2]-minwidth, el_bottom, + lbrt_inch[2], el_top) + else: + el_lbrt_inch = (lbrt_inch[0], el_bottom, + lbrt_inch[0]+minwidth, el_top) + + else: #horizonal + el_left = el_lt + el_right = el_rb + if el.flag.get('expand',False): + # expand vertically + el_lbrt_inch = (el_left, lbrt_inch[1], el_right, lbrt_inch[3]) + else: + minheight = el.minsize_bordered[1] + if (el.flag.get('align_centre_vertical',False) or + el.flag.get('align_centre',False)): + #print 'sizer_height_inch',sizer_height_inch + #print 'minheight',minheight + h0 = sizer_height_inch/2-minheight/2 + h1 = sizer_height_inch/2+minheight/2 + #print 'h0',h0 + #print 'h1',h1 + el_lbrt_inch = (el_left, lbrt_inch[1]+h0, + el_right, lbrt_inch[1]+h1) + elif el.flag.get('align_bottom',False): + el_lbrt_inch = (el_left, lbrt_inch[1], + el_right, lbrt_inch[1]+minheight) + else: + el_lbrt_inch = (el_left, lbrt_inch[3]-minheight, + el_right, lbrt_inch[3]) + #print 'BoxSizer',self.name,'allocating',el_lbrt_inch,'to',el.name + this_req_w_inch, this_req_h_inch = el._layout(el_lbrt_inch, + fig_w_inch,fig_h_inch) + req_w_inch = max(req_w_inch,this_req_w_inch) + req_h_inch = max(req_h_inch,this_req_h_inch) + #print 'MplBoxSizer',self,'req_w_inch, req_h_inch',req_w_inch, req_h_inch + + # call base class + return req_w_inch, req_h_inch + +class MplGridSizer( MplSizer ): + """vertical or horizontal sizer""" + def __init__(self,cols=2,hgap=0.0,vgap=0.0,append_horiz=True): + self.cols = cols + self.hgap_inch = hgap + self.vgap_inch = vgap + self.append_horiz = append_horiz # if true, add horizontally + MplSizer.__init__(self) + + def _show_contents(self,indent=0): + buf = (' '*indent)+'MplGridSizer:\n' + buf += MplSizer._show_contents(self,indent+2) + return buf + + def Update(self): + # calculate minsize based on minsize_bordered of children + maxel = [0,0] + for el in self.elements: + el.Update() # updates minsize, may not be necessary + maxel[0] = max(maxel[0],el.minsize_bordered[0]) + maxel[1] = max(maxel[1],el.minsize_bordered[1]) + + n_hgaps = max(0,self.cols-1) + total_hgap = n_hgaps*self.hgap_inch + rows = int(math.ceil(len(self.elements)/self.cols)) + n_vgaps = max(0,rows-1) + total_vgap = n_vgaps*self.vgap_inch + minsize0 = maxel[0]*self.cols + total_hgap + minsize1 = maxel[1]*rows + total_vgap + self.minsize = (minsize0,minsize1) + #print self.name,'MplGridSizer.Update() setting minsize',self.minsize + MplSizer.Update(self) # call base class (sets self.minsize_bordered) + + def _layout_core(self,lbrt_inch,fig_w_inch,fig_h_inch): + #print + #print 'MplGridSizer._layout_core',self,self.name,lbrt_inch + +## print 'len(self.elements)',len(self.elements) +## print 'self.cols',self.cols +## print 'len(self.elements)/self.cols',len(self.elements)/self.cols + rows = int(math.ceil(len(self.elements)/self.cols)) +## print 'rows',rows + + n_hgaps = max(0,self.cols-1) + total_hgap = n_hgaps*self.hgap_inch + + if self.flag.get('expand',False): + total_width_inches = lbrt_inch[2]-lbrt_inch[0] + else: + total_width_inches = self.minsize[0] + col_width = (total_width_inches-total_hgap)/self.cols + col_stride = col_width + self.hgap_inch + + n_vgaps = max(0,rows-1) + total_vgap = n_vgaps*self.vgap_inch + + if self.flag.get('expand',False): + total_height_inches = lbrt_inch[3]-lbrt_inch[1] + else: + total_height_inches = self.minsize[1] + row_height = (total_height_inches-total_vgap)/rows + row_stride = row_height + self.vgap_inch + + req_w_inch = None + req_h_inch = None + + for i in range(rows): + y1 = lbrt_inch[3] - i*row_stride # top + y0 = lbrt_inch[3] - i*row_stride - row_height # bottom + #print 'i',i + #print 'y0,y1',y0,y1 + for j in range(self.cols): + if self.append_horiz: + idx = i*self.cols+j + else: + idx = j*rows+i + if idx >= len(self.elements): + continue + + el = self.elements[idx] + + x0 = lbrt_inch[0] + j*col_stride + x1 = lbrt_inch[0] + j*col_stride + col_width + + if el.flag.get('expand',False): + el_lbrt_inch = (x0,y0,x1,y1) + else: + x05 = (x0+x1)/2 + y05 = (y0+y1)/2 + w = el.minsize_bordered[0] + h = el.minsize_bordered[1] + w2 = w/2 + h2 = h/2 + if el.flag.get('align_centre',False): + el_lbrt_inch = (x05-w2,y05-h2, + x05+w2,y05+h2) + elif el.flag.get('align_centre_horizontal',False): + el_lbrt_inch = (x05-w2,y1-h, + x05+w2,y1) + elif el.flag.get('align_centre_vertical',False): + el_lbrt_inch = (x0, y05-h2, + x0+w,y05+h2) + # XXX more needed + else: + # top left default + el_lbrt_inch = (x0, y1-h, + x0+w,y1) + #print 'el_lbrt_inch',el_lbrt_inch + this_req_w_inch, this_req_h_inch = el._layout(el_lbrt_inch, + fig_w_inch,fig_h_inch) + req_w_inch = max(req_w_inch,this_req_w_inch) + req_h_inch = max(req_h_inch,this_req_h_inch) + + if req_w_inch is not None: + req_w_inch = self.cols*req_w_inch + + if req_h_inch is not None: + req_h_inch = rows*req_h_inch + + # call base class + return req_w_inch, req_h_inch + +class MplSizerFrame: + def __init__(self,fig): + self.fig = fig + self.sizer = None + def _show_contents(self,indent=0): + buf = (' '*indent)+'MplSizerFrame:\n' + buf += self.sizer._show_contents(indent+2) + return buf + def SetSizer(self,sizer, **kwargs): + """like Add but only a single sizer can be added""" + sizer._update_sizer_element_kwargs(**kwargs) + sizer.Update() # calculate minsize requirements + self.sizer = sizer + + def Layout(self): + self.sizer.Update() # calculate minsize requirements + + fig_w_inch = self.fig.get_figwidth() + fig_h_inch = self.fig.get_figheight() + lbrt_inch = (0,0,fig_w_inch,fig_h_inch) # bounding box within figure + req_w_inch, req_h_inch = self.sizer._layout(lbrt_inch,fig_w_inch,fig_h_inch) +# print '1: req_w_inch, req_h_inch',repr(req_w_inch), repr(req_h_inch) + + # this is a mini-hack to deal with floating point imprecision + max_tries = 1 + eps=1e-8 + for ntry in range(max_tries): + if (req_w_inch is not None) or (req_h_inch is not None): + # request was made to enlarge the figure + if req_w_inch is not None: + self.fig.set_figwidth(req_w_inch+ntry*eps) + if req_h_inch is not None: + self.fig.set_figheight(req_h_inch+ntry*eps) + + fig_w_inch = self.fig.get_figwidth() +## print 'fig_w_inch',fig_w_inch + fig_h_inch = self.fig.get_figheight() +## print 'fig_h_inch',fig_h_inch + lbrt_inch = (0,0,fig_w_inch,fig_h_inch) # bounding box within figure + + req_w_inch, req_h_inch = self.sizer._layout(lbrt_inch,fig_w_inch,fig_h_inch) +## print 'ntry %d: req_w_inch, req_h_inch'%(ntry,),repr(req_w_inch), repr(req_h_inch) + if (req_w_inch is not None) or (req_h_inch is not None): + raise RuntimeError('failed to layout') + Modified: trunk/toolkits/mplsizer/setup.py =================================================================== --- trunk/toolkits/mplsizer/setup.py 2008年01月10日 13:33:03 UTC (rev 4844) +++ trunk/toolkits/mplsizer/setup.py 2008年01月10日 13:38:31 UTC (rev 4845) @@ -16,6 +16,6 @@ version='0.1', license='MIT', url='http://matplotlib.sourceforge.net/', - packages=['matplotlib.toolkits.mplsizer'], - namespace_packages = ['matplotlib.toolkits'], + packages=['mpl_toolkits','mpl_toolkits.mplsizer'], + namespace_packages = ['mpl_toolkits'], ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 4844 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4844&view=rev Author: mdboom Date: 2008年01月10日 05:33:03 -0800 (2008年1月10日) Log Message: ----------- Merged revisions 4826-4843 via svnmerge from https://matplotlib.svn.sourceforge.net/svnroot/matplotlib/branches/v0_91_maint ........ r4826 | mdboom | 2008年01月08日 17:13:08 -0500 (2008年1月08日) | 1 line Undoing last commit. Testing was successful. ........ r4841 | mdboom | 2008年01月10日 08:28:01 -0500 (2008年1月10日) | 1 line Fix offset labels (so the times symbol is displayed correctly) ........ Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/ticker.py Property Changed: ---------------- trunk/matplotlib/ Property changes on: trunk/matplotlib ___________________________________________________________________ Name: svnmerge-integrated - /branches/v0_91_maint:1-4816 + /branches/v0_91_maint:1-4843 Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2008年01月10日 13:29:16 UTC (rev 4843) +++ trunk/matplotlib/CHANGELOG 2008年01月10日 13:33:03 UTC (rev 4844) @@ -1,7 +1,7 @@ 2008年01月10日 Moved toolkits to mpl_toolkits, made mpl_toolkits a namespace package - JSWHIT -2008年01月10日 Use setup.cfg to set the default parameters (tkagg, +2008年01月10日 Use setup.cfg to set the default parameters (tkagg, numpy) when building windows installers - DSD =============================================================== Modified: trunk/matplotlib/lib/matplotlib/ticker.py =================================================================== --- trunk/matplotlib/lib/matplotlib/ticker.py 2008年01月10日 13:29:16 UTC (rev 4843) +++ trunk/matplotlib/lib/matplotlib/ticker.py 2008年01月10日 13:33:03 UTC (rev 4844) @@ -327,12 +327,16 @@ if self.offset > 0: offsetStr = '+' + offsetStr if self.orderOfMagnitude: if self._usetex or self._useMathText: - sciNotStr = r'\times'+self.format_data(10**self.orderOfMagnitude) + sciNotStr = self.format_data(10**self.orderOfMagnitude) else: - sciNotStr = u'\xd7'+'1e%d'% self.orderOfMagnitude + sciNotStr = '1e%d'% self.orderOfMagnitude if self._useMathText: - return ''.join(('$\mathdefault{',sciNotStr,offsetStr,'}$')) + if sciNotStr != '': + sciNotStr = r'\times\mathdefault{%s}' % sciNotStr + return ''.join(('$',sciNotStr,r'\mathdefault{',offsetStr,'}$')) elif self._usetex: + if sciNotStr != '': + sciNotStr = u'\xd7%s' % sciNotStr return ''.join(('$',sciNotStr,offsetStr,'$')) else: return ''.join((sciNotStr,offsetStr)) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 4843 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4843&view=rev Author: jswhit Date: 2008年01月10日 05:29:16 -0800 (2008年1月10日) Log Message: ----------- change docstring to reflect move to mpl_toolkits Modified Paths: -------------- trunk/matplotlib/lib/mpl_toolkits/exceltools.py trunk/matplotlib/lib/mpl_toolkits/gtktools.py Modified: trunk/matplotlib/lib/mpl_toolkits/exceltools.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/exceltools.py 2008年01月10日 13:29:16 UTC (rev 4842) +++ trunk/matplotlib/lib/mpl_toolkits/exceltools.py 2008年01月10日 13:29:16 UTC (rev 4843) @@ -4,7 +4,7 @@ Example usage: import matplotlib.mlab as mlab - import matplotlib.toolkits.exceltools as exceltools + import mpl_toolkits.exceltools as exceltools r = mlab.csv2rec('somefile.csv', checkrows=0) Modified: trunk/matplotlib/lib/mpl_toolkits/gtktools.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/gtktools.py 2008年01月10日 13:29:16 UTC (rev 4842) +++ trunk/matplotlib/lib/mpl_toolkits/gtktools.py 2008年01月10日 13:29:16 UTC (rev 4843) @@ -7,7 +7,7 @@ Example usage import matplotlib.mlab as mlab - import matplotlib.toolkits.gtktools as gtktools + import mpl_toolkits.gtktools as gtktools r = mlab.csv2rec('somefile.csv', checkrows=0) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.