Skip to content

Commit b5e957c

Browse files
authored
Added time_start and time_end properties to the ImageHeader class. (#39)
1 parent 1573a00 commit b5e957c

File tree

4 files changed

+51
-23
lines changed

4 files changed

+51
-23
lines changed

msfc_ccd/_images/_sensor_images.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ def from_fits(
177177
"""
178178
path = na.as_named_array(path)
179179

180-
time = na.ScalarArray.zeros(na.shape(path))
180+
time_start = na.ScalarArray.zeros(na.shape(path))
181181

182182
timedelta = np.empty_like(path, dtype=np.int64)
183183
timedelta_requested = np.empty_like(path, dtype=float) << u.s
@@ -211,7 +211,7 @@ def from_fits(
211211
data[index] = data_index
212212

213213
header = hdu.header
214-
time[index] = astropy.time.Time(header["IMG_TS"]).jd
214+
time_start[index] = astropy.time.Time(header["IMG_TS"]).jd
215215
timedelta[index] = header["MEAS_EXP"]
216216
timedelta_requested[index] = header["IMG_EXP"] * u.ms
217217
serial_number[index] = header.get("CAM_SN")
@@ -251,11 +251,11 @@ def from_fits(
251251
)
252252

253253
t = astropy.time.Time(
254-
val=time.ndarray,
254+
val=time_start.ndarray,
255255
format="jd",
256256
)
257257
t.format = "isot"
258-
time.ndarray = t
258+
time_start.ndarray = t
259259

260260
for axis in serial_number.shape:
261261
sn0 = serial_number[{axis: 0}]
@@ -265,7 +265,7 @@ def from_fits(
265265
return cls(
266266
inputs=ImageHeader(
267267
pixel=pixel,
268-
time=time,
268+
time_start=time_start,
269269
timedelta=timedelta,
270270
timedelta_requested=timedelta_requested,
271271
serial_number=serial_number,

msfc_ccd/_images/_tests/test_vectors.py

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
stop=32,
1616
axis=na.Cartesian2dVectorArray(x="x", y="y"),
1717
),
18-
time=na.ScalarArray(
18+
time_start=na.ScalarArray(
1919
ndarray=np.linspace(
2020
astropy.time.Time("2024-03-25T20:49"),
2121
astropy.time.Time("2024-03-25T21:49"),
@@ -59,30 +59,42 @@ def test__getitem__(
5959
assert isinstance(b, msfc_ccd.ImageHeader)
6060
assert np.all(a.time[item] == b.time)
6161

62-
def test_time(self, a: msfc_ccd.abc.AbstractImageData):
62+
def test_time_start(self, a: msfc_ccd.ImageHeader):
63+
result = a.time_start
64+
if not isinstance(result, astropy.time.Time):
65+
assert isinstance(result.ndarray, astropy.time.Time)
66+
67+
def test_time(self, a: msfc_ccd.ImageHeader):
6368
result = a.time
6469
if not isinstance(result, astropy.time.Time):
6570
assert isinstance(result.ndarray, astropy.time.Time)
71+
assert np.all(result > a.time_start)
72+
73+
def test_time_end(self, a: msfc_ccd.ImageHeader):
74+
result = a.time_end
75+
if not isinstance(result, astropy.time.Time):
76+
assert isinstance(result.ndarray, astropy.time.Time)
77+
assert np.all(result > a.time)
6678

67-
def test_timedelta(self, a: msfc_ccd.abc.AbstractImageData):
79+
def test_timedelta(self, a: msfc_ccd.ImageHeader):
6880
result = a.timedelta
6981
assert np.all(result >= 1 * u.s)
7082
assert np.all(result < 1000 * u.s)
7183

72-
def test_timedelta_requested(self, a: msfc_ccd.abc.AbstractImageData):
84+
def test_timedelta_requested(self, a: msfc_ccd.ImageHeader):
7385
result = a.timedelta
7486
assert np.all(result >= 1 * u.s)
7587
assert np.all(result < 1000 * u.s)
7688

77-
def test_serial_number(self, a: msfc_ccd.abc.AbstractImageData):
89+
def test_serial_number(self, a: msfc_ccd.ImageHeader):
7890
result = a.serial_number
7991
assert isinstance(result, (str, na.AbstractScalar))
8092

81-
def test_run_mode(self, a: msfc_ccd.abc.AbstractImageData):
93+
def test_run_mode(self, a: msfc_ccd.ImageHeader):
8294
result = a.run_mode
8395
assert isinstance(result, (str, na.AbstractScalar))
8496

85-
def test_status(self, a: msfc_ccd.abc.AbstractImageData):
97+
def test_status(self, a: msfc_ccd.ImageHeader):
8698
result = a.status
8799
assert isinstance(result, (str, na.AbstractScalar))
88100

@@ -91,37 +103,37 @@ def test_voltage_fpga_vccint(self, a: msfc_ccd.abc.AbstractImageData):
91103
assert np.all(result >= 0 * u.V)
92104
assert np.all(result < 50 * u.V)
93105

94-
def test_voltage_fpga_vccaux(self, a: msfc_ccd.abc.AbstractImageData):
106+
def test_voltage_fpga_vccaux(self, a: msfc_ccd.ImageHeader):
95107
result = a.voltage_fpga_vccaux
96108
assert np.all(result >= 0 * u.V)
97109
assert np.all(result < 50 * u.V)
98110

99-
def test_voltage_fpga_vccbram(self, a: msfc_ccd.abc.AbstractImageData):
111+
def test_voltage_fpga_vccbram(self, a: msfc_ccd.ImageHeader):
100112
result = a.voltage_fpga_vccbram
101113
assert np.all(result >= 0 * u.V)
102114
assert np.all(result < 50 * u.V)
103115

104-
def test_temperature_fpga(self, a: msfc_ccd.abc.AbstractImageData):
116+
def test_temperature_fpga(self, a: msfc_ccd.ImageHeader):
105117
result = a.temperature_fpga
106118
assert np.all(result >= 0 * u.deg_C)
107119
assert np.all(result < 100 * u.deg_C)
108120

109-
def test_temperature_adc_1(self, a: msfc_ccd.abc.AbstractImageData):
121+
def test_temperature_adc_1(self, a: msfc_ccd.ImageHeader):
110122
result = a.temperature_adc_1
111123
assert np.all(result >= 0 * u.deg_C)
112124
assert np.all(result < 100 * u.deg_C)
113125

114-
def test_temperature_adc_2(self, a: msfc_ccd.abc.AbstractImageData):
126+
def test_temperature_adc_2(self, a: msfc_ccd.ImageHeader):
115127
result = a.temperature_adc_2
116128
assert np.all(result >= 0 * u.deg_C)
117129
assert np.all(result < 100 * u.deg_C)
118130

119-
def test_temperature_adc_3(self, a: msfc_ccd.abc.AbstractImageData):
131+
def test_temperature_adc_3(self, a: msfc_ccd.ImageHeader):
120132
result = a.temperature_adc_3
121133
assert np.all(result >= 0 * u.deg_C)
122134
assert np.all(result < 100 * u.deg_C)
123135

124-
def test_temperature_adc_4(self, a: msfc_ccd.abc.AbstractImageData):
136+
def test_temperature_adc_4(self, a: msfc_ccd.ImageHeader):
125137
result = a.temperature_adc_4
126138
assert np.all(result >= 0 * u.deg_C)
127139
assert np.all(result < 100 * u.deg_C)

msfc_ccd/_images/_vectors.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ class ImageHeader(
1919
pixel: na.AbstractCartesian2dVectorArray = dataclasses.MISSING
2020
"""The indices of each pixel in the image."""
2121

22-
time: astropy.time.Time | na.AbstractScalar = dataclasses.MISSING
23-
"""The time in UTC at the midpoint of the exposure."""
22+
time_start: astropy.time.Time | na.AbstractScalar = dataclasses.MISSING
23+
"""The time in UTC at the start of the exposure."""
2424

2525
timedelta: u.Quantity | na.AbstractScalar = dataclasses.MISSING
2626
"""The measured exposure time of each image."""
@@ -81,7 +81,7 @@ def from_scalar(
8181
) -> Self:
8282
return cls(
8383
pixel=scalar,
84-
time=scalar,
84+
time_start=scalar,
8585
timedelta=scalar,
8686
timedelta_requested=scalar,
8787
serial_number=scalar,
@@ -96,3 +96,19 @@ def from_scalar(
9696
temperature_adc_3=scalar,
9797
temperature_adc_4=scalar,
9898
)
99+
100+
@property
101+
def time(self) -> astropy.time.Time | na.ScalarArray:
102+
"""The time in UTC at the midpoint of the exposure."""
103+
time_start = self.time_start
104+
axes = time_start.axes
105+
result = time_start.ndarray + self.timedelta.ndarray_aligned(axes) / 2
106+
return na.ScalarArray(result, axes=axes)
107+
108+
@property
109+
def time_end(self) -> astropy.time.Time | na.ScalarArray:
110+
"""The time in UTC at the end of the exposure."""
111+
time_start = self.time_start
112+
axes = time_start.axes
113+
result = time_start.ndarray + self.timedelta.ndarray_aligned(axes)
114+
return na.ScalarArray(result, axes=axes)

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ classifiers = [
1515
]
1616
dependencies = [
1717
"astropy",
18-
"named-arrays==0.24.0",
18+
"named-arrays>=0.25.0",
1919
]
2020
dynamic = ["version"]
2121

0 commit comments

Comments
 (0)