Skip to content
83 changes: 83 additions & 0 deletions ultraplot/axes/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1870,6 +1870,16 @@ def _get_size_inches(self):
bbox = self.get_position()
width = width * abs(bbox.width)
height = height * abs(bbox.height)
dpi = getattr(self.figure, "dpi", None)
if dpi:
width = round(width * dpi) / dpi
height = round(height * dpi) / dpi
fig = self.figure
if fig is not None and getattr(fig, "_refnum", None) == self.number:
if getattr(fig, "_refwidth", None) is not None:
width = fig._refwidth
if getattr(fig, "_refheight", None) is not None:
height = fig._refheight
return np.array([width, height])

def _get_topmost_axes(self):
Expand Down Expand Up @@ -2791,6 +2801,79 @@ def _reposition_subplot(self):
self.update_params()
setter(self.figbox) # equivalent to above

# In UltraLayout, place panels relative to their parent axes, not the grid.
if (
self._panel_parent
and self._panel_side
and self.figure.gridspec._use_ultra_layout
):
gs = self.get_subplotspec().get_gridspec()
figwidth, figheight = self.figure.get_size_inches()
ss = self.get_subplotspec().get_topmost_subplotspec()
row1, row2, col1, col2 = ss._get_rows_columns(ncols=gs.ncols_total)
side = self._panel_side
parent_bbox = self._panel_parent.get_position()
panels = list(self._panel_parent._panel_dict.get(side, ()))
anchor_ax = self._panel_parent
if self in panels:
idx = panels.index(self)
if idx > 0:
anchor_ax = panels[idx - 1]
elif panels:
anchor_ax = panels[-1]
anchor_bbox = anchor_ax.get_position()
anchor_ss = anchor_ax.get_subplotspec().get_topmost_subplotspec()
a_row1, a_row2, a_col1, a_col2 = anchor_ss._get_rows_columns(
ncols=gs.ncols_total
)

if side in ("right", "left"):
boundary = None
width = sum(gs._wratios_total[col1 : col2 + 1]) / figwidth
if a_col2 < col1:
boundary = a_col2
elif col2 < a_col1:
boundary = col2
# Fall back to an interface adjacent to this panel
boundary = min(
max(
_not_none(boundary, a_col2 if side == "right" else col2),
0,
),
len(gs.wspace_total) - 1,
)
pad = gs.wspace_total[boundary] / figwidth
if side == "right":
x0 = anchor_bbox.x1 + pad
else:
x0 = anchor_bbox.x0 - pad - width
bbox = mtransforms.Bbox.from_bounds(
x0, parent_bbox.y0, width, parent_bbox.height
)
else:
boundary = None
height = sum(gs._hratios_total[row1 : row2 + 1]) / figheight
if a_row2 < row1:
boundary = a_row2
elif row2 < a_row1:
boundary = row2
boundary = min(
max(
_not_none(boundary, a_row2 if side == "top" else row2),
0,
),
len(gs.hspace_total) - 1,
)
pad = gs.hspace_total[boundary] / figheight
if side == "top":
y0 = anchor_bbox.y1 + pad
else:
y0 = anchor_bbox.y0 - pad - height
bbox = mtransforms.Bbox.from_bounds(
parent_bbox.x0, y0, parent_bbox.width, height
)
setter(bbox)

def _update_abc(self, **kwargs):
"""
Update the a-b-c label.
Expand Down
2 changes: 1 addition & 1 deletion ultraplot/axes/plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -3287,9 +3287,9 @@ def _parse_level_lim(
for z in zs:
if z is None: # e.g. empty scatter color
continue
z = inputs._to_numpy_array(z)
if z.ndim > 2: # e.g. imshow data
continue
z = inputs._to_numpy_array(z)
if inbounds and x is not None and y is not None: # ignore if None coords
z = self._inbounds_vlim(x, y, z, to_centers=to_centers)
imin, imax = inputs._safe_range(z, pmin, pmax)
Expand Down
2 changes: 2 additions & 0 deletions ultraplot/figure.py
Original file line number Diff line number Diff line change
Expand Up @@ -1841,6 +1841,8 @@ def _axes_dict(naxs, input, kw=False, default=None):
# Create or update the gridspec and add subplots with subplotspecs
# NOTE: The gridspec is added to the figure when we pass the subplotspec
if gs is None:
if "layout_array" not in gridspec_kw:
gridspec_kw = {**gridspec_kw, "layout_array": array}
gs = pgridspec.GridSpec(*array.shape, **gridspec_kw)
else:
gs.update(**gridspec_kw)
Expand Down
Loading
Loading