22from matplotlib .numerix import npyma as ma
33MaskedArray = ma .MaskedArray
44
5- from ticker import NullFormatter , ScalarFormatter , LogFormatterMathtext
6- from ticker import NullLocator , LogLocator , AutoLocator , SymmetricalLogLocator
5+ from ticker import NullFormatter , ScalarFormatter , LogFormatterMathtext , Formatter
6+ from ticker import NullLocator , LogLocator , AutoLocator , SymmetricalLogLocator , FixedLocator
77from transforms import Transform , IdentityTransform
88
99class ScaleBase (object ):
@@ -28,6 +28,7 @@ def set_default_locators_and_formatters(self, axis):
2828 def get_transform (self ):
2929 return IdentityTransform ()
3030
31+
3132def _mask_non_positives (a ):
3233 mask = a <= 0.0
3334 if mask .any ():
@@ -185,7 +186,17 @@ def limit_range_for_scale(self, vmin, vmax, minpos):
185186 return (vmin <= 0.0 and minpos or vmin ,
186187 vmax <= 0.0 and minpos or vmax )
187188
189+
188190class SymmetricalLogScale (ScaleBase ):
191+ """
192+ The symmetrical logarithmic scale is logarithmic in both the
193+ positive and negative directions from the origin.
194+
195+ Since the values close to zero tend toward infinity, there is
196+ usually need to have a range around zero that is linear. The
197+ parameter "linthresh" allows the user to specify the size of this
198+ range (-linthresh, linthresh).
199+ """
189200 name = 'symlog'
190201
191202 class SymmetricalLogTransform (Transform ):
@@ -263,10 +274,83 @@ def get_transform(self):
263274 return self ._transform
264275
265276
277+ class MercatorLatitudeScale (ScaleBase ):
278+ """
279+ Scales data in range -pi/2 to pi/2 (-90 to 90 degrees) using
280+ the system used to scale latitudes in a Mercator projection.
281+
282+ The scale function:
283+ ln(tan(y) + sec(y))
284+
285+ The inverse scale function:
286+ atan(sinh(y))
287+
288+ source:
289+ http://en.wikipedia.org/wiki/Mercator_projection
290+ """
291+ name = 'mercator_latitude'
292+
293+ class MercatorLatitudeTransform (Transform ):
294+ input_dims = 1
295+ output_dims = 1
296+ is_separable = True
297+
298+ def __init__ (self , thresh ):
299+ Transform .__init__ (self )
300+ self .thresh = thresh
301+
302+ def transform (self , a ):
303+ masked = ma .masked_where ((a < - self .thresh ) | (a > self .thresh ), a )
304+ return ma .log (ma .tan (masked ) + 1.0 / ma .cos (masked ))
305+
306+ def inverted (self ):
307+ return MercatorLatitudeScale .InvertedMercatorLatitudeTransform ()
308+
309+ class InvertedMercatorLatitudeTransform (Transform ):
310+ input_dims = 1
311+ output_dims = 1
312+ is_separable = True
313+
314+ def transform (self , a ):
315+ return npy .arctan (npy .sinh (a ))
316+
317+ def inverted (self ):
318+ return MercatorLatitudeScale .MercatorLatitudeTransform ()
319+
320+ def __init__ (self , axis , ** kwargs ):
321+ thresh = kwargs .pop ("thresh" , (85 / 180.0 ) * npy .pi )
322+ if thresh >= npy .pi / 2.0 :
323+ raise ValueError ("thresh must be less than pi/2" )
324+ self .thresh = thresh
325+ self ._transform = self .MercatorLatitudeTransform (thresh )
326+
327+ def set_default_locators_and_formatters (self , axis ):
328+ class ThetaFormatter (Formatter ):
329+ """
330+ Used to format the theta tick labels. Converts the native
331+ unit of radians into degrees and adds a degree symbol.
332+ """
333+ def __call__ (self , x , pos = None ):
334+ # \u00b0 : degree symbol
335+ return u"%d\u00b0 " % ((x / npy .pi ) * 180.0 )
336+
337+ deg2rad = npy .pi / 180.0
338+ axis .set_major_locator (FixedLocator (
339+ npy .arange (- 90 , 90 , 10 ) * deg2rad ))
340+ axis .set_major_formatter (ThetaFormatter ())
341+ axis .set_minor_formatter (ThetaFormatter ())
342+
343+ def get_transform (self ):
344+ return self ._transform
345+
346+ def limit_range_for_scale (self , vmin , vmax , minpos ):
347+ return max (vmin , - self .thresh ), min (vmax , self .thresh )
348+
266349_scale_mapping = {
267- 'linear' : LinearScale ,
268- 'log' : LogScale ,
269- 'symlog' : SymmetricalLogScale
350+ 'linear' : LinearScale ,
351+ 'log' : LogScale ,
352+ 'symlog' : SymmetricalLogScale ,
353+ 'mercator_latitude' : MercatorLatitudeScale
270354 }
271355def scale_factory (scale , axis , ** kwargs ):
272356 scale = scale .lower ()
0 commit comments