diff --git a/esis/optics/__init__.py b/esis/optics/__init__.py index 81654a2..0f6ce68 100644 --- a/esis/optics/__init__.py +++ b/esis/optics/__init__.py @@ -4,6 +4,7 @@ from . import mixins from . import abc +from ._requirements import * from ._front_apertures import * from ._central_obscurations import * from ._primary_mirrors import PrimaryMirror diff --git a/esis/optics/_requirements.py b/esis/optics/_requirements.py new file mode 100644 index 0000000..213ae8a --- /dev/null +++ b/esis/optics/_requirements.py @@ -0,0 +1,42 @@ +import dataclasses +import numpy as np +import astropy.units as u +import optika + +__all__ = [ + "Requirements", +] + + +@dataclasses.dataclass +class Requirements( + optika.mixins.Printable, +): + """ + Dataclass for storing the requirements of the ESIS optical system. + """ + + resolution_spatial: u.Quantity + """The required spatial resolution of the instrument.""" + + resolution_spectral: u.Quantity + """The required spectral resolution of the instrument.""" + + fov: u.Quantity + """The required field of view of the instrument.""" + + snr: u.Quantity + """The required signal-to-noise ratio of the instrument.""" + + cadence: u.Quantity + """The required cadence of the instrument.""" + + length_observation: u.Quantity + """The required amount of observing time.""" + + @property + def resolution_angular(self) -> u.Quantity: + """ + The angular resolution of the instrument. + """ + return np.arctan2(self.resolution_spatial, 1 * u.AU).to(u.arcsec) diff --git a/esis/optics/_tests/test_requirements.py b/esis/optics/_tests/test_requirements.py new file mode 100644 index 0000000..e9c6ba6 --- /dev/null +++ b/esis/optics/_tests/test_requirements.py @@ -0,0 +1,43 @@ +import pytest +import astropy.units as u +import optika._tests.test_mixins +import esis + + +@pytest.mark.parametrize( + argnames="a", + argvalues=[ + esis.optics.Requirements( + resolution_spatial=1.5 * u.Mm, + resolution_spectral=18 * u.km / u.s, + fov=10 * u.arcmin, + snr=17.3 * u.dimensionless_unscaled, + cadence=15 * u.s, + length_observation=150 * u.s, + ) + ], +) +class TestRequirements( + optika._tests.test_mixins.AbstractTestPrintable, +): + + def test_resolution_spatial(self, a: esis.optics.Requirements): + assert a.resolution_spatial > (0 * u.m) + + def test_resolution_spectral(self, a: esis.optics.Requirements): + assert a.resolution_spectral > (0 * u.km / u.s) + + def test_fov(self, a: esis.optics.Requirements): + assert a.fov > (0 * u.arcmin) + + def test_snr(self, a: esis.optics.Requirements): + assert a.snr > 0 + + def test_cadence(self, a: esis.optics.Requirements): + assert a.cadence > (0 * u.s) + + def test_length_observation(self, a: esis.optics.Requirements): + assert a.length_observation > (0 * u.s) + + def test_resolution_angular(self, a: esis.optics.Requirements): + assert a.resolution_angular > (0 * u.arcsec)