Repository: scipp/plopp

Issue:
Cannot pass float for size of markers in 2d scatter plot
```Py
import plopp as pp

pp.scatter(pp.data.scatter(), size=4)
```
raises an error as it wants the `size` argument to be the name of a coord that represents the sizes.
However, this does work fine in `scatter3d`.

A workaround is to use `pp.scatter(pp.data.scatter(), s=4)`, but we should make the interfaces consistent.

Discussion:

Patch:
diff --git a/docs/user-guide/plot-types/scatter-plot.ipynb b/docs/user-guide/plot-types/scatter-plot.ipynb
index fdf1e2e..99c9a70 100644
--- a/docs/user-guide/plot-types/scatter-plot.ipynb
+++ b/docs/user-guide/plot-types/scatter-plot.ipynb
@@ -53,7 +53,7 @@
    "metadata": {},
    "outputs": [],
    "source": [
-    "pp.scatter(a, color='r', marker='P')"
+    "pp.scatter(a, color='r', marker='P', size=120)"
    ]
   },
   {
@@ -147,7 +147,9 @@
    "id": "14",
    "metadata": {},
    "source": [
-    "## Scatter plot with sizes"
+    "## Scatter plot with variable sizes\n",
+    "\n",
+    "We can use a coordinate of the input data array to represent the marker sizes by giving the name of the coordinate as the `size` argument."
    ]
   },
   {
diff --git a/src/plopp/backends/matplotlib/scatter.py b/src/plopp/backends/matplotlib/scatter.py
index 258164c..047cca9 100644
--- a/src/plopp/backends/matplotlib/scatter.py
+++ b/src/plopp/backends/matplotlib/scatter.py
@@ -24,7 +24,7 @@ class Scatter:
         data: sc.DataArray,
         x: str = 'x',
         y: str = 'y',
-        size: str | None = None,
+        size: str | float | None = None,
         artist_number: int = 0,
         mask_color: str = 'black',
         cbar: bool = False,
@@ -40,6 +40,8 @@ class Scatter:
         # Because all keyword arguments from the figure are forwarded to both the canvas
         # and the line, we need to remove the arguments that belong to the canvas.
         kwargs.pop('ax', None)
+        if 's' in kwargs:
+            raise ValueError("Use 'size' instead of 's' for scatter plot.")
 
         scatter_kwargs = parse_dicts_in_kwargs(kwargs, name=data.name)
 
@@ -55,15 +57,16 @@ class Scatter:
             default_plot_style['color'] = f'C{artist_number}'
 
         merged_kwargs = {**default_plot_style, **scatter_kwargs}
-        if self._size is None:
-            s = merged_kwargs.pop('s', None)
-        else:
-            s = self._data.coords[self._size].values
+        marker_size = (
+            self._data.coords[self._size].values
+            if isinstance(self._size, str)
+            else self._size
+        )
 
         self._scatter = self._ax.scatter(
             self._data.coords[self._x].values,
             self._data.coords[self._y].values,
-            s=s,
+            s=marker_size,
             label=self.label,
             **merged_kwargs,
         )
@@ -79,7 +82,7 @@ class Scatter:
         self._mask = self._ax.scatter(
             xmask,
             ymask,
-            s=s,
+            s=marker_size,
             marker=merged_kwargs['marker'],
             edgecolors=mask_color,
             facecolor="None",
@@ -105,7 +108,7 @@ class Scatter:
                 axis=1,
             )
         )
-        if self._size is not None:
+        if isinstance(self._size, str):
             self._scatter.set_sizes(self._data.coords[self._size].values)
 
     def remove(self):
diff --git a/src/plopp/plotting/scatter.py b/src/plopp/plotting/scatter.py
index 7e80cc6..d84ec29 100644
--- a/src/plopp/plotting/scatter.py
+++ b/src/plopp/plotting/scatter.py
@@ -22,7 +22,7 @@ def _preprocess_scatter(
     check_not_binned(da)
 
     cnames = [x, y]
-    if size is not None:
+    if isinstance(size, str):
         cnames.append(size)
     coords = {k: da.coords[k] for k in cnames}
     out = sc.DataArray(data=da.data, masks=da.masks, coords=coords)


Test patch:
diff --git a/tests/plotting/scatter_test.py b/tests/plotting/scatter_test.py
index 7ddcc83..423716d 100644
--- a/tests/plotting/scatter_test.py
+++ b/tests/plotting/scatter_test.py
@@ -50,7 +50,17 @@ def test_scatter_with_cmap():
     assert scat.view.colormapper.cmap.name == name
 
 
-def test_scatter_with_size():
+def test_scatter_with_int_size():
+    a = scatter_data()
+    pp.scatter(a, size=10)
+
+
+def test_scatter_with_float_size():
+    a = scatter_data()
+    pp.scatter(a, size=33.3)
+
+
+def test_scatter_with_variable_size():
     a = scatter_data()
     a.coords['s'] = sc.abs(a.coords['x']) * 5
     pp.scatter(a, size='s')
@@ -62,6 +72,12 @@ def test_scatter_with_size_and_cbar():
     pp.scatter(a, size='s', cbar=True)
 
 
+def test_scatter_with_s_kwarg_raises():
+    a = scatter_data()
+    with pytest.raises(ValueError, match="Use 'size' instead of 's' for scatter plot."):
+        pp.scatter(a, s=10)
+
+
 def test_scatter_with_masks():
     a = scatter_data()
     a.masks['m'] = a.coords['x'] > sc.scalar(10, unit='m')