Skip to content

Commit 55a5bef

Browse files
committed
Better handled Spectrum1D images across classes
1 parent 67b6b8b commit 55a5bef

File tree

3 files changed

+50
-25
lines changed

3 files changed

+50
-25
lines changed

specreduce/background.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class Background:
2727
2828
Parameters
2929
----------
30-
image : `~astropy.nddata.NDData` or array-like
30+
image : `~astropy.nddata.NDData`-like or array-like
3131
image with 2-D spectral image data
3232
traces : List
3333
list of trace objects (or integers to define FlatTraces) to
@@ -60,7 +60,7 @@ def __post_init__(self):
6060
6161
Parameters
6262
----------
63-
image : `~astropy.nddata.NDData` or array-like
63+
image : `~astropy.nddata.NDData`-like or array-like
6464
image with 2-D spectral image data
6565
traces : List
6666
list of trace objects (or integers to define FlatTraces) to
@@ -88,14 +88,18 @@ def _to_trace(trace):
8888

8989
if self.width < 0:
9090
raise ValueError("width must be positive")
91-
9291
if self.width == 0:
9392
self.bkg_array = np.zeros(self.image.shape[self.disp_axis])
9493
return
9594

9695
if isinstance(self.traces, Trace):
9796
self.traces = [self.traces]
9897

98+
if isinstance(self.image, NDData):
99+
# NOTE: should the NDData structure instead be preserved?
100+
# (NDData includes Spectrum1D under its umbrella)
101+
self.image = self.image.data
102+
99103
bkg_wimage = np.zeros_like(self.image, dtype=np.float64)
100104
for trace in self.traces:
101105
trace = _to_trace(trace)
@@ -150,7 +154,7 @@ def two_sided(cls, image, trace_object, separation, **kwargs):
150154
151155
Parameters
152156
----------
153-
image : nddata-compatible image
157+
image : `~astropy.nddata.NDData`-like or array-like
154158
image with 2-D spectral image data
155159
trace_object: Trace
156160
estimated trace of the spectrum to center the background traces
@@ -183,7 +187,7 @@ def one_sided(cls, image, trace_object, separation, **kwargs):
183187
184188
Parameters
185189
----------
186-
image : nddata-compatible image
190+
image : `~astropy.nddata.NDData`-like or array-like
187191
image with 2-D spectral image data
188192
trace_object: Trace
189193
estimated trace of the spectrum to center the background traces

