Repository: mathause/mplotutils

Issue:
enable set_map_layout for subfigures
I doubt this is possible. Currently subfigs can only have relative sizes, and it seems not possible to change them after the fact. Also the can be nested or vertical (I guess it would only work if they would span the whole width of the figure).


```python
%matplotlib

import mplotutils as mpu
import matplotlib.pyplot as plt
import cartopy.crs as ccrs

f = plt.figure()

sf1, sf2 = f.subfigures(2, 1)

axs = sf1.subplots(1, 2, subplot_kw={"projection": ccrs.Robinson()})
sf1.set_facecolor("0.5")
sf1.canvas.draw()

# errors
# mpu.set_map_layout(axs)

```


Discussion:

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2b56449..6b4777e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,8 @@
 ### Enhancements
 
 - Enable passing `AxesGrid` (from `mpl_toolkits.axes_grid1`) to `set_map_layout` ([#116](https://github.com/mathause/mplotutils/pull/116)).
+- Raise more informative error when a wrong type is passed to `set_map_layout` ([#121](https://github.com/mathause/mplotutils/pull/121)).
+- `set_map_layout` now raises an explicit error when the figure contains SubFigure ([#121](https://github.com/mathause/mplotutils/pull/121)).
 
 ## v0.5.0 (27.03.2024)
 
diff --git a/mplotutils/map_layout.py b/mplotutils/map_layout.py
index a03cf41..fa2232a 100644
--- a/mplotutils/map_layout.py
+++ b/mplotutils/map_layout.py
@@ -1,5 +1,6 @@
 import warnings
 
+import matplotlib as mpl
 import matplotlib.pyplot as plt
 import numpy as np
 from mpl_toolkits.axes_grid1 import AxesGrid
@@ -50,20 +51,23 @@ def set_map_layout(obj=None, width=17.0, *, nrow=None, ncol=None, axes=None):
         _set_map_layout_axes(obj, width, nrow, ncol)
 
 
-def _set_map_layout_axes(axes, width, nrow, ncol):
+def _set_map_layout_axes(axs, width, nrow, ncol):
 
     if (nrow is None and ncol is not None) or (nrow is not None and ncol is None):
         raise ValueError("Must set none or both of 'nrow' and 'ncol'")
 
-    if isinstance(axes, plt.Axes):
-        ax = axes
-    else:
-        # assumes the first of the axes is representative for all
-        ax = np.asarray(axes).flat[0]
+    # assumes the first of the axes is representative for all
+    ax = np.asarray(axs).flat[0]
+
+    if not isinstance(ax, plt.Axes):
+        raise TypeError(f"Expected axes or an array of axes, got {type(ax)}")
 
     # read figure data
     f = ax.get_figure()
 
+    if isinstance(f, mpl.figure.SubFigure) or f.subfigs:
+        raise RuntimeError("matplotlib SubFigure not supported")
+
     # getting the correct data ratio of geoaxes requires draw
     f.canvas.draw()
 


Test patch:
diff --git a/mplotutils/tests/test_set_map_layout.py b/mplotutils/tests/test_set_map_layout.py
index 391f3fc..d6f3e0d 100644
--- a/mplotutils/tests/test_set_map_layout.py
+++ b/mplotutils/tests/test_set_map_layout.py
@@ -25,6 +25,29 @@ def test_set_map_layout_deprecated_kwarg():
         set_map_layout(object, axes=object)
 
 
+def test_map_layout_not_axes_error():
+
+    with figure_context() as f:
+        with pytest.raises(TypeError, match="Expected axes or an array of axes"):
+            set_map_layout(f)
+
+    with pytest.raises(TypeError, match="Expected axes or an array of axes"):
+        set_map_layout(object)
+
+
+def test_map_layout_subfigures_error():
+
+    with figure_context() as f:
+        sf = f.subfigures(1, 1)
+        axs = sf.subplots(1, 2)
+
+        with pytest.raises(RuntimeError, match="matplotlib SubFigure not supported"):
+            set_map_layout(f.axes)
+
+        with pytest.raises(RuntimeError, match="matplotlib SubFigure not supported"):
+            set_map_layout(axs)
+
+
 def test_set_map_layout_default_width():
     with subplots_context() as (f, ax):
         set_map_layout(ax)