Skip to content

Commit 11bc150

Browse files
committed
Better handled Spectrum1D images across classes
1 parent 78e68b7 commit 11bc150

File tree

3 files changed

+53
-26
lines changed

3 files changed

+53
-26
lines changed

specreduce/background.py

+12-6
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
from specreduce.extract import _ap_weight_image
1010
from specreduce.tracing import Trace, FlatTrace
11+
from specutils import Spectrum1D
1112

1213
__all__ = ['Background']
1314

@@ -26,7 +27,7 @@ class Background:
2627
2728
Parameters
2829
----------
29-
image : `~astropy.nddata.NDData` or array-like
30+
image : `~astropy.nddata.NDData`-like or array-like
3031
image with 2-D spectral image data
3132
traces : List
3233
list of trace objects (or integers to define FlatTraces) to
@@ -59,7 +60,7 @@ def __post_init__(self):
5960
6061
Parameters
6162
----------
62-
image : `~astropy.nddata.NDData` or array-like
63+
image : `~astropy.nddata.NDData`-like or array-like
6364
image with 2-D spectral image data
6465
traces : List
6566
list of trace objects (or integers to define FlatTraces) to
@@ -85,6 +86,11 @@ def _to_trace(trace):
8586
raise ValueError('trace_object.trace_pos must be >= 1')
8687
return trace
8788

89+
if isinstance(self.image, NDData):
90+
# NOTE: should the NDData structure instead be preserved?
91+
# (NDData includes Spectrum1D under its umbrella)
92+
self.image = self.image.data
93+
8894
bkg_wimage = np.zeros_like(self.image, dtype=np.float64)
8995
for trace in self.traces:
9096
trace = _to_trace(trace)
@@ -132,7 +138,7 @@ def two_sided(cls, image, trace_object, separation, **kwargs):
132138
133139
Parameters
134140
----------
135-
image : nddata-compatible image
141+
image : `~astropy.nddata.NDData`-like or array-like
136142
image with 2-D spectral image data
137143
trace_object: Trace
138144
estimated trace of the spectrum to center the background traces
@@ -165,7 +171,7 @@ def one_sided(cls, image, trace_object, separation, **kwargs):
165171
166172
Parameters
167173
----------
168-
image : nddata-compatible image
174+
image : `~astropy.nddata.NDData`-like or array-like
169175
image with 2-D spectral image data
170176
trace_object: Trace
171177
estimated trace of the spectrum to center the background traces
@@ -192,7 +198,7 @@ def bkg_image(self, image=None):
192198
193199
Parameters
194200
----------
195-
image : nddata-compatible image or None
201+
image : `~astropy.nddata.NDData`-like, array-like, or None
196202
image with 2-D spectral image data. If None, will use ``image`` passed
197203
to extract the background.
198204
@@ -211,7 +217,7 @@ def sub_image(self, image=None):
211217
212218
Parameters
213219
----------
214-
image : nddata-compatible image or None
220+
image : `~astropy.nddata.NDData`-like, array-like, or None
215221
image with 2-D spectral image data. If None, will use ``image`` passed
216222
to extract the background.
217223

specreduce/extract.py

