Skip to content

Commit 37fcc3f

Browse files
authored
Merge pull request matplotlib#20069 from anntzer/vhb
Don't make VBoxDivider inherit from HBoxDivider.
2 parents 165607c + e3ed0f1 commit 37fcc3f

File tree

1 file changed

+74
-77
lines changed

1 file changed

+74
-77
lines changed

lib/mpl_toolkits/axes_grid1/axes_divider.py

Lines changed: 74 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -574,39 +574,67 @@ def get_subplotspec(self):
574574
return None
575575

576576

577-
class HBoxDivider(SubplotDivider):
577+
# Helper for HBoxDivider/VBoxDivider.
578+
# The variable names are written for a horizontal layout, but the calculations
579+
# work identically for vertical layouts (and likewise for the helpers below).
580+
def _determine_karray(summed_widths, equal_heights, total_width, max_height):
581+
n = len(equal_heights)
582+
eq_rs, eq_as = np.asarray(equal_heights).T
583+
sm_rs, sm_as = np.asarray(summed_widths).T
584+
A = np.zeros((n + 1, n + 1))
585+
B = np.zeros(n + 1)
586+
np.fill_diagonal(A[:n, :n], eq_rs)
587+
A[:n, -1] = -1
588+
A[-1, :-1] = sm_rs
589+
B[:n] = -eq_as
590+
B[-1] = total_width - sum(sm_as)
591+
# A @ K = B: This solves for {k_0, ..., k_{N-1}, H} so that
592+
# eq_r_i * k_i + eq_a_i = H for all i: all axes have the same height
593+
# sum(sm_r_i * k_i + sm_a_i) = total_summed_width: fixed total width
594+
# (foo_r_i * k_i + foo_a_i will end up being the size of foo.)
595+
karray_and_height = np.linalg.solve(A, B)
596+
karray = karray_and_height[:-1]
597+
height = karray_and_height[-1]
598+
if height > max_height: # Additionally, upper-bound the height.
599+
karray = (max_height - eq_as) / eq_rs
600+
return karray
601+
602+
603+
# Helper for HBoxDivider/VBoxDivider (see above re: variable naming).
604+
def _calc_offsets(summed_sizes, karray):
605+
offsets = [0.]
606+
for (r, a), k in zip(summed_sizes, karray):
607+
offsets.append(offsets[-1] + r*k + a)
608+
return offsets
609+
610+
611+
# Helper for HBoxDivider/VBoxDivider (see above re: variable naming).
612+
def _locate(x, y, w, h, summed_widths, equal_heights, fig_w, fig_h, anchor):
613+
karray = _determine_karray(
614+
summed_widths, equal_heights,
615+
total_width=fig_w * w, max_height=fig_h * h)
616+
ox = _calc_offsets(summed_widths, karray)
617+
618+
ww = (ox[-1] - ox[0]) / fig_w
619+
h0_r, h0_a = equal_heights[0]
620+
hh = (karray[0]*h0_r + h0_a) / fig_h
621+
pb = mtransforms.Bbox.from_bounds(x, y, w, h)
622+
pb1 = mtransforms.Bbox.from_bounds(x, y, ww, hh)
623+
pb1_anchored = pb1.anchored(anchor, pb)
624+
x0, y0 = pb1_anchored.x0, pb1_anchored.y0
625+
626+
return x0, y0, ox, hh
578627

579-
@staticmethod
580-
def _determine_karray(equivalent_sizes, appended_sizes,
581-
max_equivalent_size,
582-
total_appended_size):
583-
n = len(equivalent_sizes)
584-
eq_rs, eq_as = np.asarray(equivalent_sizes).T
585-
ap_rs, ap_as = np.asarray(appended_sizes).T
586-
A = np.zeros((n + 1, n + 1))
587-
B = np.zeros(n + 1)
588-
np.fill_diagonal(A[:n, :n], eq_rs)
589-
A[:n, -1] = -1
590-
A[-1, :-1] = ap_rs
591-
B[:n] = -eq_as
592-
B[-1] = total_appended_size - sum(ap_as)
593-
# A @ K = B: This solves for {k_0, ..., k_{N-1}, H} so that
594-
# eq_r_i * k_i + eq_a_i = H for all i: all axes have the same height
595-
# sum(ap_r_i * k_i + ap_a_i) = total_appended_size: fixed total width
596-
# (foo_r_i * k_i + foo_a_i will end up being the size of foo.)
597-
karray_H = np.linalg.solve(A, B)
598-
karray = karray_H[:-1]
599-
H = karray_H[-1]
600-
if H > max_equivalent_size: # Additionally, upper-bound the height.
601-
karray = (max_equivalent_size - eq_as) / eq_rs
602-
return karray
603628

