diff --git a/msfc_ccd/_images/_sensor_images.py b/msfc_ccd/_images/_sensor_images.py index b58f5f4..56f4f10 100644 --- a/msfc_ccd/_images/_sensor_images.py +++ b/msfc_ccd/_images/_sensor_images.py @@ -177,7 +177,7 @@ def from_fits( """ path = na.as_named_array(path) - time = na.ScalarArray.zeros(na.shape(path)) + time_start = na.ScalarArray.zeros(na.shape(path)) timedelta = np.empty_like(path, dtype=np.int64) timedelta_requested = np.empty_like(path, dtype=float) << u.s @@ -211,7 +211,7 @@ def from_fits( data[index] = data_index header = hdu.header - time[index] = astropy.time.Time(header["IMG_TS"]).jd + time_start[index] = astropy.time.Time(header["IMG_TS"]).jd timedelta[index] = header["MEAS_EXP"] timedelta_requested[index] = header["IMG_EXP"] * u.ms serial_number[index] = header.get("CAM_SN") @@ -251,11 +251,11 @@ def from_fits( ) t = astropy.time.Time( - val=time.ndarray, + val=time_start.ndarray, format="jd", ) t.format = "isot" - time.ndarray = t + time_start.ndarray = t for axis in serial_number.shape: sn0 = serial_number[{axis: 0}] @@ -265,7 +265,7 @@ def from_fits( return cls( inputs=ImageHeader( pixel=pixel, - time=time, + time_start=time_start, timedelta=timedelta, timedelta_requested=timedelta_requested, serial_number=serial_number, diff --git a/msfc_ccd/_images/_tests/test_vectors.py b/msfc_ccd/_images/_tests/test_vectors.py index 734ae06..22962f2 100644 --- a/msfc_ccd/_images/_tests/test_vectors.py +++ b/msfc_ccd/_images/_tests/test_vectors.py @@ -59,30 +59,35 @@ def test__getitem__( assert isinstance(b, msfc_ccd.ImageHeader) assert np.all(a.time[item] == b.time) - def test_time(self, a: msfc_ccd.abc.AbstractImageData): + def test_time_start(self, a: msfc_ccd.ImageHeader): + result = a.time_start + if not isinstance(result, astropy.time.Time): + assert isinstance(result.ndarray, astropy.time.Time) + + def test_time(self, a: msfc_ccd.ImageHeader): result = a.time if not isinstance(result, astropy.time.Time): assert isinstance(result.ndarray, astropy.time.Time) - def test_timedelta(self, a: msfc_ccd.abc.AbstractImageData): + def test_timedelta(self, a: msfc_ccd.ImageHeader): result = a.timedelta assert np.all(result >= 1 * u.s) assert np.all(result < 1000 * u.s) - def test_timedelta_requested(self, a: msfc_ccd.abc.AbstractImageData): + def test_timedelta_requested(self, a: msfc_ccd.ImageHeader): result = a.timedelta assert np.all(result >= 1 * u.s) assert np.all(result < 1000 * u.s) - def test_serial_number(self, a: msfc_ccd.abc.AbstractImageData): + def test_serial_number(self, a: msfc_ccd.ImageHeader): result = a.serial_number assert isinstance(result, (str, na.AbstractScalar)) - def test_run_mode(self, a: msfc_ccd.abc.AbstractImageData): + def test_run_mode(self, a: msfc_ccd.ImageHeader): result = a.run_mode assert isinstance(result, (str, na.AbstractScalar)) - def test_status(self, a: msfc_ccd.abc.AbstractImageData): + def test_status(self, a: msfc_ccd.ImageHeader): result = a.status assert isinstance(result, (str, na.AbstractScalar)) @@ -91,37 +96,37 @@ def test_voltage_fpga_vccint(self, a: msfc_ccd.abc.AbstractImageData): assert np.all(result >= 0 * u.V) assert np.all(result < 50 * u.V) - def test_voltage_fpga_vccaux(self, a: msfc_ccd.abc.AbstractImageData): + def test_voltage_fpga_vccaux(self, a: msfc_ccd.ImageHeader): result = a.voltage_fpga_vccaux assert np.all(result >= 0 * u.V) assert np.all(result < 50 * u.V) - def test_voltage_fpga_vccbram(self, a: msfc_ccd.abc.AbstractImageData): + def test_voltage_fpga_vccbram(self, a: msfc_ccd.ImageHeader): result = a.voltage_fpga_vccbram assert np.all(result >= 0 * u.V) assert np.all(result < 50 * u.V) - def test_temperature_fpga(self, a: msfc_ccd.abc.AbstractImageData): + def test_temperature_fpga(self, a: msfc_ccd.ImageHeader): result = a.temperature_fpga assert np.all(result >= 0 * u.deg_C) assert np.all(result < 100 * u.deg_C) - def test_temperature_adc_1(self, a: msfc_ccd.abc.AbstractImageData): + def test_temperature_adc_1(self, a: msfc_ccd.ImageHeader): result = a.temperature_adc_1 assert np.all(result >= 0 * u.deg_C) assert np.all(result < 100 * u.deg_C) - def test_temperature_adc_2(self, a: msfc_ccd.abc.AbstractImageData): + def test_temperature_adc_2(self, a: msfc_ccd.ImageHeader): result = a.temperature_adc_2 assert np.all(result >= 0 * u.deg_C) assert np.all(result < 100 * u.deg_C) - def test_temperature_adc_3(self, a: msfc_ccd.abc.AbstractImageData): + def test_temperature_adc_3(self, a: msfc_ccd.ImageHeader): result = a.temperature_adc_3 assert np.all(result >= 0 * u.deg_C) assert np.all(result < 100 * u.deg_C) - def test_temperature_adc_4(self, a: msfc_ccd.abc.AbstractImageData): + def test_temperature_adc_4(self, a: msfc_ccd.ImageHeader): result = a.temperature_adc_4 assert np.all(result >= 0 * u.deg_C) assert np.all(result < 100 * u.deg_C) diff --git a/msfc_ccd/_images/_vectors.py b/msfc_ccd/_images/_vectors.py index 2fcc31c..68ffaa3 100644 --- a/msfc_ccd/_images/_vectors.py +++ b/msfc_ccd/_images/_vectors.py @@ -19,8 +19,8 @@ class ImageHeader( pixel: na.AbstractCartesian2dVectorArray = dataclasses.MISSING """The indices of each pixel in the image.""" - time: astropy.time.Time | na.AbstractScalar = dataclasses.MISSING - """The time in UTC at the midpoint of the exposure.""" + time_start: astropy.time.Time | na.AbstractScalar = dataclasses.MISSING + """The time in UTC at the start of the exposure.""" timedelta: u.Quantity | na.AbstractScalar = dataclasses.MISSING """The measured exposure time of each image.""" @@ -96,3 +96,13 @@ def from_scalar( temperature_adc_3=scalar, temperature_adc_4=scalar, ) + + @property + def time(self) -> astropy.time.Time | na.ScalarArray: + """The time in UTC at the midpoint of the exposure.""" + return self.time_start + self.timedelta / 2 + + @property + def time_end(self) -> astropy.time.Time | na.ScalarArray: + """The time in UTC at the end of the exposure.""" + return self.time_start + self.timedelta