2323from matplotlib import mlab
2424from matplotlib import cm
2525from matplotlib import patches as mpatches
26+ from matplotlib import path as mpath
2627from matplotlib import pbox as mpbox
2728from matplotlib import quiver as mquiver
2829from matplotlib import scale as mscale
@@ -1461,7 +1462,7 @@ def set_axis_bgcolor(self, color):
14611462 self .axesPatch .set_facecolor (color )
14621463
14631464 ### data limits, ticks, tick labels, and formatting
1464-
1465+
14651466 def get_xlim (self ):
14661467 'Get the x axis range [xmin, xmax]'
14671468 return self .viewLim .intervalx
@@ -1503,11 +1504,6 @@ def set_xlim(self, xmin=None, xmax=None, emit=True, **kwargs):
15031504 if xmin is None : xmin = old_xmin
15041505 if xmax is None : xmax = old_xmax
15051506
1506- # MGDTODO
1507- # if (self.transData.get_funcx().get_type()==mtrans.LOG10
1508- # and min(xmin, xmax)<=0):
1509- # raise ValueError('Cannot set nonpositive limits with log transform')
1510-
15111507 xmin , xmax = mtransforms .nonsingular (xmin , xmax , increasing = False )
15121508
15131509 self .viewLim .intervalx = (xmin , xmax )
@@ -1516,7 +1512,7 @@ def set_xlim(self, xmin=None, xmax=None, emit=True, **kwargs):
15161512 # Call all of the other x-axes that are shared with this one
15171513 for other in self ._shared_x_axes .get_siblings (self ):
15181514 if other is not self :
1519- other .set_xlim (self .viewLim .xmin , self . viewLim . xmax , emit = False )
1515+ other .set_xlim (self .viewLim .intervalx , emit = False )
15201516
15211517 return xmin , xmax
15221518
@@ -1634,7 +1630,7 @@ def get_yscale(self):
16341630 'return the yaxis scale string: log or linear'
16351631 return self .yaxis .get_scale ()
16361632
1637- def set_yscale (self , value , basey = 10 , subsy = None ):
1633+ def set_yscale (self , value , ** kwargs ):
16381634 """
16391635 SET_YSCALE(value, basey=10, subsy=None)
16401636
@@ -1652,7 +1648,7 @@ def set_yscale(self, value, basey=10, subsy=None):
16521648
16531649 ACCEPTS: ['log' | 'linear']
16541650 """
1655- self .yaxis .set_scale (value , basey , subsy )
1651+ self .yaxis .set_scale (value , ** kwargs )
16561652 self ._update_transScale ()
16571653
16581654 def get_yticks (self ):
@@ -1788,6 +1784,32 @@ def set_navigate_mode(self, b):
17881784 """
17891785 self ._navigate_mode = b
17901786
1787+ def drag_pan (self , button , x , y , startx , starty , start_lim , start_trans ):
1788+ if button == 1 :
1789+ inverse = start_trans .inverted ()
1790+ dx = startx - x
1791+ dy = starty - y
1792+ result = self .bbox .frozen ().translated (dx , dy ).transformed (inverse )
1793+ elif button == 3 :
1794+ try :
1795+ inverse = start_trans .inverted ()
1796+ dx = (startx - x ) / float (self .bbox .width )
1797+ dy = (starty - y ) / float (self .bbox .height )
1798+ xmin , ymin , xmax , ymax = start_lim .lbrt
1799+
1800+ alpha = npy .power (10.0 , (dx , dy ))
1801+ start = inverse .transform_point ((startx , starty ))
1802+ lim_points = start_lim .get_points ()
1803+ result = start + alpha * (lim_points - start )
1804+ result = mtransforms .Bbox (result )
1805+ except OverflowError :
1806+ warnings .warn ('Overflow while panning' )
1807+ return
1808+
1809+ # MGDTODO: Could we do this with a single set_lim?
1810+ self .set_xlim (* result .intervalx )
1811+ self .set_ylim (* result .intervaly )
1812+
17911813 def get_cursor_props (self ):
17921814 """return the cursor props as a linewidth, color tuple where
17931815 linewidth is a float and color is an RGBA tuple"""
@@ -5658,8 +5680,253 @@ def __init__(self, fig, *args, **kwargs):
56585680 self , fig ,
56595681 [self .figLeft , self .figBottom , self .figW , self .figH ], ** kwargs )
56605682
5683+ ######################################################################
5684+ # New Polar Axes
5685+
5686+ class PolarAxes (Axes ):
5687+ class PolarTransform (mtransforms .Transform ):
5688+ input_dims = 2
5689+ output_dims = 2
5690+ is_separable = False
5691+
5692+ def transform (self , tr ):
5693+ xy = npy .zeros (tr .shape , npy .float_ )
5694+ t = tr [:, 0 :1 ]
5695+ r = tr [:, 1 :2 ]
5696+ x = xy [:, 0 :1 ]
5697+ y = xy [:, 1 :2 ]
5698+ x += r * npy .cos (t )
5699+ y += r * npy .sin (t )
5700+ return xy
5701+ transform_non_affine = transform
5702+
5703+ def interpolate (self , a , steps ):
5704+ steps = npy .floor (steps )
5705+ new_length = ((len (a ) - 1 ) * steps ) + 1
5706+ new_shape = list (a .shape )
5707+ new_shape [0 ] = new_length
5708+ result = npy .zeros (new_shape , a .dtype )
5709+
5710+ result [0 ] = a [0 ]
5711+ a0 = a [0 :- 1 ]
5712+ a1 = a [1 : ]
5713+ delta = ((a1 - a0 ) / steps )
5714+
5715+ for i in range (1 , int (steps )+ 1 ):
5716+ result [i ::steps ] = delta * i + a0
5717+
5718+ return result
5719+
5720+ # def transform_path(self, path):
5721+ # twopi = 2.0 * npy.pi
5722+ # halfpi = 0.5 * npy.pi
5723+
5724+ # vertices = path.vertices
5725+ # t0 = vertices[0:-1, 0]
5726+ # t1 = vertices[1: , 0]
5727+ # td = npy.where(t1 > t0, t1 - t0, twopi - (t0 - t1))
5728+ # maxtd = td.max()
5729+ # interpolate = npy.ceil(maxtd / halfpi)
5730+ # if interpolate > 1.0:
5731+ # vertices = self.interpolate(vertices, interpolate)
5732+
5733+ # vertices = self.transform(vertices)
5734+
5735+ # result = npy.zeros((len(vertices) * 3 - 2, 2), npy.float_)
5736+ # codes = mpath.Path.CURVE4 * npy.ones((len(vertices) * 3 - 2, ), mpath.Path.code_type)
5737+ # result[0] = vertices[0]
5738+ # codes[0] = mpath.Path.MOVETO
5739+
5740+ # kappa = 4.0 * ((npy.sqrt(2.0) - 1.0) / 3.0)
5741+ # kappa = 0.5
5742+
5743+ # p0 = vertices[0:-1]
5744+ # p1 = vertices[1: ]
5745+
5746+ # x0 = p0[:, 0:1]
5747+ # y0 = p0[:, 1: ]
5748+ # b0 = ((y0 - x0) - y0) / ((x0 + y0) - x0)
5749+ # a0 = y0 - b0*x0
5750+
5751+ # x1 = p1[:, 0:1]
5752+ # y1 = p1[:, 1: ]
5753+ # b1 = ((y1 - x1) - y1) / ((x1 + y1) - x1)
5754+ # a1 = y1 - b1*x1
5755+
5756+ # x = -(a0-a1) / (b0-b1)
5757+ # y = a0 + b0*x
5758+
5759+ # xk = (x - x0) * kappa + x0
5760+ # yk = (y - y0) * kappa + y0
5761+
5762+ # result[1::3, 0:1] = xk
5763+ # result[1::3, 1: ] = yk
5764+
5765+ # xk = (x - x1) * kappa + x1
5766+ # yk = (y - y1) * kappa + y1
5767+
5768+ # result[2::3, 0:1] = xk
5769+ # result[2::3, 1: ] = yk
5770+
5771+ # result[3::3] = p1
5772+
5773+ # print vertices[-2:]
5774+ # print result[-2:]
5775+
5776+ # return mpath.Path(result, codes)
5777+
5778+ # twopi = 2.0 * npy.pi
5779+ # halfpi = 0.5 * npy.pi
5780+
5781+ # vertices = path.vertices
5782+ # t0 = vertices[0:-1, 0]
5783+ # t1 = vertices[1: , 0]
5784+ # td = npy.where(t1 > t0, t1 - t0, twopi - (t0 - t1))
5785+ # maxtd = td.max()
5786+ # interpolate = npy.ceil(maxtd / halfpi)
5787+
5788+ # print "interpolate", interpolate
5789+ # if interpolate > 1.0:
5790+ # vertices = self.interpolate(vertices, interpolate)
5791+
5792+ # result = npy.zeros((len(vertices) * 3 - 2, 2), npy.float_)
5793+ # codes = mpath.Path.CURVE4 * npy.ones((len(vertices) * 3 - 2, ), mpath.Path.code_type)
5794+ # result[0] = vertices[0]
5795+ # codes[0] = mpath.Path.MOVETO
5796+
5797+ # kappa = 4.0 * ((npy.sqrt(2.0) - 1.0) / 3.0)
5798+ # tkappa = npy.arctan(kappa)
5799+ # hyp_kappa = npy.sqrt(kappa*kappa + 1.0)
5800+
5801+ # t0 = vertices[0:-1, 0]
5802+ # t1 = vertices[1: , 0]
5803+ # r0 = vertices[0:-1, 1]
5804+ # r1 = vertices[1: , 1]
5805+
5806+ # td = npy.where(t1 > t0, t1 - t0, twopi - (t0 - t1))
5807+ # td_scaled = td / (npy.pi * 0.5)
5808+ # rd = r1 - r0
5809+ # r0kappa = r0 * kappa * td_scaled
5810+ # r1kappa = r1 * kappa * td_scaled
5811+ # ravg_kappa = ((r1 + r0) / 2.0) * kappa * td_scaled
5812+
5813+ # result[1::3, 0] = t0 + (tkappa * td_scaled)
5814+ # result[1::3, 1] = r0*hyp_kappa
5815+ # # result[1::3, 1] = r0 / npy.cos(tkappa * td_scaled) # npy.sqrt(r0*r0 + ravg_kappa*ravg_kappa)
5816+
5817+ # result[2::3, 0] = t1 - (tkappa * td_scaled)
5818+ # result[2::3, 1] = r1*hyp_kappa
5819+ # # result[2::3, 1] = r1 / npy.cos(tkappa * td_scaled) # npy.sqrt(r1*r1 + ravg_kappa*ravg_kappa)
5820+
5821+ # result[3::3, 0] = t1
5822+ # result[3::3, 1] = r1
5823+
5824+ # print vertices[:6], result[:6], t0[:6], t1[:6], td[:6], td_scaled[:6], tkappa
5825+ # result = self.transform(result)
5826+ # return mpath.Path(result, codes)
5827+ # transform_path_non_affine = transform_path
5828+
5829+ def inverted (self ):
5830+ return PolarAxes .InvertedPolarTransform ()
5831+
5832+ class PolarAffine (mtransforms .Affine2DBase ):
5833+ def __init__ (self , limits ):
5834+ mtransforms .Affine2DBase .__init__ (self )
5835+ self ._limits = limits
5836+ self .set_children (limits )
5837+ self ._mtx = None
5838+
5839+ def get_matrix (self ):
5840+ if self ._invalid :
5841+ xmin , ymin , xmax , ymax = self ._limits .lbrt
5842+ affine = mtransforms .Affine2D ().rotate (xmin ).scale (0.5 / ymax ).translate (0.5 , 0.5 )
5843+ self ._mtx = affine .get_matrix ()
5844+ self ._inverted = None
5845+ self ._invalid = 0
5846+ return self ._mtx
5847+
5848+ class InvertedPolarTransform (mtransforms .Transform ):
5849+ input_dims = 2
5850+ output_dims = 2
5851+ is_separable = False
5852+
5853+ def transform (self , xy ):
5854+ x = xy [:, 0 :1 ]
5855+ y = xy [:, 1 :]
5856+ r = npy .sqrt (x * x + y * y )
5857+ theta = npy .arccos (x / r )
5858+ theta = npy .where (y < 0 , 2 * npy .pi - theta , theta )
5859+ return npy .concatenate ((theta , r ), 1 )
5860+
5861+ def inverted (self ):
5862+ return PolarAxes .PolarTransform ()
5863+
5864+ def _set_lim_and_transforms (self ):
5865+ """
5866+ set the dataLim and viewLim BBox attributes and the
5867+ transData and transAxes Transformation attributes
5868+ """
5869+ self .dataLim = mtransforms .Bbox .unit ()
5870+ self .viewLim = mtransforms .Bbox .unit ()
5871+ self .transAxes = mtransforms .BboxTransform (
5872+ mtransforms .Bbox .unit (), self .bbox )
56615873
5874+ # Transforms the x and y axis separately by a scale factor
5875+ # It is assumed that this part will have non-linear components
5876+ self .transScale = mtransforms .TransformWrapper (mtransforms .IdentityTransform ())
5877+
5878+ # A (possibly non-linear) projection on the (already scaled) data
5879+ self .transProjection = self .PolarTransform ()
56625880
5881+ # An affine transformation on the data, generally to limit the
5882+ # range of the axes
5883+ self .transProjectionAffine = self .PolarAffine (self .viewLim )
5884+
5885+ self .transData = self .transScale + self .transProjection + \
5886+ self .transProjectionAffine + self .transAxes
5887+
5888+ def drag_pan (self , button , x , y , startx , starty , start_lim , start_trans ):
5889+ if button == 1 :
5890+ inverse = start_trans .inverted ()
5891+ startt , startr = inverse .transform_point ((startx , starty ))
5892+ t , r = inverse .transform_point ((x , y ))
5893+
5894+ scale = r / startr
5895+ self .set_ylim (start_lim .ymin , start_lim .ymax / scale )
5896+
5897+ dt0 = t - startt
5898+ dt1 = startt - t
5899+ if abs (dt1 ) < abs (dt0 ):
5900+ dt = abs (dt1 ) * sign (dt0 ) * - 1.0
5901+ else :
5902+ dt = dt0 * - 1.0
5903+ self .set_xlim (start_lim .xmin - dt , start_lim .xmin - dt + npy .pi * 2.0 )
5904+
5905+ def set_rmax (self , rmax ):
5906+ self .viewLim .maxy = rmax
5907+
5908+ class PolarSubplot (SubplotBase , PolarAxes ):
5909+ """
5910+ Create a polar subplot with
5911+
5912+ PolarSubplot(numRows, numCols, plotNum)
5913+
5914+ where plotNum=1 is the first plot number and increasing plotNums
5915+ fill rows first. max(plotNum)==numRows*numCols
5916+
5917+ You can leave out the commas if numRows<=numCols<=plotNum<10, as
5918+ in
5919+
5920+ Subplot(211) # 2 rows, 1 column, first (upper) plot
5921+ """
5922+ def __str__ (self ):
5923+ return "PolarSubplot(%gx%g)" % (self .figW ,self .figH )
5924+ def __init__ (self , fig , * args , ** kwargs ):
5925+ SubplotBase .__init__ (self , fig , * args )
5926+ PolarAxes .__init__ (
5927+ self , fig ,
5928+ [self .figLeft , self .figBottom , self .figW , self .figH ], ** kwargs )
5929+
56635930martist .kwdocd ['Axes' ] = martist .kwdocd ['Subplot' ] = martist .kwdoc (Axes )
56645931"""
56655932# this is some discarded code I was using to find the minimum positive
0 commit comments