Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KCWI scattered light #1661

Merged
merged 32 commits into from
Oct 1, 2023
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
dc1f11c
scattered light
rcooke-ast Jun 15, 2023
b095236
Merge branch 'gnirs_lifu' into kcwi_cleanse3
rcooke-ast Jun 15, 2023
11384cb
fix histogramdd
rcooke-ast Jun 15, 2023
c99ad7c
Merge branch 'gnirs_lifu' into kcwi_cleanse3
rcooke-ast Jun 17, 2023
55d2919
Merge branch 'arcresmap2' into kcwi_cleanse3
rcooke-ast Jul 5, 2023
0a9bf6f
Merge branch 'arcresmap2' into kcwi_cleanse3
rcooke-ast Aug 3, 2023
0df280e
Merge branch 'keck_kcrm' into kcwi_cleanse3
rcooke-ast Aug 11, 2023
0232a65
Merge branch 'keck_kcrm' into kcwi_cleanse3
rcooke-ast Aug 14, 2023
0e73c1e
Merge branch 'keck_kcrm' into kcwi_cleanse3
rcooke-ast Aug 15, 2023
2237bc0
typo
rcooke-ast Aug 17, 2023
b6a9c7b
temp saving
rcooke-ast Aug 18, 2023
17db695
Merge branch 'keck_kcrm' into kcwi_cleanse3
rcooke-ast Aug 26, 2023
a0b46f4
Merge branch 'develop' into kcwi_cleanse3
rcooke-ast Sep 3, 2023
f2ecd7a
binning docstring
rcooke-ast Sep 3, 2023
a5b97e9
add scattlight
rcooke-ast Sep 3, 2023
e2c0d45
add scattlight
rcooke-ast Sep 3, 2023
67db447
rm todo
rcooke-ast Sep 3, 2023
1f3a20b
fix kern order
rcooke-ast Sep 5, 2023
275b495
masked
rcooke-ast Sep 5, 2023
9e6d3b1
skysub fixes
rcooke-ast Sep 5, 2023
32a0eda
Merge branch 'develop' into kcwi_cleanse3
rcooke-ast Sep 27, 2023
cb82328
Merge remote-tracking branch 'origin/filesearch' into kcwi_cleanse3
rcooke-ast Sep 27, 2023
1a2618b
Addresses PR comments
rcooke-ast Sep 27, 2023
2af8198
minor fixes
Sep 27, 2023
b3351da
update docstring format
rcooke-ast Sep 27, 2023
369380d
update docstring format
rcooke-ast Sep 27, 2023
7fa8331
Merge branch 'tmpdelete' into kcwi_cleanse3
rcooke-ast Sep 27, 2023
4d19e01
add scattered light docs
rcooke-ast Sep 27, 2023
2f77823
Merge branch 'develop' into kcwi_cleanse3
rcooke-ast Sep 27, 2023
fb4b6c9
revert docs
rcooke-ast Sep 27, 2023
f144691
Merge branch 'develop' into kcwi_cleanse3
rcooke-ast Sep 30, 2023
9c27c69
Merge branch 'develop' into kcwi_cleanse3
rcooke-ast Oct 1, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pypeit/bspline/bspline.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ class bspline(datamodel.DataContainer):
Attributes
----------
breakpoints
Breakpoints for bspline, spacing for these breakpoints are determinated by keywords inputs;
Breakpoints for bspline, spacing for these breakpoints are determined by keywords inputs;
nord
Order of bspline; [default=4]
npoly
Expand Down
11 changes: 6 additions & 5 deletions pypeit/core/datacube.py
Original file line number Diff line number Diff line change
Expand Up @@ -1881,7 +1881,7 @@ def coadd_cube(files, opts, spectrograph=None, parset=None, overwrite=False):
except:
msgs.error("Could not load skysub image from spec2d file:" + msgs.newline() + cubepar['skysub_frame'])
skysub_default = cubepar['skysub_frame']
skyImgDef = spec2DObj.skymodel/skysub_exptime # Sky counts/second
skyImgDef = spec2DObj.sciimg/skysub_exptime # Sky counts/second
skySclDef = spec2DObj.scaleimg

# Load all spec2d files and prepare the data for making a datacube
Expand All @@ -1894,8 +1894,8 @@ def coadd_cube(files, opts, spectrograph=None, parset=None, overwrite=False):

# Load the header
hdr = spec2DObj.head0
ifu_ra = np.append(ifu_ra, spec.compound_meta([hdr], 'ra'))
ifu_dec = np.append(ifu_dec, spec.compound_meta([hdr], 'dec'))
ifu_ra = np.append(ifu_ra, spec.get_meta_value([hdr], 'ra'))
ifu_dec = np.append(ifu_dec, spec.get_meta_value([hdr], 'dec'))