specreduce/extract.py

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -137,15 +137,15 @@ class BoxcarExtract(SpecreduceOperation):
137137
138138
Parameters
139139
----------
140-
image : nddata-compatible image
140+
image : `~astropy.nddata.NDData`-like or array-like, required
141141
image with 2-D spectral image data
142-
trace_object : Trace
142+
trace_object : Trace, required
143143
trace object
144-
width : float
144+
width : float, optional
145145
width of extraction aperture in pixels
146-
disp_axis : int
146+
disp_axis : int, optional
147147
dispersion axis
148-
crossdisp_axis : int
148+
crossdisp_axis : int, optional
149149
cross-dispersion axis
150150
151151
Returns
@@ -171,15 +171,15 @@ def __call__(self, image=None, trace_object=None, width=None,
171171
172172
Parameters
173173
----------
174-
image : nddata-compatible image
174+
image : `~astropy.nddata.NDData`-like or array-like, required
175175
image with 2-D spectral image data
176-
trace_object : Trace
176+
trace_object : Trace, required
177177
trace object
178-
width : float
178+
width : float, optional
179179
width of extraction aperture in pixels [default: 5]
180-
disp_axis : int
180+
disp_axis : int, optional
181181
dispersion axis [default: 1]
182-
crossdisp_axis : int
182+
crossdisp_axis : int, optional
183183
cross-dispersion axis [default: 0]
184184
185185
@@ -195,6 +195,14 @@ def __call__(self, image=None, trace_object=None, width=None,
195195
disp_axis = disp_axis if disp_axis is not None else self.disp_axis
196196
crossdisp_axis = crossdisp_axis if crossdisp_axis is not None else self.crossdisp_axis
197197

198+
# handle image processing based on its type
199+
if isinstance(image, Spectrum1D):
200+
img = image.data
201+
unit = image.unit
202+
else:
203+
img = image
204+
unit = getattr(image, 'unit', u.DN)
205+
198206
# TODO: this check can be removed if/when implemented as a check in FlatTrace
199207
if isinstance(trace_object, FlatTrace):
200208
if trace_object.trace_pos < 1:
@@ -204,16 +212,16 @@ def __call__(self, image=None, trace_object=None, width=None,
204212
raise ValueError("width must be positive")
205213

206214
# weight image to use for extraction
207-
wimage = _ap_weight_image(
215+
wimg = _ap_weight_image(
208216
trace_object,
209217
width,
210218
disp_axis,
211219
crossdisp_axis,
212-
image.shape)
220+
img.shape)
213221

214222
# extract
215-
ext1d = np.sum(image * wimage, axis=crossdisp_axis)
216-
return _to_spectrum1d_pixels(ext1d * getattr(image, 'unit', u.DN))
223+
ext1d = np.sum(img * wimg, axis=crossdisp_axis) * unit
224+
return _to_spectrum1d_pixels(ext1d)
217225

218226

219227
@dataclass
@@ -225,7 +233,7 @@ class HorneExtract(SpecreduceOperation):
225233
Parameters
226234
----------
227235
228-
image : `~astropy.nddata.NDData` or array-like, required
236+
image : `~astropy.nddata.NDData`-like or array-like, required
229237
The input 2D spectrum from which to extract a source. An
230238
NDData object must specify uncertainty and a mask. An array
231239
requires use of the ``variance``, ``mask``, & ``unit`` arguments.
@@ -288,7 +296,7 @@ def __call__(self, image=None, trace_object=None,
288296
Parameters
289297
----------
290298
291-
image : `~astropy.nddata.NDData` or array-like, required
299+
image : `~astropy.nddata.NDData`-like or array-like, required
292300
The input 2D spectrum from which to extract a source. An
293301
NDData object must specify uncertainty and a mask. An array
294302
requires use of the ``variance``, ``mask``, & ``unit`` arguments.
@@ -341,6 +349,7 @@ def __call__(self, image=None, trace_object=None,
341349

342350
# handle image and associated data based on image's type
343351
if isinstance(image, NDData):
352+
# (NDData includes Spectrum1D under its umbrella)
344353
img = np.ma.array(image.data, mask=image.mask)
345354
unit = image.unit if image.unit is not None else u.Unit()
346355

specreduce/tracing.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@
55
import warnings
66

77
from astropy.modeling import fitting, models
8-
from astropy.nddata import CCDData, NDData
8+
from astropy.nddata import NDData
99
from astropy.stats import gaussian_sigma_to_fwhm
1010
from scipy.interpolate import UnivariateSpline
11+
from specutils import Spectrum1D
1112
import numpy as np
1213

1314
__all__ = ['Trace', 'FlatTrace', 'ArrayTrace', 'KosmosTrace']
@@ -20,15 +21,15 @@ class Trace:
2021
2122
Parameters
2223
----------
23-
image : `~astropy.nddata.CCDData`
24+
image : `~astropy.nddata.NDData`-like or array-like, required
2425
Image to be traced
2526
2627
Properties
2728
----------
2829
shape : tuple
2930
Shape of the array describing the trace
3031
"""
31-
image: CCDData
32+
image: NDData
3233

3334
def __post_init__(self):
3435
self.trace_pos = self.image.shape[0] / 2
@@ -37,6 +38,11 @@ def __post_init__(self):
3738
def __getitem__(self, i):
3839
return self.trace[i]
3940

41+
def _parse_image(self):
42+
if isinstance(self.image, Spectrum1D):
43+
# NOTE: should the Spectrum1D structure instead be preserved?
44+
self.image = self.image.data
45+
4046
@property
4147
def shape(self):
4248
return self.trace.shape
@@ -95,6 +101,8 @@ class FlatTrace(Trace):
95101
trace_pos: float
96102

97103
def __post_init__(self):
104+
super()._parse_image()
105+
98106
self.set_position(self.trace_pos)
99107

100108
def set_position(self, trace_pos):
@@ -124,6 +132,8 @@ class ArrayTrace(Trace):
124132
trace: np.ndarray
125133

126134
def __post_init__(self):
135+
super()._parse_image()
136+
127137
nx = self.image.shape[1]
128138
nt = len(self.trace)
129139
if nt != nx:
@@ -158,7 +168,7 @@ class KosmosTrace(Trace):
158168
159169
Parameters
160170
----------
161-
image : `~astropy.nddata.NDData` or array-like, required
171+
image : `~astropy.nddata.NDData`-like or array-like, required
162172
The image over which to run the trace. Assumes cross-dispersion
163173
(spatial) direction is axis 0 and dispersion (wavelength)
164174
direction is axis 1.
@@ -200,6 +210,8 @@ class KosmosTrace(Trace):
200210
_disp_axis = 1
201211

202212
def __post_init__(self):
213+
super()._parse_image()
214+
203215
# handle multiple image types and mask uncaught invalid values
204216
if isinstance(self.image, NDData):
205217
img = np.ma.masked_invalid(np.ma.masked_array(self.image.data,

0 commit comments

Comments
 (0)