Repository: ubermag/discretisedfield

Issue:
Plotting exceptions
The exceptions for wrong mesh dimensionality when trying to create a plot are not consistent between mpl, k3d. and hv.

Comments:

Patch:
diff --git a/discretisedfield/plotting/mpl_field.py b/discretisedfield/plotting/mpl_field.py
index a8724ddd..2a51e24c 100644
--- a/discretisedfield/plotting/mpl_field.py
+++ b/discretisedfield/plotting/mpl_field.py
@@ -37,7 +37,7 @@ class MplField(Mpl):
 
     def __init__(self, field):
         if field.mesh.region.ndim != 2:
-            raise ValueError(
+            raise RuntimeError(
                 "Only fields on 2d meshes can be plotted with matplotlib, not"
                 f" {field.mesh.region.ndim=}."
             )


Test patch:
diff --git a/discretisedfield/tests/test_field.py b/discretisedfield/tests/test_field.py
index fc82c893..49144f9a 100644
--- a/discretisedfield/tests/test_field.py
+++ b/discretisedfield/tests/test_field.py
@@ -2739,7 +2739,7 @@ def test_mpl_scalar(test_field):
         test_field.a.sel("x").mpl.scalar(filename=tmpfilename)
 
     # Exceptions
-    with pytest.raises(ValueError):
+    with pytest.raises(RuntimeError):
         test_field.a.mpl.scalar()  # not sliced
     with pytest.raises(ValueError):
         test_field.sel("z").mpl.scalar()  # vector field
@@ -2773,7 +2773,7 @@ def test_mpl_lightess(test_field):
             field.sel("z").mpl.lightness(filename=tmpfilename)
 
     # Exceptions
-    with pytest.raises(ValueError):
+    with pytest.raises(RuntimeError):
         test_field.mpl.lightness()  # not sliced
     with pytest.raises(ValueError):
         # wrong filter field
@@ -2829,7 +2829,7 @@ def test_mpl_vector(test_field):
         test_field.sel("x").mpl.vector(filename=tmpfilename)
 
     # Exceptions
-    with pytest.raises(ValueError):
+    with pytest.raises(RuntimeError):
         test_field.mpl.vector()  # not sliced
     with pytest.raises(ValueError):
         test_field.b.sel("z").mpl.vector()  # scalar field
@@ -2864,7 +2864,7 @@ def test_mpl_contour(test_field):
         test_field.sel("z").c.mpl.contour(filename=tmpfilename)
 
     # Exceptions
-    with pytest.raises(ValueError):
+    with pytest.raises(RuntimeError):
         test_field.mpl.contour()  # not sliced
     with pytest.raises(ValueError):
         test_field.sel("z").mpl.contour()  # vector field
@@ -2909,12 +2909,24 @@ def test_mpl(test_field):
         test_field.sel("x").mpl(filename=tmpfilename)
 
     # Exception
-    with pytest.raises(ValueError):
+    with pytest.raises(RuntimeError):
         test_field.mpl()
 
     plt.close("all")
 
 
+def test_mpl_dimension(valid_mesh):
+    field = df.Field(valid_mesh, nvdim=1)
+
+    if valid_mesh.region.ndim != 2:
+        with pytest.raises(RuntimeError):
+            field.mpl.scalar()
+    else:
+        field.mpl.scalar()
+
+    plt.close("all")
+
+
 def test_hv_scalar(test_field):
     for kdims in [["x", "y"], ["x", "z"], ["y", "z"]]:
         normal = (set("xyz") - set(kdims)).pop()
diff --git a/discretisedfield/tests/test_mesh.py b/discretisedfield/tests/test_mesh.py
index 5a2fe72d..3f08ba2d 100644
--- a/discretisedfield/tests/test_mesh.py
+++ b/discretisedfield/tests/test_mesh.py
@@ -1287,12 +1287,13 @@ def test_dV(p1, p2, cell, dV):
 
 def test_mpl(valid_mesh, tmp_path):
     if valid_mesh.region.ndim != 3:
-        pytest.xfail(reason="plotting only supports 3d")
-
-    valid_mesh.mpl()
-    valid_mesh.mpl(box_aspect=[1, 2, 3])
+        with pytest.raises(RuntimeError):
+            valid_mesh.mpl()
+    else:
+        valid_mesh.mpl()
+        valid_mesh.mpl(box_aspect=[1, 2, 3])
+        valid_mesh.mpl(filename=tmp_path / "figure.pdf")
 
-    valid_mesh.mpl(filename=tmp_path / "figure.pdf")
     plt.close("all")
 
 
@@ -1533,17 +1534,16 @@ def test_save_load_subregions(p1, p2, cell, tmp_path):
     assert test_mesh.subregions == sr
 
 
-@pytest.mark.xfail(reason="needs nd field")
-def test_coordinate_field(valid_mesh):  # TODO
+def test_coordinate_field(valid_mesh):
     cfield = valid_mesh.coordinate_field()
     assert isinstance(cfield, df.Field)
-    manually = df.Field(valid_mesh, dim=valid_mesh.region.ndim, value=lambda p: p)
+    manually = df.Field(valid_mesh, nvdim=valid_mesh.region.ndim, value=lambda p: p)
     assert cfield.allclose(manually, atol=0)
-    for dim in range(valid_mesh.region.ndim):
-        index = [
-            0,
-        ] * valid_mesh.region.ndim
+    for dim in valid_mesh.region.dims:
+        index = [0] * valid_mesh.region.ndim
         index[valid_mesh.region._dim2index(dim)] = slice(None)
+        # extra index for vector dimension: vector component along the current direction
+        index = tuple(index) + (valid_mesh.region._dim2index(dim),)
         assert np.allclose(cfield.array[index], getattr(valid_mesh.points, dim), atol=0)
 
 
diff --git a/discretisedfield/tests/test_region.py b/discretisedfield/tests/test_region.py
index 724c5eed..ac0c3edf 100644
--- a/discretisedfield/tests/test_region.py
+++ b/discretisedfield/tests/test_region.py
@@ -771,20 +771,20 @@ def test_mpl(p1, p2, tmp_path):
     region = df.Region(p1=p1, p2=p2)
 
     if region.ndim != 3:
-        pytest.xfail(reason="plotting only supports 3d")
-
-    # Check if it runs.
-    region.mpl()
-    region.mpl(
-        figsize=(10, 10),
-        multiplier=1e-9,
-        color=plot_util.cp_hex[1],
-        linewidth=3,
-        box_aspect=(1, 1.5, 2),
-        linestyle="dashed",
-    )
-
-    region.mpl(filename=tmp_path / "figure.pdf")
+        with pytest.raises(RuntimeError):
+            region.mpl()
+    else:
+        # Check if it runs.
+        region.mpl()
+        region.mpl(
+            figsize=(10, 10),
+            multiplier=1e-9,
+            color=plot_util.cp_hex[1],
+            linewidth=3,
+            box_aspect=(1, 1.5, 2),
+            linestyle="dashed",
+        )
+        region.mpl(filename=tmp_path / "figure.pdf")
 
     plt.close("all")