604-
@staticmethod
605-
def _calc_offsets(appended_sizes, karray):
606-
offsets = [0.]
607-
for (r, a), k in zip(appended_sizes, karray):
608-
offsets.append(offsets[-1] + r*k + a)
609-
return offsets
629+
class HBoxDivider(SubplotDivider):
630+
"""
631+
A `SubplotDivider` for laying out axes horizontally, while ensuring that
632+
they have equal heights.
633+
634+
Examples
635+
--------
636+
.. plot:: gallery/axes_grid1/demo_axes_hbox_divider.py
637+
"""
610638

611639
def new_locator(self, nx, nx1=None):
612640
"""
@@ -622,52 +650,25 @@ def new_locator(self, nx, nx1=None):
622650
"""
623651
return AxesLocator(self, nx, 0, nx1, None)
624652

625-
def _locate(self, x, y, w, h,
626-
y_equivalent_sizes, x_appended_sizes,
627-
figW, figH):
628-
equivalent_sizes = y_equivalent_sizes
629-
appended_sizes = x_appended_sizes
630-
631-
max_equivalent_size = figH * h
632-
total_appended_size = figW * w
633-
karray = self._determine_karray(equivalent_sizes, appended_sizes,
634-
max_equivalent_size,
635-
total_appended_size)
636-
637-
ox = self._calc_offsets(appended_sizes, karray)
638-
639-
ww = (ox[-1] - ox[0]) / figW
640-
ref_h = equivalent_sizes[0]
641-
hh = (karray[0]*ref_h[0] + ref_h[1]) / figH
642-
pb = mtransforms.Bbox.from_bounds(x, y, w, h)
643-
pb1 = mtransforms.Bbox.from_bounds(x, y, ww, hh)
644-
pb1_anchored = pb1.anchored(self.get_anchor(), pb)
645-
x0, y0 = pb1_anchored.x0, pb1_anchored.y0
646-
647-
return x0, y0, ox, hh
648-
649653
def locate(self, nx, ny, nx1=None, ny1=None, axes=None, renderer=None):
650654
# docstring inherited
651-
figW, figH = self._fig.get_size_inches()
655+
fig_w, fig_h = self._fig.get_size_inches()
652656
x, y, w, h = self.get_position_runtime(axes, renderer)
653-
654-
y_equivalent_sizes = self.get_vertical_sizes(renderer)
655-
x_appended_sizes = self.get_horizontal_sizes(renderer)
656-
x0, y0, ox, hh = self._locate(x, y, w, h,
657-
y_equivalent_sizes, x_appended_sizes,
658-
figW, figH)
657+
summed_ws = self.get_horizontal_sizes(renderer)
658+
equal_hs = self.get_vertical_sizes(renderer)
659+
x0, y0, ox, hh = _locate(
660+
x, y, w, h, summed_ws, equal_hs, fig_w, fig_h, self.get_anchor())
659661
if nx1 is None:
660662
nx1 = nx + 1
661-
662-
x1, w1 = x0 + ox[nx] / figW, (ox[nx1] - ox[nx]) / figW
663+
x1, w1 = x0 + ox[nx] / fig_w, (ox[nx1] - ox[nx]) / fig_w
663664
y1, h1 = y0, hh
664-
665665
return mtransforms.Bbox.from_bounds(x1, y1, w1, h1)
666666

667667

668-
class VBoxDivider(HBoxDivider):
668+
class VBoxDivider(SubplotDivider):
669669
"""
670-
The Divider class whose rectangle area is specified as a subplot geometry.
670+
A `SubplotDivider` for laying out axes vertically, while ensuring that they
671+
have equal widths.
671672
"""
672673

673674
def new_locator(self, ny, ny1=None):
@@ -686,20 +687,16 @@ def new_locator(self, ny, ny1=None):
686687

687688
def locate(self, nx, ny, nx1=None, ny1=None, axes=None, renderer=None):
688689
# docstring inherited
689-
figW, figH = self._fig.get_size_inches()
690+
fig_w, fig_h = self._fig.get_size_inches()
690691
x, y, w, h = self.get_position_runtime(axes, renderer)
691-
692-
x_equivalent_sizes = self.get_horizontal_sizes(renderer)
693-
y_appended_sizes = self.get_vertical_sizes(renderer)
694-
y0, x0, oy, ww = self._locate(y, x, h, w,
695-
x_equivalent_sizes, y_appended_sizes,
696-
figH, figW)
692+
summed_hs = self.get_vertical_sizes(renderer)
693+
equal_ws = self.get_horizontal_sizes(renderer)
694+
y0, x0, oy, ww = _locate(
695+
y, x, h, w, summed_hs, equal_ws, fig_h, fig_w, self.get_anchor())
697696
if ny1 is None:
698697
ny1 = ny + 1
699-
700698
x1, w1 = x0, ww
701-
y1, h1 = y0 + oy[ny] / figH, (oy[ny1] - oy[ny]) / figH
702-
699+
y1, h1 = y0 + oy[ny] / fig_h, (oy[ny1] - oy[ny]) / fig_h
703700
return mtransforms.Bbox.from_bounds(x1, y1, w1, h1)
704701

705702

0 commit comments

Comments
 (0)