+27-18
Original file line numberDiff line numberDiff line change
@@ -116,15 +116,15 @@ class BoxcarExtract(SpecreduceOperation):
116116
117117
Parameters
118118
----------
119-
image : nddata-compatible image
119+
image : `~astropy.nddata.NDData`-like or array-like, required
120120
image with 2-D spectral image data
121-
trace_object : Trace
121+
trace_object : Trace, required
122122
trace object
123-
width : float
123+
width : float, optional
124124
width of extraction aperture in pixels
125-
disp_axis : int
125+
disp_axis : int, optional
126126
dispersion axis
127-
crossdisp_axis : int
127+
crossdisp_axis : int, optional
128128
cross-dispersion axis
129129
130130
Returns
@@ -150,15 +150,15 @@ def __call__(self, image=None, trace_object=None, width=None,
150150
151151
Parameters
152152
----------
153-
image : nddata-compatible image
153+
image : `~astropy.nddata.NDData`-like or array-like, required
154154
image with 2-D spectral image data
155-
trace_object : Trace
155+
trace_object : Trace, required
156156
trace object
157-
width : float
157+
width : float, optional
158158
width of extraction aperture in pixels [default: 5]
159-
disp_axis : int
159+
disp_axis : int, optional
160160
dispersion axis [default: 1]
161-
crossdisp_axis : int
161+
crossdisp_axis : int, optional
162162
cross-dispersion axis [default: 0]
163163
164164
@@ -174,25 +174,33 @@ def __call__(self, image=None, trace_object=None, width=None,
174174
disp_axis = disp_axis if disp_axis is not None else self.disp_axis
175175
crossdisp_axis = crossdisp_axis if crossdisp_axis is not None else self.crossdisp_axis
176176

177+
# handle image processing based on its type
178+
if isinstance(image, Spectrum1D):
179+
img = image.data
180+
unit = image.unit
181+
else:
182+
img = image
183+
unit = getattr(image, 'unit', u.DN)
184+
177185
# TODO: this check can be removed if/when implemented as a check in FlatTrace
178186
if isinstance(trace_object, FlatTrace):
179187
if trace_object.trace_pos < 1:
180188
raise ValueError('trace_object.trace_pos must be >= 1')
181189

182190
# weight image to use for extraction
183-
wimage = _ap_weight_image(
191+
wimg = _ap_weight_image(
184192
trace_object,
185193
width,
186194
disp_axis,
187195
crossdisp_axis,
188-
image.shape)
196+
img.shape)
189197

190198
# extract
191-
ext1d = np.sum(image * wimage, axis=crossdisp_axis)
199+
ext1d = np.sum(img * wimg, axis=crossdisp_axis) * unit
192200

193-
# TODO: add wavelenght units, uncertainty and mask to spectrum1D object
194-
spec = Spectrum1D(spectral_axis=np.arange(len(ext1d)) * u.pixel,
195-
flux=ext1d * getattr(image, 'unit', u.DN))
201+
# TODO: add wavelength units, uncertainty and mask to Spectrum1D object
202+
pixels = np.arange(ext1d.shape[crossdisp_axis]) * u.pixel
203+
spec = Spectrum1D(spectral_axis=pixels, flux=ext1d)
196204

197205
return spec
198206

@@ -206,7 +214,7 @@ class HorneExtract(SpecreduceOperation):
206214
Parameters
207215
----------
208216
209-
image : `~astropy.nddata.NDData` or array-like, required
217+
image : `~astropy.nddata.NDData`-like or array-like, required
210218
The input 2D spectrum from which to extract a source. An
211219
NDData object must specify uncertainty and a mask. An array
212220
requires use of the ``variance``, ``mask``, & ``unit`` arguments.
@@ -269,7 +277,7 @@ def __call__(self, image=None, trace_object=None,
269277
Parameters
270278
----------
271279
272-
image : `~astropy.nddata.NDData` or array-like, required
280+
image : `~astropy.nddata.NDData`-like or array-like, required
273281
The input 2D spectrum from which to extract a source. An
274282
NDData object must specify uncertainty and a mask. An array
275283
requires use of the ``variance``, ``mask``, & ``unit`` arguments.
@@ -322,6 +330,7 @@ def __call__(self, image=None, trace_object=None,
322330

323331
# handle image and associated data based on image's type
324332
if isinstance(image, NDData):
333+
# (NDData includes Spectrum1D under its umbrella)
325334
img = np.ma.array(image.data, mask=image.mask)
326335
unit = image.unit if image.unit is not None else u.Unit()
327336

specreduce/tracing.py

+14-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from astropy.nddata import CCDData, 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,7 +21,7 @@ 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
@@ -30,6 +31,11 @@ class Trace:
3031
"""
3132
image: CCDData
3233

34+
def __init__(self):
35+
if isinstance(self.image, Spectrum1D):
36+
# NOTE: should the Spectrum1D structure instead be preserved?
37+
self.image = self.image.data
38+
3339
def __post_init__(self):
3440
self.trace_pos = self.image.shape[0] / 2
3541
self.trace = np.ones_like(self.image[0]) * self.trace_pos
@@ -95,6 +101,8 @@ class FlatTrace(Trace):
95101
trace_pos: float
96102

97103
def __post_init__(self):
104+
super().__init__()
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().__init__()
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().__init__()
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)