SourceForge logo
SourceForge logo
Menu

matplotlib-checkins — Commit notification. DO NOT POST to this list, just subscribe to it.

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
(4)
2
(9)
3
(23)
4
(34)
5
(31)
6
(25)
7
(10)
8
(7)
9
(1)
10
(18)
11
(3)
12
(18)
13
(13)
14
(6)
15
(9)
16
(6)
17
(10)
18
(12)
19
(1)
20
(8)
21
(5)
22
23
24
25
26
(4)
27
(2)
28
(4)
29
30
31





Showing results of 263

<< < 1 .. 7 8 9 10 11 > >> (Page 9 of 11)
Revision: 4597
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4597&view=rev
Author: jswhit
Date: 2007年12月04日 12:43:54 -0800 (2007年12月04日)
Log Message:
-----------
docstring additions.
Modified Paths:
--------------
 trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/basemap.py
Modified: trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/basemap.py
===================================================================
--- trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/basemap.py	2007年12月04日 20:37:37 UTC (rev 4596)
+++ trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/basemap.py	2007年12月04日 20:43:54 UTC (rev 4597)
@@ -2886,7 +2886,8 @@
 All the values currently defined in the CF metadata convention 
 (http://cf-pcmdi.llnl.gov/documents/cf-conventions/) are supported.
 Valid calendars 'standard', 'gregorian', 'proleptic_gregorian'
- 'noleap', '365_day', '360_day', 'julian'. Default is 'standard'.
+ 'noleap', '365_day', '360_day', 'julian', 'all_leap', '366_day'.
+ Default is 'standard', which is a mixed Julian/Gregorian calendar.
 
 Returns a datetime instance, or an array of datetime instances.
 
@@ -2926,7 +2927,8 @@
 All the values currently defined in the CF metadata convention 
 (http://cf-pcmdi.llnl.gov/documents/cf-conventions/) are supported.
 Valid calendars 'standard', 'gregorian', 'proleptic_gregorian'
- 'noleap', '365_day', '360_day', 'julian'. Default is 'standard'.
+ 'noleap', '365_day', '360_day', 'julian', 'all_leap', '366_day'.
+ Default is 'standard'.
 
 Returns a numeric time value, or an array of numeric time values.
 
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 4596
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4596&view=rev
Author: jswhit
Date: 2007年12月04日 12:37:37 -0800 (2007年12月04日)
Log Message:
-----------
docstring additions
Modified Paths:
--------------
 trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/basemap.py
Modified: trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/basemap.py
===================================================================
--- trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/basemap.py	2007年12月04日 20:29:54 UTC (rev 4595)
+++ trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/basemap.py	2007年12月04日 20:37:37 UTC (rev 4596)
@@ -11,6 +11,10 @@
 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 rcParams
 from matplotlib import __version__ as _matplotlib_version
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2007年12月04日 20:30:07
Revision: 4595
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4595&view=rev
Author: mdboom
Date: 2007年12月04日 12:29:54 -0800 (2007年12月04日)
Log Message:
-----------
Fix interpolation so it wraps rather than clips.
Modified Paths:
--------------
 branches/transforms/src/_image.cpp
Modified: branches/transforms/src/_image.cpp
===================================================================
--- branches/transforms/src/_image.cpp	2007年12月04日 20:28:24 UTC (rev 4594)
+++ branches/transforms/src/_image.cpp	2007年12月04日 20:29:54 UTC (rev 4595)
@@ -392,10 +392,11 @@
 agg::conv_transform<agg::path_storage> imageBox(path, srcMatrix);
 ras.add_path(imageBox);
 
- typedef agg::image_accessor_clip<pixfmt> img_accessor_type;
+ typedef agg::wrap_mode_reflect reflect_type;
+ typedef agg::image_accessor_wrap<pixfmt, reflect_type, reflect_type> img_accessor_type;
 
 pixfmt pixfmtin(*rbufIn);
- img_accessor_type ia(pixfmtin, background);
+ img_accessor_type ia(pixfmtin);
 switch(interpolation)
 {
 
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 4594
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4594&view=rev
Author: mdboom
Date: 2007年12月04日 12:28:24 -0800 (2007年12月04日)
Log Message:
-----------
Fix bbox_artist
Modified Paths:
--------------
 branches/transforms/lib/matplotlib/patches.py
Modified: branches/transforms/lib/matplotlib/patches.py
===================================================================
--- branches/transforms/lib/matplotlib/patches.py	2007年12月04日 20:08:28 UTC (rev 4593)
+++ branches/transforms/lib/matplotlib/patches.py	2007年12月04日 20:28:24 UTC (rev 4594)
@@ -933,6 +933,7 @@
 height=h,
 fill=fill,
 )
+ r.set_transform(transforms.IdentityTransform())
 r.set_clip_on( False )
 r.update(props)
 r.draw(renderer)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2007年12月04日 20:08:40
Revision: 4593
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4593&view=rev
Author: mdboom
Date: 2007年12月04日 12:08:28 -0800 (2007年12月04日)
Log Message:
-----------
Fix direction of left and right caret markers.
Modified Paths:
--------------
 branches/transforms/lib/matplotlib/lines.py
Modified: branches/transforms/lib/matplotlib/lines.py
===================================================================
--- branches/transforms/lib/matplotlib/lines.py	2007年12月04日 20:07:59 UTC (rev 4592)
+++ branches/transforms/lib/matplotlib/lines.py	2007年12月04日 20:08:28 UTC (rev 4593)
@@ -309,13 +309,13 @@
 xyt = self.get_transform().transform(self._xy)
 xt = xyt[:, 0]
 yt = xyt[:, 1]
- 
+
 if self.figure == None:
 print str(self),' has no figure set'
 pixels = self.pickradius
 else:
 pixels = self.figure.dpi/72. * self.pickradius
- 
+
 if self._linestyle == 'None':
 # If no line, return the nearby point(s)
 d = npy.sqrt((xt-mouseevent.x)**2 + (yt-mouseevent.y)**2)
@@ -387,7 +387,7 @@
 if not ma.isMaskedArray(y):
 y = npy.asarray(y)
 not_masked += 1
- 
+
 if (not_masked < 2 or
 (x is not self._xorig and
 (x.shape != self._xorig.shape or npy.any(x != self._xorig))) or
@@ -413,7 +413,7 @@
 y = npy.asarray(self.convert_yunits(self._yorig), float)
 x = npy.ravel(x)
 y = npy.ravel(y)
- 
+
 if len(x)==1 and len(y)>1:
 x = x * npy.ones(y.shape, float)
 if len(y)==1 and len(x)>1:
@@ -447,7 +447,7 @@
 Artist.set_transform(self, t)
 self._invalid = True
 # self._transformed_path = TransformedPath(self._path, self.get_transform())
- 
+
 def _is_sorted(self, x):
 "return true if x is sorted"
 if len(x)<2: return 1
@@ -456,7 +456,7 @@
 def draw(self, renderer):
 if self._invalid:
 self.recache()
- 
+
 renderer.open_group('line2d')
 
 if not self._visible: return
@@ -481,7 +481,7 @@
 tpath, affine = self._transformed_path.get_transformed_path_and_affine()
 lineFunc = getattr(self, funcname)
 lineFunc(renderer, gc, tpath, affine.frozen())
-	 
+
 if self._marker is not None:
 gc = renderer.new_gc()
 self._set_gc_clip(gc)
@@ -565,7 +565,7 @@
 if self._invalid:
 self.recache()
 return self._xy
- 
+
 def set_antialiased(self, b):
 """
 True if line should be drawin with antialiased rendering
@@ -596,7 +596,7 @@
 
 'steps' is equivalent to 'steps-pre' and is maintained for
 backward-compatibility.
- 
+
 ACCEPTS: [ '-' | '--' | '-.' | ':' | 'steps' | 'steps-pre' | 'steps-mid' | 'steps-post' | 'None' | ' ' | '' ]
 """
 if linestyle not in self._lineStyles:
@@ -693,12 +693,12 @@
 def _draw_nothing(self, *args, **kwargs):
 pass
 
- 
+
 def _draw_solid(self, renderer, gc, path, trans):
 gc.set_linestyle('solid')
 	renderer.draw_path(gc, path, trans)
 
- 
+
 def _draw_steps_pre(self, renderer, gc, path, trans):
 vertices = self._xy
 steps = ma.zeros((2*len(vertices)-1, 2), npy.float_)
@@ -720,7 +720,7 @@
 path = Path(steps)
 self._draw_solid(renderer, gc, path, trans)
 
- 
+
 def _draw_steps_mid(self, renderer, gc, path, trans):
 vertices = self._xy
 steps = ma.zeros((2*len(vertices), 2), npy.float_)
@@ -733,8 +733,8 @@
 
 path = Path(steps)
 self._draw_solid(renderer, gc, path, trans)
- 
 
+
 def _draw_dashed(self, renderer, gc, path, trans):
 gc.set_linestyle('dashed')
 if self._dashSeq is not None:
@@ -747,12 +747,12 @@
 gc.set_linestyle('dashdot')
 	renderer.draw_path(gc, path, trans)
 
-	 
+
 def _draw_dotted(self, renderer, gc, path, trans):
 gc.set_linestyle('dotted')
 	renderer.draw_path(gc, path, trans)
 
-	
+
 def _draw_point(self, renderer, gc, path, path_trans):
 w = renderer.points_to_pixels(self._markersize) * \
 	 self._point_size_reduction * 0.5
@@ -768,8 +768,8 @@
 	renderer.draw_markers(gc, Path.unit_rectangle(),
 self._draw_pixel_transform,
 			 path, path_trans, rgbFace)
-	
-	
+
+
 def _draw_circle(self, renderer, gc, path, path_trans):
 w = renderer.points_to_pixels(self._markersize) * 0.5
 rgbFace = self._get_rgb_face()
@@ -795,7 +795,7 @@
 	renderer.draw_markers(gc, self._triangle_path, transform,
 			 path, path_trans, rgbFace)
 
-	
+
 def _draw_triangle_left(self, renderer, gc, path, path_trans):
 offset = 0.5*renderer.points_to_pixels(self._markersize)
 	transform = Affine2D().scale(offset, offset).rotate_deg(90)
@@ -819,7 +819,7 @@
 	renderer.draw_markers(gc, Path.unit_rectangle(), transform,
 			 path, path_trans, rgbFace)
 
-	
+
 def _draw_diamond(self, renderer, gc, path, path_trans):
 side = renderer.points_to_pixels(self._markersize)
 	transform = Affine2D().translate(-0.5, -0.5).rotate_deg(45).scale(side)
@@ -827,7 +827,7 @@
 	renderer.draw_markers(gc, Path.unit_rectangle(), transform,
 			 path, path_trans, rgbFace)
 
-	
+
 def _draw_thin_diamond(self, renderer, gc, path, path_trans):
 offset = renderer.points_to_pixels(self._markersize)
 	transform = Affine2D().translate(-0.5, -0.5) \
@@ -836,7 +836,7 @@
 	renderer.draw_markers(gc, Path.unit_rectangle(), transform,
 			 path, path_trans, rgbFace)
 
-	
+
 def _draw_pentagon(self, renderer, gc, path, path_trans):
 offset = 0.5 * renderer.points_to_pixels(self._markersize)
 	transform = Affine2D().scale(offset)
@@ -844,7 +844,7 @@
 	renderer.draw_markers(gc, Path.unit_regular_polygon(5), transform,
 			 path, path_trans, rgbFace)
 
-	
+
 def _draw_hexagon1(self, renderer, gc, path, path_trans):
 offset = 0.5 * renderer.points_to_pixels(self._markersize)
 	transform = Affine2D().scale(offset)
@@ -852,7 +852,7 @@
 	renderer.draw_markers(gc, Path.unit_regular_polygon(6), transform,
 			 path, path_trans, rgbFace)
 
-	
+
 def _draw_hexagon2(self, renderer, gc, path, path_trans):
 offset = 0.5 * renderer.points_to_pixels(self._markersize)
 	transform = Affine2D().scale(offset).rotate_deg(30)
@@ -868,14 +868,14 @@
 	renderer.draw_markers(gc, self._line_marker_path, transform,
 			 path, path_trans)
 
-		
+
 def _draw_hline(self, renderer, gc, path, path_trans):
 offset = 0.5*renderer.points_to_pixels(self._markersize)
 	transform = Affine2D().scale(offset).rotate_deg(90)
 	renderer.draw_markers(gc, self._line_marker_path, transform,
 			 path, path_trans)
 
-		
+
 _tickhoriz_path = Path([[0.0, 0.5], [1.0, 0.5]])
 def _draw_tickleft(self, renderer, gc, path, path_trans):
 offset = renderer.points_to_pixels(self._markersize)
@@ -883,14 +883,14 @@
 	renderer.draw_markers(gc, self._tickhoriz_path, marker_transform,
 			 path, path_trans)
 
-	
+
 def _draw_tickright(self, renderer, gc, path, path_trans):
 offset = renderer.points_to_pixels(self._markersize)
 	marker_transform = Affine2D().scale(offset, 1.0)
 	renderer.draw_markers(gc, self._tickhoriz_path, marker_transform,
 			 path, path_trans)
 
-	
+
 _tickvert_path = Path([[-0.5, 0.0], [-0.5, 1.0]])
 def _draw_tickup(self, renderer, gc, path, path_trans):
 offset = renderer.points_to_pixels(self._markersize)
@@ -898,7 +898,7 @@
 	renderer.draw_markers(gc, self._tickvert_path, marker_transform,
 			 path, path_trans)
 
-	
+
 def _draw_tickdown(self, renderer, gc, path, path_trans):
 offset = renderer.points_to_pixels(self._markersize)
 	marker_transform = Affine2D().scale(1.0, -offset)
@@ -929,21 +929,21 @@
 	renderer.draw_markers(gc, self._tri_path, transform,
 			 path, path_trans)
 
-	
+
 def _draw_tri_up(self, renderer, gc, path, path_trans):
 offset = 0.5*renderer.points_to_pixels(self._markersize)
 	transform = Affine2D().scale(offset).rotate_deg(180)
 	renderer.draw_markers(gc, self._tri_path, transform,
 			 path, path_trans)
 
-	
+
 def _draw_tri_left(self, renderer, gc, path, path_trans):
 	offset = 0.5*renderer.points_to_pixels(self._markersize)
 	transform = Affine2D().scale(offset).rotate_deg(90)
 	renderer.draw_markers(gc, self._tri_path, transform,
 			 path, path_trans)
 
-	
+
 def _draw_tri_right(self, renderer, gc, path, path_trans):
 	offset = 0.5*renderer.points_to_pixels(self._markersize)
 	transform = Affine2D().scale(offset).rotate_deg(270)
@@ -958,24 +958,24 @@
 	renderer.draw_markers(gc, self._caret_path, transform,
 			 path, path_trans)
 
-	
+
 def _draw_caretup(self, renderer, gc, path, path_trans):
 offset = 0.5*renderer.points_to_pixels(self._markersize)
 	transform = Affine2D().scale(offset).rotate_deg(180)
 	renderer.draw_markers(gc, self._caret_path, transform,
 			 path, path_trans)
 
-	
+
 def _draw_caretleft(self, renderer, gc, path, path_trans):
 offset = 0.5*renderer.points_to_pixels(self._markersize)
-	transform = Affine2D().scale(offset).rotate_deg(90)
+	transform = Affine2D().scale(offset).rotate_deg(270)
 	renderer.draw_markers(gc, self._caret_path, transform,
 			 path, path_trans)
 
-	
+
 def _draw_caretright(self, renderer, gc, path, path_trans):
 offset = 0.5*renderer.points_to_pixels(self._markersize)
-	transform = Affine2D().scale(offset).rotate_deg(270)
+	transform = Affine2D().scale(offset).rotate_deg(90)
 	renderer.draw_markers(gc, self._caret_path, transform,
 			 path, path_trans)
 
@@ -990,7 +990,7 @@
 	renderer.draw_markers(gc, self._x_path, transform,
 			 path, path_trans)
 
-	
+
 def update_from(self, other):
 'copy properties from other to self'
 Artist.update_from(self, other)
@@ -1163,14 +1163,14 @@
 """
 return self._dashcapstyle
 
- 
+
 def get_solid_capstyle(self):
 """
 Get the cap style for solid linestyles
 """
 return self._solidcapstyle
 
- 
+
 def is_dashed(self):
 'return True if line is dashstyle'
 return self._linestyle in ('--', '-.', ':')
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 4592
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4592&view=rev
Author: mdboom
Date: 2007年12月04日 12:07:59 -0800 (2007年12月04日)
Log Message:
-----------
Bugfix for broken_barh demo
Modified Paths:
--------------
 branches/transforms/lib/matplotlib/collections.py
Modified: branches/transforms/lib/matplotlib/collections.py
===================================================================
--- branches/transforms/lib/matplotlib/collections.py	2007年12月04日 20:07:31 UTC (rev 4591)
+++ branches/transforms/lib/matplotlib/collections.py	2007年12月04日 20:07:59 UTC (rev 4592)
@@ -54,7 +54,7 @@
 _offsets = npy.array([], npy.float_)
 _transOffset = transforms.IdentityTransform()
 _transforms = []
- 
+
 zorder = 1
 def __init__(self,
 edgecolors=None,
@@ -82,7 +82,7 @@
 if linewidths is None: linewidths = (mpl.rcParams['patch.linewidth'],)
 if antialiaseds is None: antialiaseds = (mpl.rcParams['patch.antialiased'],)
 self.set_linestyles(linestyles)
- 
+
 self._facecolors = _colors.colorConverter.to_rgba_array(facecolors)
 if edgecolors == 'None':
 self._edgecolors = self._facecolors
@@ -117,13 +117,13 @@
 else: return val
 
 raise TypeError('val must be a float or nonzero sequence of floats')
- 
+
 def get_paths(self):
 raise NotImplementedError
 
 def get_transforms(self):
 return self._transforms
- 
+
 def get_datalim(self, transData):
 transform = self.get_transform()
 transOffset = self._transOffset
@@ -136,7 +136,7 @@
 offsets = transOffset.transform_non_affine(offsets)
 transOffset = transOffset.get_affine()
 offsets = npy.asarray(offsets, npy.float_)
- 
+
 result = mpath.get_path_collection_extents(
 transform.frozen(), paths, self.get_transforms(),
 offsets, transOffset.frozen())
@@ -163,7 +163,7 @@
 xs = self.convert_xunits(self._offsets[:0])
 ys = self.convert_yunits(self._offsets[:1])
 offsets = zip(xs, ys)
- 
+
 offsets = npy.asarray(offsets, npy.float_)
 
 self.update_scalarmappable()
@@ -171,18 +171,18 @@
 clippath, clippath_trans = self.get_transformed_clip_path_and_affine()
 if clippath_trans is not None:
 clippath_trans = clippath_trans.frozen()
- 
+
 if not transform.is_affine:
 paths = [transform.transform_path_non_affine(path) for path in paths]
 transform = transform.get_affine()
 if not transOffset.is_affine:
 offsets = transOffset.transform_non_affine(offsets)
 transOffset = transOffset.get_affine()
- 
+
 renderer.draw_path_collection(
 transform.frozen(), self.clipbox, clippath, clippath_trans,
 paths, self.get_transforms(),
- offsets, transOffset, 
+ offsets, transOffset,
 self._facecolors, self._edgecolors, self._linewidths,
 self._linestyles, self._antialiaseds)
 renderer.close_group(self.__class__.__name__)
@@ -210,7 +210,7 @@
 
 def set_pickradius(self,pickradius): self.pickradius = 5
 def get_pickradius(self): return self.pickradius
- 
+
 def set_linewidths(self, lw):
 """
 Set the linewidth(s) for the collection. lw can be a scalar or a
@@ -221,7 +221,7 @@
 """
 self._linewidths = self._get_value(lw)
 set_lw = set_linewidth = set_linewidths
- 
+
 def set_linestyles(self, ls):
 """
 Set the linestyles(s) for the collection.
@@ -251,7 +251,7 @@
 raise ValueError('Do not know how to convert %s to dashes'%ls)
 self._linestyles = dashes
 set_dashes = set_linestyle = set_linestyles
- 
+
 def set_color(self, c):
 """
 Set both the edgecolor and the facecolor.
@@ -307,11 +307,11 @@
 def get_linewidths(self):
 return self._linewidths
 get_linewidth = get_linewidths
- 
+
 def get_linestyles(self):
 return self._linestyles
 get_dashes = get_linestyle = get_linestyles
- 
+
 def update_scalarmappable(self):
 """
 If the scalar mappable array is not none, update colors
@@ -348,7 +348,7 @@
 None, they default to their patch.* rc params setting, in sequence
 form.
 """
- 
+
 class QuadMesh(Collection):
 """
 Class for the efficient drawing of a quadrilateral mesh.
@@ -391,7 +391,7 @@
 # By converting to floats now, we can avoid that on every draw.
 self._coordinates = self._coordinates.reshape((meshHeight + 1, meshWidth + 1, 2))
 self._coordinates = npy.array(self._coordinates, npy.float_)
- 
+
 def get_paths(self, dataTrans=None):
 if self._paths is None:
 self._paths = self.convert_mesh_to_paths(
@@ -401,14 +401,14 @@
 #@staticmethod
 def convert_mesh_to_paths(meshWidth, meshHeight, coordinates):
 Path = mpath.Path
- 
+
 c = coordinates
 # We could let the Path constructor generate the codes for us,
 # but this is faster, since we know they'll always be the same
 codes = npy.array(
 [Path.MOVETO, Path.LINETO, Path.LINETO, Path.LINETO, Path.CLOSEPOLY],
 Path.code_type)
- 
+
 points = npy.concatenate((
 c[0:-1, 0:-1],
 c[0:-1, 1: ],
@@ -419,10 +419,10 @@
 points = points.reshape((meshWidth * meshHeight, 5, 2))
 return [Path(x, codes) for x in points]
 convert_mesh_to_paths = staticmethod(convert_mesh_to_paths)
- 
+
 def get_datalim(self, transData):
 return self._bbox
- 
+
 def draw(self, renderer):
 if not self.get_visible(): return
 renderer.open_group(self.__class__.__name__)
@@ -444,7 +444,7 @@
 clippath, clippath_trans = self.get_transformed_clip_path_and_affine()
 if clippath_trans is not None:
 clippath_trans = clippath_trans.frozen()
- 
+
 assert transform.is_affine
 if not transOffset.is_affine:
 offsets = transOffset.transform_non_affine(offsets)
@@ -478,7 +478,7 @@
 
 def get_paths(self):
 return self._paths
- 
+
 class BrokenBarHCollection(PolyCollection):
 """
 A colleciton of horizontal bars spanning yrange with a sequence of
@@ -493,13 +493,13 @@
 """
 ymin, ywidth = yrange
 ymax = ymin + ywidth
- verts = [ [(xmin, ymin), (xmin, ymax), (xmin+xwidth, ymax), (xmin+xwidth, ymin)] for xmin, xwidth in xranges]
+ verts = [ [(xmin, ymin), (xmin, ymax), (xmin+xwidth, ymax), (xmin+xwidth, ymin), (xmin, ymin)] for xmin, xwidth in xranges]
 PolyCollection.__init__(self, verts, **kwargs)
 __init__.__doc__ = cbook.dedent(__init__.__doc__) % artist.kwdocd
 
 class RegularPolyCollection(Collection):
 _path_generator = mpath.Path.unit_regular_polygon
- 
+
 def __init__(self,
 dpi,
 numsides,
@@ -550,7 +550,7 @@
 (math.sqrt(x) * self._dpi / 72.0) / math.sqrt(math.pi))
 for x in sizes]
 self.set_transform(transforms.IdentityTransform())
- 
+
 __init__.__doc__ = cbook.dedent(__init__.__doc__) % artist.kwdocd
 
 def get_paths(self):
@@ -559,12 +559,12 @@
 
 class StarPolygonCollection(RegularPolyCollection):
 _path_generator = mpath.Path.unit_regular_star
- 
- 
+
+
 class AsteriskPolygonCollection(RegularPolyCollection):
 _path_generator = mpath.Path.unit_regular_asterisk
- 
- 
+
+
 class LineCollection(Collection, cm.ScalarMappable):
 """
 All parameters must be sequences or scalars; if scalars, they will
@@ -630,7 +630,7 @@
 self.set_linestyles(linestyles)
 
 colors = _colors.colorConverter.to_rgba_array(colors)
- 
+
 Collection.__init__(
 self,
 edgecolors=colors,
@@ -649,14 +649,14 @@
 
 def get_paths(self):
 return self._paths
- 
+
 def set_segments(self, segments):
 if segments is None: return
 segments = [npy.asarray(seg, npy.float_) for seg in segments]
 if self._uniform_offsets is not None:
 segments = self._add_offsets(segments)
 self._paths = [mpath.Path(seg) for seg in segments]
- 
+
 set_verts = set_segments # for compatibility with PolyCollection
 
 def _add_offsets(self, segs):
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2007年12月04日 20:07:44
Revision: 4591
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4591&view=rev
Author: mdboom
Date: 2007年12月04日 12:07:31 -0800 (2007年12月04日)
Log Message:
-----------
Bugfix for faceted pcolor-based quadmeshes.
Modified Paths:
--------------
 branches/transforms/lib/matplotlib/axes.py
Modified: branches/transforms/lib/matplotlib/axes.py
===================================================================
--- branches/transforms/lib/matplotlib/axes.py	2007年12月04日 20:06:45 UTC (rev 4590)
+++ branches/transforms/lib/matplotlib/axes.py	2007年12月04日 20:07:31 UTC (rev 4591)
@@ -4694,12 +4694,14 @@
 
 
 if shading == 'faceted':
- edgecolors = (0,0,0,1),
+ edgecolors = (0,0,0,1),
+ linewidths = (0.25,)
 else:
 edgecolors = 'None'
+ linewidths = (0.0,)
 kwargs.setdefault('edgecolors', edgecolors)
 kwargs.setdefault('antialiaseds', (0,))
- kwargs.setdefault('linewidths', (0.25,))
+ kwargs.setdefault('linewidths', linewidths)
 
 collection = mcoll.PolyCollection(verts, **kwargs)
 
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2007年12月04日 20:06:57
Revision: 4590
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4590&view=rev
Author: mdboom
Date: 2007年12月04日 12:06:45 -0800 (2007年12月04日)
Log Message:
-----------
Bugfix for missing markers. Bugfix for faceted pcolor-based quadmeshes.
Modified Paths:
--------------
 branches/transforms/src/_backend_agg.cpp
Modified: branches/transforms/src/_backend_agg.cpp
===================================================================
--- branches/transforms/src/_backend_agg.cpp	2007年12月04日 19:57:01 UTC (rev 4589)
+++ branches/transforms/src/_backend_agg.cpp	2007年12月04日 20:06:45 UTC (rev 4590)
@@ -506,6 +506,8 @@
 //maxim's suggestions for cached scanlines
 agg::scanline_storage_aa8 scanlines;
 theRasterizer->reset();
+ theRasterizer->reset_clipping();
+ rendererBase->reset_clipping(true);
 
 agg::int8u staticFillCache[MARKER_CACHE_SIZE];
 agg::int8u staticStrokeCache[MARKER_CACHE_SIZE];
@@ -792,8 +794,12 @@
 // Render stroke
 if (gc.linewidth != 0.0) {
 double linewidth = gc.linewidth;
- if (!gc.isaa)
- linewidth = round(linewidth);
+ if (!gc.isaa) {
+ if (linewidth < 0.5)
+	linewidth = 0.5;
+ else
+	linewidth = round(linewidth);
+ }
 if (gc.dashes.size() == 0) {
 stroke_t stroke(path);
 stroke.width(linewidth);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <js...@us...> - 2007年12月04日 19:57:10
Revision: 4589
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4589&view=rev
Author: jswhit
Date: 2007年12月04日 11:57:01 -0800 (2007年12月04日)
Log Message:
-----------
fix typo
Modified Paths:
--------------
 trunk/py4science/workbook/basemap.tex
Modified: trunk/py4science/workbook/basemap.tex
===================================================================
--- trunk/py4science/workbook/basemap.tex	2007年12月04日 19:55:12 UTC (rev 4588)
+++ trunk/py4science/workbook/basemap.tex	2007年12月04日 19:57:01 UTC (rev 4589)
@@ -97,7 +97,7 @@
 data, such as output from climate models. These data often come on
 latitude/longitude grids. One common data format for storing such
 grids is NetCDF. Basemap includes a NetCDF file reader (written in
-pure python by Roberto D'Almeida). 
+pure python by Roberto De Almeida). 
 You can also access remote datasets over the web using the OPeNDAP
 protocol - just give the NetCDFFile function a URL instead of a local file name
 and Roberto's pydap module (\texttt{http://pydap.org}) will be used.
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 4588
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4588&view=rev
Author: jswhit
Date: 2007年12月04日 11:55:12 -0800 (2007年12月04日)
Log Message:
-----------
fix typo
Modified Paths:
--------------
 trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/netcdftime.py
Modified: trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/netcdftime.py
===================================================================
--- trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/netcdftime.py	2007年12月04日 19:49:01 UTC (rev 4587)
+++ trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/netcdftime.py	2007年12月04日 19:55:12 UTC (rev 4588)
@@ -736,7 +736,7 @@
 
 Lots of things are optional; just the date is mandatory.
 
- by Roberto D'Almeida 
+ by Roberto De Almeida
 
 excerpted from coards.py - http://cheeseshop.python.org/pypi/coards/
 """
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 4587
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4587&view=rev
Author: jswhit
Date: 2007年12月04日 11:49:01 -0800 (2007年12月04日)
Log Message:
-----------
format string no longer needed
Modified Paths:
--------------
 trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/netcdftime.py
Modified: trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/netcdftime.py
===================================================================
--- trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/netcdftime.py	2007年12月04日 19:34:11 UTC (rev 4586)
+++ trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/netcdftime.py	2007年12月04日 19:49:01 UTC (rev 4587)
@@ -434,7 +434,7 @@
 
 return datetime(year,month,int(days),int(hours),int(minutes),int(seconds),-1, int(dayofyr))
 
-def _dateparse(timestr,format='%Y-%m-%d %H:%M:%S'):
+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()
@@ -443,12 +443,10 @@
 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"
- # use strptime to parse the date string.
+ # parse the date string.
 n = timestr.find('since')+6
- #year,month,day,hour,minute,second,daywk,dayyr,tz = strptime(timestr[n:],format)
- year,month,day,hour,minute,second = _parse_date(timestr[n:])
- #if dayyr == -1: dayyr=1 # must have valid day of year for strftime to work
- #return units, datetime(year, month, day, hour, minute, second, daywk, dayyr)
+ year,month,day,hour,minute,second,utc_offset = _parse_date(timestr[n:])
+
 return units, datetime(year, month, day, hour, minute, second)
 
 class utime:
@@ -456,18 +454,13 @@
 Performs conversions of netCDF time coordinate
 data to/from datetime objects.
 
-To initialize: C{t = utime(unit_string,format='%Y-%m-%d %H:%M:%S',calendar='standard')}
+To initialize: C{t = utime(unit_string,calendar='standard')}
 
 where 
 
 B{C{unit_string}} is a string of the form
-C{'time-units since <format>'} defining the time units.
+C{'time-units since <time-origin>'} defining the time units.
 
-B{C{format}} is a string describing a reference time. This string is converted 
-to a year,month,day,hour,minute,second tuple by strptime. The default 
-format is C{'%Y-%m-%d %H:%M:%S'}. See the C{time.strptime} docstring for other 
-valid formats.
-
 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'}.
@@ -556,15 +549,11 @@
 @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,format='%Y-%m-%d %H:%M:%S',calendar='standard'):
+ def __init__(self,unit_string,calendar='standard'):
 """
 @param unit_string: a string of the form
-C{'time-units since <format>'} defining the time units.
+C{'time-units since <time-origin>'} defining the time units.
 
-@keyword format: a string describing a reference time. This string is converted 
-to a year,month,day,hour,minute,second tuple by strptime. The default 
-format is C{'%Y-%m-%d %H:%M:%S'}. See the C{time.strptime} docstring for other 
-valid formats.
 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'}.
@@ -598,7 +587,7 @@
 self.calendar = calendar
 else:
 raise ValueError, "calendar must be one of %s, got '%s'" % (str(_calendars),calendar)
- units, self.origin = _dateparse(unit_string,format=format)
+ units, self.origin = _dateparse(unit_string)
 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:
@@ -736,7 +725,9 @@
 return numpy.reshape(numpy.array(date),shape)
 
 def _parse_date(origin):
- """Parses a date string and returns a datetime object.
+ """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::
@@ -784,7 +775,7 @@
 c = m.groupdict(0)
 
 # Instantiate timezone object.
- #offset = int(c['ho'])*60 + int(c['mo'])
+ offset = int(c['ho'])*60 + int(c['mo'])
 #tz = FixedOffset(offset, 'Unknown')
 
 #return datetime(int(c['year']),
@@ -795,7 +786,7 @@
 # int(c['sec']),
 # int(c['dsec']) * 100000,
 # tz)
- return int(c['year']),int(c['month']),int(c['day']),int(c['hour']),int(c['min']),int(c['sec'])
+ 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)
 
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2007年12月04日 19:34:16
Revision: 4586
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4586&view=rev
Author: mdboom
Date: 2007年12月04日 11:34:11 -0800 (2007年12月04日)
Log Message:
-----------
Support '|' as a symbol in mathtext.
Modified Paths:
--------------
 trunk/matplotlib/lib/matplotlib/_mathtext_data.py
 trunk/matplotlib/lib/matplotlib/mathtext.py
Modified: trunk/matplotlib/lib/matplotlib/_mathtext_data.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/_mathtext_data.py	2007年12月04日 19:29:49 UTC (rev 4585)
+++ trunk/matplotlib/lib/matplotlib/_mathtext_data.py	2007年12月04日 19:34:11 UTC (rev 4586)
@@ -90,7 +90,9 @@
 r'\phi' : ('cmmi10', 42),
 r'\chi' : ('cmmi10', 17),
 r'\psi' : ('cmmi10', 31),
- 
+
+ r'|' : ('cmsy10', 47),
+ r'\|' : ('cmsy10', 47),
 r'(' : ('cmr10', 119),
 r'\leftparen' : ('cmr10', 119),
 r'\rightparen' : ('cmr10', 68),
@@ -129,7 +131,7 @@
 r'\Phi' : ('cmr10', 9),
 r'\Psi' : ('cmr10', 15),
 r'\Omega' : ('cmr10', 12),
- 
+
 # these are mathml names, I think. I'm just using them for the
 # tex methods noted
 r'\circumflexaccent' : ('cmr10', 124), # for \hat
@@ -400,7 +402,7 @@
 r'\}' : ('pncr8a', 125),
 r'\backslash' : ('pncr8a', 92),
 r'\ast' : ('pncr8a', 42),
- 
+
 r'\circumflexaccent' : ('pncri8a', 124), # for \hat
 r'\combiningbreve' : ('pncri8a', 81), # for \breve
 r'\combininggraveaccent' : ('pncri8a', 114), # for \grave
@@ -1773,6 +1775,7 @@
 'succnsim': 8937,
 'gimel': 8503,
 'vert': 124,
+'|': 124,
 'varrho': 1009,
 'P': 182,
 'approxident': 8779,
@@ -2073,7 +2076,7 @@
 'rightzigzagarrow': 8669,
 'rightarrow': 8594,
 'leftarrow': 8592,
-'__sqrt__': 8730, 
+'__sqrt__': 8730,
 'twoheaddownarrow': 8609,
 'oint': 8750,
 'bigvee': 8897,
@@ -2238,7 +2241,7 @@
 '{': 123,
 '}': 125,
 '_': 95,
-'imath': 0x131, 
+'imath': 0x131,
 'circumflexaccent' : 770,
 'combiningbreve' : 774,
 'combiningoverline' : 772,
@@ -2471,5 +2474,5 @@
 (0x0061, 0x007a, 'rm', 0x1d68a) # a-z
 ],
 }
- 
- 
+
+
Modified: trunk/matplotlib/lib/matplotlib/mathtext.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/mathtext.py	2007年12月04日 19:29:49 UTC (rev 4585)
+++ trunk/matplotlib/lib/matplotlib/mathtext.py	2007年12月04日 19:34:11 UTC (rev 4586)
@@ -2021,7 +2021,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: 4585
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4585&view=rev
Author: jswhit
Date: 2007年12月04日 11:29:49 -0800 (2007年12月04日)
Log Message:
-----------
docstring additions
Modified Paths:
--------------
 trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/basemap.py
Modified: trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/basemap.py
===================================================================
--- trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/basemap.py	2007年12月04日 19:18:03 UTC (rev 4584)
+++ trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/basemap.py	2007年12月04日 19:29:49 UTC (rev 4585)
@@ -2862,8 +2862,13 @@
 """
 Return datetime objects given numeric time values. The units
 of the numeric time values are described by the units argument
- and the calendar keyword.
+ and the calendar keyword. The time zone is assumed to be UTC.
 
+ Like the matplotlib num2date function, except that it allows
+ for different units and calendars. Behaves the same if
+ units = 'days since 0001年01月01日 00:00:00' and 
+ calendar = 'proleptic_gregorian'.
+
 Arguments:
 
 times - numeric time values. Maximum resolution is 1 second.
@@ -2897,8 +2902,13 @@
 """
 Return numeric time values given datetime objects. The units
 of the numeric time values are described by the units argument
- and the calendar keyword.
+ and the calendar keyword. The time zone is assumed to UTC.
 
+ Like the matplotlib date2num function, except that it allows
+ for different units and calendars. Behaves the same if
+ units = 'days since 0001年01月01日 00:00:00' and 
+ calendar = 'proleptic_gregorian'.
+
 Arguments:
 
 dates - A datetime object or a sequence of datetime objects.
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <js...@us...> - 2007年12月04日 19:18:08
Revision: 4584
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4584&view=rev
Author: jswhit
Date: 2007年12月04日 11:18:03 -0800 (2007年12月04日)
Log Message:
-----------
move netcdftime.py
Modified Paths:
--------------
 trunk/toolkits/basemap/MANIFEST.in
 trunk/toolkits/basemap/examples/fcstmaps.py
 trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/basemap.py
 trunk/toolkits/basemap/setup.py
Added Paths:
-----------
 trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/netcdftime.py
Modified: trunk/toolkits/basemap/MANIFEST.in
===================================================================
--- trunk/toolkits/basemap/MANIFEST.in	2007年12月04日 19:16:57 UTC (rev 4583)
+++ trunk/toolkits/basemap/MANIFEST.in	2007年12月04日 19:18:03 UTC (rev 4584)
@@ -68,6 +68,7 @@
 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 pyshapelib/README pyshapelib/COPYING pyshapelib/ChangeLog pyshapelib/NEWS
 include pyshapelib/*.i pyshapelib/*.c pyshapelib/*.py pyshapelib/*.h
 include pyshapelib/*.shp pyshapelib/*.shx pyshapelib/*.dbf
@@ -78,7 +79,6 @@
 recursive-include lib/httplib2 *
 recursive-include lib/dbflib *
 recursive-include lib/shapelib *
-recursive-include lib/netcdftime *
 include lib/matplotlib/toolkits/basemap/data/5minmask.bin
 include lib/matplotlib/toolkits/basemap/data/GL27
 include lib/matplotlib/toolkits/basemap/data/countries_c.dat
Modified: trunk/toolkits/basemap/examples/fcstmaps.py
===================================================================
--- trunk/toolkits/basemap/examples/fcstmaps.py	2007年12月04日 19:16:57 UTC (rev 4583)
+++ trunk/toolkits/basemap/examples/fcstmaps.py	2007年12月04日 19:18:03 UTC (rev 4584)
@@ -36,9 +36,6 @@
 longitudes = data.variables['lon']
 fcsttimes = data.variables['time']
 times = fcsttimes[0:6] # first 6 forecast times.
-# change 0.0 to 00 at end of time units string
-# (so strptime will understand it).
-timeunits = fcsttimes.units[:-2]+'0'
 ntimes = len(times)
 # put forecast times in YYYYMMDDHH format.
 verifdates = []
@@ -46,7 +43,7 @@
 for time in times:
 print time, times[0]
 fcsthrs.append(int((time-times[0])*24))
- fdate = num2date(time,'days since 0001年01月01日 00:00:00')
+ fdate = num2date(time,fcsttimes.units)
 verifdates.append(fdate.strftime('%Y%m%d%H'))
 print fcsthrs
 print verifdates
Modified: trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/basemap.py
===================================================================
--- trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/basemap.py	2007年12月04日 19:16:57 UTC (rev 4583)
+++ trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/basemap.py	2007年12月04日 19:18:03 UTC (rev 4584)
@@ -2858,28 +2858,21 @@
 f = pupynere._LocalFile(file,maskandscale)
 return f
 
-def num2date(times,units,unit_format='%Y-%m-%d %H:%M:%S',calendar='standard'):
+def num2date(times,units,calendar='standard'):
 """
 Return datetime objects given numeric time values. The units
 of the numeric time values are described by the units argument
- and the unit_format and calendar keywords.
+ and the calendar keyword.
 
 Arguments:
 
 times - numeric time values. Maximum resolution is 1 second.
+
 units - a string of the form '<time-units> since <reference time>'
 describing the time units. <time-units> can be days, hours, minutes
- or seconds. <reference-time> is the time origin, defined by the format
- keyword (see below). For example, a valid choice would be
- units='hours since 0001年01月01日 00:00:00'.
+ or seconds. <reference-time> is the time origin. A valid choice
+ would be units='hours since 0001年01月01日 00:00:00'.
 
- Keyword Arguments:
-
- format - a string describing a reference time. This string is converted 
- to a year,month,day,hour,minute,second tuple by strptime. The default 
- format is '%Y-%m-%d %H:%M:%S'. See the time.strptime docstring for other 
- valid formats.
-
 calendar - describes the calendar used in the time calculations. 
 All the values currently defined in the CF metadata convention 
 (http://cf-pcmdi.llnl.gov/documents/cf-conventions/) are supported.
@@ -2897,31 +2890,24 @@
 the weird dates in some calendars (such as '360_day' and 'all_leap'
 which don't exist in any real world calendar.
 """
- cdftime = netcdftime.utime(units,calendar=calendar,format=unit_format)
+ cdftime = netcdftime.utime(units,calendar=calendar)
 return cdftime.num2date(times)
 
-def date2num(dates,units,unit_format='%Y-%m-%d %H:%M:%S',calendar='standard'):
+def date2num(dates,units,calendar='standard'):
 """
 Return numeric time values given datetime objects. The units
 of the numeric time values are described by the units argument
- and the unit_format and calendar keywords.
+ and the calendar keyword.
 
 Arguments:
 
 dates - A datetime object or a sequence of datetime objects.
+
 units - a string of the form '<time-units> since <reference time>'
 describing the time units. <time-units> can be days, hours, minutes
- or seconds. <reference-time> is the time origin, defined by the format
- keyword (see below). For example, a valid choice would be
- units='hours since 0001年01月01日 00:00:00'.
+ or seconds. <reference-time> is the time origin. A valid choice
+ would be units='hours since 0001年01月01日 00:00:00'.
 
- Keyword Arguments:
-
- format - a string describing a reference time. This string is converted 
- to a year,month,day,hour,minute,second tuple by strptime. The default 
- format is '%Y-%m-%d %H:%M:%S'. See the time.strptime docstring for other 
- valid formats.
-
 calendar - describes the calendar used in the time calculations. 
 All the values currently defined in the CF metadata convention 
 (http://cf-pcmdi.llnl.gov/documents/cf-conventions/) are supported.
@@ -2932,5 +2918,5 @@
 
 The maximum resolution of the numeric time values is 1 second.
 """
- cdftime = netcdftime.utime(units,calendar=calendar,format=unit_format)
+ cdftime = netcdftime.utime(units,calendar=calendar)
 return cdftime.date2num(dates)
Added: trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/netcdftime.py
===================================================================
--- trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/netcdftime.py	 (rev 0)
+++ trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/netcdftime.py	2007年12月04日 19:18:03 UTC (rev 4584)
@@ -0,0 +1,859 @@
+"""
+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,format='%Y-%m-%d %H:%M:%S'):
+ """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"
+ # use strptime to parse the date string.
+ n = timestr.find('since')+6
+ #year,month,day,hour,minute,second,daywk,dayyr,tz = strptime(timestr[n:],format)
+ year,month,day,hour,minute,second = _parse_date(timestr[n:])
+ #if dayyr == -1: dayyr=1 # must have valid day of year for strftime to work
+ #return units, datetime(year, month, day, hour, minute, second, daywk, dayyr)
+ return units, 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,format='%Y-%m-%d %H:%M:%S',calendar='standard')}
+
+where 
+
+B{C{unit_string}} is a string of the form
+C{'time-units since <format>'} defining the time units.
+
+B{C{format}} is a string describing a reference time. This string is converted 
+to a year,month,day,hour,minute,second tuple by strptime. The default 
+format is C{'%Y-%m-%d %H:%M:%S'}. See the C{time.strptime} docstring for other 
+valid formats.
+
+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,format='%Y-%m-%d %H:%M:%S',calendar='standard'):
+ """
+@param unit_string: a string of the form
+C{'time-units since <format>'} defining the time units.
+
+@keyword format: a string describing a reference time. This string is converted 
+to a year,month,day,hour,minute,second tuple by strptime. The default 
+format is C{'%Y-%m-%d %H:%M:%S'}. See the C{time.strptime} docstring for other 
+valid formats.
+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. 
+ 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.
+
+@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, self.origin = _dateparse(unit_string,format=format)
+ 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.
+
+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)
+ if self.units in ['second','seconds']:
+ jdelta = jdelta*86400.
+ elif self.units in ['minute','minutes']:
+ jdelta = jdelta*1440.
+ elif self.units in ['hours','hours']:
+ jdelta = jdelta*24.
+ 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}.
+
+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 don't 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
+ if self.units in ['second','seconds']:
+ jdelta = time_value/86400.
+ elif self.units in ['minute','minutes']:
+ jdelta = time_value/1440.
+ elif self.units in ['hours','hours']:
+ jdelta = time_value/24.
+ elif self.units in ['day','days']:
+ jdelta = time_value
+ 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 datetime object.
+
+ 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 D'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 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)
+ 
+ # Instantiate timezone object.
+ #offset = int(c['ho'])*60 + int(c['mo'])
+ #tz = FixedOffset(offset, 'Unknown')
+
+ #return datetime(int(c['year']),
+ # int(c['month']),
+ # int(c['day']),
+ # int(c['hour']),
+ # int(c['min']),
+ # int(c['sec']),
+ # int(c['dsec']) * 100000,
+ # tz)
+ return int(c['year']),int(c['month']),int(c['day']),int(c['hour']),int(c['min']),int(c['sec'])
+ 
+ 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
Modified: trunk/toolkits/basemap/setup.py
===================================================================
--- trunk/toolkits/basemap/setup.py	2007年12月04日 19:16:57 UTC (rev 4583)
+++ trunk/toolkits/basemap/setup.py	2007年12月04日 19:18:03 UTC (rev 4584)
@@ -114,10 +114,6 @@
 packages = packages + ['httplib2']
 package_dirs['httlib2'] = os.path.join('lib','httplib2')
 
-# install netcdftime
-packages = packages + ['netcdftime']
-package_dirs['httlib2'] = os.path.join('lib','netcdftime')
-
 if 'setuptools' in sys.modules:
 # Are we running with setuptools?
 # if so, need to specify all the packages in heirarchy
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <js...@us...> - 2007年12月04日 19:16:58
Revision: 4583
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4583&view=rev
Author: jswhit
Date: 2007年12月04日 11:16:57 -0800 (2007年12月04日)
Log Message:
-----------
move 
Removed Paths:
-------------
 trunk/toolkits/basemap/lib/netcdftime/
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <js...@us...> - 2007年12月04日 18:48:07
Revision: 4582
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4582&view=rev
Author: jswhit
Date: 2007年12月04日 10:48:02 -0800 (2007年12月04日)
Log Message:
-----------
use num2date
Modified Paths:
--------------
 trunk/toolkits/basemap/examples/fcstmaps.py
Modified: trunk/toolkits/basemap/examples/fcstmaps.py
===================================================================
--- trunk/toolkits/basemap/examples/fcstmaps.py	2007年12月04日 18:37:40 UTC (rev 4581)
+++ trunk/toolkits/basemap/examples/fcstmaps.py	2007年12月04日 18:48:02 UTC (rev 4582)
@@ -6,35 +6,9 @@
 import sys
 from numpy import ma
 import datetime
-from matplotlib.toolkits.basemap import Basemap, NetCDFFile, addcyclic
+from matplotlib.toolkits.basemap import Basemap, NetCDFFile, addcyclic, num2date
 
 
-hrsgregstart = 13865688 # hrs from 00010101 to 15821015 in Julian calendar.
-# times in many datasets use mixed Gregorian/Julian calendar, datetime 
-# module uses a proleptic Gregorian calendar. So, I use datetime to compute
-# hours since start of Greg. calendar (15821015) and add this constant to
-# get hours since 1-Jan-0001 in the mixed Gregorian/Julian calendar.
-gregstart = datetime.datetime(1582,10,15) # datetime.datetime instance
-
-def dateto_hrs_since_day1CE(curdate):
- """given datetime.datetime instance, compute hours since 1-Jan-0001"""
- if curdate < gregstart:
- msg = 'date must be after start of gregorian calendar (15821015)!'
- raise ValueError, msg
- difftime = curdate-gregstart
- hrsdiff = 24*difftime.days + difftime.seconds/3600
- return hrsdiff+hrsgregstart
-
-def hrs_since_day1CE_todate(hrs):
- """return datetime.datetime instance given hours since 1-Jan-0001"""
- if hrs < 0.0:
- msg = "hrs must be positive!"
- raise ValueError, msg
- delta = datetime.timedelta(hours=1)
- hrs_sincegreg = hrs - hrsgregstart
- curdate = gregstart + hrs_sincegreg*delta
- return curdate
-
 # today's date is default.
 if len(sys.argv) > 1:
 YYYYMMDD = sys.argv[1]
@@ -62,14 +36,17 @@
 longitudes = data.variables['lon']
 fcsttimes = data.variables['time']
 times = fcsttimes[0:6] # first 6 forecast times.
+# change 0.0 to 00 at end of time units string
+# (so strptime will understand it).
+timeunits = fcsttimes.units[:-2]+'0'
 ntimes = len(times)
 # put forecast times in YYYYMMDDHH format.
 verifdates = []
 fcsthrs=[]
-print times
 for time in times:
+ print time, times[0]
 fcsthrs.append(int((time-times[0])*24))
- fdate = hrs_since_day1CE_todate(int(time*24.0)) 
+ fdate = num2date(time,'days since 0001年01月01日 00:00:00')
 verifdates.append(fdate.strftime('%Y%m%d%H'))
 print fcsthrs
 print verifdates
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <fer...@us...> - 2007年12月04日 18:37:52
Revision: 4581
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4581&view=rev
Author: fer_perez
Date: 2007年12月04日 10:37:40 -0800 (2007年12月04日)
Log Message:
-----------
Updates I forgot to commit yesterday...
Modified Paths:
--------------
 trunk/py4science/workbook/fft_imdenoise.tex
 trunk/py4science/workbook/quad_newton.tex
Added Paths:
-----------
 trunk/py4science/examples/stock_demo.py
Added: trunk/py4science/examples/stock_demo.py
===================================================================
--- trunk/py4science/examples/stock_demo.py	 (rev 0)
+++ trunk/py4science/examples/stock_demo.py	2007年12月04日 18:37:40 UTC (rev 4581)
@@ -0,0 +1,42 @@
+"""Simple data access and manipulation demo, using Yahoo Finance data."""
+
+# <demo> stop
+
+# Needed libraries
+import urllib
+import matplotlib.mlab as mlab # contains csv2rec
+import pylab as p
+
+# <demo> stop
+
+# Choose a stock, make the URL for it and download it to a local file
+ticker = 'CROX' # Boulder-based company Crocs
+
+url = 'http://ichart.finance.yahoo.com/table.csv?' +\
+ 's=%s&d=9&e=20&f=2007&g=d&a=0&b=29&c=1993&ignore=.csv'%ticker
+
+fname = '%s.csv'% ticker
+urllib.urlretrieve(url, fname)
+
+# <demo> stop
+
+# Now, make a Record Array out of this dataset:
+r = mlab.csv2rec(fname)
+
+# note that the CSV file is sorted most recent date first, so you will probably
+# want to sort the record array so most recent date is last
+r.sort()
+# A quick look at the data structure:
+print 'dtype:',r.dtype
+print 'shape:',r.shape
+
+# <demo> stop
+
+p.plot(r.date,r.adj_close)
+p.show()
+
+# <demo> stop
+# Now, make a slightly modified version of the file with cleaner formatting.
+# We'll use this later...
+mlab.rec2csv(r,'dap/myserver/data/sample.csv',
+ formatd={'date':mlab.FormatString()})
Modified: trunk/py4science/workbook/fft_imdenoise.tex
===================================================================
--- trunk/py4science/workbook/fft_imdenoise.tex	2007年12月04日 17:39:31 UTC (rev 4580)
+++ trunk/py4science/workbook/fft_imdenoise.tex	2007年12月04日 18:37:40 UTC (rev 4581)
@@ -1,50 +1,52 @@
 \section{FFT Image Denoising}
 \label{sec:fft_imdenoise}
 
-Convolution of an input with with a linear filter in the termporal or
-spatial domain is equivalent to multiplication by the fourier
-transforms of the input and the filter in the spectral domain. This
-provides a conceptually simple way to think about filtering: transform
-your signal into the frequency domain, dampen the frequencies you are
-not interested in by multiplying the frequency spectrum by the desired
-weights, and then inverse transform the multiplies spectrum back into
-the original domain. In the example below, we will simply set the
-weights of the frequencies we are uninterested in (the high frequency
-noise) to zero rather than dampening them with a smoothly varying
-function. Although this is not usually the best thing to do, since
-sharp edges in one domain usually introduce artifacts in another (eg
-high frequency ``ringing''), it is easy to do and sometimes provides
-satisfactory results.
+Convolution of an input with with a linear filter in the termporal or spatial
+domain is equivalent to multiplication by the fourier transforms of the input
+and the filter in the spectral domain. This provides a conceptually simple way
+to think about filtering: transform your signal into the frequency domain,
+dampen the frequencies you are not interested in by multiplying the frequency
+spectrum by the desired weights, and then apply the inverse transform to the
+modified spectrum, back into the original domain. In the example below, we
+will simply set the weights of the frequencies we are uninterested in (the high
+frequency noise) to zero rather than dampening them with a smoothly varying
+function. Although this is not usually the best thing to do, since sharp edges
+in one domain usually introduce artifacts in another (eg high frequency
+``ringing''), it is easy to do and sometimes provides satisfactory results.
 
-The image in the upper left panel of Figure~\ref{fig:fft_imdenoise} is
-a grayscale photo of the moon landing. There is a banded pattern of
-high frequency noise polluting the image. In the upper right panel we
-see the 2D spatial frequency spectrum. The FFT output in
-\texttt{scipy} is packed with the lower freqeuencies starting in the
-upper left, and proceeding to higher frequencies as one moves to the
-center of the spectrum (this is the most efficient way numerically to
-fill the output of the FFT algorithm). Because the input signal is
-real, the output spectrum is complex and symmetrical: the
-transformation values beyond the midpoint of the frequency spectrum
-(the Nyquist frequency) correspond to the values for negative
-frequencies and are simply the mirror image of the positive
-frequencies below the Nyquist (this is true for the 1D, 2D and ND FFTs
-in \texttt{numpy}).
+The image in the upper left panel of Figure~\ref{fig:fft_imdenoise} is a
+grayscale photo of the moon landing. There is a banded pattern of high
+frequency noise polluting the image. In the upper right panel we see the 2D
+spatial frequency spectrum. The FFT output in \texttt{scipy} is packed with
+the lower freqeuencies starting in the upper left, and proceeding to higher
+frequencies as one moves to the center of the spectrum (this is the most
+efficient way numerically to fill the output of the FFT algorithm). Because
+the input signal is real, the output spectrum is complex and symmetrical: the
+transformation values beyond the midpoint of the frequency spectrum (the
+Nyquist frequency) correspond to the values for negative frequencies and are
+simply the mirror image of the positive frequencies below the Nyquist (this is
+true for the 1D, 2D and ND FFTs in \texttt{numpy}).
 
-In this exercise we will compute the 2D spatial frequency spectra of
-the luminance image, zero out the high frequency components, and
-inverse transform back into the time domain. We can plot the input
-and output images with the \texttt{pylab.imshow} function, but the
-images must first be scaled to be withing the 0..1 luminance range.
-For best results, it helps to \textit{amplify} the image by some scale
-factor, and then \textit{clip} it to set all values greater than one
-to one. This serves to enhance contrast among the darker elements of
-the image, so it is not completely dominated by the brighter segments
+In this exercise we will compute the 2D spatial frequency spectra of the
+luminance image, zero out the high frequency components, and inverse transform
+back into the spatial domain. We can plot the input and output images with the
+\texttt{pylab.imshow} function, but the images must first be scaled to be
+within the 0..1 luminance range. For best results, it helps to
+\textit{amplify} the image by some scale factor, and then \textit{clip} it to
+set all values greater than one to one. This serves to enhance contrast among
+the darker elements of the image, so it is not completely dominated by the
+brighter segments
 
 \lstinputlisting[label=code:fft_imdenoise,caption={IGNORED}]{problems/fft_imdenoise.py}
 
 \begin{figure}
-\begin{centering}\includegraphics[width=4in]{fig/fft_imdenoise}\par\end{centering}
+ \begin{centering} \includegraphics[width=4in]{fig/fft_imdenoise} \par
+ \end{centering}
 
-\caption{\label{fig:fft_imdenoise}High freqeuency noise filtering of a 2D image in the Fourier domain. The upper panels show the original image (left) and spectral power (right) and the lower panels show the same data with the high frequency power set to zero. Although the input and output images are grayscale, you can provide colormaps to \texttt{pylab.imshow} to plot them in psudo-color}
+ \caption{\label{fig:fft_imdenoise}High freqeuency noise filtering of a 2D
+ image in the Fourier domain. The upper panels show the original image
+ (left) and spectral power (right) and the lower panels show the same data
+ with the high frequency power set to zero. Although the input and output
+ images are grayscale, you can provide colormaps to \texttt{pylab.imshow} to
+ plot them in psudo-color}
 \end{figure}
Modified: trunk/py4science/workbook/quad_newton.tex
===================================================================
--- trunk/py4science/workbook/quad_newton.tex	2007年12月04日 17:39:31 UTC (rev 4580)
+++ trunk/py4science/workbook/quad_newton.tex	2007年12月04日 18:37:40 UTC (rev 4581)
@@ -1,34 +1,35 @@
 \section{Newton's method}
 \label{sec:quad_newton}
 
-Consider the problem of solving for $t$ in\begin{equation}
-\int_{o}^{t}f(s)ds=u\end{equation}
- where $f(s)$ is a monotonically increasing function of $s$ and
-$u>0$.
+Consider the problem of solving for $t$ in
+\begin{equation}
+ \int_{o}^{t}f(s)ds=u
+\end{equation} 
+where $f(s)$ is a monotonically increasing function of $s$ and $u>0$.
 
-This problem can be simply solved if seen as a root finding question.
-Let\begin{equation}
-g(t)=\int_{o}^{t}f(s)ds-u,\end{equation}
+This problem can be simply solved if seen as a root finding question. Let
+\begin{equation}
+g(t)=\int_{o}^{t}f(s)ds-u,
+\end{equation}
 then we just need to find the root for $g(t),$ which is guaranteed
 to be unique given the conditions above. 
 
 The SciPy library includes an optimization package that contains a
 Newton-Raphson solver called \texttt{scipy.optimize.newton.} This
 solver can optionally take a known derivative for the function whose
-roots are being sought, and in this case the derivative is simply
-\begin{equation}
-\frac{dg(t)}{dt}=f(t).\end{equation}
+roots are being sought, and in this case the derivative can be trivially
+computed in exact form.
 
+For this exercise, implement the solution for the test function 
+\[
+f(t)=t\sin^{2}(t), 
+\]
+using 
+\[ 
+u=\frac{1}{4}. 
+\]
 
-For this exercise, implement the solution for the test function\[
-f(t)=t\sin^{2}(t),\]
- using \[
-u=\frac{1}{4}.\]
-
-
 The listing~\ref{code:quad_newton} contains a skeleton that
 includes for comparison the correct numerical value.
 
 \lstinputlisting[label=code:quad_newton,caption={IGNORED}]{problems/quad_newton.py}
-
-
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <js...@us...> - 2007年12月04日 17:39:37
Revision: 4580
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4580&view=rev
Author: jswhit
Date: 2007年12月04日 09:39:31 -0800 (2007年12月04日)
Log Message:
-----------
add netcdftime module
Added Paths:
-----------
 trunk/toolkits/basemap/lib/netcdftime/
 trunk/toolkits/basemap/lib/netcdftime/__init__.py
 trunk/toolkits/basemap/lib/netcdftime/netcdftime.py
 trunk/toolkits/basemap/lib/netcdftime/strftime.py
 trunk/toolkits/basemap/lib/netcdftime/strptime.py
Added: trunk/toolkits/basemap/lib/netcdftime/__init__.py
===================================================================
--- trunk/toolkits/basemap/lib/netcdftime/__init__.py	 (rev 0)
+++ trunk/toolkits/basemap/lib/netcdftime/__init__.py	2007年12月04日 17:39:31 UTC (rev 4580)
@@ -0,0 +1,2 @@
+from netcdftime import __doc__, __version__
+from netcdftime import *
Added: trunk/toolkits/basemap/lib/netcdftime/netcdftime.py
===================================================================
--- trunk/toolkits/basemap/lib/netcdftime/netcdftime.py	 (rev 0)
+++ trunk/toolkits/basemap/lib/netcdftime/netcdftime.py	2007年12月04日 17:39:31 UTC (rev 4580)
@@ -0,0 +1,737 @@
+"""
+Performs conversions of netCDF time coordinate data to/from datetime objects.
+"""
+import math
+import numpy
+from datetime import datetime as real_datetime
+from strptime import strptime
+from strftime import strftime
+
+_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.5.1'
+
+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,format='%Y-%m-%d %H:%M:%S'):
+ """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"
+ # use strptime to parse the date string.
+ n = timestr.find('since')+6
+ year,month,day,hour,minute,second,daywk,dayyr,tz = strptime(timestr[n:],format)
+ if dayyr == -1: dayyr=1 # must have valid day of year for strftime to work
+ return units, datetime(year, month, day, hour, minute, second, daywk, dayyr)
+
+class utime:
+ """
+Performs conversions of netCDF time coordinate
+data to/from datetime objects.
+
+To initialize: C{t = utime(unit_string,format='%Y-%m-%d %H:%M:%S',calendar='standard')}
+
+where 
+
+B{C{unit_string}} is a string of the form
+C{'time-units since <format>'} defining the time units.
+
+B{C{format}} is a string describing a reference time. This string is converted 
+to a year,month,day,hour,minute,second tuple by strptime. The default 
+format is C{'%Y-%m-%d %H:%M:%S'}. See the C{time.strptime} docstring for other 
+valid formats.
+
+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,format='%Y-%m-%d %H:%M:%S',calendar='standard'):
+ """
+@param unit_string: a string of the form
+C{'time-units since <format>'} defining the time units.
+
+@keyword format: a string describing a reference time. This string is converted 
+to a year,month,day,hour,minute,second tuple by strptime. The default 
+format is C{'%Y-%m-%d %H:%M:%S'}. See the C{time.strptime} docstring for other 
+valid formats.
+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. 
+ 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.
+
+@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, self.origin = _dateparse(unit_string,format=format)
+ 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.
+
+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)
+ if self.units in ['second','seconds']:
+ jdelta = jdelta*86400.
+ elif self.units in ['minute','minutes']:
+ jdelta = jdelta*1440.
+ elif self.units in ['hours','hours']:
+ jdelta = jdelta*24.
+ 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}.
+
+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 don't 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
+ if self.units in ['second','seconds']:
+ jdelta = time_value/86400.
+ elif self.units in ['minute','minutes']:
+ jdelta = time_value/1440.
+ elif self.units in ['hours','hours']:
+ jdelta = time_value/24.
+ elif self.units in ['day','days']:
+ jdelta = time_value
+ 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)
Added: trunk/toolkits/basemap/lib/netcdftime/strftime.py
===================================================================
--- trunk/toolkits/basemap/lib/netcdftime/strftime.py	 (rev 0)
+++ trunk/toolkits/basemap/lib/netcdftime/strftime.py	2007年12月04日 17:39:31 UTC (rev 4580)
@@ -0,0 +1,66 @@
+# Format a datetime through its full proleptic Gregorian date range.
+#
+# >>> strftime(datetime.date(1850, 8, 2), "%Y/%M/%d was a %A")
+# '1850/00/02 was a Friday'
+# >>>
+
+import re, time
+
+# 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/netcdftime/strptime.py
===================================================================
--- trunk/toolkits/basemap/lib/netcdftime/strptime.py	 (rev 0)
+++ trunk/toolkits/basemap/lib/netcdftime/strptime.py	2007年12月04日 17:39:31 UTC (rev 4580)
@@ -0,0 +1,438 @@
+"""Implementation of time.strptime().
+
+This version was written to work in Jython 2.1 . If you are running CPython
+2.2.x or newer, please use the version of Modules/timemodule.c and
+Lib/_strptime.py as found in CVS for CPython 2.3.x (CPython 2.2.0 requires
+defining ``True = 1; False = 0``).
+
+The main changes from the version in CVS for CPython 2.3.x is a caching
+mechanism which improves performance dramatically. LocaleTime().timezone is
+also a true set and thus does not require all the tweaking of using a version
+of Python lacking iterators. List comprehensions were also removed from the
+code. All date-calculating code was made conditional based on requiring
+datetime. If you need the calculations you can find the code in the Python CVS
+repository in the datetime code or in the dead-tree version of the 'Python
+Cookbook' under the recipe for strptime() (last recipe in the book).
+Subclassing of object and dict were also removed.
+
+$Last Edit: 2003年09月15日 $
+
+"""
+import time
+try:
+ import locale
+except ImportError:
+ class FakeLocale:
+
+ """Faked locale module (for Jython compatibility)."""
+
+ LC_TIME = None
+ 
+ def getlocale(self, whatever):
+ return (whatever, whatever)
+
+ locale = FakeLocale()
+ 
+import calendar
+from re import compile as re_compile
+from re import IGNORECASE
+# Get datetime from Python's CVS: /python/nondist/sandbox/datetime/
+#try:
+# from datetime import date as datetime_date
+#except ImportError:
+datetime_date = None
+from thread import allocate_lock as _thread_allocate_lock
+
+__author__ = "Brett Cannon"
+__email__ = "br...@py..."
+
+__all__ = ['strptime']
+
+# ----- START Code to replace Python 2.3 functionality -----
+True, False = 1, 0
+
+def sets_ImmutableSet(iterable):
+ sets_dict = {}
+ for item in iterable:
+ sets_dict[item] = None
+ return sets_dict
+
+def enumerate(iterable):
+ """Python 2.1-compatible enumerate function.
+
+ """
+ enum_list = []
+ count = 0
+ for item in iterable:
+ enum_list.append((count, item))
+ count += 1
+ return enum_list
+
+# ----- END Code to replace Python 2.3 functionality -----
+
+def _getlang():
+ # Figure out what the current language is set to.
+ return locale.getlocale(locale.LC_TIME)
+
+class LocaleTime:
+ """Stores and handles locale-specific information related to time.
+
+ ATTRIBUTES:
+ f_weekday -- full weekday names (7-item list)
+ a_weekday -- abbreviated weekday names (7-item list)
+ f_month -- full month names (13-item list; dummy value in [0], which
+ is added by code)
+ a_month -- abbreviated month names (13-item list, dummy value in
+ [0], which is added by code)
+ am_pm -- AM/PM representation (2-item list)
+ LC_date_time -- format string for date/time representation (string)
+ LC_date -- format string for date representation (string)
+ LC_time -- format string for time representation (string)
+ timezone -- daylight- and non-daylight-savings timezone representation
+ (2-item list of sets)
+ lang -- Language used by instance (2-item tuple)
+ """
+
+ def __init__(self):
+ """Set all attributes.
+ 
+ Order of methods called matters for dependency reasons.
+
+ The locale language is set at the offset and then checked again before
+ exiting. This is to make sure that the attributes were not set with a
+ mix of information from more than one locale. This would most likely
+ happen when using threads where one thread calls a locale-dependent
+ function while another thread changes the locale while the function in
+ the other thread is still running. Proper coding would call for
+ locks to prevent changing the locale while locale-dependent code is
+ running. The check here is done in case someone does not think about
+ doing this.
+
+ Only other possible issue is if someone changed the timezone and did
+ not call tz.tzset . That is an issue for the programmer, though,
+ since changing the timezone is worthless without that call.
+ 
+ """
+ self.lang = _getlang()
+ self.__calc_weekday()
+ self.__calc_month()
+ self.__calc_am_pm()
+ self.__calc_timezone()
+ self.__calc_date_time()
+ if _getlang() != self.lang:
+ raise ValueError("locale changed during initialization")
+
+ def __pad(self, seq, front):
+ # Add '' to seq to either the front (is True), else the back.
+ seq = list(seq)
+ if front:
+ seq.insert(0, '')
+ else:
+ seq.append('')
+ return seq
+
+ def __calc_weekday(self):
+ # Set self.a_weekday and self.f_weekday using the calendar
+ # module.
+ a_weekday = [calendar.day_abbr[i].lower() for i in range(7)]
+ f_weekday = [calendar.day_name[i].lower() for i in range(7)]
+ self.a_weekday = a_weekday
+ self.f_weekday = f_weekday
+
+ def __calc_month(self):
+ # Set self.f_month and self.a_month using the calendar module.
+ a_month = [calendar.month_abbr[i].lower() for i in range(13)]
+ f_month = [calendar.month_name[i].lower() for i in range(13)]
+ self.a_month = a_month
+ self.f_month = f_month
+
+ def __calc_am_pm(self):
+ # Set self.am_pm by using time.strftime().
+
+ # The magic date (1999,3,17,hour,44,55,2,76,0) is not really that
+ # magical; just happened to have used it everywhere else where a
+ # static date was needed.
+ am_pm = []
+ for hour in (01,22):
+ time_tuple = (1999,3,17,hour,44,55,2,76,0)
+ am_pm.append(time.strftime("%p", time_tuple).lower())
+ self.am_pm = am_pm
+
+ def __calc_date_time(self):
+ # Set self.date_time, self.date, & self.time by using
+ # time.strftime().
+
+ # Use (1999,3,17,22,44,55,2,76,0) for magic date because the amount of
+ # overloaded numbers is minimized. The order in which searches for
+ # values within the format string is very important; it eliminates
+ # possible ambiguity for what something represents.
+ time_tuple = (1999,3,17,22,44,55,2,76,0)
+ date_time = [None, None, None]
+ date_time[0] = time.strftime("%c", time_tuple).lower()
+ date_time[1] = time.strftime("%x", time_tuple).lower()
+ date_time[2] = time.strftime("%X", time_tuple).lower()
+ replacement_pairs = [('%', '%%'), (self.f_weekday[2], '%A'),
+ (self.f_month[3], '%B'), (self.a_weekday[2], '%a'),
+ (self.a_month[3], '%b'), (self.am_pm[1], '%p'),
+ ('1999', '%Y'), ('99', '%y'), ('22', '%H'),
+ ('44', '%M'), ('55', '%S'), ('76', '%j'),
+ ('17', '%d'), ('03', '%m'), ('3', '%m'),
+ # '3' needed for when no leading zero.
+ ('2', '%w'), ('10', '%I')]
+ for tz_values in self.timezone:
+ for tz in tz_values.keys():
+ replacement_pairs.append((tz, "%Z"))
+ for offset,directive in ((0,'%c'), (1,'%x'), (2,'%X')):
+ current_format = date_time[offset]
+ for old, new in replacement_pairs:
+ # Must deal with possible lack of locale info
+ # manifesting itself as the empty string (e.g., Swedish's
+ # lack of AM/PM info) or a platform returning a tuple of empty
+ # strings (e.g., MacOS 9 having timezone as ('','')).
+ if old:
+ current_format = current_format.replace(old, new)
+ time_tuple = (1999,1,3,1,1,1,6,3,0)
+ if time.strftime(directive, time_tuple).find('00'):
+ U_W = '%U'
+ else:
+ U_W = '%W'
+ date_time[offset] = current_format.replace('11', U_W)
+ self.LC_date_time = date_time[0]
+ self.LC_date = date_time[1]
+ self.LC_time = date_time[2] 
+
+ def __calc_timezone(self):
+ # Set self.timezone by using time.tzname.
+ # Do not worry about possibility of time.tzname[0] == timetzname[1]
+ # and time.daylight; handle that in strptime .
+ try:
+ time.tzset()
+ except AttributeError:
+ pass
+ no_saving = sets_ImmutableSet(["utc", "gmt", time.tzname[0].lower()])
+ if time.daylight:
+ has_saving = sets_ImmutableSet([time.tzname[1].lower()])
+ else:
+ has_saving = sets_ImmutableSet()
+ self.timezone = (no_saving, has_saving)
+
+
+import UserDict
+class TimeRE(UserDict.UserDict):
+ """Handle conversion from format directives to regexes."""
+
+ def __init__(self, locale_time=None):
+ """Create keys/values.
+ 
+ Order of execution is important for dependency reasons.
+ 
+ """
+ if locale_time:
+ self.locale_time = locale_time
+ else:
+ self.locale_time = LocaleTime()
+ base = UserDict.UserDict
+ base.__init__(self, {
+ # The " \d" part of the regex is to make %c from ANSI C work
+ 'd': r"(?P<d>3[0-1]|[1-2]\d|0[1-9]|[1-9]| [1-9])",
+ 'H': r"(?P<H>2[0-3]|[0-1]\d|\d)",
+ 'I': r"(?P<I>1[0-2]|0[1-9]|[1-9])",
+'j': r"(?P<j>36[0-6]|3[0-5]\d|[1-2]\d\d|0[1-9]\d|00[1-9]|[1-9]\d|0[1-9]|[1-9])",
+ 'm': r"(?P<m>1[0-2]|0[1-9]|[1-9])",
+ 'M': r"(?P<M>[0-5]\d|\d)",
+ 'S': r"(?P<S>6[0-1]|[0-5]\d|\d)",
+ 'U': r"(?P<U>5[0-3]|[0-4]\d|\d)",
+ 'w': r"(?P<w>[0-6])",
+ # W is set below by using 'U'
+ 'y': r"(?P<y>\d\d)",
+ #XXX: Does 'Y' need to worry about having less or more than
+ # 4 digits?
+ 'Y': r"(?P<Y>\d\d\d\d)",
+ 'A': self.__seqToRE(self.locale_time.f_weekday, 'A'),
+ 'a': self.__seqToRE(self.locale_time.a_weekday, 'a'),
+ 'B': self.__seqToRE(self.locale_time.f_month[1:], 'B'),
+ 'b': self.__seqToRE(self.locale_time.a_month[1:], 'b'),
+ 'p': self.__seqToRE(self.locale_time.am_pm, 'p'),
+ '%': '%'})
+ temp_list = []
+ for tz_names in self.locale_time.timezone:
+ for tz in tz_names.keys():
+ temp_list.append(tz)
+ base.__setitem__(self, 'Z', self.__seqToRE(temp_list, 'Z'))
+ base.__setitem__(self, 'W', base.__getitem__(self, 'U'))
+ base.__setitem__(self, 'c', self.pattern(self.locale_time.LC_date_time))
+ base.__setitem__(self, 'x', self.pattern(self.locale_time.LC_date))
+ base.__setitem__(self, 'X', self.pattern(self.locale_time.LC_time))
+
+ def __seqToRE(self, to_convert, directive):
+ """Convert a list to a regex string for matching a directive.
+ 
+ Want possible matching values to be from longest to shortest. This
+ prevents the possibility of a match occuring for a value that also
+ a substring of a larger value that should have matched (e.g., 'abc'
+ matching when 'abcdef' should have been the match).
+ 
+ """
+ for value in to_convert:
+ if value != '':
+ break
+ else:
+ return ''
+ to_sort = [(len(item), item) for item in to_convert]
+ to_sort.sort()
+ to_sort.reverse()
+ to_convert = [item for length, item in to_sort]
+ regex = '|'.join(to_convert)
+ regex = '(?P<%s>%s' % (directive, regex)
+ return '%s)' % regex
+
+ def pattern(self, format):
+ """Return regex pattern for the format string.
+
+ Need to make sure that any characters that might be interpreted as
+ regex syntax are escaped.
+
+ """
+ processed_format = ''
+ # The sub() call escapes all characters that might be misconstrued
+ # as regex syntax.
+ regex_chars = re_compile(r"([\\.^$*+?{}\[\]|])")
+ format = regex_chars.sub(r"\\1円", format)
+ whitespace_replacement = re_compile('\s+')
+ format = whitespace_replacement.sub('\s*', format)
+ while format.find('%') != -1:
+ directive_index = format.index('%')+1
+ processed_format = "%s%s%s" % (processed_format,
+ format[:directive_index-1],
+ self[format[directive_index]])
+ format = format[directive_index+1:]
+ return "%s%s" % (processed_format, format)
+
+ def compile(self, format):
+ """Return a compiled re object for the format string."""
+ return re_compile(self.pattern(format), IGNORECASE)
+
+_cache_lock = _thread_allocate_lock()
+# DO NOT modify _TimeRE_cache or _regex_cache without acquiring the cache lock
+# first!
+_TimeRE_cache = TimeRE()
+_CACHE_MAX_SIZE = 5 # Max number of regexes stored in _regex_cache
+_regex_cache = {}
+
+def strptime(data_string, format="%a %b %d %H:%M:%S %Y"):
+ """Return a time struct based on the input string and the format string."""
+ global _TimeRE_cache
+ _cache_lock.acquire()
+ try:
+ time_re = _TimeRE_cache
+ locale_time = time_re.locale_time
+ if _getlang() != locale_time.lang:
+ _TimeRE_cache = TimeRE()
+ if len(_regex_cache) > _CACHE_MAX_SIZE:
+ _regex_cache.clear()
+ format_regex = _regex_cache.get(format)
+ if not format_regex:
+ format_regex = time_re.compile(format)
+ _regex_cache[format] = format_regex
+ finally:
+ _cache_lock.release()
+ found = format_regex.match(data_string)
+ if not found:
+ raise ValueError("time data did not match format: data=%s fmt=%s" %
+ (data_string, format))
+ if len(data_string) != found.end():
+ raise ValueError("unconverted data remains: %s" %
+ data_string[found.end():])
+ year = 1900
+ month = day = 1
+ hour = minute = second = 0
+ tz = -1
+ # weekday and julian defaulted to -1 so as to signal need to calculate values
+ weekday = julian = -1
+ found_dict = found.groupdict()
+ for group_key in found_dict.keys():
+ if group_key == 'y':
+ year = int(found_dict['y'])
+ # Open Group specification for strptime() states that a %y
+ #value in the range of [00, 68] is in the century 2000, while
+ #[69,99] is in the century 1900
+ if year <= 68:
+ year += 2000
+ else:
+ year += 1900
+ elif group_key == 'Y':
+ year = int(found_dict['Y'])
+ elif group_key == 'm':
+ month = int(found_dict['m'])
+ elif group_key == 'B':
+ month = locale_time.f_month.index(found_dict['B'].lower())
+ elif group_key == 'b':
+ month = locale_time.a_month.index(found_dict['b'].lower())
+ elif group_key == 'd':
+ day = int(found_dict['d'])
+ elif group_key == 'H':
+ hour = int(found_dict['H'])
+ elif group_key == 'I':
+ hour = int(found_dict['I'])
+ ampm = found_dict.get('p', '').lower()
+ # If there was no AM/PM indicator, we'll treat this like AM
+ if ampm in ('', locale_time.am_pm[0]):
+ # We're in AM so the hour is correct unless we're
+ # looking at 12 midnight.
+ # 12 midnight == 12 AM == hour 0
+ if hour == 12:
+ hour = 0
+ elif ampm == locale_time.am_pm[1]:
+ # We're in PM so we need to add 12 to the hour unless
+ # we're looking at 12 noon.
+ # 12 noon == 12 PM == hour 12
+ if hour != 12:
+ hour += 12
+ elif group_key == 'M':
+ minute = int(found_dict['M'])
+ elif group_key == 'S':
+ second = int(found_dict['S'])
+ elif group_key == 'A':
+ weekday = locale_time.f_weekday.index(found_dict['A'].lower())
+ elif group_key == 'a':
+ weekday = locale_time.a_weekday.index(found_dict['a'].lower())
+ elif group_key == 'w':
+ weekday = int(found_dict['w'])
+ if weekday == 0:
+ weekday = 6
+ else:
+ weekday -= 1
+ elif group_key == 'j':
+ julian = int(found_dict['j'])
+ elif group_key == 'Z':
+ # Since -1 is default value only need to worry about setting tz if
+ # it can be something other than -1.
+ found_zone = found_dict['Z'].lower()
+ for value, tz_values in enumerate(locale_time.timezone):
+ if found_zone in tz_values:
+ # Deal with bad locale setup where timezone names are the
+ # same and yet time.daylight is true; too ambiguous to
+ # be able to tell what timezone has daylight savings
+ if time.tzname[0] == time.tzname[1] and \
+ time.daylight:
+ break
+ else:
+ tz = value
+ break
+ # Cannot pre-calculate datetime_date() since can change in Julian
+ #calculation and thus could have different value for the day of the week
+ #calculation
+ if datetime_date:
+ if julian == -1:
+ # Need to add 1 to result since first day of the year is 1, not 0.
+ julian = datetime_date(year, month, day).toordinal() - \
+ datetime_date(year, 1, 1).toordinal() + 1
+ else: # Assume that if they bothered to include Julian day it will
+ #be accurate
+ datetime_result = datetime_date.fromordinal((julian - 1) + datetime_date(year, 1, 1).toordinal())
+ year = datetime_result.year
+ month = datetime_result.month
+ day = datetime_result.day
+ if weekday == -1:
+ weekday = datetime_date(year, month, day).weekday()
+ return (year, month, day, hour, minute, second, weekday, julian, tz)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <js...@us...> - 2007年12月04日 17:36:58
Revision: 4579
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4579&view=rev
Author: jswhit
Date: 2007年12月04日 09:36:55 -0800 (2007年12月04日)
Log Message:
-----------
add date2num and num2date functions to basemap namespace.
Modified Paths:
--------------
 trunk/toolkits/basemap/Changelog
 trunk/toolkits/basemap/MANIFEST.in
 trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/basemap.py
 trunk/toolkits/basemap/setup.py
Modified: trunk/toolkits/basemap/Changelog
===================================================================
--- trunk/toolkits/basemap/Changelog	2007年12月04日 16:06:20 UTC (rev 4578)
+++ trunk/toolkits/basemap/Changelog	2007年12月04日 17:36:55 UTC (rev 4579)
@@ -1,3 +1,5 @@
+ * added num2date and date2num functions, which use 
+		 included netcdftime module.
 version 0.9.8 (svn revision 4526)
 * fixes for filling continents in orthographic projection.
 * added 'maskandscale' kwarg to NetCDFFile to
Modified: trunk/toolkits/basemap/MANIFEST.in
===================================================================
--- trunk/toolkits/basemap/MANIFEST.in	2007年12月04日 16:06:20 UTC (rev 4578)
+++ trunk/toolkits/basemap/MANIFEST.in	2007年12月04日 17:36:55 UTC (rev 4579)
@@ -78,6 +78,7 @@
 recursive-include lib/httplib2 *
 recursive-include lib/dbflib *
 recursive-include lib/shapelib *
+recursive-include lib/netcdftime *
 include lib/matplotlib/toolkits/basemap/data/5minmask.bin
 include lib/matplotlib/toolkits/basemap/data/GL27
 include lib/matplotlib/toolkits/basemap/data/countries_c.dat
Modified: trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/basemap.py
===================================================================
--- trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/basemap.py	2007年12月04日 16:06:20 UTC (rev 4578)
+++ trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/basemap.py	2007年12月04日 17:36:55 UTC (rev 4579)
@@ -28,7 +28,7 @@
 from numpy import linspace, squeeze, ma
 from matplotlib.cbook import is_scalar, dedent
 from shapelib import ShapeFile
-import _geos, pupynere
+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'])
@@ -2857,3 +2857,80 @@
 else:
 f = pupynere._LocalFile(file,maskandscale)
 return f
+
+def num2date(times,units,unit_format='%Y-%m-%d %H:%M:%S',calendar='standard'):
+ """
+ Return datetime objects given numeric time values. The units
+ of the numeric time values are described by the units argument
+ and the unit_format and calendar keywords.
+
+ Arguments:
+
+ times - numeric time values. Maximum resolution is 1 second.
+ units - a string of the form '<time-units> since <reference time>'
+ describing the time units. <time-units> can be days, hours, minutes
+ or seconds. <reference-time> is the time origin, defined by the format
+ keyword (see below). For example, a valid choice would be
+ units='hours since 0001年01月01日 00:00:00'.
+
+ Keyword Arguments:
+
+ format - a string describing a reference time. This string is converted 
+ to a year,month,day,hour,minute,second tuple by strptime. The default 
+ format is '%Y-%m-%d %H:%M:%S'. See the time.strptime docstring for other 
+ valid formats.
+
+ calendar - describes the calendar used in the time calculations. 
+ All the values currently defined in the CF metadata convention 
+ (http://cf-pcmdi.llnl.gov/documents/cf-conventions/) are supported.
+ Valid calendars 'standard', 'gregorian', 'proleptic_gregorian'
+ 'noleap', '365_day', '360_day', 'julian'. Default is 'standard'.
+
+ Returns a datetime instance, or an array of datetime instances.
+
+ The datetime instances returned are 'real' python datetime 
+ objects if the date falls in the Gregorian calendar (i.e. 
+ calendar='proleptic_gregorian', or calendar = 'standard' or 'gregorian'
+ and the date is after 1582年10月15日). Otherwise, they are 'phony' datetime 
+ objects which support some but not all the methods of 'real' python
+ datetime objects. This is because the python datetime module cannot
+ the weird dates in some calendars (such as '360_day' and 'all_leap'
+ which don't exist in any real world calendar.
+ """
+ cdftime = netcdftime.utime(units,calendar=calendar,format=unit_format)
+ return cdftime.num2date(times)
+
+def date2num(dates,units,unit_format='%Y-%m-%d %H:%M:%S',calendar='standard'):
+ """
+ Return numeric time values given datetime objects. The units
+ of the numeric time values are described by the units argument
+ and the unit_format and calendar keywords.
+
+ Arguments:
+
+ dates - A datetime object or a sequence of datetime objects.
+ units - a string of the form '<time-units> since <reference time>'
+ describing the time units. <time-units> can be days, hours, minutes
+ or seconds. <reference-time> is the time origin, defined by the format
+ keyword (see below). For example, a valid choice would be
+ units='hours since 0001年01月01日 00:00:00'.
+
+ Keyword Arguments:
+
+ format - a string describing a reference time. This string is converted 
+ to a year,month,day,hour,minute,second tuple by strptime. The default 
+ format is '%Y-%m-%d %H:%M:%S'. See the time.strptime docstring for other 
+ valid formats.
+
+ calendar - describes the calendar used in the time calculations. 
+ All the values currently defined in the CF metadata convention 
+ (http://cf-pcmdi.llnl.gov/documents/cf-conventions/) are supported.
+ Valid calendars 'standard', 'gregorian', 'proleptic_gregorian'
+ 'noleap', '365_day', '360_day', 'julian'. Default is 'standard'.
+
+ Returns a numeric time value, or an array of numeric time values.
+
+ The maximum resolution of the numeric time values is 1 second.
+ """
+ cdftime = netcdftime.utime(units,calendar=calendar,format=unit_format)
+ return cdftime.date2num(dates)
Modified: trunk/toolkits/basemap/setup.py
===================================================================
--- trunk/toolkits/basemap/setup.py	2007年12月04日 16:06:20 UTC (rev 4578)
+++ trunk/toolkits/basemap/setup.py	2007年12月04日 17:36:55 UTC (rev 4579)
@@ -114,6 +114,10 @@
 packages = packages + ['httplib2']
 package_dirs['httlib2'] = os.path.join('lib','httplib2')
 
+# install netcdftime
+packages = packages + ['netcdftime']
+package_dirs['httlib2'] = os.path.join('lib','netcdftime')
+
 if 'setuptools' in sys.modules:
 # Are we running with setuptools?
 # if so, need to specify all the packages in heirarchy
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2007年12月04日 16:06:30
Revision: 4578
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4578&view=rev
Author: mdboom
Date: 2007年12月04日 08:06:20 -0800 (2007年12月04日)
Log Message:
-----------
Oops in last commit
Modified Paths:
--------------
 branches/transforms/lib/matplotlib/axes.py
Modified: branches/transforms/lib/matplotlib/axes.py
===================================================================
--- branches/transforms/lib/matplotlib/axes.py	2007年12月04日 16:01:06 UTC (rev 4577)
+++ branches/transforms/lib/matplotlib/axes.py	2007年12月04日 16:06:20 UTC (rev 4578)
@@ -21,7 +21,6 @@
 from matplotlib import lines as mlines
 from matplotlib import mlab
 from matplotlib import patches as mpatches
-from matplotlib import path as mpath
 from matplotlib import quiver as mquiver
 from matplotlib import scale as mscale
 from matplotlib import table as mtable
@@ -771,14 +770,13 @@
 
 self.grid(self._gridOn)
 props = font_manager.FontProperties(size=rcParams['axes.titlesize'])
- self.titleOffsetTrans = mtransforms.Affine2D()
- self.title = mtext.Text(
- x=0.5, y=1.00, text='',
+ self.title = mtext.Text(
+ x=0.5, y=1.02, text='',
 fontproperties=props,
 verticalalignment='bottom',
 horizontalalignment='center',
 )
- self.title.set_transform(self.transAxes + self.titleOffsetTrans)
+ self.title.set_transform(self.transAxes)
 self.title.set_clip_box(None)
 
 self._set_artist_props(self.title)
@@ -802,8 +800,6 @@
 self.xaxis.set_clip_path(self.axesPatch)
 self.yaxis.set_clip_path(self.axesPatch)
 
- self.titleOffsetTrans.clear()
-
 def clear(self):
 'clear the axes'
 self.cla()
@@ -909,14 +905,14 @@
 ysize = max(math.fabs(ymax-ymin), 1e-30)
 return ysize/xsize
 
- def apply_aspect(self, currentPosition):
+ def apply_aspect(self):
 '''
 Use self._aspect and self._adjustable to modify the
 axes box or the view limits.
 '''
 aspect = self.get_aspect()
 if aspect == 'auto':
- self.set_position(currentPosition, 'active')
+ self.set_position( self._originalPosition , 'active')
 return
 
 if aspect == 'equal':
@@ -933,7 +929,7 @@
 fig_aspect = figH/figW
 if self._adjustable == 'box':
 box_aspect = A * self.get_data_ratio()
- pb = currentPosition.frozen()
+ pb = self._originalPosition.frozen()
 pb1 = pb.shrunk_to_aspect(box_aspect, pb, fig_aspect)
 self.set_position(pb1.anchored(self.get_anchor(), pb), 'active')
 return
@@ -1141,7 +1137,7 @@
 self._set_artist_props(collection)
 collection.set_clip_path(self.axesPatch)
 if autolim:
- if len(collection._paths):
+ if collection._paths and len(collection._paths):
 self.update_datalim(collection.get_datalim(self.transData))
 collection._remove_method = lambda h: self.collections.remove(h)
 
@@ -1293,48 +1289,25 @@
 YL = ylocator.autoscale()
 self.set_ybound(YL)
 
- def adjust_for_axis_text(self, renderer):
- pad_pixels = rcParams['xtick.major.pad'] * self.figure.dpi / 72.0
- inverse_transFigure = self.figure.transFigure.inverted()
- t_text, b_text = self.xaxis.get_text_heights(renderer)
- l_text, r_text = self.yaxis.get_text_widths(renderer)
- title_height = self.title.get_window_extent(renderer).height
- title_height += pad_pixels * 2.0
- original_t_text = t_text
-
- ((l_text, t_text),
- (r_text, b_text),
- (dummy, title_height)) = inverse_transFigure.transform(
- ((l_text, t_text),
- (r_text, b_text),
- (0.0, title_height)))
- x0, y0, x1, y1 = self.get_position(True).extents
- # Adjust the title
- self.titleOffsetTrans.clear().translate(
- 0, original_t_text + pad_pixels * 2.0)
- return mtransforms.Bbox.from_extents(
- x0 + l_text, y0 + b_text, x1 - r_text,
- y1 - t_text - title_height)
-
 #### Drawing
 def draw(self, renderer=None, inframe=False):
 "Draw everything (plot lines, axes, labels)"
- if renderer is None:
+	if renderer is None:
 renderer = self._cachedRenderer
 
 if renderer is None:
 raise RuntimeError('No renderer defined')
 if not self.get_visible(): return
 renderer.open_group('axes')
+ self.apply_aspect()
 
- currentPosition = self.adjust_for_axis_text(renderer)
- self.apply_aspect(currentPosition)
-
 if self.axison and self._frameon:
 self.axesPatch.draw(renderer)
 
 artists = []
 
+
+
 if len(self.images)<=1 or renderer.option_image_nocomposite():
 for im in self.images:
 im.draw(renderer)
@@ -1346,6 +1319,7 @@
 ims = [(im.make_image(mag),0,0)
 for im in self.images if im.get_visible()]
 
+
 im = mimage.from_images(self.bbox.height*mag,
 self.bbox.width*mag,
 ims)
@@ -1386,14 +1360,6 @@
 a.draw(renderer)
 
 renderer.close_group('axes')
-
-# ### DEBUGGING
-# gc = renderer.new_gc()
-# gc.set_linewidth(2.0)
-# x0, y0, x1, y1 = self.get_position(True).extents
-# renderer.draw_path(gc, mpath.Path(
-# [[x0, y0], [x0, y1], [x1, y1], [x1, y0], [x0, y0]]),
-# self.figure.transFigure)
 self._cachedRenderer = renderer
 
 def draw_artist(self, a):
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2007年12月04日 16:01:11
Revision: 4577
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4577&view=rev
Author: mdboom
Date: 2007年12月04日 08:01:06 -0800 (2007年12月04日)
Log Message:
-----------
Fix bug when collection is empty.
Modified Paths:
--------------
 branches/transforms/lib/matplotlib/axes.py
Modified: branches/transforms/lib/matplotlib/axes.py
===================================================================
--- branches/transforms/lib/matplotlib/axes.py	2007年12月04日 14:38:48 UTC (rev 4576)
+++ branches/transforms/lib/matplotlib/axes.py	2007年12月04日 16:01:06 UTC (rev 4577)
@@ -21,6 +21,7 @@
 from matplotlib import lines as mlines
 from matplotlib import mlab
 from matplotlib import patches as mpatches
+from matplotlib import path as mpath
 from matplotlib import quiver as mquiver
 from matplotlib import scale as mscale
 from matplotlib import table as mtable
@@ -770,13 +771,14 @@
 
 self.grid(self._gridOn)
 props = font_manager.FontProperties(size=rcParams['axes.titlesize'])
- self.title = mtext.Text(
- x=0.5, y=1.02, text='',
+ self.titleOffsetTrans = mtransforms.Affine2D()
+ self.title = mtext.Text(
+ x=0.5, y=1.00, text='',
 fontproperties=props,
 verticalalignment='bottom',
 horizontalalignment='center',
 )
- self.title.set_transform(self.transAxes)
+ self.title.set_transform(self.transAxes + self.titleOffsetTrans)
 self.title.set_clip_box(None)
 
 self._set_artist_props(self.title)
@@ -800,6 +802,8 @@
 self.xaxis.set_clip_path(self.axesPatch)
 self.yaxis.set_clip_path(self.axesPatch)
 
+ self.titleOffsetTrans.clear()
+
 def clear(self):
 'clear the axes'
 self.cla()
@@ -905,14 +909,14 @@
 ysize = max(math.fabs(ymax-ymin), 1e-30)
 return ysize/xsize
 
- def apply_aspect(self):
+ def apply_aspect(self, currentPosition):
 '''
 Use self._aspect and self._adjustable to modify the
 axes box or the view limits.
 '''
 aspect = self.get_aspect()
 if aspect == 'auto':
- self.set_position( self._originalPosition , 'active')
+ self.set_position(currentPosition, 'active')
 return
 
 if aspect == 'equal':
@@ -929,7 +933,7 @@
 fig_aspect = figH/figW
 if self._adjustable == 'box':
 box_aspect = A * self.get_data_ratio()
- pb = self._originalPosition.frozen()
+ pb = currentPosition.frozen()
 pb1 = pb.shrunk_to_aspect(box_aspect, pb, fig_aspect)
 self.set_position(pb1.anchored(self.get_anchor(), pb), 'active')
 return
@@ -1289,25 +1293,48 @@
 YL = ylocator.autoscale()
 self.set_ybound(YL)
 
+ def adjust_for_axis_text(self, renderer):
+ pad_pixels = rcParams['xtick.major.pad'] * self.figure.dpi / 72.0
+ inverse_transFigure = self.figure.transFigure.inverted()
+ t_text, b_text = self.xaxis.get_text_heights(renderer)
+ l_text, r_text = self.yaxis.get_text_widths(renderer)
+ title_height = self.title.get_window_extent(renderer).height
+ title_height += pad_pixels * 2.0
+ original_t_text = t_text
+
+ ((l_text, t_text),
+ (r_text, b_text),
+ (dummy, title_height)) = inverse_transFigure.transform(
+ ((l_text, t_text),
+ (r_text, b_text),
+ (0.0, title_height)))
+ x0, y0, x1, y1 = self.get_position(True).extents
+ # Adjust the title
+ self.titleOffsetTrans.clear().translate(
+ 0, original_t_text + pad_pixels * 2.0)
+ return mtransforms.Bbox.from_extents(
+ x0 + l_text, y0 + b_text, x1 - r_text,
+ y1 - t_text - title_height)
+
 #### Drawing
 def draw(self, renderer=None, inframe=False):
 "Draw everything (plot lines, axes, labels)"
-	if renderer is None:
+ if renderer is None:
 renderer = self._cachedRenderer
 
 if renderer is None:
 raise RuntimeError('No renderer defined')
 if not self.get_visible(): return
 renderer.open_group('axes')
- self.apply_aspect()
 
+ currentPosition = self.adjust_for_axis_text(renderer)
+ self.apply_aspect(currentPosition)
+
 if self.axison and self._frameon:
 self.axesPatch.draw(renderer)
 
 artists = []
 
-
-
 if len(self.images)<=1 or renderer.option_image_nocomposite():
 for im in self.images:
 im.draw(renderer)
@@ -1319,7 +1346,6 @@
 ims = [(im.make_image(mag),0,0)
 for im in self.images if im.get_visible()]
 
-
 im = mimage.from_images(self.bbox.height*mag,
 self.bbox.width*mag,
 ims)
@@ -1360,6 +1386,14 @@
 a.draw(renderer)
 
 renderer.close_group('axes')
+
+# ### DEBUGGING
+# gc = renderer.new_gc()
+# gc.set_linewidth(2.0)
+# x0, y0, x1, y1 = self.get_position(True).extents
+# renderer.draw_path(gc, mpath.Path(
+# [[x0, y0], [x0, y1], [x1, y1], [x1, y0], [x0, y0]]),
+# self.figure.transFigure)
 self._cachedRenderer = renderer
 
 def draw_artist(self, a):
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <jd...@us...> - 2007年12月04日 14:38:53
Revision: 4576
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4576&view=rev
Author: jdh2358
Date: 2007年12月04日 06:38:48 -0800 (2007年12月04日)
Log Message:
-----------
added additional lines to MANIFEST.in
Modified Paths:
--------------
 trunk/matplotlib/CODING_GUIDE
 trunk/matplotlib/MANIFEST.in
 trunk/matplotlib/examples/poly_editor.py
Modified: trunk/matplotlib/CODING_GUIDE
===================================================================
--- trunk/matplotlib/CODING_GUIDE	2007年12月04日 13:12:09 UTC (rev 4575)
+++ trunk/matplotlib/CODING_GUIDE	2007年12月04日 14:38:48 UTC (rev 4576)
@@ -39,8 +39,11 @@
 * If you have altered extension code, do you pass
 unit/memleak_hawaii.py?
 
+ * if you have added new files or directories, or reorganized
+ existing ones, are the new files included in the match patterns in
+ MANIFEST.in. This file determines what goes into the src
+ distribution of the mpl build.
 
-
 == Importing and name spaces ==
 
 For numpy, use:
Modified: trunk/matplotlib/MANIFEST.in
===================================================================
--- trunk/matplotlib/MANIFEST.in	2007年12月04日 13:12:09 UTC (rev 4575)
+++ trunk/matplotlib/MANIFEST.in	2007年12月04日 14:38:48 UTC (rev 4576)
@@ -5,8 +5,13 @@
 include __init__.py setupext.py setup.py setupegg.py makeswig.py
 include examples/data/*
 include lib/matplotlib/toolkits
+include lib/matplotlib/mpl-data/matplotlib.conf
+include lib/matplotlib/mpl-data/matplotlib.conf.template
+include lib/matplotlib/mpl-data/lineprops.glade
+include lib/matplotlib/mpl-data/matplotlibrc
 include lib/matplotlib/mpl-data/images/*
 include lib/matplotlib/mpl-data/fonts/ttf/*
+include lib/matplotlib/mpl-data/fonts/pdfcorefonts/*
 include lib/matplotlib/mpl-data/fonts/afm/*
 recursive-include license LICENSE*
 recursive-include examples README *.py
Modified: trunk/matplotlib/examples/poly_editor.py
===================================================================
--- trunk/matplotlib/examples/poly_editor.py	2007年12月04日 13:12:09 UTC (rev 4575)
+++ trunk/matplotlib/examples/poly_editor.py	2007年12月04日 14:38:48 UTC (rev 4576)
@@ -9,8 +9,6 @@
 from matplotlib.mlab import dist_point_to_segment
 
 
-
-
 class PolygonInteractor:
 """
 An polygon editor.
@@ -73,7 +71,7 @@
 # display coords
 xt, yt = self.poly.get_transform().numerix_x_y(x, y)
 d = sqrt((xt-event.x)**2 + (yt-event.y)**2)
- indseq = nonzero(equal(d, amin(d)))
+ indseq = nonzero(equal(d, amin(d)))[0]
 ind = indseq[0]
 
 if d[ind]>=self.epsilon:
@@ -128,6 +126,7 @@
 if event.inaxes is None: return
 if event.button != 1: return
 x,y = event.xdata, event.ydata
+
 self.poly.xy[self._ind] = x,y
 self.line.set_data(zip(*self.poly.xy))
 
@@ -160,7 +159,7 @@
 ax.add_patch(poly)
 p = PolygonInteractor( ax, poly)
 
-ax.add_line(p.line)
+#ax.add_line(p.line)
 ax.set_title('Click and drag a point to move it')
 ax.set_xlim((-2,2))
 ax.set_ylim((-2,2))
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 4575
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4575&view=rev
Author: jswhit
Date: 2007年12月04日 05:12:09 -0800 (2007年12月04日)
Log Message:
-----------
opendap and pydap URLs were reversed
Modified Paths:
--------------
 trunk/py4science/classes/0712_ncar_agenda.txt
Modified: trunk/py4science/classes/0712_ncar_agenda.txt
===================================================================
--- trunk/py4science/classes/0712_ncar_agenda.txt	2007年12月04日 06:46:07 UTC (rev 4574)
+++ trunk/py4science/classes/0712_ncar_agenda.txt	2007年12月04日 13:12:09 UTC (rev 4575)
@@ -79,8 +79,8 @@
 * (FP) - OpenDAP_ via the PyDAP_ implementation.
 * (JDH) - PyTables_: an HDF5 library.
 
-.. _OPenDAP: http://pydap.org
-.. _PyDAP: http://opendap.org
+.. _OPenDAP: http://opendap.org
+.. _PyDAP: http://pydap.org
 .. _PyTables: http://www.pytables.org
 
 
@@ -149,4 +149,4 @@
 1500-1515: Wrapup
 We'll have a bit of time for discussion, feedback and any questions that may
 have been left.
- 
\ No newline at end of file
+ 
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <fer...@us...> - 2007年12月04日 06:46:11
Revision: 4574
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4574&view=rev
Author: fer_perez
Date: 2007年12月03日 22:46:07 -0800 (2007年12月03日)
Log Message:
-----------
small makefile fixes
Modified Paths:
--------------
 trunk/py4science/workbook/Makefile
Modified: trunk/py4science/workbook/Makefile
===================================================================
--- trunk/py4science/workbook/Makefile	2007年12月04日 06:24:07 UTC (rev 4573)
+++ trunk/py4science/workbook/Makefile	2007年12月04日 06:46:07 UTC (rev 4574)
@@ -4,8 +4,10 @@
 
 # Warning: list the .aux *before* the bbl. It's probably possible to get the
 # rules right, but I'm not sure how.
+TEXFILES = $(wildcard *.tex)
+
 SKEL_SRC = workbook_skeletons.aux workbook_skeletons.bbl \
-workbook_skeletons.tex main.tex
+workbook_skeletons.tex $(TEXFILES)
 
 SOL_SRC = $(subst _skeletons,_solved,$(SKEL_SRC))
 
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <fer...@us...> - 2007年12月04日 06:24:10
Revision: 4573
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4573&view=rev
Author: fer_perez
Date: 2007年12月03日 22:24:07 -0800 (2007年12月03日)
Log Message:
-----------
Get skeleton to build correctly, rewrite makefile to do as few latex runs as possible
Modified Paths:
--------------
 trunk/py4science/workbook/Makefile
Added Paths:
-----------
 trunk/py4science/workbook/problems_skel/basemap1.py
 trunk/py4science/workbook/problems_skel/basemap2.py
 trunk/py4science/workbook/problems_skel/basemap3.py
 trunk/py4science/workbook/problems_skel/basemap4.py
 trunk/py4science/workbook/problems_skel/basemap5.py
Modified: trunk/py4science/workbook/Makefile
===================================================================
--- trunk/py4science/workbook/Makefile	2007年12月04日 03:18:39 UTC (rev 4572)
+++ trunk/py4science/workbook/Makefile	2007年12月04日 06:24:07 UTC (rev 4573)
@@ -1,20 +1,55 @@
-solved:
+# Makefile for the py4science book.
+
+# Dependencies
+
+# Warning: list the .aux *before* the bbl. It's probably possible to get the
+# rules right, but I'm not sure how.
+SKEL_SRC = workbook_skeletons.aux workbook_skeletons.bbl \
+workbook_skeletons.tex main.tex
+
+SOL_SRC = $(subst _skeletons,_solved,$(SKEL_SRC))
+
+# programs
+PDFTEX = pdflatex -file-line-error
+FASTPDFTEX = pdflatex -file-line-error -draftmode -halt-on-error
+
+# convenience shorthand for targets
+sol: workbook_solved.pdf
+skel: workbook_skeletons.pdf
+all: sol skel
+
+# actual targets
+workbook_solved.pdf: $(SOL_SRC)
 	rm -f problems
-	ln -s problems_solved problems
-	rm -f workbook_solved.tex
-	ln -s main.tex workbook_solved.tex
-	pdflatex workbook_solved
-	bibtex workbook_solved
-	pdflatex workbook_solved
-	rm -f workbook_solved.tex
+	ln -sf problems_solved problems
+	$(PDFTEX) workbook_solved
+	$(PDFTEX) workbook_solved
 
-skeletons:
+workbook_skeletons.pdf: $(SKEL_SRC)
 	rm -f problems
-	ln -s problems_skel problems
-	rm -f workbook_skeletons.tex
-	ln -s main.tex workbook_skeletons.tex
-	pdflatex workbook_skeletons
-	rm -f workbook_skeletons.tex
+	ln -sf problems_skel problems
+	$(PDFTEX) workbook_skeletons
 
+workbook_skeletons.tex:
+	ln -sf main.tex workbook_skeletons.tex
+
+workbook_solved.tex:
+	ln -sf main.tex workbook_solved.tex
+
 clean:
-	rm -f *~ *.aux *.log *.toc *.out
\ No newline at end of file
+	rm -f *~ *.aux *.log *.toc *.out *.bbl *.blg
+
+distclean: clean
+	rm -f workbook_solved.pdf workbook_skeletons.pdf
+
+# Basic rules
+empty :=
+%.bbl : %.aux
+	bibtex $(subst .aux,$(empty),$<)
+	$(FASTPDFTEX) $(subst .aux,$(empty),$<)
+
+%.aux : %.tex
+	$(FASTPDFTEX) $<
+
+# Phony targets
+.PHONY: all clean
Added: trunk/py4science/workbook/problems_skel/basemap1.py
===================================================================
--- trunk/py4science/workbook/problems_skel/basemap1.py	 (rev 0)
+++ trunk/py4science/workbook/problems_skel/basemap1.py	2007年12月04日 06:24:07 UTC (rev 4573)
@@ -0,0 +1 @@
+link ../../examples/skel/basemap1_skel.py
\ No newline at end of file
Property changes on: trunk/py4science/workbook/problems_skel/basemap1.py
___________________________________________________________________
Name: svn:special
 + *
Added: trunk/py4science/workbook/problems_skel/basemap2.py
===================================================================
--- trunk/py4science/workbook/problems_skel/basemap2.py	 (rev 0)
+++ trunk/py4science/workbook/problems_skel/basemap2.py	2007年12月04日 06:24:07 UTC (rev 4573)
@@ -0,0 +1 @@
+link ../../examples/skel/basemap2_skel.py
\ No newline at end of file
Property changes on: trunk/py4science/workbook/problems_skel/basemap2.py
___________________________________________________________________
Name: svn:special
 + *
Added: trunk/py4science/workbook/problems_skel/basemap3.py
===================================================================
--- trunk/py4science/workbook/problems_skel/basemap3.py	 (rev 0)
+++ trunk/py4science/workbook/problems_skel/basemap3.py	2007年12月04日 06:24:07 UTC (rev 4573)
@@ -0,0 +1 @@
+link ../../examples/skel/basemap3_skel.py
\ No newline at end of file
Property changes on: trunk/py4science/workbook/problems_skel/basemap3.py
___________________________________________________________________
Name: svn:special
 + *
Added: trunk/py4science/workbook/problems_skel/basemap4.py
===================================================================
--- trunk/py4science/workbook/problems_skel/basemap4.py	 (rev 0)
+++ trunk/py4science/workbook/problems_skel/basemap4.py	2007年12月04日 06:24:07 UTC (rev 4573)
@@ -0,0 +1 @@
+link ../../examples/skel/basemap4_skel.py
\ No newline at end of file
Property changes on: trunk/py4science/workbook/problems_skel/basemap4.py
___________________________________________________________________
Name: svn:special
 + *
Added: trunk/py4science/workbook/problems_skel/basemap5.py
===================================================================
--- trunk/py4science/workbook/problems_skel/basemap5.py	 (rev 0)
+++ trunk/py4science/workbook/problems_skel/basemap5.py	2007年12月04日 06:24:07 UTC (rev 4573)
@@ -0,0 +1 @@
+link ../../examples/skel/basemap5_skel.py
\ No newline at end of file
Property changes on: trunk/py4science/workbook/problems_skel/basemap5.py
___________________________________________________________________
Name: svn:special
 + *
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.

Showing results of 263

<< < 1 .. 7 8 9 10 11 > >> (Page 9 of 11)
Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.
Thanks for helping keep SourceForge clean.
X





Briefly describe the problem (required):
Upload screenshot of ad (required):
Select a file, or drag & drop file here.
Screenshot instructions:

Click URL instructions:
Right-click on the ad, choose "Copy Link", then paste here →
(This may not be possible with some types of ads)

More information about our ad policies

Ad destination/click URL:

AltStyle によって変換されたページ (->オリジナル) /