Repository: feder-observatory/stellarphot

Issue:
`Camera` model validation code contains an error
In writing #298 I stumbled on what is, I think, an error in the validation logic for the `Camera` model.

Consider this code, which *should* be a valid `Camera` but is not:

```python
from stellarphot.settings import Camera
c = Camera(
     name="should_work",
      data_unit="electron",
      gain="1",
      dark_current="0.01 electron / second",
      read_noise="1.2 electron",
      pixel_scale="0.55 arcsec / pix",
      max_data_value="80000 electron"
 )
```

It fails because of the way that we check that the the `gain` has units `read_noise` / `data_unit` is this:

```python
            len(gain.unit.bases) != 2
            or gain.unit.bases[0] != rn_unit
            or gain.unit.bases[1] != self.data_unit
```

That fails here because `1` fails the first test.

Opening a PR shortly to fix this....

Discussion:

Patch:
diff --git a/stellarphot/settings/models.py b/stellarphot/settings/models.py
index db043c2..09c9e8a 100644
--- a/stellarphot/settings/models.py
+++ b/stellarphot/settings/models.py
@@ -7,7 +7,7 @@ from typing import Annotated, Any, Literal
 from astropy.coordinates import EarthLocation, Latitude, Longitude, SkyCoord
 from astropy.io.misc.yaml import AstropyDumper, AstropyLoader
 from astropy.time import Time
-from astropy.units import Quantity, Unit
+from astropy.units import Quantity, Unit, UnitConversionError
 from astropy.utils import lazyproperty
 from pydantic import (
     AfterValidator,
@@ -294,15 +294,14 @@ class Camera(BaseModelWithTableRep):
         # Check that gain and read noise have compatible units, that is that
         # gain is read noise per data unit.
         gain = self.gain
-        if (
-            len(gain.unit.bases) != 2
-            or gain.unit.bases[0] != rn_unit
-            or gain.unit.bases[1] != self.data_unit
-        ):
+
+        try:
+            gain.to(self.read_noise.unit / self.data_unit)
+        except UnitConversionError as e:
             raise ValueError(
                 f"Gain units {gain.unit} are not compatible with "
                 f"read noise units {rn_unit}."
-            )
+            ) from e
 
         # Check that dark current and read noise have compatible units, that is
         # that dark current is read noise per second.


Test patch:
diff --git a/stellarphot/settings/tests/test_models.py b/stellarphot/settings/tests/test_models.py
index a580347..577d5cd 100644
--- a/stellarphot/settings/tests/test_models.py
+++ b/stellarphot/settings/tests/test_models.py
@@ -302,6 +302,21 @@ def test_camera_incompatible_gain_units():
         )
 
 
+def test_camera_unitsless_gain():
+    # Regression test for #299
+    c = Camera(
+        name="should_work",
+        data_unit="electron",
+        gain="1",
+        dark_current="0.01 electron / second",
+        read_noise="1.2 electron",
+        pixel_scale="0.55 arcsec / pix",
+        max_data_value="80000 electron",
+    )
+
+    assert c.gain == u.Quantity(1)
+
+
 def test_camera_incompatible_max_val_units():
     camera_for_test = TEST_CAMERA_VALUES.copy()
     # data unit is adu, not count