Skip to content

Commit

Permalink
corrected spatial flexure in flatfield
Browse files Browse the repository at this point in the history
  • Loading branch information
rcooke-ast committed Sep 11, 2024
1 parent 6bfa9fa commit 13daa62
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 32 deletions.
2 changes: 1 addition & 1 deletion deprecated/find_objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ def illum_profile_spectral(self, global_sky, skymask=None):
# relative spectral sensitivity is calculated at a given wavelength for all slits simultaneously.
scaleImg = flatfield.illum_profile_spectral(self.sciImg.image.copy(), self.waveimg, self.slits,
slit_illum_ref_idx=sl_ref, model=global_sky, gpmask=gpm,
skymask=skymask, trim=trim, flexure=self.spat_flexure_shift,
skymask=skymask, trim=trim, spat_flexure=self.spat_flexure_shift,
smooth_npix=smooth_npix)
# Now apply the correction to the science frame
self.apply_relative_scale(scaleImg)
Expand Down
2 changes: 1 addition & 1 deletion deprecated/reduce.py
Original file line number Diff line number Diff line change
Expand Up @@ -1701,7 +1701,7 @@ def illum_profile_spectral(self, global_sky, skymask=None):
gpm = self.sciImg.select_flag(invert=True)
scaleImg = flatfield.illum_profile_spectral(self.sciImg.image.copy(), self.waveimg, self.slits,
slit_illum_ref_idx=ref_idx, model=global_sky, gpmask=gpm,
skymask=skymask, trim=trim, flexure=self.spat_flexure_shift)
skymask=skymask, trim=trim, spat_flexure=self.spat_flexure_shift)
# Now apply the correction to the science frame
self.apply_relative_scale(scaleImg)

