@@ -581,39 +581,65 @@ def get_subplotspec(self):
581
581
return None
582
582
583
583
584
- class HBoxDivider (SubplotDivider ):
584
+ def _hvboxdiv_determine_karray (
585
+ equal_sizes , summed_sizes , max_equal_size , total_summed_size ):
586
+ n = len (equal_sizes )
587
+ eq_rs , eq_as = np .asarray (equal_sizes ).T
588
+ sm_rs , sm_as = np .asarray (summed_sizes ).T
589
+ A = np .zeros ((n + 1 , n + 1 ))
590
+ B = np .zeros (n + 1 )
591
+ np .fill_diagonal (A [:n , :n ], eq_rs )
592
+ A [:n , - 1 ] = - 1
593
+ A [- 1 , :- 1 ] = sm_rs
594
+ B [:n ] = - eq_as
595
+ B [- 1 ] = total_summed_size - sum (sm_as )
596
+ # A @ K = B: This solves for {k_0, ..., k_{N-1}, H} so that
597
+ # eq_r_i * k_i + eq_a_i = H for all i: all axes have the same height
598
+ # sum(sm_r_i * k_i + sm_a_i) = total_summed_size: fixed total width
599
+ # (foo_r_i * k_i + foo_a_i will end up being the size of foo.)
600
+ karray_H = np .linalg .solve (A , B )
601
+ karray = karray_H [:- 1 ]
602
+ H = karray_H [- 1 ]
603
+ if H > max_equal_size : # Additionally, upper-bound the height.
604
+ karray = (max_equal_size - eq_as ) / eq_rs
605
+ return karray
606
+
607
+
608
+ def _hvboxdiv_calc_offsets (summed_sizes , karray ):
609
+ offsets = [0. ]
610
+ for (r , a ), k in zip (summed_sizes , karray ):
611
+ offsets .append (offsets [- 1 ] + r * k + a )
612
+ return offsets
613
+
614
+
615
+ # The variable names are written for a horizontal layout, but the calculations
616
+ # work identically for vertical layouts.
617
+ def _hvboxdiv_locate (x , y , w , h , equal_ys , summed_xs , fig_w , fig_h , anchor ):
618
+ karray = _hvboxdiv_determine_karray (
619
+ equal_ys , summed_xs ,
620
+ max_equal_size = fig_h * h , total_summed_size = fig_w * w )
621
+ ox = _hvboxdiv_calc_offsets (summed_xs , karray )
622
+
623
+ ww = (ox [- 1 ] - ox [0 ]) / fig_w
624
+ ref_h = equal_ys [0 ]
625
+ hh = (karray [0 ]* ref_h [0 ] + ref_h [1 ]) / fig_h
626
+ pb = mtransforms .Bbox .from_bounds (x , y , w , h )
627
+ pb1 = mtransforms .Bbox .from_bounds (x , y , ww , hh )
628
+ pb1_anchored = pb1 .anchored (anchor , pb )
629
+ x0 , y0 = pb1_anchored .x0 , pb1_anchored .y0
630
+
631
+ return x0 , y0 , ox , hh
585
632
586
- @staticmethod
587
- def _determine_karray (equivalent_sizes , appended_sizes ,
588
- max_equivalent_size ,
589
- total_appended_size ):
590
- n = len (equivalent_sizes )
591
- eq_rs , eq_as = np .asarray (equivalent_sizes ).T
592
- ap_rs , ap_as = np .asarray (appended_sizes ).T
593
- A = np .zeros ((n + 1 , n + 1 ))
594
- B = np .zeros (n + 1 )
595
- np .fill_diagonal (A [:n , :n ], eq_rs )
596
- A [:n , - 1 ] = - 1
597
- A [- 1 , :- 1 ] = ap_rs
598
- B [:n ] = - eq_as
599
- B [- 1 ] = total_appended_size - sum (ap_as )
600
- # A @ K = B: This solves for {k_0, ..., k_{N-1}, H} so that
601
- # eq_r_i * k_i + eq_a_i = H for all i: all axes have the same height
602
- # sum(ap_r_i * k_i + ap_a_i) = total_appended_size: fixed total width
603
- # (foo_r_i * k_i + foo_a_i will end up being the size of foo.)
604
- karray_H = np .linalg .solve (A , B )
605
- karray = karray_H [:- 1 ]
606
- H = karray_H [- 1 ]
607
- if H > max_equivalent_size : # Additionally, upper-bound the height.
608
- karray = (max_equivalent_size - eq_as ) / eq_rs
609
- return karray
610
633
611
- @staticmethod
612
- def _calc_offsets (appended_sizes , karray ):
613
- offsets = [0. ]
614
- for (r , a ), k in zip (appended_sizes , karray ):
615
- offsets .append (offsets [- 1 ] + r * k + a )
616
- return offsets
634
+ class HBoxDivider (SubplotDivider ):
635
+ """
636
+ A `SubplotDivider` for laying out axes horizontally, while ensuring that
637
+ they have equal heights.
638
+
639
+ Examples
640
+ --------
641
+ .. plot:: gallery/axes_grid1/demo_axes_hbox_divider.py
642
+ """
617
643
618
644
def new_locator (self , nx , nx1 = None ):
619
645
"""
@@ -629,52 +655,26 @@ def new_locator(self, nx, nx1=None):
629
655
"""
630
656
return AxesLocator (self , nx , 0 , nx1 , None )
631
657
632
- def _locate (self , x , y , w , h ,
633
- y_equivalent_sizes , x_appended_sizes ,
634
- figW , figH ):
635
- equivalent_sizes = y_equivalent_sizes
636
- appended_sizes = x_appended_sizes
637
-
638
- max_equivalent_size = figH * h
639
- total_appended_size = figW * w
640
- karray = self ._determine_karray (equivalent_sizes , appended_sizes ,
641
- max_equivalent_size ,
642
- total_appended_size )
643
-
644
- ox = self ._calc_offsets (appended_sizes , karray )
645
-
646
- ww = (ox [- 1 ] - ox [0 ]) / figW
647
- ref_h = equivalent_sizes [0 ]
648
- hh = (karray [0 ]* ref_h [0 ] + ref_h [1 ]) / figH
649
- pb = mtransforms .Bbox .from_bounds (x , y , w , h )
650
- pb1 = mtransforms .Bbox .from_bounds (x , y , ww , hh )
651
- pb1_anchored = pb1 .anchored (self .get_anchor (), pb )
652
- x0 , y0 = pb1_anchored .x0 , pb1_anchored .y0
653
-
654
- return x0 , y0 , ox , hh
655
-
656
658
def locate (self , nx , ny , nx1 = None , ny1 = None , axes = None , renderer = None ):
657
659
# docstring inherited
658
- figW , figH = self ._fig .get_size_inches ()
660
+ fig_w , fig_h = self ._fig .get_size_inches ()
659
661
x , y , w , h = self .get_position_runtime (axes , renderer )
660
-
661
- y_equivalent_sizes = self .get_vertical_sizes (renderer )
662
- x_appended_sizes = self .get_horizontal_sizes (renderer )
663
- x0 , y0 , ox , hh = self ._locate (x , y , w , h ,
664
- y_equivalent_sizes , x_appended_sizes ,
665
- figW , figH )
662
+ y_equal_sizes = self .get_vertical_sizes (renderer )
663
+ x_summed_sizes = self .get_horizontal_sizes (renderer )
664
+ x0 , y0 , ox , hh = _hvboxdiv_locate (
665
+ x , y , w , h , y_equal_sizes , x_summed_sizes , fig_w , fig_h ,
666
+ self .get_anchor ())
666
667
if nx1 is None :
667
668
nx1 = nx + 1
668
-
669
- x1 , w1 = x0 + ox [nx ] / figW , (ox [nx1 ] - ox [nx ]) / figW
669
+ x1 , w1 = x0 + ox [nx ] / fig_w , (ox [nx1 ] - ox [nx ]) / fig_w
670
670
y1 , h1 = y0 , hh
671
-
672
671
return mtransforms .Bbox .from_bounds (x1 , y1 , w1 , h1 )
673
672
674
673
675
- class VBoxDivider (HBoxDivider ):
674
+ class VBoxDivider (SubplotDivider ):
676
675
"""
677
- The Divider class whose rectangle area is specified as a subplot geometry.
676
+ A `SubplotDivider` for laying out axes vertically, while ensuring that they
677
+ have equal widths.
678
678
"""
679
679
680
680
def new_locator (self , ny , ny1 = None ):
@@ -693,20 +693,17 @@ def new_locator(self, ny, ny1=None):
693
693
694
694
def locate (self , nx , ny , nx1 = None , ny1 = None , axes = None , renderer = None ):
695
695
# docstring inherited
696
- figW , figH = self ._fig .get_size_inches ()
696
+ fig_w , fig_h = self ._fig .get_size_inches ()
697
697
x , y , w , h = self .get_position_runtime (axes , renderer )
698
-
699
- x_equivalent_sizes = self .get_horizontal_sizes (renderer )
700
- y_appended_sizes = self .get_vertical_sizes (renderer )
701
- y0 , x0 , oy , ww = self ._locate (y , x , h , w ,
702
- x_equivalent_sizes , y_appended_sizes ,
703
- figH , figW )
698
+ x_equal_sizes = self .get_horizontal_sizes (renderer )
699
+ y_summed_sizes = self .get_vertical_sizes (renderer )
700
+ y0 , x0 , oy , ww = _hvboxdiv_locate (
701
+ y , x , h , w , x_equal_sizes , y_summed_sizes , fig_h , fig_w ,
702
+ self .get_anchor ())
704
703
if ny1 is None :
705
704
ny1 = ny + 1
706
-
707
705
x1 , w1 = x0 , ww
708
- y1 , h1 = y0 + oy [ny ] / figH , (oy [ny1 ] - oy [ny ]) / figH
709
-
706
+ y1 , h1 = y0 + oy [ny ] / fig_h , (oy [ny1 ] - oy [ny ]) / fig_h
710
707
return mtransforms .Bbox .from_bounds (x1 , y1 , w1 , h1 )
711
708
712
709
0 commit comments