@@ -583,39 +583,67 @@ def get_subplotspec(self):
583583 return None
584584
585585
586- class HBoxDivider (SubplotDivider ):
586+ # Helper for HBoxDivider/VBoxDivider.
587+ def _determine_karray (equivalent_sizes , appended_sizes ,
588+ max_equivalent_size , total_appended_size ):
589+ n = len (equivalent_sizes )
590+ eq_rs , eq_as = np .asarray (equivalent_sizes ).T
591+ ap_rs , ap_as = np .asarray (appended_sizes ).T
592+ A = np .zeros ((n + 1 , n + 1 ))
593+ B = np .zeros (n + 1 )
594+ np .fill_diagonal (A [:n , :n ], eq_rs )
595+ A [:n , - 1 ] = - 1
596+ A [- 1 , :- 1 ] = ap_rs
597+ B [:n ] = - eq_as
598+ B [- 1 ] = total_appended_size - sum (ap_as )
599+ # A @ K = B: This solves for {k_0, ..., k_{N-1}, H} so that
600+ # eq_r_i * k_i + eq_a_i = H for all i: all axes have the same height
601+ # sum(ap_r_i * k_i + ap_a_i) = total_summed_width: fixed total width
602+ # (foo_r_i * k_i + foo_a_i will end up being the size of foo.)
603+ karray_H = np .linalg .solve (A , B )
604+ karray = karray_H [:- 1 ]
605+ H = karray_H [- 1 ]
606+ if H > max_equivalent_size : # Additionally, upper-bound the height.
607+ karray = (max_equivalent_size - eq_as ) / eq_rs
608+ return karray
609+
610+
611+ # Helper for HBoxDivider/VBoxDivider.
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
617+
618+
619+ # Helper for HBoxDivider/VBoxDivider.
620+ def _locate (
621+ x , y , w , h , equivalent_sizes , appended_sizes , fig_w , fig_h , anchor ):
622+ karray = _determine_karray (
623+ equivalent_sizes , appended_sizes ,
624+ max_equivalent_size = fig_h * h , total_appended_size = fig_w * w )
625+ ox = _calc_offsets (appended_sizes , karray )
626+
627+ ww = (ox [- 1 ] - ox [0 ]) / fig_w
628+ h0_r , h0_a = equivalent_sizes [0 ]
629+ hh = (karray [0 ]* h0_r + h0_a ) / fig_h
630+ pb = mtransforms .Bbox .from_bounds (x , y , w , h )
631+ pb1 = mtransforms .Bbox .from_bounds (x , y , ww , hh )
632+ pb1_anchored = pb1 .anchored (anchor , pb )
633+ x0 , y0 = pb1_anchored .x0 , pb1_anchored .y0
634+
635+ return x0 , y0 , ox , hh
587636
588- @staticmethod
589- def _determine_karray (equivalent_sizes , appended_sizes ,
590- max_equivalent_size ,
591- total_appended_size ):
592- n = len (equivalent_sizes )
593- eq_rs , eq_as = np .asarray (equivalent_sizes ).T
594- ap_rs , ap_as = np .asarray (appended_sizes ).T
595- A = np .zeros ((n + 1 , n + 1 ))
596- B = np .zeros (n + 1 )
597- np .fill_diagonal (A [:n , :n ], eq_rs )
598- A [:n , - 1 ] = - 1
599- A [- 1 , :- 1 ] = ap_rs
600- B [:n ] = - eq_as
601- B [- 1 ] = total_appended_size - sum (ap_as )
602- # A @ K = B: This solves for {k_0, ..., k_{N-1}, H} so that
603- # eq_r_i * k_i + eq_a_i = H for all i: all axes have the same height
604- # sum(ap_r_i * k_i + ap_a_i) = total_appended_size: fixed total width
605- # (foo_r_i * k_i + foo_a_i will end up being the size of foo.)
606- karray_H = np .linalg .solve (A , B )
607- karray = karray_H [:- 1 ]
608- H = karray_H [- 1 ]
609- if H > max_equivalent_size : # Additionally, upper-bound the height.
610- karray = (max_equivalent_size - eq_as ) / eq_rs
611- return karray
612637
613- @staticmethod
614- def _calc_offsets (appended_sizes , karray ):
615- offsets = [0. ]
616- for (r , a ), k in zip (appended_sizes , karray ):
617- offsets .append (offsets [- 1 ] + r * k + a )
618- return offsets
638+ class HBoxDivider (SubplotDivider ):
639+ """
640+ A `SubplotDivider` for laying out axes horizontally, while ensuring that
641+ they have equal heights.
642+
643+ Examples
644+ --------
645+ .. plot:: gallery/axes_grid1/demo_axes_hbox_divider.py
646+ """
619647
620648 def new_locator (self , nx , nx1 = None ):
621649 """
@@ -631,52 +659,26 @@ def new_locator(self, nx, nx1=None):
631659 """
632660 return AxesLocator (self , nx , 0 , nx1 , None )
633661
634- def _locate (self , x , y , w , h ,
635- y_equivalent_sizes , x_appended_sizes ,
636- figW , figH ):
637- equivalent_sizes = y_equivalent_sizes
638- appended_sizes = x_appended_sizes
639-
640- max_equivalent_size = figH * h
641- total_appended_size = figW * w
642- karray = self ._determine_karray (equivalent_sizes , appended_sizes ,
643- max_equivalent_size ,
644- total_appended_size )
645-
646- ox = self ._calc_offsets (appended_sizes , karray )
647-
648- ww = (ox [- 1 ] - ox [0 ]) / figW
649- ref_h = equivalent_sizes [0 ]
650- hh = (karray [0 ]* ref_h [0 ] + ref_h [1 ]) / figH
651- pb = mtransforms .Bbox .from_bounds (x , y , w , h )
652- pb1 = mtransforms .Bbox .from_bounds (x , y , ww , hh )
653- pb1_anchored = pb1 .anchored (self .get_anchor (), pb )
654- x0 , y0 = pb1_anchored .x0 , pb1_anchored .y0
655-
656- return x0 , y0 , ox , hh
657-
658662 def locate (self , nx , ny , nx1 = None , ny1 = None , axes = None , renderer = None ):
659663 # docstring inherited
660664 figW , figH = self ._fig .get_size_inches ()
661665 x , y , w , h = self .get_position_runtime (axes , renderer )
662-
663666 y_equivalent_sizes = self .get_vertical_sizes (renderer )
664667 x_appended_sizes = self .get_horizontal_sizes (renderer )
665- x0 , y0 , ox , hh = self . _locate (x , y , w , h ,
666- y_equivalent_sizes , x_appended_sizes ,
667- figW , figH )
668+ x0 , y0 , ox , hh = _locate (x , y , w , h ,
669+ y_equivalent_sizes , x_appended_sizes ,
670+ figW , figH , self . get_anchor () )
668671 if nx1 is None :
669672 nx1 = nx + 1
670-
671673 x1 , w1 = x0 + ox [nx ] / figW , (ox [nx1 ] - ox [nx ]) / figW
672674 y1 , h1 = y0 , hh
673-
674675 return mtransforms .Bbox .from_bounds (x1 , y1 , w1 , h1 )
675676
676677
677- class VBoxDivider (HBoxDivider ):
678+ class VBoxDivider (SubplotDivider ):
678679 """
679- The Divider class whose rectangle area is specified as a subplot geometry.
680+ A `SubplotDivider` for laying out axes vertically, while ensuring that they
681+ have equal widths.
680682 """
681683
682684 def new_locator (self , ny , ny1 = None ):
@@ -697,18 +699,15 @@ def locate(self, nx, ny, nx1=None, ny1=None, axes=None, renderer=None):
697699 # docstring inherited
698700 figW , figH = self ._fig .get_size_inches ()
699701 x , y , w , h = self .get_position_runtime (axes , renderer )
700-
701702 x_equivalent_sizes = self .get_horizontal_sizes (renderer )
702703 y_appended_sizes = self .get_vertical_sizes (renderer )
703- y0 , x0 , oy , ww = self . _locate (y , x , h , w ,
704- x_equivalent_sizes , y_appended_sizes ,
705- figH , figW )
704+ y0 , x0 , oy , ww = _locate (y , x , h , w ,
705+ x_equivalent_sizes , y_appended_sizes ,
706+ figH , figW , self . get_anchor () )
706707 if ny1 is None :
707708 ny1 = ny + 1
708-
709709 x1 , w1 = x0 , ww
710710 y1 , h1 = y0 + oy [ny ] / figH , (oy [ny1 ] - oy [ny ]) / figH
711-
712711 return mtransforms .Bbox .from_bounds (x1 , y1 , w1 , h1 )
713712
714713
0 commit comments