Expand Down
2 changes: 1 addition & 1 deletion pypeit/coadd2d.py
Original file line number Diff line number Diff line change
Expand Up @@ -838,7 +838,7 @@ def reduce(self, pseudo_dict, show=False, clear_ginga=True, show_peaks=False, sh
platescale = sciImage.detector.platescale * self.spat_samp_fact

# Assign slitmask design information to detected objects
slits.assign_maskinfo(sobjs_obj, platescale, None, TOLER=parcopy['reduce']['slitmask']['obj_toler'])
slits.assign_maskinfo(sobjs_obj, platescale, None, tolerance=parcopy['reduce']['slitmask']['obj_toler'])

if parcopy['reduce']['slitmask']['extract_missing_objs'] is True:
# Set the FWHM for the extraction of missing objects
Expand Down
2 changes: 1 addition & 1 deletion pypeit/coadd3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -846,7 +846,7 @@ def add_grating_corr(self, flatfile, waveimg, slits, spat_flexure=None):
scale_model = flatfield.illum_profile_spectral(flatframe, waveimg, slits,
slit_illum_ref_idx=self.flatpar['slit_illum_ref_idx'],
model=None, trim=self.flatpar['slit_trim'],
flexure=spat_flexure,
spat_flexure=spat_flexure,
smooth_npix=self.flatpar['slit_illum_smooth_npix'])
else:
msgs.info("Using relative spectral illumination from FlatImages")
Expand Down
46 changes: 22 additions & 24 deletions pypeit/flatfield.py
Original file line number Diff line number Diff line change
Expand Up @@ -856,10 +856,6 @@ def fit(self, spat_illum_only=False, doqa=True, debug=False):
npoly = self.flatpar['twod_fit_npoly']
saturated_slits = self.flatpar['saturated_slits']

# Build wavelength image -- not always used, but for convenience done here
# TODO :: This was deleted in a recent PR -- figure out why? I think it was moved to the init method
if self.waveimg is None: self.build_waveimg()

# Setup images
nspec, nspat = self.rawflatimg.image.shape
rawflat = self.rawflatimg.image
Expand Down Expand Up @@ -1487,8 +1483,8 @@ def spatial_fit_finecorr(self, normed, onslit_tweak, slit_idx, slit_spat, gpm,
onslit_tweak_trim = self.slits.slit_img(pad=-slit_trim, slitidx=slit_idx, initial=False) == slit_spat
# Setup
slitimg = (slit_spat + 1) * onslit_tweak.astype(int) - 1 # Need to +1 and -1 so that slitimg=-1 when off the slit
# TODO :: need to fix the 0.0 value on the next line, and the same one a few lines below.
left, right, msk = self.slits.select_edges(spat_flexure=self.wavetilts.spat_flexure if self.wavetilts is not None else 0.0)
spat_flexure = self.wavetilts.spat_flexure if self.wavetilts is not None else np.zeros((self.slits.nslits, 2))
left, right, msk = self.slits.select_edges(spat_flexure=spat_flexure)
this_left = left[:, slit_idx]
this_right = right[:, slit_idx]
slitlen = int(np.median(this_right - this_left))
Expand All @@ -1498,7 +1494,7 @@ def spatial_fit_finecorr(self, normed, onslit_tweak, slit_idx, slit_spat, gpm,
this_wave = self.waveimg[this_slit]
xpos_img = self.slits.spatial_coordinate_image(slitidx=slit_idx,
slitid_img=slitimg,
spat_flexure=self.wavetilts.spat_flexure if self.wavetilts is not None else 0.0)
spat_flexure=spat_flexure)
# Generate the trimmed versions for fitting
this_slit_trim = np.where(onslit_tweak_trim & self.rawflatimg.select_flag(invert=True))
this_wave_trim = self.waveimg[this_slit_trim]
Expand Down Expand Up @@ -1595,11 +1591,11 @@ def extract_structure(self, rawflat_orig, slit_trim=3):
# Now fit the spectral profile
# TODO: Should this be *any* flag, or just BPM?
gpm = self.rawflatimg.select_flag(flag='BPM', invert=True)
# TODO :: Need to fix the flexure 0.0 value below, and also rename this argument to spat_flexure for consistency
spat_flexure = self.wavetilts.spat_flexure if self.wavetilts is not None else np.zeros((self.slits.nslits, 2))
scale_model = illum_profile_spectral(rawflat, self.waveimg, self.slits,
slit_illum_ref_idx=self.flatpar['slit_illum_ref_idx'],
model=None, gpmask=gpm, skymask=None, trim=self.flatpar['slit_trim'],
flexure=self.wavetilts.spat_flexure if self.wavetilts is not None else 0.0,
spat_flexure=spat_flexure,
smooth_npix=self.flatpar['slit_illum_smooth_npix'])
# Trim the edges by a few pixels to avoid edge effects
onslits_trim = gpm & (self.slits.slit_img(pad=-slit_trim, initial=False) != -1)
Expand Down Expand Up @@ -1648,8 +1644,7 @@ def spectral_illumination(self, gpm=None, debug=False):
# check if the waveimg is available
if self.waveimg is None:
msgs.warn("Cannot perform the spectral illumination without the wavelength image.")
# TODO :: Should this really be None? Probably it should be ones.
return None
return np.ones_like(self.rawflatimg.image)
msgs.info('Performing a joint fit to the flat-field response')
# Grab some parameters
trim = self.flatpar['slit_trim']
Expand All @@ -1660,13 +1655,11 @@ def spectral_illumination(self, gpm=None, debug=False):
gpm = self.rawflatimg.select_flag(flag='BPM', invert=True)

# Obtain relative spectral illumination
# TODO :: fix the 0.0 value for the flexure argument. Also, rename flexure to spat_flexure for consistency
spat_flexure = self.wavetilts.spat_flexure if self.wavetilts is not None else np.zeros((self.slits.nslits, 2))
return illum_profile_spectral(rawflat, self.waveimg, self.slits,
slit_illum_ref_idx=self.flatpar['slit_illum_ref_idx'],
model=None, gpmask=gpm, skymask=None, trim=trim,
flexure=self.wavetilts.spat_flexure if self.wavetilts is not None else 0.0,
smooth_npix=self.flatpar['slit_illum_smooth_npix'],
debug=debug)
model=None, gpmask=gpm, skymask=None, trim=trim, spat_flexure=spat_flexure,
smooth_npix=self.flatpar['slit_illum_smooth_npix'], debug=debug)

def tweak_slit_edges(self, left, right, spat_coo, norm_flat, method='threshold', thresh=0.93,
maxfrac=0.1, debug=False):
Expand Down Expand Up @@ -2164,7 +2157,7 @@ def show_flats(image_list, wcs_match=True, slits=None, waveimg=None):

# TODO :: This could possibly be moved to core.flat
def illum_profile_spectral(rawimg, waveimg, slits, slit_illum_ref_idx=0, smooth_npix=None, polydeg=None,
model=None, gpmask=None, skymask=None, trim=3, flexure=None, maxiter=5, debug=False):
model=None, gpmask=None, skymask=None, trim=3, spat_flexure=None, maxiter=5, debug=False):
"""
Determine the relative spectral illumination of all slits.
Currently only used for image slicer IFUs.
Expand All @@ -2184,17 +2177,22 @@ def illum_profile_spectral(rawimg, waveimg, slits, slit_illum_ref_idx=0, smooth_
polydeg : int, optional
Degree of polynomial to be used for determining relative spectral sensitivity. If None,
coadd.smooth_weights will be used, with the smoothing length set to smooth_npix.
model : `numpy.ndarray`_, None
model : `numpy.ndarray`_, optional
A model of the rawimg data. If None, rawimg will be used.
gpmask : `numpy.ndarray`_, None
gpmask : `numpy.ndarray`_, optional
Good pixel mask
skymask : `numpy.ndarray`_, None
skymask : `numpy.ndarray`_, optional
Sky mask
trim : int
Number of pixels to trim from the edges of the slit
when deriving the spectral illumination
flexure : float, None
Spatial flexure
spat_flexure : `numpy.ndarray`_, optional
If provided, this is the shift, in spatial pixels, to
apply to each slit. This is used to correct for spatial
flexure. The shape of the array should be (nslits, 2),
where the first column is the shift to apply to the
left edge of each slit and the second column is the
shift to apply to the right edge of each slit.
maxiter : :obj:`int`
Maximum number of iterations to perform
debug : :obj:`bool`
Expand All @@ -2215,8 +2213,8 @@ def illum_profile_spectral(rawimg, waveimg, slits, slit_illum_ref_idx=0, smooth_
gpm = gpmask if (gpmask is not None) else np.ones_like(rawimg, dtype=bool)
modelimg = model if (model is not None) else rawimg.copy()
# Setup the slits
slitid_img = slits.slit_img(pad=0, spat_flexure=flexure)
slitid_img_trim = slits.slit_img(pad=-trim, spat_flexure=flexure)
slitid_img = slits.slit_img(pad=0, spat_flexure=spat_flexure)
slitid_img_trim = slits.slit_img(pad=-trim, spat_flexure=spat_flexure)
scaleImg = np.ones_like(rawimg)
modelimg_copy = modelimg.copy()
# Obtain the minimum and maximum wavelength of all slits
Expand Down
8 changes: 4 additions & 4 deletions pypeit/slittrace.py
Original file line number Diff line number Diff line change
Expand Up @@ -1011,7 +1011,7 @@ def mask_add_missing_obj(self, sobjs, spat_flexure, fwhm, boxcar_rad):
# Return
return sobjs

def assign_maskinfo(self, sobjs, plate_scale, spat_flexure, TOLER=1.):
def assign_maskinfo(self, sobjs, plate_scale, spat_flexure, tolerance=1.):
"""
Assign RA, DEC, Name to objects.
Modified in place.
Expand All @@ -1030,7 +1030,7 @@ def assign_maskinfo(self, sobjs, plate_scale, spat_flexure, TOLER=1.):
shift to apply to the right edge of each slit.
det_buffer (:obj:`int`):
Minimum separation between detector edges and a slit edge.
TOLER (:obj:`float`, optional):
tolerance (:obj:`float`, optional):
Matching tolerance in arcsec.
Returns:
Expand Down Expand Up @@ -1124,7 +1124,7 @@ def assign_maskinfo(self, sobjs, plate_scale, spat_flexure, TOLER=1.):
obj_fwhm = cut_sobjs[ipeak].FWHM*plate_scale
else:
obj_fwhm = 0.
in_toler = np.abs(separ*plate_scale) < (TOLER + cc_rms + obj_fwhm/2)
in_toler = np.abs(separ*plate_scale) < (tolerance + cc_rms + obj_fwhm / 2)
if np.any(in_toler):
# Find positive peakflux
peak_flux = cut_sobjs[idx].smash_peakflux[in_toler]
Expand Down Expand Up @@ -1780,7 +1780,7 @@ def assign_addobjs_alldets(sobjs, calib_slits, spat_flexure, platescale, slitmas
if calib_slits[i].maskdef_designtab is not None:
# Assign slitmask design information to detected objects
sobjs = calib_slits[i].assign_maskinfo(sobjs, platescale[i], spat_flexure[i],
TOLER=slitmask_par['obj_toler'])
tolerance=slitmask_par['obj_toler'])

if slitmask_par['extract_missing_objs']:
# Set the FWHM for the extraction of missing objects
Expand Down

0 comments on commit 13daa62

Please sign in to comment.