# Get the exposure time
exptime = hdr['EXPTIME']
Expand Down Expand Up @@ -1933,7 +1933,7 @@ def coadd_cube(files, opts, spectrograph=None, parset=None, overwrite=False):
this_skysub = "image" # Use the current spec2d for sky subtraction
else:
skyImg = skyImgDef.copy() * exptime
skyScl = skySclDef.copy() * exptime
skyScl = skySclDef.copy()
this_skysub = skysub_default # Use the global value for sky subtraction
elif opts['skysub_frame'][ff].lower() == 'image':
skyImg = spec2DObj.skymodel
Expand All @@ -1953,7 +1953,8 @@ def coadd_cube(files, opts, spectrograph=None, parset=None, overwrite=False):
msgs.error("Could not load skysub image from spec2d file:" + msgs.newline() + opts['skysub_frame'][ff])
# TODO :: Consider allowing the actual frame (instead of the skymodel) to be used as the skysub image - make sure the BPM is carried over.
# :: Allow sky data fitting (i.e. scale the flux of a skysub frame to the science frame data)
skyImg = spec2DObj_sky.skymodel * exptime / skysub_exptime # Sky counts
skyImg = spec2DObj_sky.sciimg * exptime / skysub_exptime # Sky counts
# skyImg = spec2DObj_sky.skymodel * exptime / skysub_exptime # Sky counts
kbwestfall marked this conversation as resolved.
Show resolved Hide resolved
skyScl = spec2DObj_sky.scaleimg
this_skysub = opts['skysub_frame'][ff] # User specified spec2d for sky subtraction
if this_skysub == "none":
Expand Down
2 changes: 1 addition & 1 deletion pypeit/core/flat.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ def illum_profile_spectral_poly(rawimg, waveimg, slitmask, slitmask_trim, model,
gpm = gpmask if (gpmask is not None) else np.ones_like(rawimg, dtype=bool)
# Extract the list of spatial IDs from the slitmask
slitmask_spatid = np.unique(slitmask)
slitmask_spatid = np.sort(slitmask_spatid[slitmask_spatid != 0])
slitmask_spatid = np.sort(slitmask_spatid[slitmask_spatid > 0])
# Initialise the scale image that will be returned
scaleImg = np.ones_like(rawimg)
# Divide the slit into several bins and calculate the median of each bin
Expand Down
13 changes: 13 additions & 0 deletions pypeit/core/parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,19 @@ def parse_binning(binning:str):

Args:
binning (str, `numpy.ndarray`_, tuple):
The spectral and spatial binning. Several formats are supported, including
the following examples. Note that in all examples, the binning in the spectral
direction is 2, and the binning in the spatial direction is 1:

* string format
-- comma delimited string (e.g. '2,1')
-- x delimited string (e.g. '2x1')
-- space delimited string (e.g. '2 1')
-- 'None' will always assume 1x1 binning
* tuple format
-- this must be of the form of tuple, for example: (2,1)
* numpy array
-- this must be of the form of tuple, for example: np.array([2,1])
kbwestfall marked this conversation as resolved.
Show resolved Hide resolved

Returns:
tuple: binspectral, binspatial as integers
Expand Down
2 changes: 1 addition & 1 deletion pypeit/core/skysub.py
Original file line number Diff line number Diff line change
Expand Up @@ -1450,7 +1450,7 @@ def convolve_skymodel(input_img, fwhm_map, thismask, subpixel=5, nsample=10):
xkern = np.arange(kernsize, dtype=int) - midp
kern = np.exp(-0.5 * (xkern / kernwids[kk]) ** 2)
kern = kern / np.sum(kern)
conv_allkern[:, :, kk] = utils.rebinND(utils.convolve_fft(_input_img, _input_msk, kern), input_img.shape)
conv_allkern[:, :, kk] = utils.rebinND(utils.convolve_fft(_input_img, kern, _input_msk), input_img.shape)
rcooke-ast marked this conversation as resolved.
Show resolved Hide resolved

# Collect all of the images
msgs.info(f"Collating all convolution steps")
Expand Down
4 changes: 4 additions & 0 deletions pypeit/find_objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -1244,6 +1244,10 @@ def global_skysub(self, skymask=None, update_crmask=True, trim_edg=(0,0),
correction using the sky spectrum, if requested. See Reduce.global_skysub()
for parameter definitions.
"""
if self.par['reduce']['findobj']['skip_skysub']:
rcooke-ast marked this conversation as resolved.
Show resolved Hide resolved
msgs.info("Skipping global sky sub as per user request")
return np.zeros_like(self.sciImg.image)

rcooke-ast marked this conversation as resolved.
Show resolved Hide resolved
# Generate a global sky sub for all slits separately
global_sky_sep = super().global_skysub(skymask=skymask, update_crmask=update_crmask,
trim_edg=trim_edg, show_fit=show_fit, show=show,
Expand Down
28 changes: 26 additions & 2 deletions pypeit/images/rawimage.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ def __init__(self, ifile, spectrograph, det):
subtract_pattern=False,
subtract_overscan=False,
subtract_continuum=False,
subtract_scattlight=False,
trim=False,
orient=False,
subtract_bias=False,
Expand Down Expand Up @@ -633,6 +634,10 @@ def process(self, par, bpm=None, flatimages=None, bias=None, slits=None, dark=No
self.spat_flexure_shift = self.spatial_flexure_shift(slits) \
if self.par['spat_flexure_correct'] else None

# - Subtract scattered light... this needs to be done before flatfielding.
if self.par['subtract_scattlight']:
self.subtract_scattlight()

# Flat-field the data. This propagates the flat-fielding corrections to
# the variance. The returned bpm is propagated to the PypeItImage
# bitmask below.
Expand Down Expand Up @@ -1106,6 +1111,27 @@ def subtract_continuum(self, force=False):
#cont = ndimage.median_filter(self.image, size=(1,101,3), mode='reflect')
self.steps[step] = True

def subtract_scattlight(self):
"""
Analyze and subtract the scattered light from the image.

This is primarily a wrapper for
:func:`~pypeit.spectrograph.procimg.subtract_pattern`.
kbwestfall marked this conversation as resolved.
Show resolved Hide resolved

"""
step = inspect.stack()[0][3]
if self.steps[step]:
# Already pattern subtracted
msgs.warn("The scattered light has already been subtracted from the image!")
return

# Loop over the images
for ii in range(self.nimg):
binning = self.detector[0].binning
scatt_img = self.spectrograph.scattered_light(self.image[ii, :, :], binning)
self.image[ii, :, :] -= scatt_img
kbwestfall marked this conversation as resolved.
Show resolved Hide resolved
self.steps[step] = True

def trim(self, force=False):
"""
Trim image attributes to include only the science data.
Expand Down Expand Up @@ -1244,5 +1270,3 @@ def build_mosaic(self):
def __repr__(self):
return f'<{self.__class__.__name__}: file={self.filename}, nimg={self.nimg}, ' \
f'steps={self.steps}>'


13 changes: 10 additions & 3 deletions pypeit/par/pypeitpar.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,8 @@ def __init__(self, trim=None, apply_gain=None, orient=None,
dark_expscale=None,
empirical_rn=None, shot_noise=None, noise_floor=None,
use_pixelflat=None, use_illumflat=None, use_specillum=None,
use_pattern=None, subtract_continuum=None, spat_flexure_correct=None):
use_pattern=None, subtract_scattlight=None, subtract_continuum=None,
spat_flexure_correct=None):

# Grab the parameter names and values from the function
# arguments
Expand Down Expand Up @@ -298,6 +299,12 @@ def __init__(self, trim=None, apply_gain=None, orient=None,
'be set to True to combine arcs with multiple different lamps. ' \
'For all other cases, this parameter should probably be False.'

defaults['subtract_scattlight'] = False
dtypes['subtract_scattlight'] = bool
descr['subtract_scattlight'] = 'Subtract off the scattered light from an image. This parameter should only ' \
'be set to True for spectrographs that have dedicated methods to subtract ' \
'scattered light. For all other cases, this parameter should be False.'

defaults['empirical_rn'] = False
dtypes['empirical_rn'] = bool
descr['empirical_rn'] = 'If True, use the standard deviation in the overscan region to ' \
Expand Down Expand Up @@ -429,8 +436,8 @@ def __init__(self, trim=None, apply_gain=None, orient=None,
@classmethod
def from_dict(cls, cfg):
k = np.array([*cfg.keys()])
parkeys = ['trim', 'apply_gain', 'orient', 'use_biasimage', 'subtract_continuum', 'use_pattern',
'use_overscan', 'overscan_method', 'overscan_par', 'use_darkimage',
parkeys = ['trim', 'apply_gain', 'orient', 'use_biasimage', 'subtract_continuum', 'subtract_scattlight',
'use_pattern', 'use_overscan', 'overscan_method', 'overscan_par', 'use_darkimage',
'dark_expscale', 'spat_flexure_correct', 'use_illumflat', 'use_specillum',
'empirical_rn', 'shot_noise', 'noise_floor', 'use_pixelflat', 'combine',
'satpix', #'calib_setup_and_bit',
Expand Down
39 changes: 39 additions & 0 deletions pypeit/spectrographs/keck_kcwi.py
Original file line number Diff line number Diff line change
Expand Up @@ -886,6 +886,12 @@ def default_pypeit_par(cls):
par['calibrations']['illumflatframe']['process']['use_pattern'] = True
par['calibrations']['standardframe']['process']['use_pattern'] = True
par['scienceframe']['process']['use_pattern'] = True
# Subtract scattered light, but only for the pixel and illum flats,
# as well as and science/standard star data.
par['calibrations']['pixelflatframe']['process']['subtract_scattlight'] = True
par['calibrations']['illumflatframe']['process']['subtract_scattlight'] = True
par['calibrations']['standardframe']['process']['subtract_scattlight'] = True
par['scienceframe']['process']['subtract_scattlight'] = True

# Correct the illumflat for pixel-to-pixel sensitivity variations
par['calibrations']['illumflatframe']['process']['use_pixelflat'] = True
Expand Down Expand Up @@ -1017,6 +1023,39 @@ def get_rawimage(self, raw_file, det):
# Return
return detpar, raw_img, hdu, exptime, rawdatasec_img, oscansec_img

def scattered_light(self, frame, binning):
"""
Calculate a model of the scattered light of the input frame.

Parameters
----------
frame : `numpy.ndarray`_
Raw 2D data frame to be used to compute the scattered light.
binning : (str, `numpy.ndarray`_, tuple):
kbwestfall marked this conversation as resolved.
Show resolved Hide resolved
Binning of the frame (e.g. '2x1' refers to a binning of 2 in the spectral
direction, and a binning of 1 in the spatial direction). For the supported
formats, refer to `~pypeit.core.parse.parse_binning`.
kbwestfall marked this conversation as resolved.
Show resolved Hide resolved

Returns
-------
scatt_img : `numpy.ndarray`_
A 2D image of the scattered light determined from the input frame
"""
spatbin = parse.parse_binning(binning)[1]
ym = 4096 // (2 * spatbin)
y0 = ym - 180 // spatbin
y1 = ym + 180 // spatbin
scattlightl = np.nanmedian(frame[:, :20//spatbin], axis=1)[:, None]
scattlightr = np.nanmedian(frame[:, -40//spatbin:], axis=1)[:, None]
kbwestfall marked this conversation as resolved.
Show resolved Hide resolved
scattlight = np.nanmedian(frame[:, y0:y1], axis=1)[:, None]
medl = np.median(scattlightl / scattlight)
medr = np.median(scattlightr / scattlight)
spatimg = np.meshgrid(np.arange(frame.shape[1]), np.arange(frame.shape[0]))[0]
scatt_img = np.outer(scattlight, np.ones(frame.shape[1]))
scatt_img[spatimg < ym] *= 1 + (medl - 1) * (spatimg[spatimg < ym] / ym - 1) ** 2
scatt_img[spatimg >= ym] *= 1 + (medr - 1) * (spatimg[spatimg >= ym] / (4095//spatbin - ym) - ym / (4095//spatbin - ym)) ** 2
return scatt_img
kbwestfall marked this conversation as resolved.
Show resolved Hide resolved

def fit_2d_det_response(self, det_resp, gpmask):
r"""
Perform a 2D model fit to the KCWI detector response.
Expand Down
22 changes: 22 additions & 0 deletions pypeit/spectrographs/spectrograph.py
Original file line number Diff line number Diff line change
Expand Up @@ -1879,6 +1879,28 @@ def calc_pattern_freq(self, frame, rawdatasec_img, oscansec_img, hdu):
msgs.info("Pattern noise removal is not implemented for spectrograph {0:s}".format(self.name))
return []

def scattered_light(self, frame, binning):
"""
Calculate a model of the scattered light of the input frame.

Parameters
----------
frame : `numpy.ndarray`_
Raw 2D data frame to be used to compute the scattered light.
binning : (str, `numpy.ndarray`_, tuple):
Binning of the frame (e.g. '2x1' refers to a binning of 2 in the spectral
direction, and a binning of 1 in the spatial direction). For the supported
formats, refer to `~pypeit.core.parse.parse_binning`.
kbwestfall marked this conversation as resolved.
Show resolved Hide resolved

Returns
-------
scatt_img : `numpy.ndarray`_, float
A 2D image of the scattered light determined from the input frame.
Alternatively, if a constant value is used, a constant floating point
value can be returned as well.
"""
msgs.info("Scattered light removal is not implemented for spectrograph {0:s}".format(self.name))
return 0.0

def __repr__(self):
"""Return a string representation of the instance."""
Expand Down