From b9fe47d52652ab9dd455393b84c2ff6e5e89002f Mon Sep 17 00:00:00 2001 From: Kyle Conroy Date: Mon, 14 Feb 2022 09:50:03 -0500 Subject: [PATCH 01/18] initial implementation of boxcar extract Co-authored-by: @duytnguyendtn Co-authored-by: @ibusko Co-authored-by: @ojustino --- specreduce/extract.py | 334 ++++++++++++++++++++++++------------------ 1 file changed, 193 insertions(+), 141 deletions(-) diff --git a/specreduce/extract.py b/specreduce/extract.py index 68113228..9ae5a3fc 100644 --- a/specreduce/extract.py +++ b/specreduce/extract.py @@ -14,6 +14,118 @@ __all__ = ['BoxcarExtract'] +def _get_boxcar_weights(center, hwidth, npix): + """ + Compute the weights given an aperture center, half widths, and number of pixels + """ + # TODO: this code may fail when regions fall partially or entirely outside the image. + + weights = np.zeros((npix)) + + # 2d + if type(npix) is not tuple: + # pixels with full weight + fullpixels = [max(0, int(center - hwidth + 1)), min(int(center + hwidth), npix)] + weights[fullpixels[0]:fullpixels[1]] = 1.0 + + # pixels at the edges of the boxcar with partial weight + if fullpixels[0] > 0: + weights[fullpixels[0] - 1] = hwidth - (center - fullpixels[0]) + if fullpixels[1] < npix: + weights[fullpixels[1]] = hwidth - (fullpixels[1] - center) + # 3d + else: + # pixels with full weight + fullpixels_x = [max(0, int(center[1] - hwidth + 1)), min(int(center[1] + hwidth), npix[1])] + fullpixels_y = [max(0, int(center[0] - hwidth + 1)), min(int(center[0] + hwidth), npix[0])] + weights[fullpixels_x[0]:fullpixels_x[1], fullpixels_y[0]:fullpixels_y[1]] = 1.0 + + # not yet handling pixels at the edges of the boxcar + + return weights + + +def _ap_weight_images(center, width, disp_axis, crossdisp_axis, bkg_offset, bkg_width, image_shape): + + """ + Create a weight image that defines the desired extraction aperture + and the weight image for the requested background regions. + + The disp_axis and crossdisp_axis parameters could perhaps be derived from the + jdatamodel wcs and/or meta instances. Since we have test data that lacks the + these, for now we pass then explictly via calling sequence. + + + Parameters + ---------- + center : float + center of aperture in pixels + width : float + width of apeture in pixels + disp_axis : int + dispersion axis + crossdisp_axis : int or tuple + cross-dispersion axis + bkg_offset : float + offset from the extaction edge for the background + never scaled for wavelength + bkg_width : float + width of background region + never scaled with wavelength + image_shape : tuple with 2 or 3 elements + size (shape) of image + wavescale : float + scale the width with wavelength (default=None) + wavescale gives the reference wavelenth for the width value NOT USED + + Returns + ------- + wimage, bkg_wimage : (2D image, 2D image) + wimage is the weight image defining the aperature + bkg_image is the weight image defining the background regions + """ + wimage = np.zeros(image_shape) + bkg_wimage = np.zeros(image_shape) + hwidth = 0.5 * width + + if len(crossdisp_axis) == 1: + # 2d + image_sizes = image_shape[crossdisp_axis[0]] + else: + # 3d + image_shape_array = np.array(image_shape) + crossdisp_axis_array = np.array(crossdisp_axis) + image_sizes = image_shape_array[crossdisp_axis_array] + image_sizes = tuple(image_sizes.tolist()) + + # loop in dispersion direction and compute weights + # + # This loop may be removed or highly cleaned up, replaced by + # vectorized operations, when the extraction parameters are the + # same in every image column. We leave it in place for now, so + # the code may be upgraded later to support height-variable and + # PSF-weighted extraction modes. + + for i in range(image_shape[disp_axis]): + if len(crossdisp_axis) == 1: + wimage[:, i] = _get_boxcar_weights(center, hwidth, image_sizes) + else: + wimage[i, ::] = _get_boxcar_weights(center, hwidth, image_sizes) + + # bkg regions (only for s2d for now) + if (len(crossdisp_axis) == 1) & (bkg_width is not None) & (bkg_offset is not None): + bkg_wimage[:, i] = _get_boxcar_weights( + center - hwidth - bkg_offset, bkg_width, image_shape[0] + ) + bkg_wimage[:, i] += _get_boxcar_weights( + center + hwidth + bkg_offset, bkg_width, image_shape[0] + ) + else: + bkg_wimage = None + + return (wimage, bkg_wimage) + + @dataclass class BoxcarExtract(SpecreduceOperation): """ @@ -34,6 +146,17 @@ class BoxcarExtract(SpecreduceOperation): skydeg : int The degree of the polynomial that's fit to the sky + center : float + center of aperture in pixels + width : float + width of aperture in pixels + bkg_offset : float + offset from the extaction edge for the background + never scaled for wavelength + bkg_width : float + width of background region + never scaled with wavelength + Returns ------- spec : `~specutils.Spectrum1D` @@ -41,177 +164,106 @@ class BoxcarExtract(SpecreduceOperation): skyspec : `~specutils.Spectrum1D` The sky spectrum used in the extraction process """ - apwidth: int = 8 - skysep: int = 3 - skywidth: int = 7 - skydeg: int = 0 - - def __call__(self, img, trace_object): - self.last_trace = trace_object - self.last_img = img - - if self.apwidth < 1: - raise ValueError('apwidth must be >= 1') - if self.skysep < 1: - raise ValueError('skysep must be >= 1') - if self.skywidth < 1: - raise ValueError('skywidth must be >= 1') - - trace_line = trace_object.trace - - onedspec = np.zeros_like(trace_line) - skysubflux = np.zeros_like(trace_line) - fluxerr = np.zeros_like(trace_line) - mask = np.zeros_like(trace_line, dtype=bool) - - for i in range(0, len(trace_line)): - # if the trace isn't defined at a position (e.g. if it is out of the image boundaries), - # it will be masked. so we propagate that into the output mask and move on. - if np.ma.is_masked(trace_line[i]): - mask[i] = True - continue - - # first do the aperture flux - # juuuust in case the trace gets too close to an edge - widthup = self.apwidth / 2. - widthdn = self.apwidth / 2. - if (trace_line[i] + widthup > img.shape[0]): - widthup = img.shape[0] - trace_line[i] - 1. - if (trace_line[i] - widthdn < 0): - widthdn = trace_line[i] - 1. - - # extract from box around the trace line - low_end = trace_line[i] - widthdn - high_end = trace_line[i] + widthdn - - self._extract_from_box(img, i, low_end, high_end, onedspec) - - # now do the sky fit - # Note that we are not including fractional pixels, since we are doing - # a polynomial fit over the sky values. - j1 = self._find_nearest_int(trace_line[i] - self.apwidth/2. - - self.skysep - self.skywidth) - j2 = self._find_nearest_int(trace_line[i] - self.apwidth/2. - self.skysep) - sky_y_1 = np.arange(j1, j2) - - j1 = self._find_nearest_int(trace_line[i] + self.apwidth/2. + self.skysep) - j2 = self._find_nearest_int(trace_line[i] + self.apwidth/2. + - self.skysep + self.skywidth) - sky_y_2 = np.arange(j1, j2) - - sky_y = np.append(sky_y_1, sky_y_2) - - # sky can't be outside image - np_indices = np.indices(img[::, i].shape) - sky_y = np.intersect1d(sky_y, np_indices) - - sky_flux = img[sky_y, i] - if (self.skydeg > 0): - # fit a polynomial to the sky in this column - pfit = np.polyfit(sky_y, sky_flux, self.skydeg) - # define the aperture in this column - ap = np.arange( - self._find_nearest_int(trace_line[i] - self.apwidth/2.), - self._find_nearest_int(trace_line[i] + self.apwidth/2.) - ) - # evaluate the polynomial across the aperture, and sum - skysubflux[i] = np.nansum(np.polyval(pfit, ap)) - elif (self.skydeg == 0): - skysubflux[i] = np.nanmean(sky_flux) * self.apwidth - - # finally, compute the error in this pixel - sigma_bkg = np.nanstd(sky_flux) # stddev in the background data - n_bkg = np.float(len(sky_y)) # number of bkgd pixels - n_ap = self.apwidth # number of aperture pixels - - # based on aperture phot err description by F. Masci, Caltech: - # http://wise2.ipac.caltech.edu/staff/fmasci/ApPhotUncert.pdf - fluxerr[i] = np.sqrt( - np.nansum(onedspec[i] - skysubflux[i]) + (n_ap + n_ap**2 / n_bkg) * (sigma_bkg**2) - ) - - img_unit = u.DN - if hasattr(img, 'unit'): - img_unit = img.unit - - spec = Spectrum1D( - spectral_axis=np.arange(len(onedspec)) * u.pixel, - flux=onedspec * img_unit, - uncertainty=StdDevUncertainty(fluxerr), - mask=mask - ) - skyspec = Spectrum1D( - spectral_axis=np.arange(len(onedspec)) * u.pixel, - flux=skysubflux * img_unit, - mask=mask + # TODO: what are reasonable defaults? + # TODO: ints or floats? + center: int = 10 + width: int = 8 + bkg_offset: int = 1 + bkg_width: int = 8 + + #def __call__(self, image, trace_object, pixelarea): + def __call__(self, image, disp_axis, crossdisp_axis, pixelarea=1): + """ + Extract the 1D spectrum using the boxcar method. + Does a background subtraction as part of the extraction. + + Parameters + ---------- + image : ndarray + array with 2-D spectral image data + jdatamodel : jwst.DataModel + jwst datamodel with the 2d spectral image + + disp_axis : int + dispersion axis + crossdisp_axis : int or tuple + cross-dispersion axis + + + Returns + ------- + waves, ext1d : (ndarray, ndarray) + 2D `float` array with wavelengths + 1D `float` array with extracted 1d spectrum in Jy + """ +# self.last_trace = trace_object + self.last_image = image + + for attr in ['center', 'width', 'bkg_offset', 'bkg_width']: + if getattr(self, attr) < 1: + raise ValueError(f'{attr} must be >= 1') + + # images to use for extraction + wimage, bkg_wimage = _ap_weight_images( + self.center, + self.width, + disp_axis, + crossdisp_axis, + self.bkg_width, + self.bkg_offset, + image.shape ) - return spec, skyspec - - def _extract_from_box(self, image, wave_index, low_end, high_end, extracted_result): - - # compute nearest integer endpoints defining an internal interval, - # and fractional pixel areas that remain outside this interval. - # (taken from the HST STIS pipeline code: - # https://github.com/spacetelescope/hstcal/blob/master/pkg/stis/calstis/cs6/x1dspec.c) - # - # This assumes that the pixel coordinates represent the center of the pixel. - # E.g. pixel at y=15.0 covers the image from y=14.5 to y=15.5 - - # nearest integer endpoints - j1 = self._find_nearest_int(low_end) - j2 = self._find_nearest_int(high_end) - - # fractional pixel areas at the end points - s1 = 0.5 - (low_end - j1) - s2 = 0.5 + high_end - j2 + # select weight images + if bkg_wimage is not None: + ext1d_boxcar_bkg = np.average(image, weights=bkg_wimage, axis=0) + data_bkgsub = image - np.tile(ext1d_boxcar_bkg, (image.shape[0], 1)) + else: + data_bkgsub = image - # add up the total flux around the trace_line - extracted_result[wave_index] = np.nansum(image[j1 + 1:j2, wave_index]) - extracted_result[wave_index] += np.nansum(image[j1, wave_index]) * s1 - extracted_result[wave_index] += np.nansum(image[j2, wave_index]) * s2 + # extract. Note that, for a cube, this is arbitrarily picking one of the + # spatial axis to collapse. This should be handled by the API somehow. + ext1d = np.sum(data_bkgsub * wimage, axis=crossdisp_axis) + ext1d *= pixelarea - def _find_nearest_int(self, end_point): - if (end_point % 1) < 0.5: - return int(end_point) - else: - return int(end_point + 1) + # TODO: used to return a Spectrum object but now just returns a 1D and 2D array + return (ext1d, data_bkgsub) def get_checkplot(self): trace_line = self.last_trace.line fig = plt.figure() - plt.imshow(self.last_img, origin='lower', aspect='auto', cmap=plt.cm.Greys_r) - plt.clim(np.percentile(self.last_img, (5, 98))) + plt.imshow(self.last_image, origin='lower', aspect='auto', cmap=plt.cm.Greys_r) + plt.clim(np.percentile(self.last_image, (5, 98))) plt.plot(np.arange(len(trace_line)), trace_line, c='C0') plt.fill_between( np.arange(len(trace_line)), - trace_line + self.apwidth, - trace_line - self.apwidth, + trace_line + self.width, + trace_line - self.width, color='C0', alpha=0.5 ) plt.fill_between( np.arange(len(trace_line)), - trace_line + self.apwidth + self.skysep, - trace_line + self.apwidth + self.skysep + self.skywidth, + trace_line + self.width + self.bkg_offset, + trace_line + self.width + self.bkg_offset + self.bkg_width, color='C1', alpha=0.5 ) plt.fill_between( np.arange(len(trace_line)), - trace_line - self.apwidth - self.skysep, - trace_line - self.apwidth - self.skysep - self.skywidth, + trace_line - self.width - self.bkg_offset, + trace_line - self.width - self.bkg_offset - self.bkg_width, color='C1', alpha=0.5 ) plt.ylim( np.min( - trace_line - (self.apwidth + self.skysep + self.skywidth) * 2 + trace_line - (self.width + self.bkg_offset + self.bkg_width) * 2 ), np.max( - trace_line + (self.apwidth + self.skysep + self.skywidth) * 2 + trace_line + (self.width + self.bkg_offset + self.bkg_width) * 2 ) ) From b4937088b75abb0587d9b7853f653b8f434eb932 Mon Sep 17 00:00:00 2001 From: Kyle Conroy Date: Tue, 15 Feb 2022 12:36:09 -0500 Subject: [PATCH 02/18] remove background subtraction and cleanup API * return as Spectrum1D object * remove get_checkplot (at least for now) * update API docs to match new parameter names --- specreduce/extract.py | 133 ++++++------------------------------------ 1 file changed, 19 insertions(+), 114 deletions(-) diff --git a/specreduce/extract.py b/specreduce/extract.py index 9ae5a3fc..51a7be2f 100644 --- a/specreduce/extract.py +++ b/specreduce/extract.py @@ -3,10 +3,8 @@ from dataclasses import dataclass import numpy as np -import matplotlib.pyplot as plt from astropy import units as u -from astropy.nddata import StdDevUncertainty from specreduce.core import SpecreduceOperation from specutils import Spectrum1D @@ -45,16 +43,10 @@ def _get_boxcar_weights(center, hwidth, npix): return weights -def _ap_weight_images(center, width, disp_axis, crossdisp_axis, bkg_offset, bkg_width, image_shape): +def _ap_weight_images(center, width, disp_axis, crossdisp_axis, image_shape): """ - Create a weight image that defines the desired extraction aperture - and the weight image for the requested background regions. - - The disp_axis and crossdisp_axis parameters could perhaps be derived from the - jdatamodel wcs and/or meta instances. Since we have test data that lacks the - these, for now we pass then explictly via calling sequence. - + Create a weight image that defines the desired extraction aperture. Parameters ---------- @@ -66,12 +58,6 @@ def _ap_weight_images(center, width, disp_axis, crossdisp_axis, bkg_offset, bkg_ dispersion axis crossdisp_axis : int or tuple cross-dispersion axis - bkg_offset : float - offset from the extaction edge for the background - never scaled for wavelength - bkg_width : float - width of background region - never scaled with wavelength image_shape : tuple with 2 or 3 elements size (shape) of image wavescale : float @@ -80,12 +66,10 @@ def _ap_weight_images(center, width, disp_axis, crossdisp_axis, bkg_offset, bkg_ Returns ------- - wimage, bkg_wimage : (2D image, 2D image) - wimage is the weight image defining the aperature - bkg_image is the weight image defining the background regions + wimage : 2D image, 2D image + weight image defining the aperature """ wimage = np.zeros(image_shape) - bkg_wimage = np.zeros(image_shape) hwidth = 0.5 * width if len(crossdisp_axis) == 1: @@ -112,18 +96,7 @@ def _ap_weight_images(center, width, disp_axis, crossdisp_axis, bkg_offset, bkg_ else: wimage[i, ::] = _get_boxcar_weights(center, hwidth, image_sizes) - # bkg regions (only for s2d for now) - if (len(crossdisp_axis) == 1) & (bkg_width is not None) & (bkg_offset is not None): - bkg_wimage[:, i] = _get_boxcar_weights( - center - hwidth - bkg_offset, bkg_width, image_shape[0] - ) - bkg_wimage[:, i] += _get_boxcar_weights( - center + hwidth + bkg_offset, bkg_width, image_shape[0] - ) - else: - bkg_wimage = None - - return (wimage, bkg_wimage) + return wimage @dataclass @@ -133,29 +106,14 @@ class BoxcarExtract(SpecreduceOperation): Parameters ---------- - img : nddata-compatible image + image : nddata-compatible image The input image trace_object : The trace of the spectrum to be extracted TODO: define - apwidth : int - The width of the extraction aperture in pixels - skysep : int - The spacing between the aperture and the sky regions - skywidth : int - The width of the sky regions in pixels - skydeg : int - The degree of the polynomial that's fit to the sky - center : float center of aperture in pixels width : float width of aperture in pixels - bkg_offset : float - offset from the extaction edge for the background - never scaled for wavelength - bkg_width : float - width of background region - never scaled with wavelength Returns ------- @@ -168,11 +126,9 @@ class BoxcarExtract(SpecreduceOperation): # TODO: ints or floats? center: int = 10 width: int = 8 - bkg_offset: int = 1 - bkg_width: int = 8 - #def __call__(self, image, trace_object, pixelarea): - def __call__(self, image, disp_axis, crossdisp_axis, pixelarea=1): + #def __call__(self, image, trace_object): + def __call__(self, image, disp_axis, crossdisp_axis): """ Extract the 1D spectrum using the boxcar method. Does a background subtraction as part of the extraction. @@ -181,9 +137,6 @@ def __call__(self, image, disp_axis, crossdisp_axis, pixelarea=1): ---------- image : ndarray array with 2-D spectral image data - jdatamodel : jwst.DataModel - jwst datamodel with the 2d spectral image - disp_axis : int dispersion axis crossdisp_axis : int or tuple @@ -197,74 +150,26 @@ def __call__(self, image, disp_axis, crossdisp_axis, pixelarea=1): 1D `float` array with extracted 1d spectrum in Jy """ # self.last_trace = trace_object - self.last_image = image +# self.last_image = image - for attr in ['center', 'width', 'bkg_offset', 'bkg_width']: + for attr in ['center', 'width']: if getattr(self, attr) < 1: raise ValueError(f'{attr} must be >= 1') # images to use for extraction - wimage, bkg_wimage = _ap_weight_images( + wimage = _ap_weight_images( self.center, self.width, disp_axis, crossdisp_axis, - self.bkg_width, - self.bkg_offset, - image.shape - ) - - # select weight images - if bkg_wimage is not None: - ext1d_boxcar_bkg = np.average(image, weights=bkg_wimage, axis=0) - data_bkgsub = image - np.tile(ext1d_boxcar_bkg, (image.shape[0], 1)) - else: - data_bkgsub = image + image.shape) # extract. Note that, for a cube, this is arbitrarily picking one of the # spatial axis to collapse. This should be handled by the API somehow. - ext1d = np.sum(data_bkgsub * wimage, axis=crossdisp_axis) - ext1d *= pixelarea - - # TODO: used to return a Spectrum object but now just returns a 1D and 2D array - return (ext1d, data_bkgsub) - - def get_checkplot(self): - trace_line = self.last_trace.line - - fig = plt.figure() - plt.imshow(self.last_image, origin='lower', aspect='auto', cmap=plt.cm.Greys_r) - plt.clim(np.percentile(self.last_image, (5, 98))) - - plt.plot(np.arange(len(trace_line)), trace_line, c='C0') - plt.fill_between( - np.arange(len(trace_line)), - trace_line + self.width, - trace_line - self.width, - color='C0', - alpha=0.5 - ) - plt.fill_between( - np.arange(len(trace_line)), - trace_line + self.width + self.bkg_offset, - trace_line + self.width + self.bkg_offset + self.bkg_width, - color='C1', - alpha=0.5 - ) - plt.fill_between( - np.arange(len(trace_line)), - trace_line - self.width - self.bkg_offset, - trace_line - self.width - self.bkg_offset - self.bkg_width, - color='C1', - alpha=0.5 - ) - plt.ylim( - np.min( - trace_line - (self.width + self.bkg_offset + self.bkg_width) * 2 - ), - np.max( - trace_line + (self.width + self.bkg_offset + self.bkg_width) * 2 - ) - ) - - return fig + ext1d = np.sum(image * wimage, axis=crossdisp_axis) + + # TODO: add 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 From 5b0fc630d1742bd58837486f355aa82253cd373e Mon Sep 17 00:00:00 2001 From: Ivo Date: Tue, 15 Feb 2022 15:40:46 -0500 Subject: [PATCH 03/18] Remove sky background processing in test_extract code. --- specreduce/tests/test_extract.py | 67 ++++---------------------------- 1 file changed, 8 insertions(+), 59 deletions(-) diff --git a/specreduce/tests/test_extract.py b/specreduce/tests/test_extract.py index 531bd0d2..ed72b0e1 100644 --- a/specreduce/tests/test_extract.py +++ b/specreduce/tests/test_extract.py @@ -26,85 +26,34 @@ def test_extraction(): boxcar.apwidth = 5 trace = FlatTrace(image, 15.0) - spectrum, bkg_spectrum = boxcar(image, trace) + spectrum = boxcar(image, trace) assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 75.)) trace.set_position(14.5) - spectrum, bkg_spectrum = boxcar(image, trace) + spectrum = boxcar(image, trace) assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 72.5)) trace.set_position(14.7) - spectrum, bkg_spectrum = boxcar(image, trace) + spectrum = boxcar(image, trace) assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 73.5)) boxcar.apwidth = 6 trace.set_position(15.0) - spectrum, bkg_spectrum = boxcar(image, trace) + spectrum = boxcar(image, trace) assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 90.)) trace.set_position(14.5) - spectrum, bkg_spectrum = boxcar(image, trace) + spectrum = boxcar(image, trace) assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 87.)) boxcar.apwidth = 4.5 trace.set_position(15.0) - spectrum, bkg_spectrum = boxcar(image, trace) + spectrum = boxcar(image, trace) assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 67.5)) -def test_sky_extraction(): - # - # Try combinations of sky extraction parameters - # - boxcar = BoxcarExtract() - - boxcar.apwidth = 5. - boxcar.skysep = int(2) - boxcar.skywidth = 5. - - trace = FlatTrace(image, 15.0) - spectrum, bkg_spectrum = boxcar(image, trace) - assert np.allclose(bkg_spectrum.flux.value, np.full_like(bkg_spectrum.flux.value, 75.)) - - trace.set_position(14.5) - spectrum, bkg_spectrum = boxcar(image, trace) - assert np.allclose(bkg_spectrum.flux.value, np.full_like(bkg_spectrum.flux.value, 70.)) - - boxcar.skydeg = 1 - - trace.set_position(15.0) - spectrum, bkg_spectrum = boxcar(image, trace) - assert np.allclose(bkg_spectrum.flux.value, np.full_like(bkg_spectrum.flux.value, 75.)) - - trace.set_position(14.5) - spectrum, bkg_spectrum = boxcar(image, trace) - assert np.allclose(bkg_spectrum.flux.value, np.full_like(bkg_spectrum.flux.value, 70.)) - - boxcar.skydeg = 2 - - trace.set_position(15.0) - spectrum, bkg_spectrum = boxcar(image, trace) - assert np.allclose(bkg_spectrum.flux.value, np.full_like(bkg_spectrum.flux.value, 75.)) - - trace.set_position(14.5) - spectrum, bkg_spectrum = boxcar(image, trace) - assert np.allclose(bkg_spectrum.flux.value, np.full_like(bkg_spectrum.flux.value, 70.)) - - boxcar.apwidth = 7. - boxcar.skysep = int(3) - boxcar.skywidth = 8. - - trace.set_position(15.0) - spectrum, bkg_spectrum = boxcar(image, trace) - assert np.allclose(bkg_spectrum.flux.value, np.full_like(bkg_spectrum.flux.value, 105.)) - - trace.set_position(14.5) - spectrum, bkg_spectrum = boxcar(image, trace) - assert np.allclose(bkg_spectrum.flux.value, np.full_like(bkg_spectrum.flux.value, 98.)) - - def test_outside_image_condition(): # # Trace is such that one of the sky regions lays partially outside the image @@ -116,5 +65,5 @@ def test_outside_image_condition(): boxcar.skywidth = 5. trace = FlatTrace(image, 22.0) - spectrum, bkg_spectrum = boxcar(image, trace) - assert np.allclose(bkg_spectrum.flux.value, np.full_like(bkg_spectrum.flux.value, 99.375)) + spectrum = boxcar(image, trace) + assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 99.375)) From 484a71f70c79808be2659e90d742487248f70e2c Mon Sep 17 00:00:00 2001 From: Ivo Date: Tue, 15 Feb 2022 16:14:57 -0500 Subject: [PATCH 04/18] Add reference to trace object --- specreduce/extract.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/specreduce/extract.py b/specreduce/extract.py index 51a7be2f..57276ece 100644 --- a/specreduce/extract.py +++ b/specreduce/extract.py @@ -127,16 +127,19 @@ class BoxcarExtract(SpecreduceOperation): center: int = 10 width: int = 8 - #def __call__(self, image, trace_object): - def __call__(self, image, disp_axis, crossdisp_axis): + # TODO: should disp_axis and crossdisp_axis be defined in the Trace object? + + def __call__(self, image, trace_object, disp_axis=1, crossdisp_axis=(0,)): + # def __call__(self, image, disp_axis, crossdisp_axis): """ Extract the 1D spectrum using the boxcar method. - Does a background subtraction as part of the extraction. Parameters ---------- image : ndarray array with 2-D spectral image data + trace_object : Trace + object with the trace disp_axis : int dispersion axis crossdisp_axis : int or tuple @@ -152,6 +155,8 @@ def __call__(self, image, disp_axis, crossdisp_axis): # self.last_trace = trace_object # self.last_image = image + self.center = trace_object.trace_pos + for attr in ['center', 'width']: if getattr(self, attr) < 1: raise ValueError(f'{attr} must be >= 1') From a65a04a0738d01c134bbbaf9c6cbdc13e13c8140 Mon Sep 17 00:00:00 2001 From: Ivo Date: Wed, 16 Feb 2022 12:46:23 -0500 Subject: [PATCH 05/18] Extraction uses Trace from specreduce --- specreduce/extract.py | 84 +++++++++++++------------------- specreduce/tests/test_extract.py | 32 +++++++----- 2 files changed, 53 insertions(+), 63 deletions(-) diff --git a/specreduce/extract.py b/specreduce/extract.py index 57276ece..b8034766 100644 --- a/specreduce/extract.py +++ b/specreduce/extract.py @@ -14,10 +14,8 @@ def _get_boxcar_weights(center, hwidth, npix): """ - Compute the weights given an aperture center, half widths, and number of pixels + Compute weights given an aperture center, half width, and number of pixels """ - # TODO: this code may fail when regions fall partially or entirely outside the image. - weights = np.zeros((npix)) # 2d @@ -28,9 +26,13 @@ def _get_boxcar_weights(center, hwidth, npix): # pixels at the edges of the boxcar with partial weight if fullpixels[0] > 0: - weights[fullpixels[0] - 1] = hwidth - (center - fullpixels[0]) + w = hwidth - (center - fullpixels[0] + 0.5) + if w >= 0: + weights[fullpixels[0] - 1] = w + else: + weights[fullpixels[0]] = 1. + w if fullpixels[1] < npix: - weights[fullpixels[1]] = hwidth - (fullpixels[1] - center) + weights[fullpixels[1]] = hwidth - (fullpixels[1] - center - 0.5) # 3d else: # pixels with full weight @@ -43,31 +45,28 @@ def _get_boxcar_weights(center, hwidth, npix): return weights -def _ap_weight_images(center, width, disp_axis, crossdisp_axis, image_shape): +def _ap_weight_image(trace, width, disp_axis, crossdisp_axis, image_shape): """ Create a weight image that defines the desired extraction aperture. Parameters ---------- - center : float - center of aperture in pixels + trace : Trace + trace object width : float - width of apeture in pixels + width of extraction aperture in pixels disp_axis : int dispersion axis - crossdisp_axis : int or tuple + crossdisp_axis : int (2D image) or tuple (3D image) cross-dispersion axis image_shape : tuple with 2 or 3 elements size (shape) of image - wavescale : float - scale the width with wavelength (default=None) - wavescale gives the reference wavelenth for the width value NOT USED Returns ------- - wimage : 2D image, 2D image - weight image defining the aperature + wimage : 2D image + weight image defining the aperture """ wimage = np.zeros(image_shape) hwidth = 0.5 * width @@ -82,19 +81,15 @@ def _ap_weight_images(center, width, disp_axis, crossdisp_axis, image_shape): image_sizes = image_shape_array[crossdisp_axis_array] image_sizes = tuple(image_sizes.tolist()) - # loop in dispersion direction and compute weights - # - # This loop may be removed or highly cleaned up, replaced by - # vectorized operations, when the extraction parameters are the - # same in every image column. We leave it in place for now, so - # the code may be upgraded later to support height-variable and - # PSF-weighted extraction modes. - + # loop in dispersion direction and compute weights. for i in range(image_shape[disp_axis]): if len(crossdisp_axis) == 1: - wimage[:, i] = _get_boxcar_weights(center, hwidth, image_sizes) + # 2d + # TODO trace must handle transposed data (disp_axis == 0) + wimage[:, i] = _get_boxcar_weights(trace[i], hwidth, image_sizes) else: - wimage[i, ::] = _get_boxcar_weights(center, hwidth, image_sizes) + # 3d + wimage[i, ::] = _get_boxcar_weights(trace[i], hwidth, image_sizes) return wimage @@ -107,63 +102,50 @@ class BoxcarExtract(SpecreduceOperation): Parameters ---------- image : nddata-compatible image - The input image - trace_object : - The trace of the spectrum to be extracted TODO: define - center : float - center of aperture in pixels + image with 2-D spectral image data width : float - width of aperture in pixels + width of extraction aperture in pixels Returns ------- spec : `~specutils.Spectrum1D` - The extracted spectrum - skyspec : `~specutils.Spectrum1D` - The sky spectrum used in the extraction process + The extracted 1d spectrum expressed in DN and pixel units """ - # TODO: what are reasonable defaults? - # TODO: ints or floats? - center: int = 10 - width: int = 8 + # TODO: what is a reasonable default? + # TODO: int or float? + width: int = 5 # TODO: should disp_axis and crossdisp_axis be defined in the Trace object? def __call__(self, image, trace_object, disp_axis=1, crossdisp_axis=(0,)): - # def __call__(self, image, disp_axis, crossdisp_axis): """ Extract the 1D spectrum using the boxcar method. Parameters ---------- - image : ndarray - array with 2-D spectral image data + image : nddata-compatible image + image with 2-D spectral image data trace_object : Trace object with the trace disp_axis : int dispersion axis - crossdisp_axis : int or tuple + crossdisp_axis : tuple (to support both 2D and 3D data) cross-dispersion axis Returns ------- - waves, ext1d : (ndarray, ndarray) - 2D `float` array with wavelengths - 1D `float` array with extracted 1d spectrum in Jy + spec : `~specutils.Spectrum1D` + The extracted 1d spectrum expressed in DN and pixel units """ -# self.last_trace = trace_object -# self.last_image = image - self.center = trace_object.trace_pos - for attr in ['center', 'width']: if getattr(self, attr) < 1: raise ValueError(f'{attr} must be >= 1') # images to use for extraction - wimage = _ap_weight_images( - self.center, + wimage = _ap_weight_image( + trace_object, self.width, disp_axis, crossdisp_axis, diff --git a/specreduce/tests/test_extract.py b/specreduce/tests/test_extract.py index ed72b0e1..d004b22c 100644 --- a/specreduce/tests/test_extract.py +++ b/specreduce/tests/test_extract.py @@ -22,10 +22,9 @@ def test_extraction(): # extraction aperture sizes. # boxcar = BoxcarExtract() - - boxcar.apwidth = 5 - trace = FlatTrace(image, 15.0) + boxcar.width = 5 + spectrum = boxcar(image, trace) assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 75.)) @@ -37,7 +36,7 @@ def test_extraction(): spectrum = boxcar(image, trace) assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 73.5)) - boxcar.apwidth = 6 + boxcar.width = 6 trace.set_position(15.0) spectrum = boxcar(image, trace) @@ -47,23 +46,32 @@ def test_extraction(): spectrum = boxcar(image, trace) assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 87.)) - boxcar.apwidth = 4.5 + boxcar.width = 4.5 trace.set_position(15.0) spectrum = boxcar(image, trace) assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 67.5)) + boxcar.width = 4.7 + + trace.set_position(15.0) + spectrum = boxcar(image, trace) + assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 70.5)) + + boxcar.width = 4.7 + + trace.set_position(14.3) + spectrum = boxcar(image, trace) + assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 67.0)) + def test_outside_image_condition(): # - # Trace is such that one of the sky regions lays partially outside the image + # Trace is such that extraction aperture lays partially outside the image # boxcar = BoxcarExtract() + trace = FlatTrace(image, 3.0) + boxcar.width = 10. - boxcar.apwidth = 5. - boxcar.skysep = int(2) - boxcar.skywidth = 5. - - trace = FlatTrace(image, 22.0) spectrum = boxcar(image, trace) - assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 99.375)) + assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 32.0)) From 562ce8f59ec86ef6b5dc613826ab020b794325f5 Mon Sep 17 00:00:00 2001 From: Ivo Date: Wed, 16 Feb 2022 13:52:31 -0500 Subject: [PATCH 06/18] Add test for ArrayTrace --- specreduce/extract.py | 10 ++++++---- specreduce/tests/test_extract.py | 15 ++++++++++++++- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/specreduce/extract.py b/specreduce/extract.py index b8034766..95bc25fc 100644 --- a/specreduce/extract.py +++ b/specreduce/extract.py @@ -138,10 +138,12 @@ def __call__(self, image, trace_object, disp_axis=1, crossdisp_axis=(0,)): spec : `~specutils.Spectrum1D` The extracted 1d spectrum expressed in DN and pixel units """ - self.center = trace_object.trace_pos - for attr in ['center', 'width']: - if getattr(self, attr) < 1: - raise ValueError(f'{attr} must be >= 1') + # this check only applies to FlatTrace instances + if hasattr(trace_object, 'trace_pos'): + self.center = trace_object.trace_pos + for attr in ['center', 'width']: + if getattr(self, attr) < 1: + raise ValueError(f'{attr} must be >= 1') # images to use for extraction wimage = _ap_weight_image( diff --git a/specreduce/tests/test_extract.py b/specreduce/tests/test_extract.py index d004b22c..7dfef1a8 100644 --- a/specreduce/tests/test_extract.py +++ b/specreduce/tests/test_extract.py @@ -4,7 +4,7 @@ from astropy.nddata import CCDData from specreduce.extract import BoxcarExtract -from specreduce.tracing import FlatTrace +from specreduce.tracing import FlatTrace, ArrayTrace # Test image is comprised of 30 rows with 10 columns each. Row content @@ -75,3 +75,16 @@ def test_outside_image_condition(): spectrum = boxcar(image, trace) assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 32.0)) + + +def test_array_trace(): + boxcar = BoxcarExtract() + + trace_array = np.ones_like(image[1]) * 15. + + trace = ArrayTrace(image, trace_array) + boxcar.width = 5 + + spectrum = boxcar(image, trace) + assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 75.)) + From 733ad3a752193ef9dde425549c3b7143b5307f13 Mon Sep 17 00:00:00 2001 From: Ivo Date: Wed, 16 Feb 2022 13:59:51 -0500 Subject: [PATCH 07/18] Fix codestyle --- specreduce/tests/test_extract.py | 1 - 1 file changed, 1 deletion(-) diff --git a/specreduce/tests/test_extract.py b/specreduce/tests/test_extract.py index 7dfef1a8..def78924 100644 --- a/specreduce/tests/test_extract.py +++ b/specreduce/tests/test_extract.py @@ -87,4 +87,3 @@ def test_array_trace(): spectrum = boxcar(image, trace) assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 75.)) - From dc35c48ad0a6c4a45400aef483f0f3eb32d3c165 Mon Sep 17 00:00:00 2001 From: Ivo Date: Fri, 18 Feb 2022 11:09:41 -0500 Subject: [PATCH 08/18] New demo notebook --- .../jwst_boxcar/boxcar_extraction.ipynb | 403 ++++++++++++++++++ 1 file changed, 403 insertions(+) create mode 100644 notebook_sandbox/jwst_boxcar/boxcar_extraction.ipynb diff --git a/notebook_sandbox/jwst_boxcar/boxcar_extraction.ipynb b/notebook_sandbox/jwst_boxcar/boxcar_extraction.ipynb new file mode 100644 index 00000000..40d67256 --- /dev/null +++ b/notebook_sandbox/jwst_boxcar/boxcar_extraction.ipynb @@ -0,0 +1,403 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Boxcar extraction with specreduce" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This notebook demonstrates a simplified boxcar extraction scenario, using a rectified spectrum in a 2D spectral image where the dispersion axis is the second (X) axis. \n", + "\n", + "The extraction algorithm in `specreduce` is a plain adaptation of the algorithm presented in the MIRI LRS extraction notebook at https://github.com/spacetelescope/jdat_notebooks/tree/main/notebooks/MIRI_LRS_spectral_extraction This algorithm is demonstrated separately from the `specreduce` package, in the acompanying notebook http://localhost:8888/notebooks/notebook_sandbox/jwst_boxcar/jwst_boxcar_algorithm.ipynb\n", + "\n", + "Note that the extraction algorithm in the MIRI LRS extraction notebook performs simultaneous background subtraction when extracting from the source. Although it can only subtract the average of the two background extraction boxes. The original extraction code in `specreduce`'s `BoxcarExtract` class was capable of modeling the background with a polynomial along the cross-dispersion direction. This feature was lost in the conversion. \n", + "\n", + "Note also that we cannot yet perform offline, after-the-fact background subtractions from spectra extracted with `BoxcarExtract`. The reason is that `BoxcarExtract` delivers its products in units of `DN` and `pixel`. Subsequent operations with such spectra, such as subtraction, are severely limited due to the `pixel` units." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "import os\n", + "\n", + "import numpy as np\n", + "\n", + "import matplotlib.pyplot as plt\n", + "import matplotlib as mpl\n", + "from matplotlib.colors import LogNorm\n", + "%matplotlib inline\n", + "\n", + "from astropy.io import fits\n", + "from astropy.table import Table\n", + "from astropy.visualization import simple_norm\n", + "from astropy.utils.data import download_file\n", + "\n", + "from jwst import datamodels\n", + "\n", + "from specreduce.extract import BoxcarExtract\n", + "from specreduce.tracing import FlatTrace\n", + "\n", + "import ccdproc\n", + "\n", + "from pathlib import Path\n", + "import tempfile\n", + "from zipfile import ZipFile" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Ingest s2d data" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "# data is taken from s2d file. x1d is used for comparison with pipeline extraction.\n", + "zipped_datapath = Path(download_file('https://stsci.box.com/shared/static/qdj79y7rv99wuui2hot0l3kg5ohq0ah9.zip', cache=True))\n", + "\n", + "data_dir = Path(tempfile.gettempdir())\n", + "\n", + "with ZipFile(zipped_datapath, 'r') as sample_data_zip:\n", + " sample_data_zip.extractall(data_dir)\n", + "\n", + "s2dfile = str(data_dir / \"nirspec_fssim_d1_s2d.fits\")\n", + "x1dfile = str(data_dir / \"nirspec_fssim_d1_x1d.fits\")" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "DEBUG:jwst.datamodels.util:Opening /var/folders/f2/dsq1cxxd78n9vltk6_6kwxtr0000zf/T/nirspec_fssim_d1_s2d.fits as \n" + ] + } + ], + "source": [ + "# use a jwst datamodel to provide a good interface to the data and wcs info\n", + "s2d = datamodels.open(s2dfile)\n", + "image = s2d.slits[0].data" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0.5, 1.0, 'slit[0]')" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA2cAAABwCAYAAACacAjbAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8vihELAAAACXBIWXMAAAsTAAALEwEAmpwYAAAdpUlEQVR4nO3df6w0V33f8c939t7neQx2cAiuRW0KJLESOZFwoialIq0oqI1Jq7ptaGRSpbSicivZEkhRCgS1pVKRyB8NTZQ0klMotE3q0AQUFKGmCBy1/aMEp3FCDFhxYtPgGgwpP8wP+7l359s/5pzdM2dn9vfOzJ19v6Tn2d2ZM3POnP11PvfM7pq7CwAAAADQr6LvBgAAAAAACGcAAAAAMAiEMwAAAAAYAMIZAAAAAAwA4QwAAAAABoBwBgAAAAADQDgDAAAAgAEgnAEALjwze6uZ/adw/c+Z2VfNbNJS9kVm5qHMXWvu/91m9g0z+8w+2w0AQIpwBgAYFXf/P+5+rbtPJcnMfsvM/lFD0evd/d54w8xeaWafMrOvm9n9ZvbCZJ//QNKrDt54AMBRI5wBAI6emT1P0vsk/TNJz5X0gKRf6bVRAICjQzgDAFwoZvZGM3vczJ4ys4fN7JXZ+nja4omZvU3SX5L0c+E0xp9r2e3fkfSQu/8Xd39a0lslvcTMvvOgBwMAQIJwBgC4MMzsOyTdI+n73P06ST8o6bG28u7+Fkn/Q9I94VTHe1qKfpek30u2+5qkPwrLAQDoxEnfDQAAYANTSZcl3Wpmn3f3xyTJzHbd77WSPp8t+7Kk63bdMQAA62LmDABwYbj7I5LeoOq0wyfN7D4z+7N72PVXJX1TtuybJD21h30DALAWwhkA4EJx91929x+Q9EJJLumnVm2yxm4fkvSSeMPMni3p28JyAAA6QTgDAFwYZvYdZvYKM7ss6WlJ35BUrtjsc5K+dUWZ90v6bjP7YTO7IumfS/p9d//Uzo0GAGBNhDMAwEVyWdLbJX1B0mcl/RlJb16xzc9IerWZfdHMfrapgLt/XtIPS3qbpC9K+guS7txXowEAWIe5r3O2BwAA4xB+XPphVTNvP+Huv7jGNu+U9HclPenu337gJgIAjhThDAAAAAAGgNMaAQAAAGAACGcAAAAAMACd/gj15Lpn+8kN13dZJQAAAAAMxtVH/+8X3P2GpnWdhrOTG67XTW+7u8sqAQAAAGAwHv3Rt3y6bR2nNQIAAADAABDOAAAAAGAACGcAAAAAMACdfuYMR846+k09t27qAQAAAPaIcLaLrsIGNrOP+4WABwAAgI6NN5wNIDgxvO/HXu75ATx+ZgiKAAAAR2G04ayL4aztOoDvIgAc4cB+1yP2nvosPhosuz2ooIiL7whfEwAAuCjGGc7MNTmZypaMQdqCVdPytv3EsrPLZF2R7ScvOy+3uv58X7FcGiLKhgHXNiEjrd/d1g6gsY15O4qW487bGNc3HWubWFfcR1p307GXya7z9Xlfnk8LlWUhM5eZazIpW8svW1Ytb26/r2jvqu1XbberZfVutqNhh4G+wviutr57CPvjd0Ef0wCAkYazwlzPunI1GfDX1+dBIA0OaTiwZFlT2IrLJ1YN3E+KsraPQrGecla2MFeh+v4KKzVZ2Gb5+qiUaeqm0udfvNkU1PJt0n2Vstp+C/PaPmbHY2WtnsLmgWUSjiu2J7b3xKa1fUxUbTNVoTK0O/bPRGWtr2PZWL52DG6zNp75RKUXC30R18fjjetKt9myMgl28fq5T/Sn33iWrp6faFKUmhSlrj29qklRqnSrBzlZbR9RU3Cehcls+bQsFrap1s+vNwW5VfdzWldt2ZoDt1XlmsLbvva9bn3bSuu3DWLOPtuwvKLV/dPn8HvXQJt247HEiE4jMQEcFx1/YMARG2U4k6RJ4ZoUZeOMTBq64mVTQJuFBKvPmsR1J0WpQq6TYroQvPJAdVJMNTHXiU0XwkdhrtMsxMR6Y2iKbWgKZ7mpt/9CQlo+31dbHc3HXy07takmCserchai4rHF4zq187Cv+b6nbipVqFDVV6d2rkuhfK2usK8yCWhTLzRVFbZinXF/V/1kIbhUYTDdJlzOQl11eVZONFWhL11zja6WJ7P+uGZyNgunMQRKqoW9pvBXlWkKgiFAZuGuKeCtCoD5sdbKZH2Zzza2WTULWZVp3nb5LGD7urawuWyYuW1I2Hamctt9bl52eSMOHRJXtW/XQDu4YVcHA8FD1HBRZ32Hhig7QPyBoX+8vvRmnOHMXJdOznXaEM7yWa10BixdF2dz4jbpbFIMYSfFVKdW6vKkCh4xeMUZoNN420qd2nT2rwoy80AjSVeKs1kISQPMLNQsefuoQtxigMqVKmrBbR7GSk1Cm+LtuD6tdyqblwltf7ad6TSEyIn5LLRcsipKTaz6Mb1LZtVtmQqLocJ1Jlch6dQKnWqiZxWXNPV0Rm4xaE69VCnXmS8GuVKlvu5TTT0NuXHmzHUm6cyrYzkLIe3MC535JFw/0VSmp/1UUy9mtyfyWhg884kkzYJgLBdn8eL6tL9nIdBtFijTQFZfVswC3lk5qQW+NBjOyq8Ig/N18/2m69M/CtTLL4a5vK58Vrlp+9TiDGHTKaj1Wca29Zvss8mq01+32X6bALqwjy3q3UfZ+nZbbbZTnfvafv16Ztf2sK/Dtzm/T3b+3PMuLvDALT1l392G98eCC4goNUJjCsgX7PVqnOEsKN10Np3Mbi87ZbEpxKUBTqp/PmrdmbN4+7SY1kJfDHCxrlObNs5QzWbUkpe+fLasCkarw9k0GZin+5yFtHCZBrB4e5rVGcPlFTubhcN6OJvO9jEJ7YshMN1nDC8TK3Wqqa4UZ1KY5Zq1Mzu2MgSh6njq4W0q09PlpVp74/HEcHXVJ7UZtjirFgNaGq7OfFILWHF5DFXx9MzzWD4JUtNaSNksSOUhauHUyOyUzbbZs7bQsir8rNpPU51NNpl12yTorKp7k7eUZfXmn8Fcb3+71X2Iberb77T5GvvvOlgNwAV744+OeeZtoz9wHLAdwKAd8WtEn0YdzqZuevrqafU5IS2eVpJ/5qx+auO8XFM4i9ubeW2mK52Bs+R6DG5Np1k2faZttq7hbaEpnOUBplY+OYVumbyuxVC0GJhOinKttqefW2vaZxpmm0/VzENG0TzjItN5uTjbloee/FTCplMIpfnnwVZ9biw/xbD+mbN6W5Z9GUm6j9n6lnJty6rljYvX+BzZqvVLV2+1z33UMd+4i9mL/t+sGCzioAbwGAeAYzXKcOZloaeevixJOj+fLC2bBrKmb2VcdtpI/i2NTV8wkn8pSeuXj+w4fbzOtxzmwWFVnctOVytajj2Wy7dt+kKVfJC7bh+s+kKMGMbb1jXtY357sa5l4cmzsk3X58taGrVkm+XLN9/Xpm1avvHhBnB9BqCjDT6xz/d5KguDfAAANjLOcOamr3/tiqTtQs/WQWnN7ZZ9xT8Ob61AssOg8lDBYtShgUH8cHBfAADQm1GGs9Q2A9qFGZ21N1xecn565BaNwsHsO0xd+LuXwTkAAEAvRh/O9jHQXDrY3mCWbQifVUFPuO8BAACwwvjD2aF1NeiOIXAfnwvJ2zymr0vdFuEJAAAAPSOcXRR5eNhnmCCYAAAAAL1b/M5xAAAAAEDnCGcAAAAAMAArw5mZvcDM7jezT5jZQ2b2+rD8uWb2ITP7w3D5zYdvLgAAAACM0zozZ+eSftzdb5X0Ukl3m9mtkt4k6cPufoukD4fbAAAAAIAtrPxCEHd/QtIT4fpTZvZJSTdJukPSy0Ox90j6LUlvPEgrsRK/nTbHj3wDAADgItro2xrN7EWSvkfSRyXdGIKbJH1W0o0t29wl6S5JmjzvOVs39CIjOHVr0/4mzAEAAGAI1g5nZnatpF+T9AZ3/4olI1p3d7PmH8ty93sl3StJl7/1ps5jCsEIq2zzGIkP/74eXwRKAACA8VkrnJnZqapg9kvu/r6w+HNm9nx3f8LMni/pyUM1clt7GzjH/VjDsgPz5DfIWvLvheArfkstHltbuUEce9K0vkN/3/WPEYEXAAD0bWU4s2qK7J2SPunuP52s+oCk10p6e7j89YO0cEc+XXPEtSI8pINhs2xwvM6POOeD6WWD65b9NW4SQ0ufPyS99Fji5Yr+3aEKtQW3WKWrHqzzMmkfrtrXquUt26czbWuFgE3C6DrHuaVBhOJl9vlb7AM/VAxH+h5AqAcA7NM6M2cvk/Rjkj5uZg+GZT+pKpS918xeJ+nTkn7kIC3cgrskr2ZhvFzxztkUGlYEKbewbJNt1ymbLbOGbdy8ttzD4Lmp7Ma2GZx6drmwvmrXwhg/3S5vutfLtx7aQjDKyreFrnS7YrFPq02yBlt2udCWbHo1LWf17vFa+YY6sv1YEWYV2x7LGwaoTQaTnh/wvsLavga0G3++cEQJjFDQmzTIE+qxbwR+4Lit822N/1Ptw4BX7rc5++Glyb96Ug24J+m7aF4wCTX56DkJVU1BwVyy82y9z9el+7EyXoaytWX1uq2sX8agMssXTXW0dkRy3Ravz/YZ60z2GZebu6ysynphstJVTJN9lVXZ4lyy0uVmkknlpFo9Oau2t2nos9JrdRRnrvLEVJ5Ux1xMXXYuFee+GMqK2O4Y+OYH6GaaXjF5YVXdJpWTIvRlNV1VTkxeSF6EPjDp/IqpvBTaN533Q9yHLBz7SeyDej96LDNp6GfF9V7bblZ/rUyyLARWL1zlqaTnnMnPTcVXsqdrvB+LxcwU621qU6OGx0euMbDGP1S07au1vjVHtKv2tckgxnzFDOwG+9r3PrYMjekgbt2ZHDupnvA+jQ/gdSvrMIU0Pa7y5T0OYFedhr1sm16kry0X0ZGFFQI/sJv8vfGi/cFjo29rvDBCEGqalVmYYaoFsXiZzPak65XcwWkdnlSTBS4rs3Jl0/r6tmm9tffz9PZs/eKreC28ZH0Qw1NVINbpCwFxHs5CaAlhIQatuP94LDGEeVGFqvKkqmRytVpenLms9Pmxqqq3uFrKJ6bp5UI2dRVnruKsVHE2rbdVVTic3QGFpGmcNazWnU1PpEIqT2NIq9YX0yrAlJPq0idVeTepmLi8sCpcTn3ev6UlYbDKr5aGsziuzX8psGk2z5Kps6bAFPeR3F3ukslk7vVNs8DtVn/81Cbu3OazvI3pLVmePk6aZjNVtae2CyXbrrIwO2rzvzq0buPL9902gG+qL9ZZ23fDlO0y67y4t/1BZOV2WdvW3ayh6LKBXe0NatPZ9nXK7yuAtO0m/yNare6G5Qd6Q94klK2zjZkvrB/VLO+utu2K2uO9YRmAUcrfB/M/Xg79tPRRhjMrXOWVaZjqqK/zhXuscRQ3GyjHm/UKQpEkdKX7W5jVck8Cly0ErLjL+jZhedOb0so3qoYCSQX5IS895VAhXJons3fzdLdwLMlsk8xl06K+rziet3q9XmgePtN9tR7HojgjNZutagxKcf38uhfekF3qDa7Ndi3Menl7uxq3ycq3bluVM0kqpOl10+Z+Wbb9utZ9gdr0hWwPM0I76XqAO9AXeikZ7MeH9qRsL3yR7fs+2GR2uO11a51qunisDvjxeXDHfOzAEkMNKIc09GMeZTiTqTqdsWHmq8azd922kNK2eZGV8fBfmgpC/d6wvvXUxHQWa6twpvqAIp8sXDFZsVBPPvOS1d/URg+fk0pnyhb+ot30F+5anW2NbF6cn8rXGM6Sy6XBaqFsw4xXW1tWfp6s6XbLNnGCq/D5qZNt9a7a37Li275QpTNQ+x5cDvDFcxSzGU0zTIesZwwO9ccLAAex6uduhj44x3EbZziTVMTPVWx86s4WlS2pY9kpRr5i2+V1Llm37xedPCh1MT7d4S/QM3sIMPEFvHVX+/rs1NI2hKA7WVGwS7XjGUFgOUYDHJwwYAKwT7ym4CIaZTirfcRn04Hjpllu2devt+3OW2+MU1df87/trMYegtNB8eYyGE1fwLHrfgAAAKJRhrOaAw+CRnGa067aZrlaP7Q3AAyOOze2QDK24wEAAP0bbThrGzjxFbUHsOFnw9ANwgMAAMDFMtpw1qbvASvh8Dj0/TgDAADAxXN04axvqwbthLfhI3gBAADgEAhnA5MP/Alr/SCAAQAAoGuEsy0QmMaP30YBAABA10YfzghS2KdNH0+EOQAAAKxrtOFsr6Fs/qNpzcuxtqYfBR/zzxFs9DiMXdP2eMPRINQDAHCcRhnO3LWX4LQQJMI+Y5hoChpN5Y/aGj9A7cp+yHvoP1rdur8dt8+b0+HjZxQBeUSB5thn/M3mfUBQBQAck1GGM7lUnk2afxy5bdCzMDC25nUWbqYBsCXEySVr2o83lW2YUWoq1ySfaVl3YJdWuWwbUziWhrJu1fK8rWHfC8cQ95NmsaK5LevmhYWuM83vp3g7W1/bJq3Ikn1adjuWtaRsevfG/TS1Zx1NB2wt11dt11pH8+KN8vCWQe4gg+x9hcqBBYBRhOUdzF5jFULawO4fAKvF13x3/sgCbGKU4czdpKuFVEoq0hX1y9bglAWmWZjIXlzsXPVwEsftZdgmXqb7KVUPJ0lYqWWEMitTar6PhQNO2mfZMeTbhHKeBYumOmIZn0g2Df9Kn5WLfVBMk22n9YAyuarZK7OVrskzLitdxTNhg8JUnprOrylkZdh/qCf2Vbyb5uGw3gnlaVG1M4Q8L0xeSNPT6tInVj+eUNYn8SBCOTOpmK9XIZUTzZal/eaTUG62D6/WFYt96+n9EvsmXx8PsGl5kd1WVj4N5WlwXKEWJvcRzlZNJG/z5rwypFjtYlWx3erazC6DEW9rcPqEyJd36dADrQPOIh978D0YBt/IpG/VXZ0NkAZCjM+xhPxRhrOZIrsdB8jh0pM3aWt8ZwmnL8qyGYwwQCokcw+nUVYhzT2pN8zemHtVn0tWzE+HjKHMVYWb2YtJw1+ZGmetGppUCwH5tnEXTYPxhhmt2THEsw7LKtCm4UylQqhKdz5XTOeDSXOTTas6ium8eAxKs/3ks3TLZj8tBKikrTEglSc2n0WzhjJp6MnDVxbC6ut9vm1yX89m6xrDWZJ4i3on5yFsYXkW2mb1zY5nxYxbm33N6G27/20GyWu3edP97u+d/OBvHoSLnbgbAe0Q8jM4gB4QyvZraGH3WGZhRxnOzFw+qWZeJNUDQ9tpXeGdxWIQS0NB06MypKH4+bZZSIv1pSEw7ipcl3u1eVgWGlCNwUubV9k2+7XE0tmJtlmVOIFSarWmdnlyPWuHlVZv+5IZQCvn6xvb3SQPVFJ99ivbvha0imwfkjwGp4bwNWtyXt9s+TxE1U+bTNvgzdvlx5ldXwhgG8yQNdr1VMh9zURtNZu2xTZL97efd529vmF0ER7SGdcjQ0A7oGXdegSDKmCM0s8B992OKG3P2ALbKMOZTNJJOQ9JtQ84NZRPRss+S1Dp+uZqZl8Iks1qrf05s6TuhVP2lsyQtVnrtLG2MiuedK31+vKKF7bL+yMbIC6UX3FMtcCUXK/NVmXr01m01tMLG9av9fmyNdq89kxUW4hbu54V6zexxUD2woUVaTCDx06Dw0COeW+a/vg0tmMEsLOxDegPbWj9NbT27NM4w5kkmyTnDK5rww/F1GbK0uULV5o2brm5bht2PYVkn9+O2HSc2/xVftPxaFuzG4POBqfmrbt9U7FdThVsLbt+0dZdXPRZghG/CI/ZIN48h9AGAADWNMpwZumsyUZvzL766/HTepLttjo1qLGuPgbR29fZNs3d13nKGw0GOw5Is10d2SwQNjeIUAMAADo3ynAmaeuBabczDG3TZxdHl2fW7cXgGnR8CB4AAADNRhvO8gHgED7IuBKDVuwJAQgAAODiGW04yw1hsHohAiL2YgiPNwAAAFwsRxPOhoABOwAAAIA2+c80AwAAAAB6QDgDAAAAgAEgnAEAAADAABDOAAAAAGAACGcAAAAAMAA7hTMzu93MHjazR8zsTftqFAAAAAAcm63DmZlNJP28pFdJulXSa8zs1n01DAAAAACOyS4zZ98v6RF3/2N3vyrpPkl37KdZAAAAAHBcdglnN0n6k+T2Z8KyGjO7y8weMLMHpk99bYfqAAAAAGC8Tg5dgbvfK+leSTKzzz/6o2/5mqQvHLpetHqe6P8+0f/9ov/7x33QL/q/X/R/v+j/ftH/cy9sW7FLOHtc0guS2zeHZa3c/QYze8Dd//wO9WIH9H+/6P9+0f/94z7oF/3fL/q/X/R/v+j/9exyWuPHJN1iZi82s0uS7pT0gf00CwAAAACOy9YzZ+5+bmb3SPpNSRNJ73L3h/bWMgAAAAA4Ijt95szdPyjpgxtudu8udWJn9H+/6P9+0f/94z7oF/3fL/q/X/R/v+j/NZi7990GAAAAADh6u3zmDAAAAACwJ4QzAAAAABiAzsKZmd1uZg+b2SNm9qau6j1mZvaYmX3czB40swfCsuea2YfM7A/D5Tf33c4xMbN3mdmTZvYHybLGPrfKz4bnxO+b2ff21/JxaOn/t5rZ4+F58KCZ/VCy7s2h/x82sx/sp9XjYWYvMLP7zewTZvaQmb0+LOc50IEl/c9zoANmdsXMftvMfi/0/78My19sZh8N/fwr4RuuZWaXw+1HwvoX9XoAI7DkPni3mT2aPAduC8t5DToAM5uY2e+a2W+E2zwHNtBJODOziaSfl/QqSbdKeo2Z3dpF3dBfcffbkt+VeJOkD7v7LZI+HG5jf94t6fZsWVufv0rSLeHfXZJ+oaM2jtm7tdj/kvSO8Dy4LXyRkcJr0J2Svits82/DaxW2dy7px939VkkvlXR36GeeA91o63+J50AXnpH0Cnd/iaTbJN1uZi+V9FOq+v/bJX1R0utC+ddJ+mJY/o5QDrtpuw8k6SeS58CDYRmvQYfxekmfTG7zHNhAVzNn3y/pEXf/Y3e/Kuk+SXd0VDfq7pD0nnD9PZL+Vn9NGR93/++S/l+2uK3P75D0H7zyvyRdb2bP76ShI9XS/23ukHSfuz/j7o9KekTVaxW25O5PuPv/DtefUvXmfJN4DnRiSf+34TmwR+Fx/NVw8zT8c0mvkPSrYXn++I/Pi1+V9Eozs25aO05L7oM2vAbtmZndLOmvS/p34baJ58BGugpnN0n6k+T2Z7T8DQP74ZL+m5n9jpndFZbd6O5PhOuflXRjP007Km19zvOiO/eEU1beZfNTeen/Awqnp3yPpI+K50Dnsv6XeA50IpzO9aCkJyV9SNIfSfqSu5+HImkfz/o/rP+ypG/ptMEjlN8H7h6fA28Lz4F3mNnlsIznwP79G0n/VFIZbn+LeA5shC8EGbcfcPfvVTVtf7eZ/eV0pVe/o8BvKXSIPu/FL0j6NlWnuDwh6V/32pojYGbXSvo1SW9w96+k63gOHF5D//Mc6Ii7T939Nkk3q5qF/M5+W3R88vvAzL5b0ptV3RffJ+m5kt7YXwvHy8z+hqQn3f13+m7LRdZVOHtc0guS2zeHZTggd388XD4p6f2q3ig+F6fsw+WT/bXwaLT1Oc+LDrj758KbdSnpFzU/bYv+PwAzO1UVDH7J3d8XFvMc6EhT//Mc6J67f0nS/ZL+oqpT5U7CqrSPZ/0f1j9H0p9229LxSu6D28Mpv+7uz0j69+I5cCgvk/Q3zewxVR9heoWknxHPgY10Fc4+JumW8G0tl1R9APkDHdV9lMzs2WZ2Xbwu6a9J+gNV/f7aUOy1kn69nxYelbY+/4Ckvx++Leqlkr6cnPqFPck+P/C3VT0PpKr/7wzfFvViVR8I/+2u2zcm4bMC75T0SXf/6WQVz4EOtPU/z4FumNkNZnZ9uH6NpL+q6nN/90t6dSiWP/7j8+LVkj4SZpaxpZb74FPJH4dM1eed0ucAr0F74u5vdveb3f1Fqsb6H3H3vyeeAxs5WV1kd+5+bmb3SPpNSRNJ73L3h7qo+4jdKOn94XOVJ5J+2d3/q5l9TNJ7zex1kj4t6Ud6bOPomNl/lvRySc8zs89I+heS3q7mPv+gpB9S9SH8r0v6h503eGRa+v/l4WuTXdJjkv6xJLn7Q2b2XkmfUPUtd3e7+7SHZo/JyyT9mKSPh898SNJPiudAV9r6/zU8BzrxfEnvCd94WUh6r7v/hpl9QtJ9ZvavJP2uqgCtcPkfzewRVV9kdGcfjR6ZtvvgI2Z2gyST9KCkfxLK8xrUjTeK58DajIAKAAAAAP3jC0EAAAAAYAAIZwAAAAAwAIQzAAAAABgAwhkAAAAADADhDAAAAAAGgHAGAAAAAANAOAMAAACAAfj/pR4E6XYqecEAAAAASUVORK5CYII=\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "# display s2d image\n", + "norm_data = simple_norm(image, \"sqrt\")\n", + "plt.figure(figsize=(15, 15))\n", + "plt.imshow(image, norm=norm_data, origin=\"lower\")\n", + "plt.title(\"slit[0]\")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + }, + { + "data": { + "image/png": "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iIhcl5lFewCZNnGKiIiIBBgVNBEREZEAo4ImIiIiEmBU0EREREQCjAqaiIiISIBRQRMREREJMCpoIiIiIgFGBU1EREQkwKigiYiIiAQYFTQRERGRAKOCJiIiIhJggupanBK3jh07xtatW8mfPz+nTp1i+/btnDlzhtDQUEJDQ8mUKRPFixf3OqaIiEjQUUGTaLVt25aZM2fGOE/NmjV57bXXKFWqVAKlEhERCX4qaHJN69evZ+bMmXTu3JkiRYqQMmVKChUqROrUqbl48SIXLlxg3bp1vPbaa9xzzz3MnDmTWrVqeR1bREQkKJhzzusMcaZ06dJu3bp1XsdIlM6cOUPy5MkJCfHtlti4cWMWL17Mzp07SZcuXbSvO3LkCNWrV2f79u3MnDmTatWqJVRkERGRRM3M1jvnSl/rOR0kkMRNnjyZXLlykSpVKkqWLMnx48dZvnw5M2bM4Omnn46xnAHceuutzJ07l5w5c1K9enXuvPNO+vXrx759+xLoHYiIiASfoChoZtbAzEYfO3bM6yiJymuvvUaLFi3Ili0bvXr1YvPmzTRr1oyGDRuSL18+nnzyyVgt57bbbmPlypWMGDGCrFmz0rdvX3Lnzs2rr74az+9AREQkOGkTZxI1atQoHnnkEVq1asW4ceNIlSoVgwcPpmfPnmTNmpXly5dz++2339Cyf/75Z5555hm++uortm3bdsPLERERCWYxbeJUQUuCZs+eTYMGDahTpw4zZswgWTLfsSLOOd5//32qVKlCoUKFbmod+/bt44477qBZs2ZMmDAhLmKLiIgEFe2DJpdt2LCBFi1aUKJECT7//PPL5QzAzOjSpctNlzOAbNmy0a1bNz7++GO2bNly08sTERFJSjSCFuQuXLjACy+8QJYsWahcuTINGjQgVapUrFq1imzZssXrug8fPsztt99O6tSpadOmDalSpWLp0qVERETw2muvkTp16nhdv4iISCCLaQRN50ELYs45nnzySUaOHHl5Wp48eZg7d268lzOAjBkzMnv2bAYPHszw4cO5ePEixYoV4+2332bRokVMnjyZggULxnsOERGRxEYjaEEsMjKShg0b0qNHDyIiIoiMjGTo0KEJUs6uduzYMUJCQggPD2fOnDm0bduWtGnTsmHDBm699dYEzyMiIuI1HSSQRDVs2JB169bx+++/X7GvWSBYu3YtFStW5L777mPGjBmXT5ArIiKSVOgggSRo3759zJ49m/bt2wdcOQMoU6YMQ4YMYebMmbz++utexxEREQkoKmhBatSoUVy4cIGOHTt6HSVaTzzxBA8++CAvvPACEydO9DqOiIhIwAi8oRX51y5cuMDAgQPZuHEjHTp0YNGiRQwdOpSGDRtSoEABr+NFy8wYP348f/zxBx06dCBTpkzcd999XscSERHxnPZBS+RWrFhBjx49WLlyJWFhYfz9998AdOrUiZEjR5IyZUqPE17fsWPHqFKlCtu2bSMyMpKaNWt6HUlERCTeaR+0RODnn39myJAhLFy4kE2bNtGlSxdeeOEFzpw5w8WLF7m6SP/55580adKEihUrsmPHDj766CP279/P7Nmz2b17N2PGjEkU5Qwgffr0fP311xQsWJAGDRowd+5cryOJiIh4SiNoAWDVqlVUrVqVM2fOABAaGkqaNGk4ceIE6dKl4/Tp00RERLBkyRJSpEjB6dOnqV+/PkuXLqVPnz48/fTThIWFefwubt6hQ4eoWbMmO3bsYNOmTeTLl8/rSCIiIvFGp9kIYOfPn6dQoUI455g7dy5ffvklixYtYtSoUaxfv56vvvqKs2fPMnbsWJ599lnuuusuevToweHDh/nwww9p166d128hTu3cuZPixYtTrFgxFi1aFJBHoIqIiMQFFbQANmrUKB555BFmzJhBw4YNo52vS5cuvP/++wBUrlyZl156iWrVqiVUzAQ1ceJE2rZtS//+/endu7fXcUREROKFCloAcs7Rq1cvBg8eTKlSpVizZk2MJ2t1zjFu3Dh++eUXXnrpJVKkSJGAaRNemzZt+Oyzz5g/fz5Vq1b1Oo6IiEicU0ELQKtXr6Z8+fJ07dqVoUOHkiZNGq8jBZQTJ05QtmxZjhw5woYNG8iRI4fXkUREROKUjuIMQAsWLACgf//+KmfXEB4eztSpUzl58iQtW7b8x1GsIiIiwUwFzSOLFy+maNGiZM6c2esoAatIkSK8/PLLLFu2jN9++83rOCIiIglGBc0Du3btYtGiRdSoUcPrKAGvVq1aACxdutTjJCIiIglHBc0D/fv3B+CZZ57xOEngK1q0KLfccosKmoiIJCkqaAns+PHjl08jkSdPHq/jBLyQkBAqVqyogiYiIkmKCloCi4yM5OTJk3Tq1MnrKIlGpUqV2LZtGwcOHPA6ioiISIJQQUtgy5cvJzw8nLJly3odJdGoVKkSAMuWLbs8bcuWLRQuXJhZs2Z5FUtERCTeqKAlsBUrVlCuXDlCQ0O9jpJolCpVilSpUl1R0Pr168e2bdto0aIFa9eu9TCdiIhI3FNBS0AnT57k+++/p3z58l5HSVRSpEhBuXLlLu+Htm3bNiZPnkynTp3IkiUL999/Pz///LPHKUVEROKOCloC+vHHH7l48SIlSpTwOkqiU7lyZTZu3MjEiRN57bXXSJkyJa+++ipz5szhwoULVK1ale3bt3sdU0REJE6ooCWgzZs3A75TR8i/89hjj1GmTBnatm3L+PHj6dy5M1myZKFQoUIsWLCAM2fOULVqVX766Sevo4qIiNw0FbQEtGXLFlKkSEH+/Pm9jpLoZM2alWXLljF06FDKli1Lr169Lj9XvHhxFi5cyLlz56hZsya7du3yMKmIiMjN08XSE1D16tX5888/2bhxo9dRgtLGjRupWrUq2bJlY8mSJWTJksXrSCIiItHSxdIDwPHjx1m6dCm1a9f2OkrQioiIYNasWfz++++0aNGCCxcueB1JRETkhqigJZD58+dz/vx56tev73WUoHbvvffyzjvvsHjxYl577TWv44iIiNwQFbQEsmLFClKmTKlTbCSA9u3b06pVK/r27cuKFSu8jiMiIvKvqaAlkFWrVlGyZElSpEjhdZSgZ2a8++675M6dm4ceeoi///7b60giIiL/SsAUNDO73czGmtkXUaaFmdmHZva+mbXxMt/NOHfuHOvXr9foWQJKnz4948eP59dff+W5557zOo6IiMi/Eq8FzczGmdkBM9t81fQ6ZrbNzH42s+cBnHM7nHNXX0G8CfCFc64z0DA+s8an77//nlOnTlGuXDmvoyQplStX5sknn2TkyJEsWLDA6zgiIiKxFt8jaOOBOlEnmFkoMBKoC9wJtDKzO6N5fU7g0kmtEu0heatWrQLQCJoHXnnlFQoWLEi7du04ePCg13FERERiJV4LmnNuCXDkqsllgZ/9I2Zngc+ARtEsYje+kgbRZDWzLma2zszWBeov4NWrV5M1a1Zy587tdZQkJ02aNHz22WccPnyYli1bcv78ea8jiYiIXJcX+6Dl4P9HxcBXwnKYWUYzew+IMLMX/M9NBZqa2btA5LUW5pwb7Zwr7ZwrnTlz5ngNfqNWrVpFuXLlMDOvoyRJERERvPvuuyxYsIBnnnmGc+fOeR1JREQkRsm8DnCJc+4w8MhV0/4G/uNNorhx5MgRfvrpJ/7zn0T9NhK9Dh06sGHDBoYPH84333zDm2++qZMGi4hIwPJiBG0PkCvK45z+aUHp0gXSIyIiPE4ib731Fl9++SVnz57lvvvuo2HDhvz8889exxIREfkHLwraWqCAmeUzsxRAS+BLD3IkiD17fN0zV65c15lT4puZ0aBBA7Zs2cKgQYNYuHAhxYoVY/r06V5HExERuUJ8n2bjU2AlUMjMdptZJ+fceeAJYC7wIzDJObclPnN4ae/evQDkyJHD4yRyScqUKenVqxc//fQTd999N02bNmXMmDFexxIREbksXvdBc861imb6bGB2XK3HzBoADfLnzx9Xi4wze/fuJU2aNKRLl87rKHKVbNmyMX/+fJo1a0bnzp0BePjhhz1OJSIiEkBXErgZzrlI51yX9OnTex3lH/bu3Uv27Nl1BGeACgsLY8aMGdSpU4euXbsyY8YMryOJiIgER0ELZJcKmgSuFClSMHnyZEqXLk3Lli0ZNmyYTsUhIiKeUkGLZypoiUPatGmZNWsWVatW5ZlnnqF48eJs377d61giIpJEqaDFI+ecCloikilTJmbPns3MmTM5cOAALVu25OzZs17HEhGRJEgFLR4dP36ckydPqqAlImZG/fr1GTt2LBs2bKBv375eRxIRkSRIBS0eXTrFhgpa4tO4cWM6d+7MoEGDmDNnjtdxREQkiQmKgmZmDcxs9LFjx7yOcgUVtMRt2LBh3H333TzwwAMsWLDA6zgiIpKEBEVBC8TTbJw+fZqlS5cCKmiJVVhYGF9//TX58+fn/vvv54svvsA553UsERFJAoKioAWiF198kZdffhmA22+/3eM0cqMyZcrE/PnzKVKkCM2bN6dx48aXR0ZFRETiiwpaPJk923ehhB49ehAaGupxGrkZWbJkYdWqVbz++ut8/fXXVKpUid9//93rWCIiEsRU0OLB+fPn2bVrFx06dGDgwIFex5E4kDx5cnr27MnChQs5fPgwVapUYefOnV7HEhGRIKWCFg++++47Tp48yX333UeyZPF6uVNJYOXKleObb77hzz//pH379tonTURE4oUKWjxYtWoVAOXLl/c4icSH0qVLM3DgQBYvXsz06dO9jiMiIkEoKApaoJ1mY+XKlWTNmpU8efJ4HUXiSefOnSlatCg9e/bkzJkzXscREZEgExQFLdBOs7Fy5UrKly+PmXkdReJJsmTJGDp0KL/88guDBg3yOo6IiASZoChogeTgwYP88ssvVKhQwesoEs9q165N69at6du3L+PGjfM6joiIBBHtwR7HLu1/poKWNIwbN47Dhw/TuXNnzIwOHTpo5FRERG6aRtDi2KpVq0iWLBmlSpXyOookgJQpUzJ16lSqVq1Kx44dadmyJUeOHPE6loiIJHIqaHHs+++/p1ChQqRJk8brKJJA0qRJw7x583j11VeZOnUqVapU4c8///Q6loiIJGIqaHFs+/btFCxY0OsYksBCQ0N54YUXmDNnDtu2baNRo0acOnXK61giIpJIqaDFoQsXLrBjxw4KFCjgdRTxSI0aNfjoo49YunSpTmQrIiI3LCgOEjCzBkCD/Pnze7L+EydOsGnTJnLkyMHZs2c1gpbEPfjgg/z+++/06tWLYsWK8b///c/rSCIiksgExQia1+dBa9euHZUqVWL58uUAGkETevTowUMPPUSfPn0YNmwYR48e9TqSiIgkIkFR0Ly2detWABU0uczMGD16NFWqVOGZZ54hS5YsdOzYkUOHDnkdTUREEgEVtDhwaeRu3bp1hIWFkTVrVo8TSSBIlSoVCxcuZM2aNTzyyCN8/PHHFCpUiGnTpnkdTUREApwKWhxIly4d4CtoxYsX14lK5TIzo0yZMrz99tt8++235M+fn+bNmzN16lSvo4mISABTQYsDUfd9K126tIdJJJDdeeedzJ8/n7Jly9KyZUtmzpzpdSQREQlQKmhxIGpBu/feez1MIoEubdq0fPXVV5QoUYLGjRvz0UcfeR1JREQCkApaHLi0iROgYcOGHiaRxCB9+vR88803VKlShXbt2tGrVy+OHz/udSwREQkgKmhxIOoIWqpUqTxMIolFunTpmD17Np06deKNN96gQIECzJgxw+tYIiISIFTQ4kBYWBgAvXv39jiJJCYpU6ZkzJgxrF27lly5ctGkSRPGjh3rdSwREQkAKmhx4NJRm7169fI4iSRGpUuXZvHixdSuXZuHH36Y119/3etIIiLisaAoaGbWwMxGHzt2zOsoIjckLCyMGTNm0LJlS5577jl69uyp63iKiCRhQXEtTudcJBBZunTpzl5nEblRKVKkYOLEiWTMmJHBgwdz+PBhRo8e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h7fffpvbbruNxo0bU62azo0tIklHTPug5U3AHCIihIaGMmLECCpUqEDFihVJnz49586dY8SIEUydOpVGjRp5HVFEJEFoT1wRCSjly5enT58+tGvXju3bt3PgwAFKly5Ny5Yt+fLLL72OJyKSIGJ1qScRkYT08ssvX/F45syZ1KxZk0aNGtGwYUMeeOABWrRoQZo0aTxKKCISvzSCJiIBL3PmzKxdu5Z+/fqxcuVK/vOf/1CjRg2OHDnidTQRkXhx3YJmZlPNrL6ZqcyJiGdSpEjB//73P/bv38+kSZPYuHEj99xzD2vXrvU6mohInItN6XoHaA1sN7PXzKxQPGcSEYlWSEgIzZs3Z968efz1119UqFCBMWPGeB1LRCROXbegOee+cc61AUoCvwHfmNkKM/uPmSWP74CxYWYNzGz0sWO6NKhIUlG5cmU2b95MzZo1eeSRR5g3b57XkURE4kysNluaWUagA/Awvss7vYWvsH0db8n+BedcpHOuy6ULMotI0pAhQwYmT57MnXfeSfPmzdmyZYvXkURE4kRs9kGbBiwF0gANnHMNnXOfO+e6AWnjO6CISEzCw8OZOXMmqVOn5v7772fNmjWcPn3a61giIjclNiNo7zvn7nTODXTO7YPLF0rHOVc6XtOJiMRC7ty5iYyM5I8//qBcuXLcdtttDBkyhLNnz3odTUTkhsSmoA24xrSVcR1ERORmlClThu3btzN58mTuvfdeevToQZ06dThx4oTX0URE/rVoC5qZZTWzUkBqM4sws5L+W1V8mztFRAJKjhw5aNasGbNmzWL8+PEsWbKEKlWq8O2333odTUTkX4lpBO0+YDCQExgKDPHfngFejP9oIiI3rn379syYMYPdu3dTqlQpunfvztGjR72OJSISK9EWNOfch865akAH51y1KLeGzrmpCZhRROSG1K9fn23btvHoo48ycuRIcuXKRZMmTdi0aZPX0UREYhTTJs62/rt5zeyZq28JlE9E5KbccsstjBgxgnXr1tGmTRuWLVtGxYoViYyM9DqaiEi0YtrEGeb/My0Qfo2biEiiERERwXvvvcemTZsoUqQITZs2ZdGiRV7HEhG5pmTRPeGcG+X/8+WEiyMiEr+yZcvG119/TYUKFWjSpAmLFi2iePHiXscSEblCbE5U+7qZpTOz5GY238wORtn8KSKS6GTIkIFZs2aROnVq7r33XkaMGMGCBQu4ePGi19FERIDYnQettnPuOHA/vmtx5gd6xmcoEZH4dvvtt7N69Wry589Pt27dqFGjBtWrV+e3337zOpqISKwK2qXNoPWByc45XZFcRIJCzpw5Wbt2LTt27GDUqFFs3LiRBg0acO7cOa+jiUgSF5uCNtPMtgKlgPlmlhnQhe5EJCiEhoaSL18+unTpwvjx49m8eTMjRozwOpaIJHHXLWjOueeBe4DSzrlzwN9Ao/gOJiKS0Bo3bkzdunXp06cPX331lddxRCQJi80IGkBh4EEzawc0A2rHXyQREW+YGaNGjSJfvnzUq1ePjBkzkidPHh555BF+/fVXr+OJSBIS7Wk2LjGzj4A7gG+BC/7JDpgQf7FERLyRK1cuVq9ezRtvvMGBAwfYt28fEyZMYOLEiTz99NPUq1eP8uXLex1TRILcdQsaUBq40znn4juMiEggSJ06NX369Ln8eOfOnXTt2pX+/fvTv39/PvnkE1q1auVhQhEJdrHZxLkZyBrfQUREAlWePHmYM2cOR44coWLFinTu3JnFixej/7eKSHyJTUHLBPxgZnPN7MtLt/gOJiISaG655RY+++wzwsPDqVq1KuXKlePIkSNexxKRIBSbTZwvxXcIEZHEImfOnGzdupXPPvuMJ598knr16jFr1iwyZszodTQRCSLXLWjOucVmlgco4Jz7xszSAKHxH01EJDClT5+erl27kjVrVpo1a0ahQoUoWbIkZ86cYdasWaRNm9briCKSyMXmWpydgS+AUf5JOYDp8ZhJRCRRaNSoERs2bKBUqVLs37+fJUuWMHLkSHbu3MmOHTu8jiciiVhs9kF7HKgIHAdwzm0HssRnKBGRxKJYsWLMnTuX7777jjp16jBw4EDuuusuypUrx549e7yOJyKJVGwK2hnn3NlLD8wsGb7zoImISBT9+vXj2LFj3HHHHZw6dYqWLVuyatUqdu3axenTukKeiMRebAraYjN7EUhtZrWAyUBk/MYSEUl8ypQpw+bNm1m5ciWjRo1i5cqVVKhQgdy5c5MjRw5ef/11Lly4cP0FiUiSF5uC9jxwEPge6ArMBnrHZygRkcSqaNGipE6dmjZt2rB//36++OILRo8eTfny5Xnuued49NFHdf40Ebmu2BzFedHMpgPTnXMH4z+SiEhwyJQpE02bNgWgc+fO9O7dm1deeYW0adMyZMgQzMzjhCISqKItaOb7l6Mv8AT+kTYzuwAMd871S5h4IiLBo3///vz1118MGzaMkJAQBg4cSPLkyb2OJSIBKKZNnE/jO3qzjHPuVufcrUA5oKKZPZ0g6UREgoiZMWzYMB577DGGDBlCqVKl+PTTT7Vfmoj8Q0wF7SGglXPu10sTnHM7gLZAu/gOJiISjMyMkSNHMm3aNE6dOkXr1q159NFHvY4lIgEmpoKW3Dl36OqJ/v3QNCYvInITGjduzLZt2+jRowfvv/8+EydO9DqSiASQmAra2Rt8TkREYuHSfmgVK1akW7duHDr0j/8Ti0gSFVNBu9vMjl/jdgIollABRUSCWbJkyRg1ahTHjx/nueee48yZM15HEpEAEG1Bc86FOufSXeMW7pxLkE2cZnanmU0ys3fNrFlCrFNEJKEVLVqUbt26MW7cONKlS8djjz3G4cOHvY4lIh6KzYlq45SZjTOzA2a2+arpdcxsm5n9bGbP+yfXxXdaj0fRgQkiEsTeeOMNpkyZQvv27Rk9ejRPPPEEAM45mjZtytChQz1OKCIJ6bonqo0H44ERwIRLE8wsFBgJ1AJ2A2vN7EvgI6CvmTUEMiZ8VBGRhJEsWTKaNGlCkyZN+Pvvv1m6dCkAW7duZerUqUydOpVUqVLx2GOPeZxURBJCghc059wSM8t71eSywM/+03hgZp8BjZxzA4HH/QVuasImFRHxRsmSJfnkk084ePAg8+fPB6BixYo8/vjjrFmzhtatW7N3714yZ85M9erVSZ06tceJRSSuXbegmdmdzrkfrppW1Tm3KA5z5AB2RXm8GyjnL3IvAmHAG9Hk6wJ0AcidO3ccRhIR8UbJkiUB2LBhA/PnzydfvnwsWrSI//3vf7zxxht8+OGHl+ctVKgQ69evJywszKu4IhIPYrMP2iQze858UpvZcGBgfAcDcM795pzr4pxr45xbFs08o51zpZ1zpTNnzpwQsURE4lVERAQAa9euZdGiRdSoUYNkyZIxcOBADh06xLx58/jxxx/5+OOP2bZtG//73/88TiwicS02mzjLAYOAFUA4MBHfJaDi0h4gV5THOf3TRESSnAwZMnDHHXcwatQojh49SvXq1a94rlatWgAULlyYpUuXMmzYMFauXEnr1q1p37496dKl8yq6iMSR2IygnQNOAamBVMCvzrmLcZxjLVDAzPKZWQqgJfBlHK9DRCTRKFWqFLt376Z8+fI0atQo2vmGDRvGoEGD+Pvvv+nevTu1atXi3LlzCZhUROJDbAraWnwFrQxQCWhlZpNvdIVm9imwEihkZrvNrJNz7jzwBDAX+BGY5JzbcqPrEBFJ7Lp27UqHDh2YO3cuadKkiXa+1KlT06tXL7777jsmTpzImjVreOGFFxIwqYjEh9hs4uzknFvnv78PaGRmD93oCp1zraKZPhuYfSPLNLMGQIP8+fPfaCwRkYBSvXr1KzZtxkbr1q1Zvnw5Q4YMIW3atOTLl48iRYoQERFB8uS6hLJIYhKbgnbAzK4+PHJxfIS5Uc65SCCydOnSnb3OIiLipbfeeos9e/bw8ssvX54WFhZG3rx5yZIlC++88w6FCxf2MKGIxEZsCtoswAGGbx+0fMA2oGg85hIRkRuQLFkyJk+ezPr168mQIQPfffcdixcvZv/+/SxdupQyZcqwYsUKihXTJZVFAtl1C5pz7oq/xWZWEtCprEVEAlTy5MkpX7484DvSs0WLFgDs3r2bkiVL0rlzZ1asWEFISIJf7U9EYulf/+10zm3Ad+oNERFJRHLmzMnQoUNZvXo1b731ltdxRCQGsbmSwDNRHoYAJYG98ZZIRETiTZs2bfjiiy/o1asX+fPnp379+hpJEwlAsflbGR7llhLfPmnRn5RHREQClpkxfvx48uXLR8OGDYmIiGDr1q1exxKRq1y3oDnnXo5ye8U5N9E5dzohwsWWmTUws9HHjh3zOoqISMDLkCEDGzZs4IMPPmDfvn1ERETQvXt31q9fj3PO63giAlh0fxnNLBLf0ZvX5JxrGF+hblTp0qXdunXrrj9jHBsyZAg9evTg+PHjhIeHJ/j6RURu1J49e+jTpw8TJkzg/Pnz1KtXj3r16nH06FGKFi1Ko0aNMDOvY4oEJTNb75wrfa3nYtoHbXA85RERkQCRI0cOxo4dy+uvv864cePo06cPs2f//znDGzVqxJgxY8iUKZOHKUWSnpg2cf7qnFsc3S3BEoqISLzLmDEjPXv2ZOfOnfz++++cOnWKoUOHMnv2bO6++24WLlzodUSRJCWmgjb90h0zmxL/UURExGtZsmQhV65cpEqViqeffprVq1cTHh5OjRo1aNKkCStXrvQ6okiSEFNBi7rTwe3xHURERAJPREQE69evp0ePHqxYsYKaNWuyYsUKr2OJBL2YCpqL5r6IiCQhYWFhvP7662zatIns2bNTqVIlWrduzenTAXVAv0hQiamg3W1mx83sBFDcf/+4mZ0ws+MJFTA2dJoNEZH4d9ttt7F8+XJ69OjBp59+SqtWrfj66685e/as19FEgk60Bc05F+qcS+ecC3fOJfPfv/Q4XUKGvB7nXKRzrkv69Om9jiIiEtSyZMnCoEGDGDx4MNOnT6d27doUKlSIb775xutoIkFF1/cQEZF/7dlnn2X37t1MmzaNNGnSULduXVq3bs3kyZO9jiYSFK57LU4REZFryZEjBzly5KBatWo8/PDDLFiwgM8++4zkyZPTuHFjr+OJJGoaQRMRkZuSPn16Jk+ezI4dOyhTpgxt2rRh/fr1XscSSdRU0EREJE6kSZOGGTNmkClTJmrVqsWzzz7L3r17vY4lkiipoImISJzJmjUr8+bNo2rVqgwfPpz8+fOzYMECr2OJJDoqaCIiEqcKFSrE1KlT2bZtG/ny5aNly5bs2bPH61giiYoKmoiIxIt8+fIxZcoUTp48SYsWLTh9+jTvvfce48eP9zqaSMALiqM4zawB0CB//vxeRxERkSgKFy7M2LFjadmyJeHh4Zw/fx6AgwcP0rNnT4/TiQSuoBhB04lqRUQC14MPPsgXX3zBU089xaRJk3jwwQfp1asXJUuWJG3atBQoUIB169Z5HVMkoATFCJqIiAS2pk2b0rRpUwCaNGlCvnz5iIyMpH379syaNYu6deuycOFC7rrrLo+TigSGoBhBExGRxCM0NJSBAweyefNmRo4cyddff02KFCmoXLkyffr04ZtvvtH1PSXJU0ETERFPFShQgGXLllG0aFFeeeUVatWqRalSpfjxxx+9jibiGRU0ERHxXL58+Vi6dClHjx7l888/58CBA9SuXZsDBw54HU3EEypoIiISMMLDw2nRogVz5szh0KFDVK5cmYkTJ3Ls2DGvo4kkKBU0EREJOBEREURGRuKco23bthQuXJhffvnF61giCUYFTUREAlLNmjX54YcfWLBgAefOnaN27drs37/f61giCUIFTUREAlZoaCjVqlVj9uzZ/PHHH1SrVo1PPvmE/fv3M2LECA4fPux1RJF4ERQFzcwamNlo7aMgIhKcypYty4wZMzh79ixt2rQhe/bsdOvWjaJFizJjxgycc15HFIlTQVHQdCUBEZHgV6NGDbZv3860adN49NFHmTJlClmzZqVx48ZkzpyZOXPmeB1RJM4ERUETEZGkISQkhMaNGzNy5EiaNGnCmjVreP/998mUKRNdu3bl5MmTXkcUiRMqaCIikmilSJGChx9+mPfff5/ff/+de+65hy1btngdS+SmqaCJiEiiV6lSJT7//HN+//13evfu7XUckZumi6WLiEhQaNGiBatXr2b48OEcPnyYPXv2cODAAcqVK0d4eLjX8UT+FY2giYhI0Gjbti3nzp2jVq1alChRglq1alGsWDE2b97sdTSRf0UFTUREgkaJEiV46KGHOHPmDE8++SRffvklZ8+epUmTJpw7dw7nHBs3buT777/3OqpIjLSJU0REgoaZMWHChH9Ma9CgAW+++SbLly9nxowZpEqVivnz53PPPfd4lFQkZhpBExGRoFa/fn1q1KhBr169mDFjBn379iVXrlzUqVOHefPmeR1P5Jo0giYiIkHNzIiMjGTUqFGkTZuWhx9+mIcffpj69etTr149XnjhBSpUqEDt2rVJlky/FiUw6CdRRESCXurUqXnqqacuP86ZMydLly6ldevWDBgwAIC77rqLZcuWoavSSCAIik2cuhaniIj8W+nSpSMyMpJDhw4xceJEtm7dSqNGjZgzZw5nz571Op4kcUFR0HQtThERuRFmRsaMGWndujXvvvsuGzdupG7duhQrVoy//vrL63iShAVFQRMREblZDz/8MAcOHOCjjz7ip59+urzpU8QL2gdNRETEL2XKlLRt25YFCxYwaNAgNm3axIULF6hYsSL//e9/dRCBJBj9pImIiFzlnXfeISwsjNmzZ5MhQwZeeukltm3bxsSJEzEzr+NJEqCCJiIicpVUqVIxfPhwhg8fDsArr7xC7969yZo1K9myZQOgbt263HXXXV7GlCCmgiYiInIdL774IqtXr2bYsGGXp/Xq1Yt27drx6quvkiNHDg/TSTDSQQIiIiLXYWZMnz6drVu3cvToUfbv30+vXr347LPPiIiIYNOmTV5HlCCjgiYiIhILISEhFCpUiPTp03PbbbcxaNAgvv32W5IlS0aJEiVIly4dBQsW5IMPPvA6qgQBFTQREZEbVKRIEdauXcvAgQPp2LEjt956Kx07dqRdu3Zs2bLF63iSiKmgiYiI3IQcOXLw/PPP8+abb7J8+XKee+45Jk+ezF133cWzzz7rdTxJpFTQRERE4khoaCivvfYau3btonPnzgwdOpRnn32WvXv3eh1NEhkVNBERkTiWKVMm3n33XR566CGGDRtGnjx5qFixImvXrvU6miQSKmgiIiLxIDQ0lAkTJrB9+3Z69OjBjh076NixIxcuXPA6miQCKmgiIiLx6I477mDgwIG89dZbbN68mffee8/rSJIIqKCJiIgkgObNm1O7dm2effZZVq9e7XUcCXBBUdDMrIGZjT527JjXUURERK7JzPj444/JkSMHtWvXZuDAgcydO5eLFy+yd+9eJk+erM2fcllQFDTnXKRzrkv69Om9jiIiIhKtzJkzs3DhQkqUKMGLL75InTp1aNmyJREREbRo0YIaNWpw4sQJr2NKAAiKgiYiIpJY5M6dm8WLF7Nv3z4effRRJk+eTI4cOXjjjTdYtmwZlSpVYtiwYezfv9/rqOIhFTQREREPZM2alREjRvDjjz+yfv16evToweeff8758+d55plnqFixIqdPn/Y6pnhEBU1ERMQjISEhFC5cGDMDoGnTpmzevJlZs2axY8cO6tatS7t27Xj33XdV1pIYFTQREZEAU69ePXr06MHu3btZsGABjz32GA0bNmTcuHEcPXrU63iSAFTQREREAtAbb7zB9u3b2bVrF++99x5ff/01nTp1olq1ahw5csTreBLPVNBEREQCmJnRtWtX1q1bx6RJk9iyZQvNmzfnt99+4+LFi17Hk3iSzOsAIiIicn2lSpWiVKlSnDx5ko4dO5IvXz5y5szJlClTKFu2rNfxJI5pBE1ERCQRad++Pdu3b+ftt98mWbJkVKpUicGDB2s0LciooImIiCQyt99+O926dWPdunXUr1+fnj170rx5c86fP+91NIkjKmgiIiKJVMaMGZkyZQpvvPEGU6dOpWnTpgwYMIDdu3d7HU1ukvZBExERScTMjB49epA8eXJ69uzJl19+yZQpU2jdujXh4eF07dr18nnWJPHQCJqIiEgQePLJJ9m3bx+TJk3ihx9+oFevXjz66KPMmzfP62hyA1TQREREgkTGjBlp3rw5hw4d4siRI2TPnp033njD61hyA1TQREREgkx4eDi33HIL3bp1Y/78+WzduvXyc845/vzzTw/TSWyooImIiASpDh06EBoayptvvkmLFi1o3749efPm5dZbb2XcuHFs3bqVY8eOeR1T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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "# pipeline 1d extraction (for comparison)\n", + "jpipe_x1d = Table.read(x1dfile, hdu=1)\n", + "print(jpipe_x1d.columns)\n", + "# plot\n", + "fig, ax = plt.subplots(figsize=(10, 6))\n", + "ax.plot(jpipe_x1d['WAVELENGTH'], jpipe_x1d['FLUX'], 'k-', label=\"jpipe_x1d\")\n", + "ax.set_title(\"JWST Pipeline x1d extracted spectrum\")\n", + "ax.set_xlabel(\"wavelength\")\n", + "ax.set_ylabel(\"Flux Density [Jy]\")\n", + "ax.set_yscale(\"log\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Define region to be extracted" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "At this point, `specreduce` doesn't provide a tool for finding the trace. Since this is rectified data, we can use the `FlatTrace` class and find the spectrum position and width by eye." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0.5, 1.0, 'slit[0] slice')" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA2cAAAFLCAYAAABSuvQBAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8vihELAAAACXBIWXMAAAsTAAALEwEAmpwYAAAc4UlEQVR4nO3dfaxteVkf8O9zz70zA8OFGV6cDgMKCNGMNgzNFLHaFqFaoLZgtVZq7dhgRhNpobEviGnFpCTaqGijsRmFOqkoUoRAjLFSSqs2KfUiiMBAeRFkxoGB8nYZmZd77tM/ziZe6Z3zW3P3Puf87jmfT3Jzz95r7fV71tprrX2+Z+29n+ruAAAAcLCOHXQBAAAACGcAAABTEM4AAAAmIJwBAABMQDgDAACYgHAGAAAwAeEMAABgAsIZAFOoqpdU1S+tfv7SqvpcVW3dx7yPqapezXPjwuX/YlV9vqpuvYDa/ntVfc/q5++sqt+6v8sAgBHhDIDpdPcfd/eDuns7+fPh6Itc0d03feFGVT29qt5TVX9aVW+uqi87Z5nfneSZG6jtld39TesuBwC+mHAGwKFQVQ9P8tok/zrJQ5OcSvKrB1oUANwPwhkA+6qq/lVV3VZVp6vqvVX19PPM84W3LR6vqpcm+atJfmb1NsafuY9F/90k7+ru/9zddyV5SZInVtVXLqzrsqr6par6v1X16ar6vaq66jzzfXdV/e45t7+qqt5YVZ+sqo9V1YtX9x+rqhdV1QdWy3x1VT10SS0AHE3CGQD7pqq+Isnzk/zl7j6Z5G8m+dBuj+nuH0ryO0mev3qr4/PvY9avSvIH5zzuziQfWN2/xA1JHpLk0UkeluT7knx+twdU1ckk/zXJbyZ5ZJLHJ3nTavI/SfKcJH99Ne1TSX52YS0AHEHCGQD7aTvJpUmuraoT3f2h7v7Ahpb9oCSf+aL7PpPk5MLH35udUPb47t7u7rd292cHj/nmJB/t7p/o7ru6+3R3v2U17fuS/FB339rdd2fnSt63VdXxhfUAcMQIZwDsm+5+f5IXZieo3FFVr6qqR25o8Z9L8uAvuu/BSU4vfPx/SvJfkryqqv6kqv5dVZ0YPObR2bk6dz5fluR1q7dIfjrJLdkJp//fWyUBIBHOANhn3f3L3f312QkvneTHljxswTzvSvLEL9yoqsuTfPnq/iV13dvdP9Ld1yb5K9m5KvaPBg/7SJLH7TLtmd19xTn/Luvu25bUA8DRI5wBsG+q6iuq6mlVdWmSu7Lzma6zCx76sdx3CPqC1yX56qr61qq6LMm/SfKO7n7Pwtq+oar+4qq32mez8zbHUW2/nuTqqnphVV1aVSer6mtW0/5Dkpd+4ev8q+oRVfXsJbUAcDQJZwDsp0uT/GiSTyT5aJIvSfKDCx7309n5vNanqurfn2+G7v54km9N8tLsfPnG1yT5jvtR219I8prsBLNbkvyP7LzV8T519+kk35jkb2dnfd6X5BvOqfkNSX6rqk4n+V+rmgDgvKp7yTtFAGAeq6tR783O1bd/0d0/v+AxL0/y95Lc0d2P3+MSAeB+E84AAAAm4G2NAAAAExDOAAAAJrCvjTC3Tl7exx9xxX4OCQAAMI17/uhPPtHdjzjftH0NZ8cfcUWueen37+eQAAAA0/ijf/BDH76vad7WCAAAMAHhDAAAYALCGQAAwASEMwAAgAkIZwAAABMQzgAAACYgnAEAAExAOAMAAJiAcAYAADAB4QwAAGACwhkAAMAEhDMAAIAJCGcAAAATEM4AAAAmIJwBAABMQDgDAACYgHAGAAAwAeEMAABgAsIZAADABIQzAACACQhnAAAAExDOAAAAJiCcAQAATOD4QRcA7LPqg64AAJhJ10FXwMrwyllVXVZV/7uq/qCq3lVVP7K6/7FV9Zaqen9V/WpVXbL35QIAABxOS97WeHeSp3X3E5Ncl+QZVfWUJD+W5GXd/fgkn0ryvD2rEgAA4JAbhrPe8bnVzROrf53kaUles7r/5iTP2YsCAQAAjoJFXwhSVVtV9fYkdyR5Y5IPJPl0d59ZzXJrkmv2pEIAAIAjYFE46+7t7r4uyaOSPDnJVy4doKpurKpTVXVq+/SdF1YlAADAIXe/vkq/uz+d5M1JvjbJFVX1hW97fFSS2+7jMTd19/Xdff3WycvXqRUAAODQWvJtjY+oqitWPz8gyTcmuSU7Ie3bVrPdkOT1e1QjAADAobekz9nVSW6uqq3shLlXd/evV9W7k7yqqv5tkrclefke1gkAAHCoDcNZd78jyZPOc/8Hs/P5M46w0tD4ouM5O4dtwfloxgrrGZ1bHWPT8Wo4j/v1mTMAAAD2hnAGAAAwAeEMAABgAsIZAADABIQzAACACQhnAAAAExDOAAAAJrCkCTXcpyse/Kd7PsaSvlzH1uxXtR9jJMmos8vxY2fXH2NQ52iME8e2h2OMtsXx2n2MY4PpSyzZVpcM1mUTdZwYruv6+82ozlENS5Yxcqa3hvNsr9m76MzZ8Rgjm9jeZ/ehB9Mm6hyPsf7+vQlbg3U9NuiwdHZ45hwv4/jgXLCVJcfQoM4F+829g+PoRO1e55Lz3mhdNrEeI9uDv/0vGePus7v/inq2x9cX7h3MM1rGsud0vTHOLFiPkTNnx8sYrctHPnvlrtOPb41/N3jYA3b/nXBUZy/Y3qPzwZLnbN19fFGdg3k+uMs0V84AAAAmIJwBAABMQDgDAACYgHAGAAAwAeEMAABgAsIZAADABIQzAACACehzxlouv+Se4TyjvlujnitL+gGNetxsDXrDLBljE727hv3BBnUu6c0xGuMBW/euNT1Jjg968Vx67Myu00e9fJJxv7UHHhvve5ce231dRnUs6X30wGN3776MDfSzOlG7b8+twf6/X4Z1Do6R7QX9fkbLGLm3xy97ozpG65mM6xw9Z8cW7HuXDPbf0TlpSZ+o0TIuyfhYPjk4Vkd9+pb0z7ts2Atw9PjxGCdq9+21taAf2129+/YajfGQYw8YjjGD7d79+bi7x8fQJnyud38N2O7dj8MTC/aLewfLuGtwer5rwXF496A/3p19YriMuwbz3PXIwfSzlwzHGBn1+btnQT/Nu3r3Ou4+u2Rb7P46MFrGkteqkf+5yzRXzgAAACYgnAEAAExAOAMAAJiAcAYAADAB4QwAAGACwhkAAMAEhDMAAIAJCGcAAAAT0ISaPffJOx+46/RR+9xxC8ixUWPmUaPsJfMc20ChozF6QTPW0TJGDbk30TR51Ex7yfYeNuxe0Ix4Xxqgb2B7DcfYhybTZzdwpI2akw9r2EBjz+EYC9Zz1Ox9E8/5Jp7TJY3vd7OJ7b2khtH5YLQ9R8/HkmWMtveyY3297Z2sv80vPTZu3nzvPhxHI6P1XPKcbsI9Z3dvaryJY/3MaIzBOWfJtjhzdvftueR3gzNr7hfbgxqS8bqMpi85Kw6XsWBbrLuMsxt5SX7DfU45+CMYAAAA4QwAAGAGwhkAAMAEhDMAAIAJCGcAAAATEM4AAAAmIJwBAABMQJ8z1nLrx68czrOkp9VhcFTWM0lykaxr7U8rHQA4r744Xi6Tfeo9dzFY0ittLw2vnFXVo6vqzVX17qp6V1W9YHX/S6rqtqp6++rfs/a+XAAAgMNpyZWzM0l+oLt/v6pOJnlrVb1xNe1l3f3je1ceAADA0TAMZ919e5LbVz+frqpbklyz14UBAAAcJffrC0Gq6jFJnpTkLau7nl9V76iqV1TVeT98VFU3VtWpqjq1ffrO9aoFAAA4pBaHs6p6UJJfS/LC7v5skp9L8uVJrsvOlbWfON/juvum7r6+u6/fOnn5+hUDAAAcQovCWVWdyE4we2V3vzZJuvtj3b3d3WeT/HySJ+9dmQAAAIfbkm9rrCQvT3JLd//kOfdffc5s35LknZsvDwAA4GhY8m2NX5fku5L8YVW9fXXfi5M8t6quS9JJPpTke/egPg6Bg+4XsV8umvXcRI+yi2VdAQD22xq/Jy35tsbfTXK+EX7jgkcFAADgz7lf39YIAADA3hDOAAAAJiCcAQAATEA4AwAAmIBwBgAAMAHhDAAAYALCGQAAwASWNKEGDhMNpAEApuTKGQAAwASEMwAAgAkIZwAAABMQzgAAACYgnAEAAExAOAMAAJiAcAYAADAB4QwAAGACwhkAAMAEhDMAAIAJCGcAAAATEM4AAAAmIJwBAABMQDgDAACYgHAGAAAwAeEMAABgAsIZAADABIQzAACACQhnAAAAExDOAAAAJiCcAQAATEA4AwAAmIBwBgAAMAHhDAAAYALHD7oAgItZ90FXAMDFquqgK2A2wytnVfXoqnpzVb27qt5VVS9Y3f/QqnpjVb1v9f+Ve18uAADA4bTkbY1nkvxAd1+b5ClJvr+qrk3yoiRv6u4nJHnT6jYAAAAXYBjOuvv27v791c+nk9yS5Jokz05y82q2m5M8Z49qBAAAOPTu1xeCVNVjkjwpyVuSXNXdt68mfTTJVffxmBur6lRVndo+fec6tQIAABxai8NZVT0oya8leWF3f/bcad3dSc77sfjuvqm7r+/u67dOXr5WsQAAAIfVonBWVSeyE8xe2d2vXd39saq6ejX96iR37E2JAAAAh9+Sb2usJC9Pckt3/+Q5k96Q5IbVzzckef3mywMAADgalvQ5+7ok35XkD6vq7av7XpzkR5O8uqqel+TDSb59TyrkoqcPFHvCfsXFTG8jIH5HOteSnm9HYXsNw1l3/27u+2Xk6ZstBwAA4Gi6X9/WCAAAwN4QzgAAACYgnAEAAExAOAMAAJiAcAYAADAB4QwAAGACwhkAAMAEljShhrX0mfn/BjBNU8Peh860M6zrJmrYxLbaj22xH+taMzyp3C/7cayPLNlvZqhzE0aruk+HUA22Zw+ek9HjdxZyfyo63yBrPn6B0XpuzGhdRtOXlLkfh8gM5/gl63mxbIt169zj9Zz/t2YAAIAjQDgDAACYgHAGAAAwAeEMAABgAsIZAADABIQzAACACQhnAAAAE9DnjLX0xy8dz3PJ2bXGqLN7389qUduMQX+ZWrKam6hjNMRgc23dM5hhQQ3DdR1MX/Kc1vbu04+dGS5iWOcmxhg+p4MxRtOTpM6OBlmyjPWmj57TjdjAemykLdfgz5ZLxhjuO6OndMH2Pra9+0KO3TsoYWs8xtY9g0IXnC+Ondl9puN37n4Q9NZ4g29ftvuTduL07mNs3TU+2I/dveSEMFjGZ/501+nbDz+56/Stz941HGP73f9n92VceeVwGSN1+QN3n2FrcBDdM9g5k/S9u8+z/bhHDpex/cATu0+/bPeD4Ng94wNxtO9tX7r79LMLfhP//MN2r/P4eLcYnlO2LxktYDzG9qW7z3R2dM5ZcMmoB/Oc3f0p31nGfvTyWyNhuXIGAAAwAeEMAABgAsIZAADABIQzAACACQhnAAAAExDOAAAAJiCcAQAATEA4AwAAmIAm1Kzl7MkFTTnXbCLdvYnOzOsvYtS1cBNDDBeyiX7cgyaRG1mRDTQsHjaqXtQ4fDDGaBkbaIA+HGMj++YGljGwDz0792M1NrMiS5axHyszOCeN9r0ljVhrE91ah8fh7p1pF5Uw+lPzoPtt9agD76Y8eNepo3Wtvnw8RH/tYCHjRaxrP5r8LmpYPJphE7v3qI7Rgbight5avxn8aJzhczZ8Mcv6l3yWbIsNbM+17fEYrpwBAABMQDgDAACYgHAGAAAwAeEMAABgAsIZAADABIQzAACACQhnAAAAE9DnjLUcu2T7oEuYRu9LY5eLxCSt6WYYY8h+c/FZ0u/H88oe2ETbz5Fa0mtq1GrK7r/ckvPJxWIfnvcZdq3a4+dseOWsql5RVXdU1TvPue8lVXVbVb199e9Ze1olAADAIbfkbY2/mOQZ57n/Zd193erfb2y2LAAAgKNlGM66+7eTfHIfagEAADiy1vlCkOdX1TtWb3u88r5mqqobq+pUVZ3aPn3nGsMBAAAcXhcazn4uyZcnuS7J7Ul+4r5m7O6buvv67r5+6+TlFzgcAADA4XZB4ay7P9bd2919NsnPJ3nyZssCAAA4Wi4onFXV1efc/JYk77yveQEAABgb9jmrql9J8tQkD6+qW5P8cJKnVtV12WkT9KEk37t3JTK1GRpOTGKv+15wWNlvDifPK5s3y0vuLHXAYTQMZ9393PPc/fI9qAUAAODIWufbGgEAANgQ4QwAAGACwhkAAMAEhDMAAIAJCGcAAAATEM4AAAAmIJwBAABMYNjnDHZTOlFyxLVewwCwL47C752unAEAAExAOAMAAJiAcAYAADAB4QwAAGACwhkAAMAEhDMAAIAJCGcAAAAT0OcMYA370XNFLzUA1nEU+oMdFq6cAQAATEA4AwAAmIBwBgAAMAHhDAAAYALCGQAAwASEMwAAgAkIZwAAABPQ54w9p0cTAMDB8bvY5ux1zzhXzgAAACYgnAEAAExAOAMAAJiAcAYAADAB4QwAAGACwhkAAMAEhDMAAIAJCGcAAAAT0ISatZzdHnfiqzoanQ+797gr4UKj7T1FnUdjlwBmMcN5b4lNvF5eLOvKjiPyO9JU1jxE9voZG145q6pXVNUdVfXOc+57aFW9saret/r/yr0tEwAA4HBb8rbGX0zyjC+670VJ3tTdT0jyptVtAAAALtAwnHX3byf55Bfd/ewkN69+vjnJczZbFgAAwNFyoV8IclV33776+aNJrrqvGavqxqo6VVWntk/feYHDAQAAHG5rf1tjd3d2+Wxcd9/U3dd39/VbJy9fdzgAAIBD6ULD2ceq6uokWf1/x+ZKAgAAOHouNJy9IckNq59vSPL6zZQDAABwNA37nFXVryR5apKHV9WtSX44yY8meXVVPS/Jh5N8+14Wybz6c+NWeT36E8AGGkbU2X1oWjGaZ9Eydq+zzg4ev4H2NcfODIZYsC2HdQ6m1/ZwiGEdS1rDDMcZLGO4ngvn2fXxC7bFRupc9zjbxDEyOhesuS2TBeu5ZD0Gh8DwnLZgnNFztuT5GrWz6sHp+dg94zGOnVn/BL119+7TR8fAse1xDaPn5Phdg/6PC86txz+/+zK27lpyMO/unoec2HX6kufj2L27z1OD7dnHlrwGDMbYwOv69qW7P6lLjsPe2n1dzly2+/Szx9d/0T27tfv00XGajNf17GA9kwzPv2cHdZzdfddMkvRoXQc1jB6fjOtcsvOtW+cS6yxjuEt093PvY9LTL3xYAAAAzrWBbAgAAMC6hDMAAIAJCGcAAAATEM4AAAAmIJwBAABMQDgDAACYgHAGAAAwgQWt72AXx5d0Sh3NsH6Txz62gY6XA8PmzItKGDX/XFzOGnZfjx40F00WND0eNdte0GgyvYEmp6NGwBtoWDxsJjzab/aj8fIkljT63XNLathEnRtoHD6FBU3pR9ZvuD2uYbRvbaLp9+hYrWF33Ky9b9WZ9R6/bJA5xhg2LF5S57B58+DxG9gWm2i8PKpjybYY/p40qnPJ7yfr/pq0pLH4JvbPwbbYzBgH8lAAAAA2RTgDAACYgHAGAAAwAeEMAABgAsIZAADABIQzAACACQhnAAAAE9DnjLXUZdvjmS6SHkxDUzRpWt+wjdl+rOcs+8R+1HGx7Deb2BYXyaoObaJx3MXyvO+H/TjORpt7lnPOyMVS57r26/DYl55taz5ptsW+q8lPz66cAQAATEA4AwAAmIBwBgAAMAHhDAAAYALCGQAAwASEMwAAgAkIZwAAABPQ54y11LGLo6fFZhyOdZ28vcfF53DsFgDsBS+63E+unAEAAExAOAMAAJiAcAYAADAB4QwAAGACwhkAAMAEhDMAAIAJCGcAAAATEM4AAAAmoAk1aynNFTkgPUvzZ8cAABwZe/2771rhrKo+lOR0ku0kZ7r7+k0UBQAAcNRs4srZN3T3JzawHAAAgCPLZ84AAAAmsG446yS/VVVvraobzzdDVd1YVaeq6tT26TvXHA4AAOBwWvdtjV/f3bdV1ZckeWNVvae7f/vcGbr7piQ3Jcmlj7tmlo/wAwAATGWtK2fdfdvq/zuSvC7JkzdRFAAAwFFzweGsqi6vqpNf+DnJNyV556YKAwAAOErWeVvjVUleVztf9n88yS93929upCqAAT32AIDD5oLDWXd/MMkTN1gLAADAkeWr9AEAACYgnAEAAExAOAMAAJiAcAYAADAB4QwAAGACwhkAAMAEhDMAAIAJCGcAAAATEM4AAAAmIJwBAABMQDgDAACYgHAGAAAwAeEMAABgAsIZAADABIQzAACACQhnAAAAExDOAAAAJiCcAQAATEA4AwAAmIBwBgAAMAHhDAAAYALCGQAAwASEMwAAgAkIZwAAABMQzgAAACYgnAEAAExAOAMAAJiAcAYAADAB4QwAAGACwhkAAMAEhDMAAIAJCGcAAAATEM4AAAAmsFY4q6pnVNV7q+r9VfWiTRUFAABw1FxwOKuqrSQ/m+SZSa5N8tyqunZThQEAABwl61w5e3KS93f3B7v7niSvSvLszZQFAABwtKwTzq5J8pFzbt+6uu/Pqaobq+pUVZ3aPn3nGsMBAAAcXnv+hSDdfVN3X9/d12+dvHyvhwMAALgorRPObkvy6HNuP2p1HwAAAPfTOuHs95I8oaoeW1WXJPmOJG/YTFkAAABHS3X3hT+46llJfirJVpJXdPdLB/N/PMmHz7nr4Uk+ccEFwN6yfzIr+yazsm8yM/sns/iy7n7E+SasFc7WVVWnuvv6AysAdmH/ZFb2TWZl32Rm9k8uBnv+hSAAAACMCWcAAAATOOhwdtMBjw+7sX8yK/sms7JvMjP7J9M70M+cAQAAsOOgr5wBAAAQ4QwAAGAKBxbOquoZVfXeqnp/Vb3ooOqAqnp0Vb25qt5dVe+qqhes7n9oVb2xqt63+v/Kg66Vo6mqtqrqbVX166vbj62qt6zOn79aVZccdI0cTVV1RVW9pqreU1W3VNXXOncyg6r6Z6vX9HdW1a9U1WXOnVwMDiScVdVWkp9N8swk1yZ5blVdexC1QJIzSX6gu69N8pQk37/aH1+U5E3d/YQkb1rdhoPwgiS3nHP7x5K8rLsfn+RTSZ53IFVB8tNJfrO7vzLJE7Oznzp3cqCq6pok/zTJ9d391Um2knxHnDu5CBzUlbMnJ3l/d3+wu+9J8qokzz6gWjjiuvv27v791c+ns/PLxTXZ2SdvXs12c5LnHEiBHGlV9agkfyvJL6xuV5KnJXnNahb7Jgeiqh6S5K8leXmSdPc93f3pOHcyh+NJHlBVx5M8MMntce7kInBQ4eyaJB855/atq/vgQFXVY5I8KclbklzV3bevJn00yVUHVRdH2k8l+ZdJzq5uPyzJp7v7zOq28ycH5bFJPp7kP67edvsLVXV5nDs5YN19W5IfT/LH2Qlln0ny1jh3chHwhSCwUlUPSvJrSV7Y3Z89d1rv9JzQd4J9VVXfnOSO7n7rQdcC53E8yV9K8nPd/aQkd+aL3sLo3MlBWH3O8dnZ+QPCI5NcnuQZB1oULHRQ4ey2JI8+5/ajVvfBgaiqE9kJZq/s7teu7v5YVV29mn51kjsOqj6OrK9L8neq6kPZefv307LzGZ8rVm/VSZw/OTi3Jrm1u9+yuv2a7IQ1504O2t9I8kfd/fHuvjfJa7NzPnXuZHoHFc5+L8kTVt+ac0l2PqT5hgOqhSNu9Rmelye5pbt/8pxJb0hyw+rnG5K8fr9r42jr7h/s7kd192Oyc578b939nUnenOTbVrPZNzkQ3f3RJB+pqq9Y3fX0JO+OcycH74+TPKWqHrh6jf/CvuncyfRq5x0HBzBw1bOy81mKrSSv6O6XHkghHHlV9fVJfifJH+bPPtfz4ux87uzVSb40yYeTfHt3f/JAiuTIq6qnJvnn3f3NVfW47FxJe2iStyX5h9199wGWxxFVVddl58tqLknywST/ODt/+HXu5EBV1Y8k+fvZ+UbmtyX5nux8xsy5k6kdWDgDAADgz/hCEAAAgAkIZwAAABMQzgAAACYgnAEAAExAOAMAAJiAcAYAADAB4QwAAGAC/w+lHM9r7O00uwAAAABJRU5ErkJggg==\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "# blow up of the region to be extracted\n", + "plt.figure(figsize=(15, 15))\n", + "plt.imshow(image[::,0:100], norm=norm_data, origin=\"lower\")\n", + "plt.title(\"slit[0] slice\")" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "# extraction parameters based on image above\n", + "ext_center = 27\n", + "ext_width = 4" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0.5, 1.0, 'Cross-dispersion Cut at Pixel=70')" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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R6L43qjv8b1R3ws6jIRL1byTgYoyaVbOOussjjvuOJ555pmgQ6lV+AYV3XkZG1OmTOGkk07it7/9bdLfibthwwYuuugi+vTpw5w5c2jRokXQIYlIElBRJs1Keno6ubm55OXlJf2CooWFhaSlpTF06NCgQ2kW0tLSmDlzJu+++y7z588POpxq7du3j69+9auUlZXx0ksv0aVLl6BDkmpMfGoiE5+aGHQYCZeqeScDFWXS7EybNo3y8nKef/75oEOpUVFRESeffDLt2rULOpRmIzc3lz59+vCb3/wmaXvLvvOd71BcXMycOXPIzMwMOhypweSBk5k8cHIgbV96qbcFIci8U53WKZNmxznHoEGD6N27N0uWLAk6nKiccxxzzDFMnDiRRx99NOhwmpUHH3yQ73znO7z22muMCer2tWp8/vnndOzYkauvvpoHHngg6HBEJABap0xSipkxbdo0XnvtNTZv3hx0OFFt3LiRzz77TJP84+Cqq66iR48e/Pa3vw06lCOsWLGCAwcOJF2xKMln3z5vk9SiokyapWnTpuGcY+7cuUGHElVRURGAirI4yMjI4Ic//CGLFi2ioKAg6HAOkZ+fD8CIESMCjkTqYtzj4xj3+LhA2p40yduCEGTeqU5FmTRLmZmZnH766Ul7F2ZhYSHp6emcdtppQYfSLH3rW9+ic+fO3HbbbUGHcoiCggK6detGnz59gg5F6mDqKVOZesrUoMNIuFTNOxmoKJNma/r06eTn57NmzZqgQzlCYWEhp5xyCm3atAk6lGapQ4cOfPe73+WFF15g1apVQYdzUH5+PiNGjNDDxpuIa4dfy7XDrw06jIRL1byTgYoyabamTvX+n96cOXMCjuRQzjmt5J8A3/3ud2nXrh2333570KEAUFpayqpVq8jOzg46FBFJUirKpNnq3bs3X/7yl3n66aeTanmEDRs2sHXrVhVlcda1a1euv/56nn76adatWxd0OCxfvpyqqioVZU3ImEfHMObRMUGHkXCpmncyUFEmzdq0adN47733eOedd4IO5SCt5J84P/jBD0hPT+eOO+4IOhRN8m+Crhx6JVcOvTKYtq/0tkDaDjDvVKeiTJq1Sy65hBYtWiTVhP+ioiJatGjBkCFDgg6l2evZsydXXnkls2fPDnx5lIKCAvr06UP37t0DjUPqTkWZJJqKMmnWunXrxrnnnssz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r3Prrbfy3//+t8HXWbVqFQcOHFBR1sTk5OTw+eefN7h3Mz8/n7Zt23LyySfHNjAJxIrPVrDisxWBtP3mm1/0liVakHmnOhVlIoe555576Nq1K1dddRXl5eUNukZ4SF3LYTQtZ555Jm3btm3wvLKCggKGDRumh883Ezfm3ciNeTcG0vbNN3tbEILMO9WpKBM5TNeuXXnwwQd5++23+d3vftegaxQWFtKpUyf69+8f4+gknlq3bs0555zToKKsvLyct99+W5P8m5E7xt/BHePvCDqMhEvVvJOBijKRKC688EJyc3P51a9+xYoV9e/GLyoqYvjw4aSl6T+xpiYnJ4c1a9awZs2aep23YsUKysrKNJ+sGRnRcwQjeqbev2eq5p0M9BdDpBr/93//R+fOnbnyyivr9bDyzz//nP/+978aumyicnJyAFi4cGG9zsvPzwdQT1kzUvxJMcWfFAcdRsKlat7JQEWZSDW6devGAw88QFFREbNmzarzeStWrODzzz/XJP8mqn///px44on1HsLMz8+na9eu9O3bN06RSaLNWDCDGQtmBB1GwqVq3slAs1FFanDJJZdwySWXcMstt3DBBRfU6a66oqIiQCv5N2U5OTnMnj2bAwcO0Lp16zqdU1BQwIgRIzCzOEcniXJ3zt3BtR1c04HmnerUUyZSi/vvv58OHTpw1VVX1WkYs7CwkC5duqjHpAnLyclh3759vPHGG3U6fu/evaxcuVLzyZqZoccMZegxQ4Npe6i3BdJ2gHmnOhVlIrU4+uijue+++8jPz+euu+6q9fjCwkKGDx+uHpMmbMyYMbRq1arOQ5jLly+nqqpK88mamYJNBRRsKgik7cWLvS0IQead6lSUidTB1KlTufDCC/nZz37G+++/X+1xBw4c4N1339XQZRPXrl07zjrrrDoXZeFJ/uopa15+vOjH/HjRjwNp+9ZbvS0IQead6lSUidSBmfHAAw/Qrl07rr76aiorK6Me9+6771JeXq47L5uBnJwcVqxYwcaNG2s9tqCggOOPP54ePXokIDJJlPsm3cd9k+4LOoyES9W8k4GKMpE6OuaYY7j33nt56623uOeee6IeE17JXz1lTV99lsbIz8/X0GUzNPjowQw+enDQYSRcquadDFSUidTD9OnTmTx5Mv/zP//Dhx9+eMT7RUVFdO3alRNOOCGA6CSWTjnlFHr2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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "# Plot along cross-disperion cut showing the extraction parameters\n", + "fig, ax = plt.subplots(figsize=(10, 6))\n", + "y = np.arange(image.shape[0])\n", + "ax.plot(y, image[:,70], 'k-')\n", + "mm = np.array([ext_center, ext_center])\n", + "mm_y = ax.get_ylim()\n", + "\n", + "ax.plot(mm, mm_y, 'b--')\n", + "ax.plot(mm - ext_width/2., mm_y, 'g:')\n", + "ax.plot(mm + ext_width/2., mm_y, 'g:')\n", + "\n", + "ax.set_title(\"Cross-dispersion Cut at Pixel=70\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Extract" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "# define the Trace\n", + "trace = FlatTrace(image, ext_center)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "# extract\n", + "boxcar = BoxcarExtract()\n", + "\n", + "boxcar.width = ext_width\n", + "spectrum = boxcar(image, trace)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "# this one crashes with \"UnitConversionError: 'pix' and 'Angstrom' (length) are not convertible\"\n", + "# print(spectrum.wavelength)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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H3ht27blwoULjBgxwusoIiKSzAVlIUsOVq1aRXh4OLfccovXUZKswoUL07BhQ9555x3279/vdRwREUnGVMgSIeccK1as0OhYAhgwYADnzp2jU6dOBPNdK0REJLipkCUimzdvpmzZsrRr147t27dTp04dryMleQULFuSVV15h8uTJvPrqq17HERGRZEr3skxEnnzyScaNGwdA9erViYqKIkUKdeZAc84RGRnJpEmTWLNmDaVKlfI6koiIJEGx3ctShSyROH78OLfccgsNGzbkrrvuomHDhuTIkcPrWMnGsWPHKFy4MHfccQcLFy7Utd9ERCTeJbmbiydFH330EWfOnOH555/n6aefVhlLYFmyZKFXr14sXrxY97kUEZEEF5SFLKldh+zvv/9m0KBB3H333ZQtW9brOMlWs2bNSJEiBdOmTfM6ioiIJDNBWciS2nXIJk+ezK5du+jevbvXUZK1nDlzUrlyZaZOnep1FBERSWaCspAlJadOnaJnz56ULFmS2rVrex0n2WvQoAFbtmxh3bp1XkcREZFkRIXMY3369GH37t0MHz5cZ1QmAk2bNiVz5sz07NnT6ygiIpKMqAF46JdffmHo0KE89dRTVKpUyes4AmTNmpUePXowZ84c5s6d63UcERFJJlTIPNS7d29SpkzJa6+95nUUiaZjx47cfvvtNG/enF9++cXrOCIikgyokHlk//79fPrppzz77LPkypXL6zgSTZo0afjiiy9wzvHcc895HUdERJIBFTKPTJkyBeccTzzxhNdR5CoKFixI165dmTNnDj/88IPXcUREJIkLyiv1m1ldoG6hQoXabNu2zes416VSpUqcOnWK9evXex1FYnDy5Eny5ctHxYoVmT17ttdxREQkyCW5K/UH03XIPvroI64sjbt27WLp0qU0btzYo1QSFxkzZuSll17SKJmIiARcUBayYBIZGUmRIkX+Me2zzz4DUCELAs8++yxZs2blxRdf5MiRI17HERGRJEqFzAOTJ0+mXLlyFCxY0Osocg0ZM2Zk4MCBLF++nGLFirFp0yavI4mISBKkQpbAtm3bxurVq2nSpInXUSSOnnzySdasWUNoaCg1atRg3759XkcSEZEkRoUsgfz9998ADB48mNDQUO2uDDIlSpRg/vz5HD16VPccFRGReKdClkB2797N3r17GTNmDK1atSI8PNzrSPIv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SpEiBffeey9RUVHcc8899OjRgwIFClCsWDGef/55Lly44HVEkXijQiYiIola1qxZ+eabb9ixYwdvvfUW+fLlY+jQobz33nteRxOJN0FZyMysrpmNPH78uNdRREQkgeTLl48uXbowZ84c6tSpQ/fu3Vm9erXXsUTiRVAWMufcTOdc27CwMK+jiIhIAjMzRo0axU033cQDDzzwj7sCiASroCxkIiKSvN1yyy188803ZMyYkfvuu4/evXszd+5c9u/fD8DZs2eZNGkSBw4c8DipSNyokImISFAqUKAAK1asoGrVqvTv35/atWtTtGhRhgwZQkREBC1atKBQoUKMHj3a66gi16RCJiIiQeumm25i9uzZHDhwgEWLFpErVy46derEyZMn+fDDD7nrrrto06YNDRs2ZMSIEezcudPryCJXpZuLi4hI0MuRIweVK1dm2bJlrF+/nnvuuYeQkBCaNm1K9+7dmTRpEtOmTSNNmjSsWLGCkiVLeh1Z5B80QiYiIklG5syZqVy5MiEhIQCEhoby9ttvs2/fPjZv3kxYWBgNGzakU6dOdOrUibFjx/LHH394G1oEFTIREUkGzIzixYszceJETp48ydixYxk1ahRPPfUUd955JzNmzOCLL77QDc3FMypkIiKSbFSvXp39+/dz/PhxTp48ycKFCzl58iSPPPII9evXp3bt2hw7dszrmJIMqZCJiEiyZGZUqVKFdevWMW/ePIYNG8bChQu59957WbZsmUbLJEHpoH4REUnWcufOTe7cuQEoWrQoDRo04O677yYkJITq1aszfPhwChQo4HFKSeo0QiYiIuJXrVo19uzZw/jx4+nUqRNLly6laNGitGvXjoMHD3odT5IwFTIREZFoMmTIQGRkJAMHDuTHH3+kTZs2jBs3jqJFixIVFeV1PEmiVMhERERikDt3boYNG8b69evJkycPderUoVu3bowfP55169Z5HU+SEB1DJiIicg3FihXju+++47nnnuPNN98EIHXq1Lz11lukS5cOM+Pxxx8nNDTU46QSrFTIRERE4iBjxoyMGzeO7t27c/r0aVq3bs3zzz9/ef4ff/zBiy++6GFCCWbaZSkiIvIvFClShDvvvJPly5fz448/snv3bmrXrs2rr77KgQMHvI4nQUqFTERE5DqEhoZSrFgx8uTJw5AhQzhz5gx9+/a96rJ///13AqeTYKNCJiIicoMKFy5Mq1atGDVqFNu2baNv3740b96c119/nVy5cpEmTRpee+01/vzzT3bv3s2ZM2e8jiyJjDnnvM5w3SIiItyqVau8jhGr0NBQunbtSr9+/byOIiIiAbRr1y4KFy58eTQsQ4YMnDp1igceeIDUqVMzc+ZMUqVKxblz58icOTODBw8mMjISM/M4uSQUM1vtnIu42jwd1C8iIhIP8ubNy/fff8/XX39NiRIlqFKlCrt376Z48eKcP3+erl27YmYUK1aMjz76iFatWhEVFUXNmjUpUKAAZcqUIX369F6vhnhEI2QBphEyERG50sWLF+nXrx99+vS5fM/M1KlTc//991O3bl0efvhhcuXK5XFKiW+xjZDpGDIREZEEliJFCnr37s2xY8fYvn07s2bNon379vz00088/fTT5M2bl5deeok2bdowbNgwTp486XVkCbCgHCEzs7pA3UKFCrXZtm2b13FipREyERGJK+ccW7Zs4dVXX+Wzzz4jffr0nD59miJFijBz5kyKFCnidUS5AUluhMw5N9M51zYsLMzrKCIiIvHGzChevDiffvope/bs4fjx43zzzTccPXqUChUq8Oabb9KrVy8WLlx4eVenJA1BWchERESSMjMjd+7chISEUK1aNVauXEmePHno1q0b/fv3p1q1atxxxx2MGzeOc+fOeR1X4oEKmYiISCKXL18+Vq1axY4dOzhx4gQTJkwgVapUPPnkk9SpU4cNGzbw9ddfex1TboAKmYiISBBIlSoV+fLlI0OGDLRo0YK1a9cyYsQIvv76a0qVKkWNGjWYO3eu1zHlOuk6ZCIiIkHIzGjXrh0XLlxg586dREVF0bx5c/r06cOpU6coUaIEDz74IKlSpfI6qsSBCpmIiEgQ69ChAwDt2rWjSZMmPP/885fnZc2alcqVK3PnnXfSrVs3QkNDvYop16BCJiIikgQULFiQH374gY0bN5I7d26WLVvGxIkTWbduHZ9//jmLFi2iadOm7N+/n4cffphSpUp5HVmi0TFkIiIiSYSZUbJkSbJmzUqdOnX45JNP2LJlC6NGjWLlypW0adOGl19+mfLlyzNy5MjL7wvGa5ImNSpkIiIiSVzr1q05evQoP//8M3v27KFatWq0a9eOSpUqUbhwYTJkyMDzzz/PihUrOH/+vNdxkyXtshQREUkGUqZMSeHChQGYOXMmL7/8MgsWLKBEiRKUL1+eYcOGMXToUMLCwqhatSoFChQgS5YsvPTSS6RJk8bj9EmfCpmIiEgykzJlSvr37/+PaUOGDGHhwoV89dVXfP3110RFRXHmzBlmzJjBwoULyZgxo0dpkwftshQRERFy5MhBo0aNGDVqFDt27ODPP/9k2rRprF69moEDB3odL8nTCJmIiIhc1aOPPkrjxo0ZNGgQGTJkYNeuXRQtWpT27dvrEhrxTIVMREREYtS/f3+WL1/Of/7zH9KlS8eff/7JJ598wvz588mQIYPX8ZIM7bIUERGRGBUoUICdO3dy7Nixy/fRXLFiBTVq1GDgwIHs27fP64hJggqZiIiIXFPmzJkJCQmhRYsWjB07lr1799K1a1fy5s1Ls2bN2LFjh9cRg5oKmYiIiPwrkZGR7Nmzh19++YWOHTsyc+ZMqlSpws6dO72OFrRUyEREROS6FChQgHfeeYfFixdz7NgxChYsSJ06ddi6davX0YKOCpmIiIjckDJlyrBmzRp69OjB999/T9myZfn555+9jhVUVMhERETkhhUqVIjXX3+dDRs2kDp1alq0aMHff//tdaygoUImIiIi8ebWW2/l/fffZ+XKlXz00UdexwkaKmQiIiISrx577DHKlStH3759OXfunNdxgoIuDCsiIiLxyszo06cPderUoVWrVtxzzz2sWbOGjRs3cuTIEUqXLs1DDz1Es2bNdMV/P42QiYiISLyrVasWffv25eOPP6ZDhw7MmDGDdOnSUapUKZYvX84TTzxBu3btcM6xf/9+du/e7XVkT2mETEREROKdmdGzZ08eeeQRUqVKRcGCBTEzAJxz9OrVi/79+xMVFcW+ffswM5o0acLw4cPJnDmzt+E9oEImIiIiAVO8ePH/mWZmvP7666RKlYodO3ZQrFgx/vjjDwYNGsSqVavo3LkzTzzxBGnSpPEgsTdUyERERCTBpUiRgldeeeUf02rVqkX79u15+umnmT17NtOnT082x5jpGDIRERFJFO677z42b97MsGHDmDVrFvfeey+rV6/+159z9uzZoDu7U4VMREREEg0zo0OHDkyYMIHdu3dz//33s3nz5n/1GWFhYRQoUCBACQNDhUxEREQSnRYtWrB8+XLSpk1LhQoVePLJJ/n111/j9N6zZ8/y22+/BThh/FIhExERkUTp1ltvZdGiRTRp0oRPP/2UYsWK8eWXX8b6nosXLyZQuvilQiYiIiKJ1m233cbo0aPZtm0bpUuX5rHHHiMqKirG5Q8ePJiA6eKPCpmIiIgkeuHh4cybN4/ixYtTv359JkyYwPnz5/9nuT179niQ7sYlqkJmZvXNbJSZTTazB7zOIyIiIolHlixZ+Oqrr7j99tt5/PHHqVu3Ls65fyxzqZCFhYV5EfG6BbyQmdlYMztoZpuumF7TzLaa2XYz6wbgnJvhnGsDtAcaBzqbiIiIBJfs2bPzww8/MGDAAObNm8eYMWP+MX/v3r0A5MmTx4t41y0hRsjGAzWjTzCzEGAYUAsoDjQ1s+iX8u3lny8iIiLyDylSpKBLly5UqVKFTp06sWnTpssjZZdGyLJnz+5lxH8t4IXMObcEOHrF5PLAdufcr865c8CnQD3zeROY65xbE+hsIiIiEpxSpEjBxIkTyZAhAxEREaRNm5avv/76ciG7dN/MYOHVrZPCgehH3e0FKgAdgepAmJkVcs6NuPKNZtYWaAu+02FFREQkeQoPD2fu3LkMHz6cRYsW0bx586ArYpckqntZOueGAkOvscxIYCRARESEi21ZERERSdpKly7NyJEj+fHHH6lYsSInT570OtJ18eosy9+A6Efb5fZPExEREfnXihcvzubNm+nYsaPXUa6LVyNkK4HCZpYfXxFrAjTzKIuIiIgkAXny5GHo0KGsW7fO6yj/WkJc9uITYBlwm5ntNbOnnHPngWeBKGAL8Jlz7t/dOVREREQkiQj4CJlzrmkM0+cAcwL9/SIiIiKJXaK6Un9cmVldMxt5/Phxr6OIiIiI3LCgLGTOuZnOubbBdlsEERERkasJykImIiIikpSokImIiIh4TIVMRERExGMqZCIiIiIeC8pCprMsRUREJCkJykKmsyxFREQkKQnKQiYiIiKSlKiQiYiIiHhMhUxERETEY+ac8zrDdTOzQ8CuAH9NduBwgL9DEpa2adKjbZr0aJsmPdqmkNc5l+NqM4K6kCUEM1vlnIvwOofEH23TpEfbNOnRNk16tE1jp12WIiIiIh5TIRMRERHxmArZtY30OoDEO23TpEfbNOnRNk16tE1joWPIRERERDymETIRERERj6mQxcLMaprZVjPbbmbdvM4jcWNmY83soJltijYtq5l9ZWbb/H9m8U83Mxvq38YbzKyMd8nlaswsj5ktNLMfzWyzmT3vn65tGqTMLI2Z/WBm6/3b9FX/9PxmtsK/7SabWSr/9NT+19v98/N5ugISIzMLMbO1ZjbL/1rbNI5UyGJgZiHAMKAWUBxoambFvU0lcTQeqHnFtG7AN865wsA3/tfg276F/Y+2wPsJlFHi7jzwonOuOFAReMb//6K2afA6C1RzzpUCSgM1zawi8CYw2DlXCDgGPOVf/ingmH/6YP9ykjg9D2yJ9lrbNI5UyGJWHtjunPvVOXcO+BSo53EmiQPn3BLg6BWT6wEf+p9/CNSPNv0j57McyGxmtyRIUIkT59x+59wa//OT+P6yD0fbNGj5t80p/8tQ/8MB1YCp/ulXbtNL23oqcL+ZWcKklbgys9xAHWC0/7WhbRpnKmQxCwf2RHu91z9NgtNNzrn9/ucHgJv8z7Wdg4h/t8adwAq0TYOaf9fWOuAg8BXwC/CHc+68f5Ho2+3yNvXPPw5kS9DAEhdDgK7ARf/rbGibxpkKmSQ7zndqsU4vDjJmlgGYBrzgnDsRfZ62afBxzl1wzpUGcuPbI1HU20RyI8zsIeCgc26111mClQpZzH4D8kR7nds/TYLT75d2W/n/POifru0cBMwsFF8Zm+Scm+6frG2aBDjn/gAWAnfh272c0j8r+na7vE3988OAIwmbVK6hEvCwme3Ed4hPNeC/aJvGmQpZzFYChf1niKQCmgBfepxJrt+XQKT/eSTwRbTpj/vPzKsIHI+2G0wSAf9xJWOALc65d6LN0jYNUmaWw8wy+5+nBWrgOzZwIdDQv9iV2/TStm4ILHC6iGai4pzr7pzL7ZzLh+/35QLnXHO0TeNMF4aNhZnVxrdPPAQY65zr520iiQsz+wSoAmQHfgdeAWYAnwG3AruARs65o/5f9u/hOyvzT6CVc26VB7ElBmZ2D/AtsJH/PzalB77jyLRNg5CZlcR3QHcIvoGBz5xzr5lZAXyjK1mBtUAL59xZM0sDTMB3/OBRoIlz7ldv0su1mFkV4CXn3EPapnGnQiYiIiLiMe2yFBEREfGYCpmIiIiIx1TIRERERDymQiYiIiLiMRUyEREREY+pkIlIsmZmo/03K/+378tnZpsCkUlEkp+U115ERCTpcs619jqDiIhGyEQkWfCPaP1kZpPMbIuZTTWzdGa2yMwizCyvmW0zs+xmlsLMvjWzB/w3wR5oZivNbIOZtfN6XUQk6dEImYgkJ7cBTznnvjezsUCHSzOcc7vM7E3gfeAH4Efn3Hwza4vv9kvlzCw18L2ZzUc3MxeReKQRMhFJTvY45773P58I3BN9pnNuNJAJaA+85J/8AL57Y67Dd7umbEDhBEkrIsmGRshEJDm5clTrH6/NLB2Q2/8yA3ASMKCjcy7qimXzBSijiCRDGiETkeTkVjO7y/+8GfDdFfPfBCYBLwOj/NOigKfNLBTAzIqYWfqECCsiyYcKmYgkJ1uBZ8xsC5AF3/FiAJhZZaAc8KZzbhJwzsxaAaOBH4E1/stcfID2LohIPDPndFyqiCR9/l2Ms5xzd3idRUTkShohExEREfGYRshEREREPKYRMhERERGPqZCJiIiIeEyFTERERMRjKmQiIiIiHlMhExEREfGYCpmIiIiIx/4PAddvndoei+gAAAAASUVORK5CYII=\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "# plot \n", + "f, ax = plt.subplots(figsize=(10, 6))\n", + "ax.plot(spectrum.flux.value, 'k-')\n", + "ax.set_title(\"Boxcar 1D extracted spectrum\")\n", + "ax.set_xlabel(r\"pixel\")\n", + "ax.set_ylabel(\"Flux Density [Jy]\")\n", + "ax.set_yscale(\"log\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## About this notebook\n", + "\n", + "**Author:** Ivo Busko, JWST\n", + "**Updated On:** 2022-02-18" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "***" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[Top of Page](#top)\n", + "\"Space " + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.12" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From b94e190fb1592cb85f17828ec9eb505e7c95f245 Mon Sep 17 00:00:00 2001 From: Ivo Date: Tue, 22 Feb 2022 09:20:17 -0500 Subject: [PATCH 09/18] Handle image flux units --- specreduce/extract.py | 9 +++++++-- specreduce/tests/test_extract.py | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/specreduce/extract.py b/specreduce/extract.py index 95bc25fc..d63cf59d 100644 --- a/specreduce/extract.py +++ b/specreduce/extract.py @@ -157,8 +157,13 @@ def __call__(self, image, trace_object, disp_axis=1, crossdisp_axis=(0,)): # spatial axis to collapse. This should be handled by the API somehow. ext1d = np.sum(image * wimage, axis=crossdisp_axis) - # TODO: add uncertainty and mask to spectrum1D object + # propagate image flux units into spectrum + unit = u.DN + if hasattr(image, 'unit') and image.unit is not None: + unit = image.unit + + # 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)) + flux=ext1d * getattr(image, 'unit', unit)) return spec diff --git a/specreduce/tests/test_extract.py b/specreduce/tests/test_extract.py index def78924..5a972c07 100644 --- a/specreduce/tests/test_extract.py +++ b/specreduce/tests/test_extract.py @@ -13,7 +13,7 @@ image = np.ones(shape=(30, 10)) for j in range(image.shape[0]): image[j, ::] *= j -image = CCDData(image, unit=u.count) +image = CCDData(image, unit=u.AA) def test_extraction(): @@ -27,6 +27,7 @@ def test_extraction(): spectrum = boxcar(image, trace) assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 75.)) + assert spectrum.unit is not None and spectrum.unit == u.AA trace.set_position(14.5) spectrum = boxcar(image, trace) From 6ef50a2bf0ba920416788bfa8f44fa91b4ce65b8 Mon Sep 17 00:00:00 2001 From: Ivo Date: Tue, 22 Feb 2022 09:22:29 -0500 Subject: [PATCH 10/18] Use correct units in test --- setup.cfg | 1 - specreduce/tests/test_extract.py | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/setup.cfg b/setup.cfg index 4095489c..fa4a830b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -68,7 +68,6 @@ testpaths = "specreduce" "docs" astropy_header = true doctest_plus = enabled text_file_format = rst -addopts = --doctest-rst [coverage:run] omit = diff --git a/specreduce/tests/test_extract.py b/specreduce/tests/test_extract.py index 5a972c07..9415e8e3 100644 --- a/specreduce/tests/test_extract.py +++ b/specreduce/tests/test_extract.py @@ -13,7 +13,7 @@ image = np.ones(shape=(30, 10)) for j in range(image.shape[0]): image[j, ::] *= j -image = CCDData(image, unit=u.AA) +image = CCDData(image, unit=u.Jy) def test_extraction(): @@ -27,7 +27,7 @@ def test_extraction(): spectrum = boxcar(image, trace) assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 75.)) - assert spectrum.unit is not None and spectrum.unit == u.AA + assert spectrum.unit is not None and spectrum.unit == u.Jy trace.set_position(14.5) spectrum = boxcar(image, trace) From 37821e159a22cf92081abfea9281166e11659c17 Mon Sep 17 00:00:00 2001 From: Ivo Date: Tue, 22 Feb 2022 09:27:41 -0500 Subject: [PATCH 11/18] Remove comment --- .../jwst_boxcar/boxcar_extraction.ipynb | 152 ++---------------- 1 file changed, 16 insertions(+), 136 deletions(-) diff --git a/notebook_sandbox/jwst_boxcar/boxcar_extraction.ipynb b/notebook_sandbox/jwst_boxcar/boxcar_extraction.ipynb index 40d67256..9ff92e9b 100644 --- a/notebook_sandbox/jwst_boxcar/boxcar_extraction.ipynb +++ b/notebook_sandbox/jwst_boxcar/boxcar_extraction.ipynb @@ -22,7 +22,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": { "slideshow": { "slide_type": "fragment" @@ -65,7 +65,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -83,17 +83,9 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "DEBUG:jwst.datamodels.util:Opening /var/folders/f2/dsq1cxxd78n9vltk6_6kwxtr0000zf/T/nirspec_fssim_d1_s2d.fits as \n" - ] - } - ], + "outputs": [], "source": [ "# use a jwst datamodel to provide a good interface to the data and wcs info\n", "s2d = datamodels.open(s2dfile)\n", @@ -102,32 +94,9 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Text(0.5, 1.0, 'slit[0]')" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "# display s2d image\n", "norm_data = simple_norm(image, \"sqrt\")\n", @@ -138,31 +107,11 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": { "scrolled": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "image/png": "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iIhcl5lFewCZNnGKiIiIBBgVNBEREZEAo4ImIiIiEmBU0EREREQCjAqaiIiISIBRQRMREREJMCpoIiIiIgFGBU1EREQkwKigiYiIiAQYFTQRERGRAKOCJiIiIhJggupanBK3jh07xtatW8mfPz+nTp1i+/btnDlzhtDQUEJDQ8mUKRPFixf3OqaIiEjQUUGTaLVt25aZM2fGOE/NmjV57bXXKFWqVAKlEhERCX4qaHJN69evZ+bMmXTu3JkiRYqQMmVKChUqROrUqbl48SIXLlxg3bp1vPbaa9xzzz3MnDmTWrVqeR1bREQkKJhzzusMcaZ06dJu3bp1XsdIlM6cOUPy5MkJCfHtlti4cWMWL17Mzp07SZcuXbSvO3LkCNWrV2f79u3MnDmTatWqJVRkERGRRM3M1jvnSl/rOR0kkMRNnjyZXLlykSpVKkqWLMnx48dZvnw5M2bM4Omnn46xnAHceuutzJ07l5w5c1K9enXuvPNO+vXrx759+xLoHYiIiASfoChoZtbAzEYfO3bM6yiJymuvvUaLFi3Ili0bvXr1YvPmzTRr1oyGDRuSL18+nnzyyVgt57bbbmPlypWMGDGCrFmz0rdvX3Lnzs2rr74az+9AREQkOGkTZxI1atQoHnnkEVq1asW4ceNIlSoVgwcPpmfPnmTNmpXly5dz++2339Cyf/75Z5555hm++uortm3bdsPLERERCWYxbeJUQUuCZs+eTYMGDahTpw4zZswgWTLfsSLOOd5//32qVKlCoUKFbmod+/bt44477qBZs2ZMmDAhLmKLiIgEFe2DJpdt2LCBFi1aUKJECT7//PPL5QzAzOjSpctNlzOAbNmy0a1bNz7++GO2bNly08sTERFJSjSCFuQuXLjACy+8QJYsWahcuTINGjQgVapUrFq1imzZssXrug8fPsztt99O6tSpadOmDalSpWLp0qVERETw2muvkTp16nhdv4iISCCLaQRN50ELYs45nnzySUaOHHl5Wp48eZg7d268lzOAjBkzMnv2bAYPHszw4cO5ePEixYoV4+2332bRokVMnjyZggULxnsOERGRxEYjaEEsMjKShg0b0qNHDyIiIoiMjGTo0KEJUs6uduzYMUJCQggPD2fOnDm0bduWtGnTsmHDBm699dYEzyMiIuI1HSSQRDVs2JB169bx+++/X7GvWSBYu3YtFStW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efJ4HUXiSefOnSlatCg9e/bkzJkzXscREZEgExQFLdBOs7Fy5UrKly+PmXkdReJJsmTJGDp0KL/88guDBg3yOo6IiASZoChogeTgwYP88ssvVKhQwesoEs9q165N69at6du3L+PGjfM6joiIBBHtwR7HLu1/poKWNIwbN47Dhw/TuXNnzIwOHTpo5FRERG6aRtDi2KpVq0iWLBmlSpXyOookgJQpUzJ16lSqVq1Kx44dadmyJUeOHPE6loiIJHIqaHHs+++/p1ChQqRJk8brKJJA0qRJw7x583j11VeZOnUqVapU4c8///Q6loiIJGIqaHFs+/btFCxY0OsYksBCQ0N54YUXmDNnDtu2baNRo0acOnXK61giIpJIqaDFoQsXLrBjxw4KFCjgdRTxSI0aNfjoo49YunSpTmQrIiI3LCgOEjCzBkCD/Pnze7L+EydOsGnTJnLkyMHZs2c1gpbEPfjgg/z+++/06tWLYsWK8b///c/rSCIiksgExQia1+dBa9euHZUqVWL58uUAGkETevTowUMPPUSfPn0YNmwYR48e9TqSiIgkIkFR0Ly2detWABU0uczMGD16NFWqVOGZZ54hS5YsdOzYkUOHDnkdTUREEgEVtDhwaeRu3bp1hIWFkTVrVo8TSSBIlSoVCxcuZM2aNTzyyCN8/PHHFCpUiGnTpnkdTUREApwKWhxIly4d4CtoxYsX14lK5TIzo0yZMrz99tt8++235M+fn+bNmzN16lSvo4mISABTQYsDUfd9K126tIdJJJDdeeedzJ8/n7Jly9KyZUtmzpzpdSQREQlQKmhxIGpBu/feez1MIoEubdq0fPXVV5QoUYLGjRvz0UcfeR1JREQCkApaHLi0iROgYcOGHiaRxCB9+vR88803VKlShXbt2tGrVy+OHz/udSwREQkgKmhxIOoIWqpUqTxMIolFunTpmD17Np06deKNN96gQIECzJgxw+tYIiISIFTQ4kBYWBgAvXv39jiJJCYpU6ZkzJgxrF27lly5ctGkSRPGjh3rdSwREQkAKmhx4NJRm7169fI4iSRGpUuXZvHixdSuXZuHH36Y119/3etIIiLisaAoaGbWwMxGHzt2zOsoIjckLCyMGTNm0LJlS5577jl69uyp63iKiCRhQXEtTudcJBBZunTpzl5nEblRKVKkYOLEiWTMmJHBgwdz+PBhRo8e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h7fffpvbbruNxo0bU62azo0tIklHTPug5U3AHCIihIaGMmLECCpUqEDFihVJnz49586dY8SIEUydOpVGjRp5HVFEJEFoT1wRCSjly5enT58+tGvXju3bt3PgwAFKly5Ny5Yt+fLLL72OJyKSIGJ1qScRkYT08ssvX/F45syZ1KxZk0aNGtGwYUMeeOABWrRoQZo0aTxKKCISvzSCJiIBL3PmzKxdu5Z+/fqxcuVK/vOf/1CjRg2OHDnidTQRkXhx3YJmZlPNrL6ZqcyJiGdSpEjB//73P/bv38+kSZPYuHEj99xzD2vXrvU6mohInItN6XoHaA1sN7PXzKxQPGcSEYlWSEgIzZs3Z968efz1119UqFCBMWPGeB1LRCROXbegOee+cc61AUoCvwHfmNkKM/uPmSWP74CxYWYNzGz0sWO6NKhIUlG5cmU2b95MzZo1eeSRR5g3b57XkURE4kysNluaWUagA/Awvss7vYWvsH0db8n+BedcpHOuy6ULMotI0pAhQwYmT57MnXfeSfPmzdmyZYvXkURE4kRs9kGbBiwF0gANnHMNnXOfO+e6AWnjO6CISEzCw8OZOXMmqVOn5v7772fNmjWcPn3a61giIjclNiNo7zvn7nTODXTO7YPLF0rHOVc6XtOJiMRC7ty5iYyM5I8//qBcuXLcdtttDBkyhLNnz3odTUTkhsSmoA24xrSVcR1ERORmlClThu3btzN58mTuvfdeevToQZ06dThx4oTX0URE/rVoC5qZZTWzUkBqM4sws5L+W1V8mztFRAJKjhw5aNasGbNmzWL8+PEsWbKEKlWq8O2333odTUTkX4lpBO0+YDCQExgKDPHfngFejP9oIiI3rn379syYMYPdu3dTqlQpunfvztGjR72OJSISK9EWNOfch865akAH51y1KLeGzrmpCZhRROSG1K9fn23btvHoo48ycuRIcuXKRZMmTdi0aZPX0UREYhTTJs62/rt5zeyZq28JlE9E5KbccsstjBgxgnXr1tGmTRuWLVtGxYoViYyM9DqaiEi0YtrEGeb/My0Qfo2biEiiERERwXvvvcemTZsoUqQITZs2ZdGiRV7HEhG5pmTRPeGcG+X/8+WEiyMiEr+yZcvG119/TYUKFWjSpAmLFi2iePHiXscSEblCbE5U+7qZpTOz5GY238wORtn8KSKS6GTIkIFZs2aR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EZHgV6NGDbZv3860adN49NFHmTJlClmzZqVx48ZkzpyZOXPmeB1RJM4ERUETEZGkISQkhMaNGzNy5EiaNGnCmjVreP/998mUKRNdu3bl5MmTXkcUiRMqaCIikmilSJGChx9+mPfff5/ff/+de+65hy1btngdS+SmqaCJiEiiV6lSJT7//HN+//13evfu7XUckZumi6WLiEhQaNGiBatXr2b48OEcPnyYPXv2cODAAcqVK0d4eLjX8UT+FY2giYhI0Gjbti3nzp2jVq1alChRglq1alGsWDE2b97sdTSRf0UFTUREgkaJEiV46KGHOHPmDE8++SRffvklZ8+epUmTJpw7dw7nHBs3buT777/3OqpIjLSJU0REgoaZMWHChH9Ma9CgAW+++SbLly9nxowZpEqVivnz53PPPfd4lFQkZhpBExGRoFa/fn1q1KhBr169mDFjBn379iVXrlzUqVOHefPmeR1P5Jo0giYiIkHNzIiMjGTUqFGkTZuWhx9+mIcffpj69etTr149XnjhBSpUqEDt2rVJlky/FiUw6CdRRESCXurUqXnqqacuP86ZMydLly6ldevWDBgwAIC77rqLZcuWoavSSCAIik2cuhaniIj8W+nSpSMyMpJDhw4xceJEtm7dSqNGjZgzZw5nz571Op4kcUFR0HQtThERuRFmRsaMGWndujXvvvsuGzdupG7duhQrVoy//vrL63iShAVFQRMREblZDz/8MAcOHOCjjz7ip59+urzpU8QL2gdNRETEL2XKlLRt25YFCxYwaNAgNm3axIULF6hYsSL//e9/dRCBJBj9pImIiFzlnXfeISwsjNmzZ5MhQwZeeukltm3bxsSJEzEzr+NJEqCCJiIicpVUqVIxfPhwhg8fDsArr7xC7969yZo1K9myZQOgbt263HXXXV7GlCCmgiYiInIdL774IqtXr2bYsGGXp/Xq1Yt27drx6quvkiNHDg/TSTDSQQIiIiLXYWZMnz6drVu3cvToUfbv30+vXr347LPPiIiIYNOmTV5HlCCjgiYiIhILISEhFCpUiPTp03PbbbcxaNAgvv32W5IlS0aJEiVIly4dBQsW5IMPPvA6qgQBFTQREZEbVKRIEdauXcvAgQPp2LEjt956Kx07dqRdu3Zs2bLF63iSiKmgiYiI3IQcOXLw/PPP8+abb7J8+XKee+45Jk+ezF133cWzzz7rdTxJpFTQRERE4khoaCivvfYau3btonPnzgwdOpRnn32WvXv3eh1NEhkVNBERkTiWKVMm3n33XR566CGGDRtGnjx5qFixImvXrvU6miQSKmgiIiLxIDQ0lAkTJrB9+3Z69OjBjh076NixIxcuXPA6miQCKmgiIiLx6I477mDgwIG89dZbbN68mffee8/rSJIIqKCJiIgkgObNm1O7dm2effZZVq9e7XUcCXBBUdDMrIGZjT527JjXUURERK7JzPj444/JkSMHtWvXZuDAgcydO5eLFy+yd+9eJk+erM2fcllQFDTnXKRzrkv69Om9jiIiIhKtzJkzs3DhQkqUKMGLL75InTp1aNmyJREREbRo0YIaNWpw4sQJr2NKAAiKgiYiIpJY5M6dm8WLF7Nv3z4effRRJk+eTI4cOXjjjTdYtmwZlSpVYtiwYezfv9/rqOIhFTQREREPZM2alREjRvDjjz+yfv16evToweeff8758+d55plnqFixIqdPn/Y6pnhEBU1ERMQjISEhFC5cGDMDoGnTpmzevJlZs2axY8cO6tatS7t27Xj33XdV1pIYFTQREZEAU69ePXr06MHu3btZsGABjz32GA0bNmTcuHEcPXrU63iSAFTQREREAtAbb7zB9u3b2bVrF++99x5ff/01nTp1olq1ahw5csTreBLPVNBEREQCmJnRtWtX1q1bx6RJk9iyZQvNmzfnt99+4+LFi17Hk3iSzOsAIiIicn2lSpWiVKlSnDx5ko4dO5IvXz5y5szJlClTKFu2rNfxJI5pBE1ERCQRad++Pdu3b+ftt98mWbJkVKpUicGDB2s0LciooImIiCQyt99+O926dWPdunXUr1+fnj170rx5c86fP+91NIkjKmgiIiKJVMaMGZkyZQpvvPEGU6dOpWnTpgwYMIDdu3d7HU1ukvZBExERScTMjB49epA8eXJ69uzJl19+yZQpU2jdujXh4eF07dr18nnWJPHQCJqIiEgQePLJJ9m3bx+TJk3ihx9+oFevXjz66KPMmzfP62hyA1TQREREgkTGjBlp3rw5hw4d4siRI2TPnp033njD61hyA1TQREREgkx4eDi33HIL3bp1Y/78+WzduvXyc845/vzzTw/TSWyooImIiASpDh06EBoayptvvkmLFi1o3749efPm5dZbb2XcuHFs3bqVY8eOeR1T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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "# pipeline 1d extraction (for comparison)\n", "jpipe_x1d = Table.read(x1dfile, hdu=1)\n", @@ -192,32 +141,9 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Text(0.5, 1.0, 'slit[0] slice')" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "# blow up of the region to be extracted\n", "plt.figure(figsize=(15, 15))\n", @@ -227,7 +153,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -238,32 +164,9 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Text(0.5, 1.0, 'Cross-dispersion Cut at Pixel=70')" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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R6L43qjv8b1R3ws6jIRL1byTgYoyaVbOOussjjvuOJ555pmgQ6lV+AYV3XkZG1OmTOGkk07it7/9bdLfibthwwYuuugi+vTpw5w5c2jRokXQIYlIElBRJs1Keno6ubm55OXlJf2CooWFhaSlpTF06NCgQ2kW0tLSmDlzJu+++y7z588POpxq7du3j69+9auUlZXx0ksv0aVLl6BDkmpMfGoiE5+aGHQYCZeqeScDFWXS7EybNo3y8nKef/75oEOpUVFRESeffDLt2rULOpRmIzc3lz59+vCb3/wmaXvLvvOd71BcXMycOXPIzMwMOhypweSBk5k8cHIgbV96qbcFIci8U53WKZNmxznHoEGD6N27N0uWLAk6nKiccxxzzDFMnDiRRx99NOhwmpUHH3yQ73znO7z22muMCer2tWp8/vnndOzYkauvvpoHHngg6HBEJABap0xSipkxbdo0XnvtNTZv3hx0OFFt3LiRzz77TJP84+Cqq66iR48e/Pa3vw06lCOsWLGCAwcOJF2xKMln3z5vk9SiokyapWnTpuGcY+7cuUGHElVRURGAirI4yMjI4Ic//CGLFi2ioKAg6HAOkZ+fD8CIESMCjkTqYtzj4xj3+LhA2p40yduCEGTeqU5FmTRLmZmZnH766Ul7F2ZhYSHp6emcdtppQYfSLH3rW9+ic+fO3HbbbUGHcoiCggK6detGnz59gg5F6mDqKVOZesrUoMNIuFTNOxmoKJNma/r06eTn57NmzZqgQzlCYWEhp5xyCm3atAk6lGapQ4cOfPe73+WFF15g1apVQYdzUH5+PiNGjNDDxpuIa4dfy7XDrw06jIRL1byTgYoyabamTvX+n96cOXMCjuRQzjmt5J8A3/3ud2nXrh2333570KEAUFpayqpVq8jOzg46FBFJUirKpNnq3bs3X/7yl3n66aeTanmEDRs2sHXrVhVlcda1a1euv/56nn76adatWxd0OCxfvpyqqioVZU3ImEfHMObRMUGHkXCpmncyUFEmzdq0adN47733eOedd4IO5SCt5J84P/jBD0hPT+eOO+4IOhRN8m+Crhx6JVcOvTKYtq/0tkDaDjDvVKeiTJq1Sy65hBYtWiTVhP+ioiJatGjBkCFDgg6l2evZsydXXnkls2fPDnx5lIKCAvr06UP37t0DjUPqTkWZJJqKMmnWunXrxrnnnssz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r3Prrbfy3//+t8HXWbVqFQcOHFBR1sTk5OTw+eefN7h3Mz8/n7Zt23LyySfHNjAJxIrPVrDisxWBtP3mm1/0liVakHmnOhVlIoe555576Nq1K1dddRXl5eUNukZ4SF3LYTQtZ555Jm3btm3wvLKCggKGDRumh883Ezfm3ciNeTcG0vbNN3tbEILMO9WpKBM5TNeuXXnwwQd5++23+d3vftegaxQWFtKpUyf69+8f4+gknlq3bs0555zToKKsvLyct99+W5P8m5E7xt/BHePvCDqMhEvVvJOBijKRKC688EJyc3P51a9+xYoV9e/GLyoqYvjw4aSl6T+xpiYnJ4c1a9awZs2aep23YsUKysrKNJ+sGRnRcwQjeqbev2eq5p0M9BdDpBr/93//R+fOnbnyyivr9bDyzz//nP/+978aumyicnJyAFi4cGG9zsvPzwdQT1kzUvxJMcWfFAcdRsKlat7JQEWZSDW6devGAw88QFFREbNmzarzeStWrODzzz/XJP8mqn///px44on1HsLMz8+na9eu9O3bN06RSaLNWDCDGQtmBB1GwqVq3slAs1FFanDJJZdwySWXcMstt3DBBRfU6a66oqIiQCv5N2U5OTnMnj2bAwcO0Lp16zqdU1BQwIgRIzCzOEcniXJ3zt3BtR1c04HmnerUUyZSi/vvv58OHTpw1VVX1WkYs7CwkC5duqjHpAnLyclh3759vPHGG3U6fu/evaxcuVLzyZqZoccMZegxQ4Npe6i3BdJ2gHmnOhVlIrU4+uijue+++8jPz+euu+6q9fjCwkKGDx+uHpMmbMyYMbRq1arOQ5jLly+nqqpK88mamYJNBRRsKgik7cWLvS0IQead6lSUidTB1KlTufDCC/nZz37G+++/X+1xBw4c4N1339XQZRPXrl07zjrrrDoXZeFJ/uopa15+vOjH/HjRjwNp+9ZbvS0IQead6lSUidSBmfHAAw/Qrl07rr76aiorK6Me9+6771JeXq47L5uBnJwcVqxYwcaNG2s9tqCggOOPP54ePXokIDJJlPsm3cd9k+4LOoyES9W8k4GKMpE6OuaYY7j33nt56623uOeee6IeE17JXz1lTV99lsbIz8/X0GUzNPjowQw+enDQYSRcquadDFSUidTD9OnTmTx5Mv/zP//Dhx9+eMT7RUVFdO3alRNOOCGA6CSWTjnlFHr27FnrEOaWLVtYt26dhi6boTdL3uTNkoAeQBmgVM07GagoE6kHM+OPf/wjGRkZXH311VRVVR3yvib5Nx9mRk5ODosWLarxrttw76h6ypqfm5fczM1LAnoAZYBSNe9koKJMpJ6OO+447r77bt544w3uu++LeRdlZWWsWLFCQ5fNSE5ODrt27WLZsmXVHpOfn4+ZaR5hM/TQ+Q/x0PkPBdP2Q94WSNsB5p3qVJSJNMDll1/OpEmTuOmmm1i7di0A77zzDhUVFSrKmpFx48aRnp5e4xBmQUEBJ510Eh06dEhgZJIIg7oNYlC3QcG0PcjbAmk7wLxTnYoykQYwMx566CFatmzJNddcQ1VVlSb5N0OdO3dm1KhR1RZlzjny8/M1n6yZWrp+KUvXLw2k7Zdf9rYgBJl3qmtUUWZmvzCzTWZW7G+TIt6baWZrzGy1mU2I2J/j71tjZjdF7O9rZsv8/XPNrFVjYhOJt169enHXXXexdOlSHnzwQQoLC+nevTu9evUKOjSJoZycHIqKitiyZcsR723YsIEtW7ZoPlkzdcvrt3DL67cE0vadd3pbEILMO9XFoqfsLufcUH/LAzCzk4Fc4BQgB3jAzNLNLB24H5gInAxM848F+J1/rROBHcA1MYhNJK6uuuoqJkyYwE9/+lMWL15MVlaWJvk3Mzk5OTjnWLRo0RHvadHY5m32lNnMnjI76DASLlXzTgbxGr6cAsxxzh1wzq0D1gDZ/rbGORdyzn0OzAGmmPdX7BzgWf/8x4Cvxik2kZgxMx5++GHS0tIoKSnR0GUzNGzYMLp16xZ1CLOgoIBWrVoxZMiQACKTeOvXpR/9uvQLOoyES9W8k0EsirIbzewdM5ttZl38fT2BkohjNvr7qtvfFdjpnKs4bH9UZnadmRWaWWG0IQWRRDr++OOZNWsWAKNGjQo4Gom1tLQ0JkyYwMKFC49YAiU/P5+hQ4fSunXrgKKTeFocWsziUEAPoAxQquadDGotysxssZmtiLJNAR4E+gNDgc1AQkbAnXMPO+eynHNZ3bt3T0STIjW69tprKSoqYuLEiUGHInGQk5PDZ599RnFx8cF9lZWVFBYWauiyGbv1n7dy6z8DegBlgFI172TQorYDnHPj6nIhM/sT8Hf/101A74i3e/n7qGb/NqCzmbXwe8sijxdJembGsGHDgg5D4uTcc88FYMGCBQf/nd9//3327t2rSf7N2BMXPhFc28E1HWjeqa6xd18eG/HrhcAK//VLQK6ZtTazvsAAIB8oAAb4d1q2wrsZ4CXnnANeAy7xz78CeLExsYmIxMrRRx/N8OHDD5lXpkn+zV/vTr3p3al37QfGo+3e3hZI2wHmneoaO6fs92b2rpm9A3wF+D6Ac24lMA9YBSwAbnDOVfq9YDcCC4H3gHn+sQA/BX5gZmvw5pj9uZGxiYjETE5ODm+++Sa7du0CvEn+HTp0YFBQK3xK3C1Ys4AFa2p+9mm8zJ3rbUEIMu9UZ14nVdOVlZXlwot2iojEyxtvvMFZZ53Fc889x0UXXURWVhYdO3bkH//4R9ChSZyMeXQMAK9f+Xri2/aa5vXENx1o3qnAzIqcc1Fv1a91TpmIiMDIkSPp2LEjCxYsYNKkSbzzzjv84Ac/CDosiaM5l8wJOoRApGreyUBFmYhIHbRs2ZJx48axYMECiouLKS8v13yyZu6Y9scEHUIgUjXvZKBnX4qI1FFOTg4lJSU89thjALrzspl7efXLvLw6oAdQBihV804G6ikTEamjCRO8x/jOnj2bHj166Dmnzdydb3lLb04eNDngSBIrVfNOBirKRETq6Pjjj+fkk09m1apVZGdn6zmnzdyzlz5b+0Hxaju4pgPNO9WpKBMRqYecnJyDRZk0b93adguu7eCaDjTvVKc5ZSIi9XDBBRcAcNZZZwUcicTb8+89z/PvPR9I248+6m1BCDLvVKeeMhGRejj77LP58MMPOfHEE4MOReLs3mX3AnDRSRclvO1wQXbllQlvOtC8U52KMhGRelJBlhpezE3Np/2lat7JQEWZiIhIFJ0yOgUdQiBSNe9koDllIiIiUcxdMZe5KwJ6AGWAUjXvZKCeMhERkSgeLHwQgKmDpwYcSWKlat7JQA8kFxERiWJf+T4A2rZsm/i2vaZpm/imA807FeiB5CIiIvUUZFESRDF2sG0VY4HRnDIREZEonnznSZ5858lA2n7gAW8LQpB5pzoVZSIiIlE8svwRHln+SCBtz5vnbUEIMu9Up+FLERGRKBZdtijoEAKRqnknAxVlIiIiUbRMbxl0CIFI1byTgYYvRUREoni0+FEeLX406DASLlXzTgYqykRERKJI1eIkVfNOBlqnTERERCRBalqnTD1lIiIiIklARZmIiIhIElBRJiIiIpIEVJSJiIiIJAEVZSIiIiJJQEWZiIiISBJQUSYiIiKSBFSUiYiIiCQBFWUiIiIiSUBFmYiIiEgSUFEmIiIikgRUlImIiIgkARVlIiIiIklARZmIiIhIEjDnXNAxNIqZbQE+inMz3YCtcW6judFnVn/6zOpPn1n96TOrH31e9afPrGYnOOe6R3ujyRdliWBmhc65rKDjaEr0mdWfPrP602dWf/rM6kefV/3pM2s4DV+KiIiIJAEVZSIiIiJJQEVZ3TwcdABNkD6z+tNnVn/6zOpPn1n96POqP31mDaQ5ZSIiIiJJQD1lIiIiIklARVktzCzHzFab2RozuynoeJoCM1tvZu+aWbGZFQYdTzIys9lm9pmZrYjYd5SZLTKzD/2fXYKMMdlU85n9wsw2+d+1YjObFGSMycTMepvZa2a2ysxWmtn3/P36nlWjhs9M37NqmFmGmeWb2X/9z+yX/v6+ZrbM/9s518xaBR1rU6DhyxqYWTrwATAe2AgUANOcc6sCDSzJmdl6IMs5p3VqqmFmXwZKgcedc4P9fb8Htjvnbvf/D0AX59xPg4wzmVTzmf0CKHXOzQoytmRkZscCxzrnlptZB6AI+CpwJfqeRVXDZ3Yp+p5FZWYGtHPOlZpZS+AN4HvAD4DnnXNzzOyPwH+dcw8GGWtToJ6ymmUDa5xzIefc58AcYErAMUkz4Jz7J7D9sN1TgMf814/h/TEQXzWfmVTDObfZObfcf70HeA/oib5n1arhM5NqOE+p/2tLf3PAOcCz/n59z+pIRVnNegIlEb9vRP+B1oUDXjWzIjO7LuhgmpAezrnN/utPgB5BBtOE3Ghm7/jDmxqKi8LM+gCnA8vQ96xODvvMQN+zaplZupkVA58Bi4C1wE7nXIV/iP521pGKMomHM51zw4CJwA3+sJPUg/PmFWhuQe0eBPoDQ4HNwJ2BRpOEzKw98Bwwwzm3O/I9fc+ii/KZ6XtWA+dcpXNuKNALb4QpM9iImi4VZTXbBPSO+L2Xv09q4Jzb5P/8DHgB7z9Sqd2n/pyW8NyWzwKOJ+k55z71/yBUAX9C37VD+HN8ngOecs497+/W96wG0T4zfc/qxjm3E3gNOAPobGYt/Lf0t7OOVJTVrAAY4N9F0grIBV4KOKakZmbt/AmymFk74FxgRc1nie8l4Ar/9RXAiwHG0iSEiwvfhei7dpA/AfvPwHvOuT9EvKXvWTWq+8z0PauemXU3s87+6zZ4N8a9h1ecXeIfpu9ZHenuy1r4tz7fDaQDs51zvwk2ouRmZv3wescAWgBP6zM7kpk9A4wBugGfArcAfwPmAccDHwGXOuc0sd1XzWc2Bm9IyQHrgesj5kulNDM7E/gX8C5Q5e++GW+OlL5nUdTwmU1D37OozGwI3kT+dLyOnnnOuV/5fwvmAEcBbwPfcM4dCC7SpkFFmYiIiEgS0PCliIiISBJQUSYiIiKSBFSUiYiIiCQBFWUiIiIiSUBFmYiIiEgSUFEmIiIikgRUlImIiIgkARVlIiIiIkng/wPPn9Yu+jaa7AAAAABJRU5ErkJggg==\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "# Plot along cross-disperion cut showing the extraction parameters\n", "fig, ax = plt.subplots(figsize=(10, 6))\n", @@ -288,7 +191,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": { "scrolled": false }, @@ -300,7 +203,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -313,32 +216,9 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": {}, "outputs": [], - "source": [ - "# this one crashes with \"UnitConversionError: 'pix' and 'Angstrom' (length) are not convertible\"\n", - "# print(spectrum.wavelength)" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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H3ht27blwoULjBgxwusoIiKSzAVlIUsOVq1aRXh4OLfccovXUZKswoUL07BhQ9555x3279/vdRwREUnGVMgSIeccK1as0OhYAhgwYADnzp2jU6dOBPNdK0REJLipkCUimzdvpmzZsrRr147t27dTp04dryMleQULFuSVV15h8uTJvPrqq17HERGRZEr3skxEnnzyScaNGwdA9erViYqKIkUKdeZAc84RGRnJpEmTWLNmDaVKlfI6koiIJEGx3ctShSyROH78OLfccgsNGzbkrrvuomHDhuTIkcPrWMnGsWPHKFy4MHfccQcLFy7Utd9ERCTeJbmbiydFH330EWfOnOH555/n6aefVhlLYFmyZKFXr14sXrxY97kUEZEEF5SFLKldh+zvv/9m0KBB3H333ZQtW9brOMlWs2bNSJEiBdOmTfM6ioiIJDNBWciS2nXIJk+ezK5du+jevbvXUZK1nDlzUrlyZaZOnep1FBERSWaCspAlJadOnaJnz56ULFmS2rVrex0n2WvQoAFbtmxh3bp1XkcREZFkRIXMY3369GH37t0MHz5cZ1QmAk2bNiVz5sz07NnT6ygiIpKMqAF46JdffmHo0KE89dRTVKpUyes4AmTNmpUePXowZ84c5s6d63UcERFJJlTIPNS7d29SpkzJa6+95nUUiaZjx47cfvvtNG/enF9++cXrOCIikgyokHlk//79fPrppzz77LPkypXL6zgSTZo0afjiiy9wzvHcc895HUdERJIBFTKPTJkyBeccTzzxhNdR5CoKFixI165dmTNnDj/88IPXcUREJIkLyiv1m1ldoG6hQoXabNu2zes416VSpUqcOnWK9evXex1FYnDy5Eny5ctHxYoVmT17ttdxREQkyCW5K/UH03XIPvroI64sjbt27WLp0qU0btzYo1QSFxkzZuSll17SKJmIiARcUBayYBIZGUmRIkX+Me2zzz4DUCELAs8++yxZs2blxRdf5MiRI17HERGRJEqFzAOTJ0+mXLlyFCxY0Osocg0ZM2Zk4MCBLF++nGLFirFp0yavI4mISBKkQpbAtm3bxurVq2nSpInXUSSOnnzySdasWUNoaCg1atRg3759XkcSEZEkRoUsgfz9998ADB48mNDQUO2uDDIlSpRg/vz5HD16VPccFRGReKdClkB2797N3r17GTNmDK1atSI8PNzrSPIv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SpEiBffeey9RUVHcc8899OjRgwIFClCsWDGef/55Lly44HVEkXijQiYiIola1qxZ+eabb9ixYwdvvfUW+fLlY+jQobz33nteRxOJN0FZyMysrpmNPH78uNdRREQkgeTLl48uXbowZ84c6tSpQ/fu3Vm9erXXsUTiRVAWMufcTOdc27CwMK+jiIhIAjMzRo0axU033cQDDzzwj7sCiASroCxkIiKSvN1yyy188803ZMyYkfvuu4/evXszd+5c9u/fD8DZs2eZNGkSBw4c8DipSNyokImISFAqUKAAK1asoGrVqvTv35/atWtTtGhRhgwZQkREBC1atKBQoUKMHj3a66gi16RCJiIiQeumm25i9uzZHDhwgEWLFpErVy46derEyZMn+fDDD7nrrrto06YNDRs2ZMSIEezcudPryCJXpZuLi4hI0MuRIweVK1dm2bJlrF+/nnvuuYeQkBCaNm1K9+7dmTRpEtOmTSNNmjSsWLGCkiVLeh1Z5B80QiYiIklG5syZqVy5MiEhIQCEhoby9ttvs2/fPjZv3kxYWBgNGzakU6dOdOrUibFjx/LHH394G1oEFTIREUkGzIzixYszceJETp48ydixYxk1ahRPPfUUd955JzNmzOCLL77QDc3FMypkIiKSbFSvXp39+/dz/PhxTp48ycKFCzl58iSPPPII9evXp3bt2hw7dszrmJIMqZCJiEiyZGZUqVKFdevWMW/ePIYNG8bChQu59957WbZsmUbLJEHpoH4REUnWcufOTe7cuQEoWrQoDRo04O677yYkJITq1aszfPhwChQo4HFKSeo0QiYiIuJXrVo19uzZw/jx4+nUqRNLly6laNGitGvXjoMHD3odT5IwFTIREZFoMmTIQGRkJAMHDuTHH3+kTZs2jBs3jqJFixIVFeV1PEmiVMhERERikDt3boYNG8b69evJkycPderUoVu3bowfP55169Z5HU+SEB1DJiIicg3FihXju+++47nnnuPNN98EIHXq1Lz11lukS5cOM+Pxxx8nNDTU46QSrFTIRERE4iBjxoyMGzeO7t27c/r0aVq3bs3zzz9/ef4ff/zBiy++6GFCCWbaZSkiIvIvFClShDvvvJPly5fz448/snv3bmrXrs2rr77KgQMHvI4nQUqFTERE5DqEhoZSrFgx8uTJw5AhQzhz5gx9+/a96rJ///13AqeTYKNCJiIicoMKFy5Mq1atGDVqFNu2baNv3740b96c119/nVy5cpEmTRpee+01/vzzT3bv3s2ZM2e8jiyJjDnnvM5w3SIiItyqVau8jhGr0NBQunbtSr9+/byOIiIiAbRr1y4KFy58eTQsQ4YMnDp1igceeIDUqVMzc+ZMUqVKxblz58icOTODBw8mMjISM/M4uSQUM1vtnIu42jwd1C8iIhIP8ubNy/fff8/XX39NiRIlqFKlCrt376Z48eKcP3+erl27YmYUK1aMjz76iFatWhEVFUXNmjUpUKAAZcqUIX369F6vhnhEI2QBphEyERG50sWLF+nXrx99+vS5fM/M1KlTc//991O3bl0efvhhcuXK5XFKiW+xjZDpGDIREZEEliJFCnr37s2xY8fYvn07s2bNon379vz00088/fTT5M2bl5deeok2bdowbNgwTp486XVkCbCgHCEzs7pA3UKFCrXZtm2b13FipREyERGJK+ccW7Zs4dVXX+Wzzz4jffr0nD59miJFijBz5kyKFCnidUS5AUluhMw5N9M51zYsLMzrKCIiIvHGzChevDiffvope/bs4fjx43zzzTccPXqUChUq8Oabb9KrVy8WLlx4eVenJA1BWchERESSMjMjd+7chISEUK1aNVauXEmePHno1q0b/fv3p1q1atxxxx2MGzeOc+fOeR1X4oEKmYiISCKXL18+Vq1axY4dOzhx4gQTJkwgVapUPPnkk9SpU4cNGzbw9ddfex1TboAKmYiISBBIlSoV+fLlI0OGDLRo0YK1a9cyYsQIvv76a0qVKkWNGjWYO3eu1zHlOuk6ZCIiIkHIzGjXrh0XLlxg586dREVF0bx5c/r06cOpU6coUaIEDz74IKlSpfI6qsSBCpmIiEgQ69ChAwDt2rWjSZMmPP/885fnZc2alcqVK3PnnXfSrVs3QkNDvYop16BCJiIikgQULFiQH374gY0bN5I7d26WLVvGxIkTWbduHZ9//jmLFi2iadOm7N+/n4cffphSpUp5HVmi0TFkIiIiSYSZUbJkSbJmzUqdOnX45JNP2LJlC6NGjWLlypW0adOGl19+mfLlyzNy5MjL7wvGa5ImNSpkIiIiSVzr1q05evQoP//8M3v27KFatWq0a9eOSpUqUbhwYTJkyMDzzz/PihUrOH/+vNdxkyXtshQREUkGUqZMSeHChQGYOXMmL7/8MgsWLKBEiRKUL1+eYcOGMXToUMLCwqhatSoFChQgS5YsvPTSS6RJk8bj9EmfCpmIiEgykzJlSvr37/+PaUOGDGHhwoV89dVXfP3110RFRXHmzBlmzJjBwoULyZgxo0dpkwftshQRERFy5MhBo0aNGDVqFDt27ODPP/9k2rRprF69moEDB3odL8nTCJmIiIhc1aOPPkrjxo0ZNGgQGTJkYNeuXRQtWpT27dvrEhrxTIVMREREYtS/f3+WL1/Of/7zH9KlS8eff/7JJ598wvz588mQIYPX8ZIM7bIUERGRGBUoUICdO3dy7Nixy/fRXLFiBTVq1GDgwIHs27fP64hJggqZiIiIXFPmzJkJCQmhRYsWjB07lr1799K1a1fy5s1Ls2bN2LFjh9cRg5oKmYiIiPwrkZGR7Nmzh19++YWOHTsyc+ZMqlSpws6dO72OFrRUyEREROS6FChQgHfeeYfFixdz7NgxChYsSJ06ddi6davX0YKOCpmIiIjckDJlyrBmzRp69OjB999/T9myZfn555+9jhVUVMhERETkhhUqVIjXX3+dDRs2kDp1alq0aMHff//tdaygoUImIiIi8ebWW2/l/fffZ+XKlXz00UdexwkaKmQiIiISrx577DHKlStH3759OXfunNdxgoIuDCsiIiLxyszo06cPderUoVWrVtxzzz2sWbOGjRs3cuTIEUqXLs1DDz1Es2bNdMV/P42QiYiISLyrVasWffv25eOPP6ZDhw7MmDGDdOnSUapUKZYvX84TTzxBu3btcM6xf/9+du/e7XVkT2mETEREROKdmdGzZ08eeeQRUqVKRcGCBTEzAJxz9OrVi/79+xMVFcW+ffswM5o0acLw4cPJnDmzt+E9oEImIiIiAVO8ePH/mWZmvP7666RKlYodO3ZQrFgx/vjjDwYNGsSqVavo3LkzTzzxBGnSpPEgsTdUyERERCTBpUiRgldeeeUf02rVqkX79u15+umnmT17NtOnT082x5jpGDIRERFJFO677z42b97MsGHDmDVrFvfeey+rV6/+159z9uzZoDu7U4VMREREEg0zo0OHDkyYMIHdu3dz//33s3nz5n/1GWFhYRQoUCBACQNDhUxEREQSnRYtWrB8+XLSpk1LhQoVePLJJ/n111/j9N6zZ8/y22+/BThh/FIhExERkUTp1ltvZdGiRTRp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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], "source": [ "# plot \n", "f, ax = plt.subplots(figsize=(10, 6))\n", From e6e64f801d7b335be65549172df16509f2f65bbd Mon Sep 17 00:00:00 2001 From: Ivo Date: Tue, 22 Feb 2022 10:07:55 -0500 Subject: [PATCH 12/18] Simpler test --- specreduce/extract.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/specreduce/extract.py b/specreduce/extract.py index d63cf59d..49183f41 100644 --- a/specreduce/extract.py +++ b/specreduce/extract.py @@ -157,13 +157,8 @@ def __call__(self, image, trace_object, disp_axis=1, crossdisp_axis=(0,)): # spatial axis to collapse. This should be handled by the API somehow. ext1d = np.sum(image * wimage, axis=crossdisp_axis) - # propagate image flux units into spectrum - unit = u.DN - if hasattr(image, 'unit') and image.unit is not None: - unit = image.unit - # 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', unit)) + flux=ext1d * getattr(image, 'unit', u.DN)) return spec From 038b1df03f65e77f45f1def11f09eb77b618cea5 Mon Sep 17 00:00:00 2001 From: Ivo Date: Tue, 22 Feb 2022 10:10:16 -0500 Subject: [PATCH 13/18] Add config setting that was removed for testing --- setup.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.cfg b/setup.cfg index fa4a830b..4095489c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -68,6 +68,7 @@ testpaths = "specreduce" "docs" astropy_header = true doctest_plus = enabled text_file_format = rst +addopts = --doctest-rst [coverage:run] omit = From 72d2bedbf63c770e671d092890fa0f22d07b61a4 Mon Sep 17 00:00:00 2001 From: Ivo Date: Tue, 22 Feb 2022 10:13:48 -0500 Subject: [PATCH 14/18] Fix doc string --- specreduce/extract.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/specreduce/extract.py b/specreduce/extract.py index 49183f41..9543733d 100644 --- a/specreduce/extract.py +++ b/specreduce/extract.py @@ -136,7 +136,8 @@ def __call__(self, image, trace_object, disp_axis=1, crossdisp_axis=(0,)): Returns ------- spec : `~specutils.Spectrum1D` - The extracted 1d spectrum expressed in DN and pixel units + The extracted 1d spectrum with flux expressed in the same + units as the input image, or u.DN, and pixel units """ # this check only applies to FlatTrace instances if hasattr(trace_object, 'trace_pos'): From e2c7f9c6e22e2fdb09e605f308863293b390da00 Mon Sep 17 00:00:00 2001 From: Ivo Date: Wed, 23 Feb 2022 12:36:48 -0500 Subject: [PATCH 15/18] Remove 3d code --- specreduce/extract.py | 70 ++++++++++++++----------------------------- 1 file changed, 22 insertions(+), 48 deletions(-) diff --git a/specreduce/extract.py b/specreduce/extract.py index 9543733d..81787ce2 100644 --- a/specreduce/extract.py +++ b/specreduce/extract.py @@ -18,29 +18,19 @@ def _get_boxcar_weights(center, hwidth, npix): """ weights = np.zeros((npix)) - # 2d - if type(npix) is not tuple: - # pixels with full weight - fullpixels = [max(0, int(center - hwidth + 1)), min(int(center + hwidth), npix)] - weights[fullpixels[0]:fullpixels[1]] = 1.0 - - # pixels at the edges of the boxcar with partial weight - if fullpixels[0] > 0: - w = hwidth - (center - fullpixels[0] + 0.5) - if w >= 0: - weights[fullpixels[0] - 1] = w - else: - weights[fullpixels[0]] = 1. + w - if fullpixels[1] < npix: - weights[fullpixels[1]] = hwidth - (fullpixels[1] - center - 0.5) - # 3d - else: - # pixels with full weight - fullpixels_x = [max(0, int(center[1] - hwidth + 1)), min(int(center[1] + hwidth), npix[1])] - fullpixels_y = [max(0, int(center[0] - hwidth + 1)), min(int(center[0] + hwidth), npix[0])] - weights[fullpixels_x[0]:fullpixels_x[1], fullpixels_y[0]:fullpixels_y[1]] = 1.0 - - # not yet handling pixels at the edges of the boxcar + # pixels with full weight + fullpixels = [max(0, int(center - hwidth + 1)), min(int(center + hwidth), npix)] + weights[fullpixels[0]:fullpixels[1]] = 1.0 + + # pixels at the edges of the boxcar with partial weight + if fullpixels[0] > 0: + w = hwidth - (center - fullpixels[0] + 0.5) + if w >= 0: + weights[fullpixels[0] - 1] = w + else: + weights[fullpixels[0]] = 1. + w + if fullpixels[1] < npix: + weights[fullpixels[1]] = hwidth - (fullpixels[1] - center - 0.5) return weights @@ -58,9 +48,9 @@ def _ap_weight_image(trace, width, disp_axis, crossdisp_axis, image_shape): width of extraction aperture in pixels disp_axis : int dispersion axis - crossdisp_axis : int (2D image) or tuple (3D image) + crossdisp_axis : int cross-dispersion axis - image_shape : tuple with 2 or 3 elements + image_shape : tuple with 2 elements size (shape) of image Returns @@ -70,26 +60,12 @@ def _ap_weight_image(trace, width, disp_axis, crossdisp_axis, image_shape): """ wimage = np.zeros(image_shape) hwidth = 0.5 * width - - if len(crossdisp_axis) == 1: - # 2d - image_sizes = image_shape[crossdisp_axis[0]] - else: - # 3d - image_shape_array = np.array(image_shape) - crossdisp_axis_array = np.array(crossdisp_axis) - image_sizes = image_shape_array[crossdisp_axis_array] - image_sizes = tuple(image_sizes.tolist()) + image_sizes = image_shape[crossdisp_axis[0]] # loop in dispersion direction and compute weights. for i in range(image_shape[disp_axis]): - if len(crossdisp_axis) == 1: - # 2d - # TODO trace must handle transposed data (disp_axis == 0) - wimage[:, i] = _get_boxcar_weights(trace[i], hwidth, image_sizes) - else: - # 3d - wimage[i, ::] = _get_boxcar_weights(trace[i], hwidth, image_sizes) + # TODO trace must handle transposed data (disp_axis == 0) + wimage[:, i] = _get_boxcar_weights(trace[i], hwidth, image_sizes) return wimage @@ -112,8 +88,7 @@ class BoxcarExtract(SpecreduceOperation): The extracted 1d spectrum expressed in DN and pixel units """ # TODO: what is a reasonable default? - # TODO: int or float? - width: int = 5 + width: float = 5. # TODO: should disp_axis and crossdisp_axis be defined in the Trace object? @@ -129,7 +104,7 @@ def __call__(self, image, trace_object, disp_axis=1, crossdisp_axis=(0,)): object with the trace disp_axis : int dispersion axis - crossdisp_axis : tuple (to support both 2D and 3D data) + crossdisp_axis : int cross-dispersion axis @@ -146,7 +121,7 @@ def __call__(self, image, trace_object, disp_axis=1, crossdisp_axis=(0,)): if getattr(self, attr) < 1: raise ValueError(f'{attr} must be >= 1') - # images to use for extraction + # weight image to use for extraction wimage = _ap_weight_image( trace_object, self.width, @@ -154,8 +129,7 @@ def __call__(self, image, trace_object, disp_axis=1, crossdisp_axis=(0,)): crossdisp_axis, image.shape) - # extract. Note that, for a cube, this is arbitrarily picking one of the - # spatial axis to collapse. This should be handled by the API somehow. + # extract ext1d = np.sum(image * wimage, axis=crossdisp_axis) # TODO: add wavelenght units, uncertainty and mask to spectrum1D object From 0efd1c6c5878233b62b0eb27d66e094a4739ac71 Mon Sep 17 00:00:00 2001 From: Ivo Date: Wed, 23 Feb 2022 12:50:09 -0500 Subject: [PATCH 16/18] Changes as per code review --- specreduce/extract.py | 31 +++++++++++++++++++------------ specreduce/tests/test_extract.py | 23 ++++++----------------- 2 files changed, 25 insertions(+), 29 deletions(-) diff --git a/specreduce/extract.py b/specreduce/extract.py index 81787ce2..68e8f7f5 100644 --- a/specreduce/extract.py +++ b/specreduce/extract.py @@ -14,12 +14,14 @@ def _get_boxcar_weights(center, hwidth, npix): """ - Compute weights given an aperture center, half width, and number of pixels + Compute weights given an aperture center, half width, + and number of pixels """ weights = np.zeros((npix)) # pixels with full weight - fullpixels = [max(0, int(center - hwidth + 1)), min(int(center + hwidth), npix)] + fullpixels = [max(0, int(center - hwidth + 1)), + min(int(center + hwidth), npix)] weights[fullpixels[0]:fullpixels[1]] = 1.0 # pixels at the edges of the boxcar with partial weight @@ -60,7 +62,7 @@ def _ap_weight_image(trace, width, disp_axis, crossdisp_axis, image_shape): """ wimage = np.zeros(image_shape) hwidth = 0.5 * width - image_sizes = image_shape[crossdisp_axis[0]] + image_sizes = image_shape[crossdisp_axis] # loop in dispersion direction and compute weights. for i in range(image_shape[disp_axis]): @@ -79,20 +81,25 @@ class BoxcarExtract(SpecreduceOperation): ---------- image : nddata-compatible image image with 2-D spectral image data + trace_object : Trace + trace object width : float width of extraction aperture in pixels + disp_axis : int + dispersion axis + crossdisp_axis : int + cross-dispersion axis Returns ------- spec : `~specutils.Spectrum1D` The extracted 1d spectrum expressed in DN and pixel units """ - # TODO: what is a reasonable default? - width: float = 5. # TODO: should disp_axis and crossdisp_axis be defined in the Trace object? - def __call__(self, image, trace_object, disp_axis=1, crossdisp_axis=(0,)): + def __call__(self, image, trace_object, width=5, + disp_axis=1, crossdisp_axis=0): """ Extract the 1D spectrum using the boxcar method. @@ -101,7 +108,9 @@ def __call__(self, image, trace_object, disp_axis=1, crossdisp_axis=(0,)): image : nddata-compatible image image with 2-D spectral image data trace_object : Trace - object with the trace + trace object + width : float + width of extraction aperture in pixels disp_axis : int dispersion axis crossdisp_axis : int @@ -116,15 +125,13 @@ def __call__(self, image, trace_object, disp_axis=1, crossdisp_axis=(0,)): """ # this check only applies to FlatTrace instances if hasattr(trace_object, 'trace_pos'): - self.center = trace_object.trace_pos - for attr in ['center', 'width']: - if getattr(self, attr) < 1: - raise ValueError(f'{attr} must be >= 1') + if trace_object.trace_pos < 1: + raise ValueError(f'{trace_object.trace_pos} must be >= 1') # weight image to use for extraction wimage = _ap_weight_image( trace_object, - self.width, + width, disp_axis, crossdisp_axis, image.shape) diff --git a/specreduce/tests/test_extract.py b/specreduce/tests/test_extract.py index 9415e8e3..55eb5af6 100644 --- a/specreduce/tests/test_extract.py +++ b/specreduce/tests/test_extract.py @@ -23,7 +23,6 @@ def test_extraction(): # boxcar = BoxcarExtract() trace = FlatTrace(image, 15.0) - boxcar.width = 5 spectrum = boxcar(image, trace) assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 75.)) @@ -37,32 +36,24 @@ def test_extraction(): spectrum = boxcar(image, trace) assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 73.5)) - boxcar.width = 6 - trace.set_position(15.0) - spectrum = boxcar(image, trace) + spectrum = boxcar(image, trace, width=6) assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 90.)) trace.set_position(14.5) - spectrum = boxcar(image, trace) + spectrum = boxcar(image, trace, width=6) assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 87.)) - boxcar.width = 4.5 - trace.set_position(15.0) - spectrum = boxcar(image, trace) + spectrum = boxcar(image, trace, width=4.5) assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 67.5)) - boxcar.width = 4.7 - trace.set_position(15.0) - spectrum = boxcar(image, trace) + spectrum = boxcar(image, trace, width=4.7) assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 70.5)) - boxcar.width = 4.7 - trace.set_position(14.3) - spectrum = boxcar(image, trace) + spectrum = boxcar(image, trace, width=4.7) assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 67.0)) @@ -72,9 +63,8 @@ def test_outside_image_condition(): # boxcar = BoxcarExtract() trace = FlatTrace(image, 3.0) - boxcar.width = 10. - spectrum = boxcar(image, trace) + spectrum = boxcar(image, trace, width=10.) assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 32.0)) @@ -84,7 +74,6 @@ def test_array_trace(): trace_array = np.ones_like(image[1]) * 15. trace = ArrayTrace(image, trace_array) - boxcar.width = 5 spectrum = boxcar(image, trace) assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 75.)) From e7f2060e3d1a9c9ab3c7259cb7e9cd829a3861c1 Mon Sep 17 00:00:00 2001 From: Ivo Date: Wed, 23 Feb 2022 13:03:31 -0500 Subject: [PATCH 17/18] Change notebook as per code review --- .../jwst_boxcar/boxcar_extraction.ipynb | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/notebook_sandbox/jwst_boxcar/boxcar_extraction.ipynb b/notebook_sandbox/jwst_boxcar/boxcar_extraction.ipynb index 9ff92e9b..1ec8e072 100644 --- a/notebook_sandbox/jwst_boxcar/boxcar_extraction.ipynb +++ b/notebook_sandbox/jwst_boxcar/boxcar_extraction.ipynb @@ -17,7 +17,7 @@ "\n", "Note that the extraction algorithm in the MIRI LRS extraction notebook performs simultaneous background subtraction when extracting from the source. Although it can only subtract the average of the two background extraction boxes. The original extraction code in `specreduce`'s `BoxcarExtract` class was capable of modeling the background with a polynomial along the cross-dispersion direction. This feature was lost in the conversion. \n", "\n", - "Note also that we cannot yet perform offline, after-the-fact background subtractions from spectra extracted with `BoxcarExtract`. The reason is that `BoxcarExtract` delivers its products in units of `DN` and `pixel`. Subsequent operations with such spectra, such as subtraction, are severely limited due to the `pixel` units." + "Note also that we cannot yet perform offline, after-the-fact background subtractions from spectra extracted with `BoxcarExtract`. The reason is that `BoxcarExtract` delivers its `Spectrum1D` product with `spectral_axis` in units of `pixel`. Subsequent operations with such spectra, such as subtraction, are severely limited due to the `pixel` units." ] }, { @@ -30,15 +30,12 @@ }, "outputs": [], "source": [ - "import os\n", - "\n", - "import numpy as np\n", - "\n", - "import matplotlib.pyplot as plt\n", - "import matplotlib as mpl\n", "from matplotlib.colors import LogNorm\n", "%matplotlib inline\n", "\n", + "from pathlib import Path\n", + "from zipfile import ZipFile\n", + "\n", "from astropy.io import fits\n", "from astropy.table import Table\n", "from astropy.visualization import simple_norm\n", @@ -49,11 +46,14 @@ "from specreduce.extract import BoxcarExtract\n", "from specreduce.tracing import FlatTrace\n", "\n", + "import os\n", + "import tempfile\n", + "\n", + "import numpy as np\n", "import ccdproc\n", "\n", - "from pathlib import Path\n", - "import tempfile\n", - "from zipfile import ZipFile" + "import matplotlib.pyplot as plt\n", + "import matplotlib as mpl" ] }, { @@ -209,9 +209,7 @@ "source": [ "# extract\n", "boxcar = BoxcarExtract()\n", - "\n", - "boxcar.width = ext_width\n", - "spectrum = boxcar(image, trace)" + "spectrum = boxcar(image, trace, width=ext_width)" ] }, { From 77b29a9cf2562a13f94f440c933808a067c9e2f2 Mon Sep 17 00:00:00 2001 From: Kyle Conroy Date: Thu, 24 Feb 2022 13:13:00 -0500 Subject: [PATCH 18/18] nest functions inside __call__ and replace hasattr with isinstance * in response to review comments --- specreduce/extract.py | 125 +++++++++++++++++++++--------------------- 1 file changed, 62 insertions(+), 63 deletions(-) diff --git a/specreduce/extract.py b/specreduce/extract.py index 68e8f7f5..0fec112b 100644 --- a/specreduce/extract.py +++ b/specreduce/extract.py @@ -7,71 +7,12 @@ from astropy import units as u from specreduce.core import SpecreduceOperation +from specreduce.tracing import FlatTrace from specutils import Spectrum1D __all__ = ['BoxcarExtract'] -def _get_boxcar_weights(center, hwidth, npix): - """ - Compute weights given an aperture center, half width, - and number of pixels - """ - weights = np.zeros((npix)) - - # pixels with full weight - fullpixels = [max(0, int(center - hwidth + 1)), - min(int(center + hwidth), npix)] - weights[fullpixels[0]:fullpixels[1]] = 1.0 - - # pixels at the edges of the boxcar with partial weight - if fullpixels[0] > 0: - w = hwidth - (center - fullpixels[0] + 0.5) - if w >= 0: - weights[fullpixels[0] - 1] = w - else: - weights[fullpixels[0]] = 1. + w - if fullpixels[1] < npix: - weights[fullpixels[1]] = hwidth - (fullpixels[1] - center - 0.5) - - return weights - - -def _ap_weight_image(trace, width, disp_axis, crossdisp_axis, image_shape): - - """ - Create a weight image that defines the desired extraction aperture. - - Parameters - ---------- - trace : Trace - trace object - width : float - width of extraction aperture in pixels - disp_axis : int - dispersion axis - crossdisp_axis : int - cross-dispersion axis - image_shape : tuple with 2 elements - size (shape) of image - - Returns - ------- - wimage : 2D image - weight image defining the aperture - """ - wimage = np.zeros(image_shape) - hwidth = 0.5 * width - image_sizes = image_shape[crossdisp_axis] - - # loop in dispersion direction and compute weights. - for i in range(image_shape[disp_axis]): - # TODO trace must handle transposed data (disp_axis == 0) - wimage[:, i] = _get_boxcar_weights(trace[i], hwidth, image_sizes) - - return wimage - - @dataclass class BoxcarExtract(SpecreduceOperation): """ @@ -123,10 +64,68 @@ def __call__(self, image, trace_object, width=5, The extracted 1d spectrum with flux expressed in the same units as the input image, or u.DN, and pixel units """ - # this check only applies to FlatTrace instances - if hasattr(trace_object, 'trace_pos'): + def _get_boxcar_weights(center, hwidth, npix): + """ + Compute weights given an aperture center, half width, + and number of pixels + """ + weights = np.zeros((npix)) + + # pixels with full weight + fullpixels = [max(0, int(center - hwidth + 1)), + min(int(center + hwidth), npix)] + weights[fullpixels[0]:fullpixels[1]] = 1.0 + + # pixels at the edges of the boxcar with partial weight + if fullpixels[0] > 0: + w = hwidth - (center - fullpixels[0] + 0.5) + if w >= 0: + weights[fullpixels[0] - 1] = w + else: + weights[fullpixels[0]] = 1. + w + if fullpixels[1] < npix: + weights[fullpixels[1]] = hwidth - (fullpixels[1] - center - 0.5) + + return weights + + def _ap_weight_image(trace, width, disp_axis, crossdisp_axis, image_shape): + + """ + Create a weight image that defines the desired extraction aperture. + + Parameters + ---------- + trace : Trace + trace object + width : float + width of extraction aperture in pixels + disp_axis : int + dispersion axis + crossdisp_axis : int + cross-dispersion axis + image_shape : tuple with 2 elements + size (shape) of image + + Returns + ------- + wimage : 2D image + weight image defining the aperture + """ + wimage = np.zeros(image_shape) + hwidth = 0.5 * width + image_sizes = image_shape[crossdisp_axis] + + # loop in dispersion direction and compute weights. + for i in range(image_shape[disp_axis]): + # TODO trace must handle transposed data (disp_axis == 0) + wimage[:, i] = _get_boxcar_weights(trace[i], hwidth, image_sizes) + + return wimage + + # TODO: this check can be removed if/when implemented as a check in FlatTrace + if isinstance(trace_object, FlatTrace): if trace_object.trace_pos < 1: - raise ValueError(f'{trace_object.trace_pos} must be >= 1') + raise ValueError('trace_object.trace_pos must be >= 1') # weight image to use for extraction wimage = _ap_weight_image(