From 9852625d4d1d3408b90c87b59f27479e49f2f6e6 Mon Sep 17 00:00:00 2001 From: Roy Smart Date: Fri, 12 Dec 2025 13:55:58 -0700 Subject: [PATCH 1/5] Added a `AbstractSensor.material` field to store the light-sensitive material used by the sensor. --- msfc_ccd/_sensors.py | 19 ++++++++++++++++++- msfc_ccd/_tests/test_sensors.py | 4 ++++ pyproject.toml | 3 ++- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/msfc_ccd/_sensors.py b/msfc_ccd/_sensors.py index aff2aee..8bf2719 100644 --- a/msfc_ccd/_sensors.py +++ b/msfc_ccd/_sensors.py @@ -4,6 +4,7 @@ import numpy as np import astropy.units as u import named_arrays as na +import optika __all__ = [ "TeledyneCCD230", @@ -37,6 +38,11 @@ def family(self) -> str: def serial_number(self) -> None | str: """A unique number which identifies this sensor.""" + @property + @abc.abstractmethod + def material(self) -> optika.sensors.materials.AbstractSiliconSensorMaterial: + """The light-sensitive material used by this sensor.""" + @property @abc.abstractmethod def num_pixel(self) -> na.Cartesian2dVectorArray[int, int]: @@ -79,9 +85,9 @@ def readout_noise(self) -> u.Quantity: """The standard deviation of the error on each pixel value.""" @property - @abc.abstractmethod def temperature(self): """The operating temperature of this sensor.""" + return self.material.temperature def dark_current( self, @@ -120,6 +126,13 @@ class TeledyneCCD230( Grade 0 is the best possible and Grade 5 is the worst possible. """ + material: None | optika.sensors.materials.AbstractSiliconSensorMaterial = None + """ + The light-sensitive material used by this sensor. + + If :obj:`None`, :func:`optika.sensors.materials.ccd_97` will be used. + """ + width_pixel: u.Quantity = 15 * u.um """The physical size of a single pixel on the imaging sensor.""" @@ -158,6 +171,10 @@ class TeledyneCCD230( width_package_y: u.Quantity = 61 * u.mm """The vertical size of the physical sensor package.""" + def __post_init__(self): + if self.material is None: + self.material = optika.sensors.materials.e2v_ccd97() + @property def num_pixel(self) -> na.Cartesian2dVectorArray: return na.Cartesian2dVectorArray( diff --git a/msfc_ccd/_tests/test_sensors.py b/msfc_ccd/_tests/test_sensors.py index 156d167..8766827 100644 --- a/msfc_ccd/_tests/test_sensors.py +++ b/msfc_ccd/_tests/test_sensors.py @@ -1,6 +1,7 @@ import pytest import astropy.units as u import msfc_ccd +from optika.sensors.materials import AbstractSiliconSensorMaterial class AbstractTestAbstractSensor: @@ -22,6 +23,9 @@ def test_serial_number(self, a: msfc_ccd.abc.AbstractSensor): if a.serial_number is not None: assert isinstance(a.serial_number, str) + def test_material(self, a: msfc_ccd.abc.AbstractSensor): + assert isinstance(a.material, AbstractSiliconSensorMaterial) + def test_width_pixel(self, a: msfc_ccd.abc.AbstractSensor): assert a.width_pixel > 0 * u.um diff --git a/pyproject.toml b/pyproject.toml index bef4110..5feb053 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,7 +15,8 @@ classifiers = [ ] dependencies = [ "astropy", - "named-arrays>=0.26.0", + "named-arrays~=1.0", + "optika~=1.0", ] dynamic = ["version"] From 5306954b69f4ecedb3f4bb15d2b785e1df2abc25 Mon Sep 17 00:00:00 2001 From: Roy Smart Date: Fri, 12 Dec 2025 14:00:11 -0700 Subject: [PATCH 2/5] bump python version --- .github/workflows/tests.yml | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 0c95273..4fb279a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -18,7 +18,7 @@ jobs: windows-latest, macOS-latest, ] - python-version: ["3.10", "3.12"] + python-version: ["3.11", "3.13"] name: ${{ matrix.os }}, Python ${{ matrix.python-version }} test steps: - uses: actions/checkout@v2 diff --git a/pyproject.toml b/pyproject.toml index 5feb053..e141a03 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ authors = [ ] description = "A Python library for characterizing and using the CCD cameras developed by Marshall Space Flight Center." readme = "README.md" -requires-python = ">=3.10" +requires-python = ">=3.11" classifiers = [ "Programming Language :: Python :: 3", ] From c4cf98b5aa7652554ee50dfb5494ef338679231a Mon Sep 17 00:00:00 2001 From: Roy Smart Date: Sat, 13 Dec 2025 10:19:13 -0700 Subject: [PATCH 3/5] fix --- msfc_ccd/_sensors.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/msfc_ccd/_sensors.py b/msfc_ccd/_sensors.py index 8bf2719..0275e63 100644 --- a/msfc_ccd/_sensors.py +++ b/msfc_ccd/_sensors.py @@ -162,9 +162,6 @@ class TeledyneCCD230( or half of the sensor is used for storage (``"transfer"``). """ - temperature: u.Quantity | na.AbstractScalar = 248 * u.K - """The operating temperature of this sensor.""" - width_package_x: u.Quantity = 42 * u.mm """The horizontal size of the physical sensor package.""" From ab022bc8fb55a4b62693e3d6b7033daf45b105d4 Mon Sep 17 00:00:00 2001 From: Roy Smart Date: Sat, 13 Dec 2025 10:27:24 -0700 Subject: [PATCH 4/5] intersphinx --- docs/conf.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index 9b99f49..c66adec 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -101,5 +101,6 @@ 'matplotlib': ('https://matplotlib.org/stable', None), 'astropy': ('https://docs.astropy.org/en/stable/', None), 'astroscrappy': ('https://astroscrappy.readthedocs.io/en/stable/', None), - 'named_arrays': ('https://named-arrays.readthedocs.io/en/stable/', None) + 'named_arrays': ('https://named-arrays.readthedocs.io/en/stable/', None), + 'optika': ('https://optika.readthedocs.io/en/stable/', None), } From 41de1e923121d3db1b21c4dbc7645a26bfade8b2 Mon Sep 17 00:00:00 2001 From: Roy Smart Date: Sat, 13 Dec 2025 10:35:42 -0700 Subject: [PATCH 5/5] docs --- msfc_ccd/_sensors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msfc_ccd/_sensors.py b/msfc_ccd/_sensors.py index 0275e63..990f04b 100644 --- a/msfc_ccd/_sensors.py +++ b/msfc_ccd/_sensors.py @@ -130,7 +130,7 @@ class TeledyneCCD230( """ The light-sensitive material used by this sensor. - If :obj:`None`, :func:`optika.sensors.materials.ccd_97` will be used. + If :obj:`None`, :func:`optika.sensors.materials.e2v_ccd97` will be used. """ width_pixel: u.Quantity = 15 * u.um