40
40
from transforms import FuncXY , Func , LOG10 , IDENTITY , POLAR
41
41
from transforms import get_bbox_transform , unit_bbox , one , origin , zero
42
42
from transforms import blend_xy_sep_transform , Interval
43
+ from transforms import PBox
43
44
from font_manager import FontProperties
44
- from pbox import PBox
45
45
46
46
import matplotlib
47
47
@@ -478,38 +478,117 @@ def apply_aspect(self, data_ratio = None):
478
478
self .set_position (pb1 .anchor (self ._anchor ), 'active' )
479
479
return
480
480
481
+
482
+ l ,b ,w ,h = self .get_position ()
483
+ box_aspect = fig_aspect * (h / w )
484
+ data_ratio = box_aspect / A
485
+ dL = self .dataLim
486
+ xr = dL .width ()
487
+ yr = dL .height ()
488
+ xmarg = xsize - xr
489
+ ymarg = ysize - yr
490
+ Ysize = data_ratio * xsize
491
+ Xsize = ysize / data_ratio
492
+ # If it is very nearly correct, don't do any more;
493
+ # we are probably just panning.
494
+ if abs (xsize - Xsize ) < 0.001 * xsize or abs (ysize - Ysize ) < 0.001 * ysize :
495
+ return
496
+
481
497
changex = ((self ._sharey or self ._mastery ) and not
482
498
(self ._sharex or self ._masterx ))
483
499
changey = ((self ._sharex or self ._masterx ) and not
484
500
(self ._sharey or self ._mastery ))
485
501
if changex and changey :
486
502
warnings .warn ("adjustable='datalim' cannot work with shared x and y axes" )
487
503
return
488
- dx0 , dx1 = self .dataLim .intervalx ().get_bounds ()
489
- dy0 , dy1 = self .dataLim .intervaly ().get_bounds ()
490
- xr = abs (dx1 - dx0 )
491
- yr = abs (dy1 - dy0 )
492
- l ,b ,w ,h = self .get_position ()
493
- box_aspect = fig_aspect * (h / w )
494
- data_ratio = box_aspect / A
495
- Ysize = data_ratio * xsize
496
- Xsize = ysize / data_ratio
497
504
if changex :
498
505
adjust_y = False
499
506
else :
500
- adjust_y = changey or ((Ysize > ysize ) and (ysize <= yr ))
507
+ adjust_y = changey or (Xsize < min (xsize , xr ))
508
+ adjust_y = adjust_y or (A * ymarg > xmarg )
501
509
if adjust_y :
502
- dy = 0.5 * (Ysize - ysize )
503
- self .set_ylim ((ymin - dy , ymax + dy ))
510
+ dy = Ysize - ysize
511
+ if ymarg < 0.01 * dy :
512
+ y0 = ymin - dy / 2.0
513
+ y1 = ymax + dy / 2.0
514
+ else :
515
+ yc = (dL .ymax () + dL .ymin ())/ 2.0
516
+ y0 = yc - Ysize / 2.0
517
+ y1 = yc + Ysize / 2.0
518
+ self .set_ylim ((y0 , y1 ))
504
519
else :
505
- dx = 0.5 * (Xsize - xsize )
506
- self .set_xlim ((xmin - dx , xmax + dx ))
520
+ dx = Xsize - xsize
521
+ if xmarg < 0.01 * dx :
522
+ x0 = xmin - dx / 2.0
523
+ x1 = xmax + dx / 2.0
524
+ else :
525
+ xc = (dL .xmax () + dL .xmin ())/ 2.0
526
+ x0 = xc - Xsize / 2.0
527
+ x1 = xc + Xsize / 2.0
528
+ self .set_xlim ((x0 , x1 ))
507
529
508
530
def get_aspect (self ):
509
531
return self ._aspect
510
532
511
- def get_aspect_adjusts (self ):
512
- return self ._aspect_adjusts
533
+ def get_adjustable (self ):
534
+ return self ._adjustable
535
+
536
+ def get_anchor (self ):
537
+ return self ._anchor
538
+
539
+ def axis (self , * v , ** kwargs ):
540
+ '''
541
+ Convenience method for manipulating the x and y view limits
542
+ and the aspect ratio of the plot.
543
+
544
+ See docstring for pylab.axis.
545
+ '''
546
+ if len (v )== 1 and is_string_like (v [0 ]):
547
+ s = v [0 ].lower ()
548
+ if s == 'on' : self .set_axis_on ()
549
+ elif s == 'off' : self .set_axis_off ()
550
+ elif s in ('equal' , 'tight' , 'scaled' , 'normal' , 'auto' , 'image' ):
551
+ self .set_autoscale_on (True )
552
+ self .set_aspect ('auto' )
553
+ self .autoscale_view ()
554
+ self .apply_aspect ()
555
+ if s == 'equal' :
556
+ self .set_aspect ('equal' , adjustable = 'datalim' )
557
+ elif s == 'scaled' :
558
+ self .set_aspect ('equal' , adjustable = 'box' , anchor = 'C' )
559
+ elif s == 'tight' :
560
+ self .autoscale_view (tight = True )
561
+ self .set_autoscale_on (False )
562
+ elif s == 'image' :
563
+ self .autoscale_view (tight = True )
564
+ self .set_autoscale_on (False )
565
+ self .set_aspect ('equal' , adjustable = 'box' , anchor = 'C' )
566
+
567
+ else :
568
+ raise ValueError ('Unrecognized string %s to axis; try on or off' % s )
569
+ xmin , xmax = self .get_xlim ()
570
+ ymin , ymax = self .get_ylim ()
571
+ #draw_if_interactive()
572
+ return xmin , xmax , ymin , ymax
573
+
574
+ try : v [0 ]
575
+ except IndexError :
576
+ xmin , xmax = self .set_xlim (** kwargs )
577
+ ymin , ymax = self .set_ylim (** kwargs )
578
+ #draw_if_interactive()
579
+ return xmin , xmax , ymin , ymax
580
+
581
+ v = v [0 ]
582
+ if len (v ) != 4 :
583
+ raise ValueError ('v must contain [xmin xmax ymin ymax]' )
584
+
585
+
586
+ self .set_xlim ([v [0 ], v [1 ]])
587
+ self .set_ylim ([v [2 ], v [3 ]])
588
+
589
+ #draw_if_interactive()
590
+ return v
591
+
513
592
514
593
def set_cursor_props (self , * args ):
515
594
"""
@@ -869,7 +948,7 @@ def get_yscale(self):
869
948
870
949
def update_datalim (self , xys ):
871
950
'Update the data lim bbox with seq of xy tups'
872
- # if no data is set currently, the bbox will ignore it's
951
+ # if no data is set currently, the bbox will ignore its
873
952
# limits and set the bound to be the bounds of the xydata.
874
953
# Otherwise, it will compute the bounds of it's current data
875
954
# and the data in xydata
@@ -3489,7 +3568,7 @@ def set_xscale(self, value, basex = 10, subsx=None):
3489
3568
3490
3569
* subsx: the location of the minor ticks; None defaults to
3491
3570
autosubs, which depend on the number of decades in the
3492
- plot.
3571
+ plot.
3493
3572
3494
3573
ACCEPTS: ['log' | 'linear' ]
3495
3574
"""
@@ -3699,6 +3778,7 @@ def specgram(self, x, NFFT=256, Fs=2, detrend=detrend_none,
3699
3778
xmin , xmax = xextent
3700
3779
extent = xmin , xmax , 0 , amax (freqs )
3701
3780
im = self .imshow (Z , cmap , extent = extent )
3781
+ self .axis ('auto' )
3702
3782
3703
3783
return Pxx , freqs , bins , im
3704
3784
0 commit comments