Skip to content

Commit 9afb03f

Browse files
authored
Add get_inset_map_bounds (#403)
* Add get_inset_map_bounds * Improve docstrings
1 parent c9ebd96 commit 9afb03f

File tree

3 files changed

+91
-4
lines changed

3 files changed

+91
-4
lines changed

nlmod/plot/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
get_figsize,
2020
get_map,
2121
inset_map,
22+
get_inset_map_bounds,
2223
rd_ticks,
2324
rotate_yticklabels,
2425
title_inside,

nlmod/plot/plotutil.py

Lines changed: 73 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,76 @@ def title_inside(
275275
)
276276

277277

278+
def _get_axes_aspect_ratio(ax):
279+
pos = ax.get_position()
280+
width = pos.width * ax.figure.get_figwidth()
281+
height = pos.height * ax.figure.get_figheight()
282+
return width / height
283+
284+
285+
def get_inset_map_bounds(
286+
ax: plt.Axes,
287+
extent: Union[tuple[float], list[float]],
288+
height: Optional[float] = None,
289+
width: Optional[float] = None,
290+
margin: Optional[float] = 0.025,
291+
right: Optional[bool] = True,
292+
bottom: Optional[bool] = True,
293+
):
294+
"""Get the bounds of the inset_map from a width or height, and a margin.
295+
296+
These bounds can be used for the parameter `axes_bounds` in the `inset_map` method.
297+
The horizontal and vertical margin (in pixels) around this map are equal (unless the
298+
figure is reshaped).
299+
300+
Parameters
301+
----------
302+
ax : matplotlib.Axes
303+
The axes to add the inset map to.
304+
extent : list of 4 floats
305+
The extent of the inset map.
306+
height : float, optional
307+
The height of the inset axes, in axes coordinates. Either height or width needs
308+
to be specified. The default is None.
309+
width : float, optional
310+
The width of the inset axes, in axes coordinates. Either height or width needs
311+
to be specified. The default is None.
312+
margin : float, optional
313+
The margin around, in axes coordinates. When height is specified, margin is
314+
relative to the height of ax. When width is specified, margin is relative to the
315+
width of ax. The default is 0.025.
316+
right : bool, optional
317+
If True, the inset axes is placed at the right corner. The default is True.
318+
bottom : bool, optional
319+
If True, the inset axes is placed at the bottom corner. The default is True.
320+
321+
Returns
322+
-------
323+
bounds: list of 4 floats
324+
The bounds (left, right, width, height) of the inset axes.
325+
326+
"""
327+
msg = "Please specify either height or width"
328+
assert (height is None) + (width is None) == 1, msg
329+
ar = _get_axes_aspect_ratio(ax)
330+
dxdy = (extent[1] - extent[0]) / (extent[3] - extent[2])
331+
if height is None:
332+
# the bounds are determined by width
333+
height = width * ar / dxdy
334+
bounds = [margin, margin * ar, width, height]
335+
else:
336+
# the bounds are determined by height
337+
width = height * dxdy / ar
338+
bounds = [margin / ar, margin, width, height]
339+
if right:
340+
# put the axes on the right side
341+
bounds[0] = 1 - bounds[0] - width
342+
if not bottom:
343+
# put the axes on the top side
344+
bounds[1] = 1 - bounds[1] - height
345+
return bounds
346+
347+
278348
def inset_map(
279349
ax: plt.Axes,
280350
extent: Union[tuple[float], list[float]],
@@ -291,9 +361,9 @@ def inset_map(
291361
The axes to add the inset map to.
292362
extent : list of 4 floats
293363
The extent of the inset map.
294-
axes_bounds : list of 4 floats, optional
295-
The bounds (left, right, width height) of the inset axes, default
296-
is [0.63, 0.025, 0.35, 0.35]. This is rescaled according to the extent of
364+
axes_bounds : list or tuple of 4 floats, optional
365+
The bounds (left, right, width, height) of the inset axes, default
366+
is (0.63, 0.025, 0.35, 0.35). This is rescaled according to the extent of
297367
the inset map.
298368
anchor : str, optional
299369
The anchor point of the inset map, default is 'SE'.

tests/test_011_dcs.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,21 @@ def test_cross_section_utils():
3333
dcs.label_layers()
3434
dcs.plot_array(ds["kh"], alpha=0.5)
3535
dcs.plot_grid(vertical=False)
36-
mapax = nlmod.plot.inset_map(ax, ds.extent, provider=None)
36+
37+
# add a map at the bottom right corner, 35 % of axes hight
38+
axes_bounds = nlmod.plot.plotutil.get_inset_map_bounds(
39+
ax=ax, extent=ds.extent, height=0.35, right=True
40+
)
41+
mapax = nlmod.plot.inset_map(ax, ds.extent, provider=None, axes_bounds=axes_bounds)
42+
nlmod.plot.add_xsec_line_and_labels(line, ax, mapax)
43+
44+
# add a map at the top left corner, 20 % of axes width
45+
axes_bounds = nlmod.plot.get_inset_map_bounds(
46+
ax=ax,
47+
extent=ds.extent,
48+
width=0.2,
49+
right=False,
50+
bottom=False,
51+
)
52+
mapax = nlmod.plot.inset_map(ax, ds.extent, provider=None, axes_bounds=axes_bounds)
3753
nlmod.plot.add_xsec_line_and_labels(line, ax, mapax)

0 commit comments

Comments
 (0)