diff --git a/CHANGES.rst b/CHANGES.rst index f7635444..4ce7192f 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -15,6 +15,8 @@ New Features ^^^^^^^^^^^^ - ``peak_method`` as an optional argument to ``KosmosTrace`` [#115] +- ``Background`` has new methods for exposing the 1D spectrum of the background or + background-subtracted regions [#143] API Changes ^^^^^^^^^^^ diff --git a/specreduce/background.py b/specreduce/background.py index a2829622..7345a039 100644 --- a/specreduce/background.py +++ b/specreduce/background.py @@ -5,8 +5,9 @@ import numpy as np from astropy.nddata import NDData +from astropy import units as u -from specreduce.extract import _ap_weight_image +from specreduce.extract import _ap_weight_image, _to_spectrum1d_pixels from specreduce.tracing import Trace, FlatTrace __all__ = ['Background'] @@ -193,8 +194,8 @@ def bkg_image(self, image=None): Parameters ---------- image : nddata-compatible image or None - image with 2-D spectral image data. If None, will use ``image`` passed - to extract the background. + image with 2-D spectral image data. If None, will extract + the background from ``image`` used to initialize the class. Returns ------- @@ -205,6 +206,28 @@ def bkg_image(self, image=None): return np.tile(self.bkg_array, (image.shape[0], 1)) + def bkg_spectrum(self, image=None): + """ + Expose the 1D spectrum of the background. + + Parameters + ---------- + image : nddata-compatible image or None + image with 2-D spectral image data. If None, will extract + the background from ``image`` used to initialize the class. + + Returns + ------- + spec : `~specutils.Spectrum1D` + The background 1-D spectrum, with flux expressed in the same + units as the input image (or u.DN if none were provided) and + the spectral axis expressed in pixel units. + """ + bkg_image = self.bkg_image(image=image) + + ext1d = np.sum(bkg_image, axis=self.crossdisp_axis) + return _to_spectrum1d_pixels(ext1d * getattr(image, 'unit', u.DN)) + def sub_image(self, image=None): """ Subtract the computed background from ``image``. @@ -212,8 +235,8 @@ def sub_image(self, image=None): Parameters ---------- image : nddata-compatible image or None - image with 2-D spectral image data. If None, will use ``image`` passed - to extract the background. + image with 2-D spectral image data. If None, will extract + the background from ``image`` used to initialize the class. Returns ------- @@ -228,6 +251,28 @@ def sub_image(self, image=None): else: return image - self.bkg_image(image) + def sub_spectrum(self, image=None): + """ + Expose the 1D spectrum of the background-subtracted image. + + Parameters + ---------- + image : nddata-compatible image or None + image with 2-D spectral image data. If None, will extract + the background from ``image`` used to initialize the class. + + Returns + ------- + spec : `~specutils.Spectrum1D` + The background 1-D spectrum, with flux expressed in the same + units as the input image (or u.DN if none were provided) and + the spectral axis expressed in pixel units. + """ + sub_image = self.sub_image(image=image) + + ext1d = np.sum(sub_image, axis=self.crossdisp_axis) + return _to_spectrum1d_pixels(ext1d * getattr(image, 'unit', u.DN)) + def __rsub__(self, image): """ Subtract the background from an image. diff --git a/specreduce/extract.py b/specreduce/extract.py index 2537d7ba..56d2b211 100644 --- a/specreduce/extract.py +++ b/specreduce/extract.py @@ -102,6 +102,12 @@ def _ap_weight_image(trace, width, disp_axis, crossdisp_axis, image_shape): return wimage +def _to_spectrum1d_pixels(fluxes): + # TODO: add wavelength units, uncertainty and mask to spectrum1D object + return Spectrum1D(spectral_axis=np.arange(len(fluxes)) * u.pixel, + flux=fluxes) + + @dataclass class BoxcarExtract(SpecreduceOperation): """ @@ -189,12 +195,7 @@ def __call__(self, image=None, trace_object=None, width=None, # extract ext1d = np.sum(image * wimage, axis=crossdisp_axis) - - # TODO: add wavelenght units, uncertainty and mask to spectrum1D object - spec = Spectrum1D(spectral_axis=np.arange(len(ext1d)) * u.pixel, - flux=ext1d * getattr(image, 'unit', u.DN)) - - return spec + return _to_spectrum1d_pixels(ext1d * getattr(image, 'unit', u.DN)) @dataclass @@ -432,10 +433,7 @@ def __call__(self, image=None, trace_object=None, extraction = result * norms # convert the extraction to a Spectrum1D object - pixels = np.arange(img.shape[disp_axis]) * u.pix - spec_1d = Spectrum1D(spectral_axis=pixels, flux=extraction * unit) - - return spec_1d + return _to_spectrum1d_pixels(extraction * unit) @dataclass diff --git a/specreduce/tests/test_background.py b/specreduce/tests/test_background.py index 7ccf8dce..f5808fb1 100644 --- a/specreduce/tests/test_background.py +++ b/specreduce/tests/test_background.py @@ -3,6 +3,7 @@ import astropy.units as u from astropy.nddata import CCDData +from specutils import Spectrum1D from specreduce.background import Background from specreduce.tracing import FlatTrace @@ -44,6 +45,11 @@ def test_background(): assert np.allclose(sub1, sub2) assert np.allclose(sub1, sub3) + bkg_spec = bg1.bkg_spectrum() + assert isinstance(bkg_spec, Spectrum1D) + sub_spec = bg1.sub_spectrum() + assert isinstance(sub_spec, Spectrum1D) + def test_oob(): # image.shape (30, 10)