Repository: Ultraplot/UltraPlot

Issue:
Error when setting `labelloc` of the figure's colorbar
A reproducible example:

```python
import ultraplot as uplt

cmap = uplt.Colormap("plasma_r")
fig, axs = uplt.subplots(nrows=1, ncols=2)
fig.colorbar(cmap, loc="bottom", label="My Label")
```

![Image](https://github.com/user-attachments/assets/61ad822e-3d08-46e0-893c-82b0a70169ed)


```python
import ultraplot as uplt

cmap = uplt.Colormap("plasma_r")
fig, axs = uplt.subplots(nrows=1, ncols=2)
fig.colorbar(cmap, loc="bottom", label="My Label", labelloc="right")  # add `labelloc="right"`
```

```text
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[40], line 5
      3 cmap = uplt.Colormap("plasma_r")
      4 fig, axs = uplt.subplots(nrows=1, ncols=2)
----> 5 fig.colorbar(cmap, loc="bottom", label="My Label", labelloc="right")  # , labelloc="right"

File /usr/local/miniforge3/envs/experiment/lib/python3.12/site-packages/ultraplot/figure.py:1796, in Figure.colorbar(self, mappable, values, loc, location, row, col, rows, cols, span, space, pad, width, **kwargs)
   1784     loc = _not_none(loc=loc, location=location, default="r")
   1785     ax = self._add_figure_panel(
   1786         loc,
   1787         row=row,
   (...)   1794         pad=pad,
   1795     )
-> 1796     cb = ax.colorbar(mappable, values, loc="fill", **kwargs)
   1797 return cb

File /usr/local/miniforge3/envs/experiment/lib/python3.12/site-packages/ultraplot/axes/base.py:3147, in Axes.colorbar(self, mappable, values, loc, location, **kwargs)
   3145     self._register_guide("colorbar", (mappable, values), (loc, align), **kwargs)
   3146 else:
-> 3147     return self._add_colorbar(mappable, values, loc=loc, align=align, **kwargs)

File /usr/local/miniforge3/envs/experiment/lib/python3.12/site-packages/ultraplot/internals/warnings.py:118, in _rename_kwargs.<locals>._decorator.<locals>._deprecate_kwargs_wrapper(*args, **kwargs)
    113         key_new = key_new.format(value)
    114     _warn_ultraplot(
    115         f"Keyword {key_old!r} was deprecated in version {version} and may "
    116         f"be removed in {next_release()}. Please use {key_new!r} instead."
    117     )
--> 118 return func_orig(*args, **kwargs)

File /usr/local/miniforge3/envs/experiment/lib/python3.12/site-packages/ultraplot/axes/base.py:1281, in Axes._add_colorbar(self, mappable, values, loc, align, space, pad, width, length, shrink, label, title, reverse, rotation, grid, edges, drawedges, extend, extendsize, extendfrac, ticks, locator, locator_kw, format, formatter, ticklabels, formatter_kw, minorticks, minorlocator, minorlocator_kw, tickminor, ticklen, ticklenratio, tickdir, tickdirection, tickwidth, tickwidthratio, ticklabelsize, ticklabelweight, ticklabelcolor, labelloc, labellocation, labelsize, labelweight, labelcolor, c, color, lw, linewidth, edgefix, rasterized, **kwargs)
   1279                 axis = obj._short_axis()
   1280         case _:
-> 1281             raise ValueError("Location not understood.")
   1282     axis.set_label_position(labelloc)
   1283 axis.label.update(kw_label)

ValueError: Location not understood.
```

Hints from issue comments:
@cvanelteren: Hm ok for singular axes it works however. Will fix this.@cvanelteren: The issue is caused by loc being set to `fill` for fig colorbars. I added the additional clause, but it is not giving the expected output (label is on the bottom). 

Solution patch:
diff --git a/ultraplot/axes/base.py b/ultraplot/axes/base.py
index 41c33bab..d5b1564b 100644
--- a/ultraplot/axes/base.py
+++ b/ultraplot/axes/base.py
@@ -1257,14 +1257,23 @@ class Axes(maxes.Axes):
                     elif labelloc in ("left", "right"):
                         obj.ax.set_ylabel(label)
                     else:
-                        raise ValueError("Could not determined position")
+                        raise ValueError("Could not determine position")
                 case "left" | "right":
                     if labelloc in (None, "left", "right"):
                         obj.set_label(label)
                     elif labelloc in ("top", "bottom"):
                         obj.ax.set_xlabel(label)
                     else:
-                        raise ValueError("Could not determined position")
+                        raise ValueError("Could not determine position")
+                case "fill":
+                    if labelloc in ("left", "right"):
+                        obj.ax.set_ylabel(label)
+                    elif labelloc in ("top", "bottom"):
+                        obj.ax.set_xlabel(label)
+                    elif labelloc is None:
+                        obj.set_label(label)
+                    else:
+                        raise ValueError("Could not determine position")
                 # Default to setting label on long axis
                 case _:
                     obj.set_label(label)
@@ -1277,6 +1286,11 @@ class Axes(maxes.Axes):
                 case "left" | "right":
                     if labelloc in ("top", "bottom"):
                         axis = obj._short_axis()
+                case "fill":
+                    if labelloc in ("top", "bottom"):
+                        axis = obj._long_axis()
+                    elif labelloc in ("left", "right"):
+                        axis = obj._short_axis()
                 case _:
                     raise ValueError("Location not understood.")
             axis.set_label_position(labelloc)


Test patch:
diff --git a/ultraplot/tests/test_colorbar.py b/ultraplot/tests/test_colorbar.py
index 98a2ec11..66f2e4db 100644
--- a/ultraplot/tests/test_colorbar.py
+++ b/ultraplot/tests/test_colorbar.py
@@ -288,3 +288,15 @@ def test_label_placement_colorbar():
     locs = "top bottom left right".split()
     for loc, labelloc in zip(locs, locs):
         ax.colorbar(h, loc=loc, labelloc=labelloc)
+
+
+@pytest.mark.mpl_image_compare
+def test_label_placement_fig_colorbar2():
+    """
+    Ensure that all potential combinations of colorbar
+    label placement is possible.
+    """
+    cmap = uplt.Colormap("plasma_r")
+    fig, axs = uplt.subplots(nrows=1, ncols=2)
+    fig.colorbar(cmap, loc="bottom", label="My Label", labelloc="right")
+    return fig