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

Iterate object tracing #1882

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
26 changes: 26 additions & 0 deletions doc/object_finding.rst
Original file line number Diff line number Diff line change
Expand Up @@ -138,4 +138,30 @@ vs spatial position vector. The best way to choose these pixels is to run PypeIt
without it set. Then run :ref:`pypeit_show_2dspec` to view the sky-subtracted
image and decide which pixels to use for object finding. Then re-run ``PypeIt``.

Object Tracing
==============

For automatically identified objects (i.e., not manual extractions),
PypeIt improves the object trace by fitting the spatial position of the peak
as a function of wavelength. In some situations, the object trace is poorly
determined by the peak location, and the code will fail to trace the object
correctly. For example, if the slit edges are not well-defined, the object's
position relative to the slit edges is also poorly defined, and the object trace
is difficult to determine. The default is to perform several iterations (typically 9)
but for some cases this is insufficient. In these cases, the user can attempt to
increase the number of iterations to improve the object tracing, in combination with
a relatively low order polynomial, as follows

.. code-block:: ini

[reduce]
[[findobj]]
find_numiterfit = 100
trace_npoly = 4

Note that the default value is typically ``trace_npoly=5``. If you notice a relatively poor object trace, sometimes in
combination with the object counts being masked, increasing the number of iterations may help to
resolve your problem. If, on the other hand, your object is relatively faint, you
may benefit from using the trace of a standard star (this is the default behaviour),
and you can provide a 1D spectrum of a previously reduced standard star with the
``std_spec1d`` parameter.
2 changes: 2 additions & 0 deletions doc/releases/1.17.2dev.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ Functionality/Performance Improvements and Additions
and `spat_flexure_vrange`, were added to control the detection of the slit edges
(used to compute the flexure) and the stretching of the image in the QA plot,
respectively.
- The object trace can now be iterated over with the `find_numiterfit`
parameter.

Instrument-specific Updates
---------------------------
Expand Down
1 change: 1 addition & 0 deletions pypeit/coadd2d.py
Original file line number Diff line number Diff line change
Expand Up @@ -1416,6 +1416,7 @@ def compute_offsets(self, offsets):
inmask=inmask[iexp,:,:], fwhm=self.par['reduce']['findobj']['find_fwhm'],
trim_edg=self.par['reduce']['findobj']['find_trim_edge'],
maxdev=self.par['reduce']['findobj']['find_maxdev'],
numiterfit=self.par['reduce']['findobj']['find_numiterfit'],
ncoeff=3, snr_thresh=self.par['reduce']['findobj']['snr_thresh'], nperslit=1,
find_min_max=self.par['reduce']['findobj']['find_min_max'],
show_trace=self.debug_offsets, show_peaks=self.debug_offsets)
Expand Down
26 changes: 17 additions & 9 deletions pypeit/core/findobj_skymask.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ def ech_findobj_ineach_order(
det='DET01', inmask=None, std_trace=None, ncoeff=5,
hand_extract_dict=None,
box_radius=2.0, fwhm=3.0,
use_user_fwhm=False, maxdev=2.0, nperorder=2,
use_user_fwhm=False, maxdev=2.0, nperorder=2, numiterfit=9,
extract_maskwidth=3.0, snr_thresh=10.0,
specobj_dict=None, trim_edg=(5,5),
show_peaks=False, show_single_fits=False,
Expand Down Expand Up @@ -260,6 +260,8 @@ def ech_findobj_ineach_order(
maxdev (:obj:`float`, optional):
Maximum deviation of pixels from polynomial fit to trace
used to reject bad pixels in trace fitting.
numiterfit (:obj:`int`, optional):
Number of iterations to use when fitting the object traces.
nperorder (:obj:`int`, optional):
Maximum number of objects allowed per order. If there are more
detections than this number, the code will select the ``nperorder``
Expand Down Expand Up @@ -331,7 +333,7 @@ def ech_findobj_ineach_order(
spec_min_max=spec_min_max[:,iord],
inmask=inmask_iord,std_trace=std_in,
ncoeff=ncoeff, fwhm=fwhm, use_user_fwhm=use_user_fwhm, maxdev=maxdev,
hand_extract_dict=hand_extract_dict,
numiterfit=numiterfit, hand_extract_dict=hand_extract_dict,
nperslit=nperorder, extract_maskwidth=extract_maskwidth,
snr_thresh=snr_thresh, trim_edg=trim_edg,
boxcar_rad=box_radius/plate_scale_ord[iord],
Expand Down Expand Up @@ -1038,7 +1040,7 @@ def ech_objfind(image, ivar, slitmask, slit_left, slit_righ, slit_spat_id, order
nabove_min_snr=2, pca_explained_var=99.0,
box_radius=2.0, fwhm=3.0,
use_user_fwhm=False, maxdev=2.0,
nperorder=2,
nperorder=2, numiterfit=9,
extract_maskwidth=3.0, snr_thresh=10.0,
specobj_dict=None, trim_edg=(5,5),
show_peaks=False, show_fits=False,
Expand Down Expand Up @@ -1181,6 +1183,8 @@ def ech_objfind(image, ivar, slitmask, slit_left, slit_righ, slit_spat_id, order
maxdev (:obj:`float`, optional):
Maximum deviation of pixels from polynomial fit to trace
used to reject bad pixels in trace fitting.
numiterfit (:obj:`int`, optional):
Number of iterations to perform when building the trace fits.
hand_extract_dict (:obj:`dict`, optional):
Dictionary with info on manual extraction; see
:class:`~pypeit.manual_extract.ManualExtractionObj`.
Expand Down Expand Up @@ -1290,6 +1294,7 @@ def ech_objfind(image, ivar, slitmask, slit_left, slit_righ, slit_spat_id, order
use_user_fwhm=use_user_fwhm,
nperorder=nperorder,
maxdev=maxdev,
numiterfit=numiterfit,
box_radius=box_radius,
objfindQA_filename=objfindQA_filename,
hand_extract_dict=manual_extract_dict)
Expand Down Expand Up @@ -1500,7 +1505,7 @@ def get_fwhm(fwhm_in, nsamp, smash_peakflux, spat_fracpos, flux_smash_smth):
def objs_in_slit(image, ivar, thismask, slit_left, slit_righ,
inmask=None, fwhm=3.0,
sigclip_smash=5.0, use_user_fwhm=False, boxcar_rad=7.,
maxdev=2.0, spec_min_max=None, hand_extract_dict=None, std_trace=None,
maxdev=2.0, numiterfit=9, spec_min_max=None, hand_extract_dict=None, std_trace=None,
ncoeff=5, nperslit=None, snr_thresh=10.0, trim_edg=(5,5),
extract_maskwidth=4.0, specobj_dict=None, find_min_max=None,
show_peaks=False, show_fits=False, show_trace=False,
Expand Down Expand Up @@ -1588,6 +1593,8 @@ def objs_in_slit(image, ivar, thismask, slit_left, slit_righ,
maxdev (:obj:`float`, optional):
Maximum deviation of pixels from polynomial fit to trace
used to reject bad pixels in trace fitting.
numiterfit (:obj:`int`, optional):
Number of iterations to use in the iterative trace fitting.
spec_min_max (:obj:`tuple`, optional):
2-tuple defining the minimum and maximum pixel in the spectral
direction with useable data for this slit/order. If None, the
Expand Down Expand Up @@ -1667,9 +1674,9 @@ def objs_in_slit(image, ivar, thismask, slit_left, slit_righ,
detected.
"""

#debug_all=True
debug_all = False
if debug_all:
show_peaks=True
show_peaks = True
show_fits = True
show_trace = True

Expand Down Expand Up @@ -1904,17 +1911,18 @@ def objs_in_slit(image, ivar, thismask, slit_left, slit_righ,
msgs.info("Automatic finding routine found {0:d} objects".format(len(sobjs)))

# Fit the object traces
tolerance = 0.1 # Tolerance in pixels before the trace fit has converged
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line should be removed right, tolerance since it is no longer used?

if len(sobjs) > 0:
msgs.info('Fitting the object traces')
msgs.info('Fitting the traces')
# Note the transpose is here to pass in the TRACE_SPAT correctly.
xinit_fweight = np.copy(sobjs.TRACE_SPAT.T).astype(float)
spec_mask = (spec_vec >= spec_min_max_out[0]) & (spec_vec <= spec_min_max_out[1])
trc_inmask = np.outer(spec_mask, np.ones(len(sobjs), dtype=bool))
xfit_fweight = fit_trace(image, xinit_fweight, ncoeff, bpm=np.invert(inmask), maxshift=1.,
xfit_fweight = fit_trace(image, xinit_fweight, ncoeff, bpm=np.invert(inmask), maxshift=1., niter=numiterfit,
trace_bpm=np.invert(trc_inmask), fwhm=fwhm, maxdev=maxdev,
idx=sobjs.NAME, debug=show_fits)[0]
xinit_gweight = np.copy(xfit_fweight)
xfit_gweight = fit_trace(image, xinit_gweight, ncoeff, bpm=np.invert(inmask), maxshift=1.,
xfit_gweight = fit_trace(image, xinit_gweight, ncoeff, bpm=np.invert(inmask), maxshift=1., niter=numiterfit,
trace_bpm=np.invert(trc_inmask), fwhm=fwhm, maxdev=maxdev,
weighting='gaussian', idx=sobjs.NAME, debug=show_fits)[0]

Expand Down
2 changes: 2 additions & 0 deletions pypeit/find_objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -819,6 +819,7 @@ def find_objects_pypeline(self, image, ivar, std_trace=None,
use_user_fwhm=self.par['reduce']['extraction']['use_user_fwhm'],
boxcar_rad=self.par['reduce']['extraction']['boxcar_radius'] / self.get_platescale(), #pixels
maxdev=self.par['reduce']['findobj']['find_maxdev'],
numiterfit=self.par['reduce']['findobj']['find_numiterfit'],
find_min_max=self.par['reduce']['findobj']['find_min_max'],
extract_maskwidth=self.par['reduce']['skysub']['local_maskwidth'],
qa_title=qa_title, nperslit=maxnumber,
Expand Down Expand Up @@ -959,6 +960,7 @@ def find_objects_pypeline(self, image, ivar, std_trace=None,
use_user_fwhm=self.par['reduce']['extraction']['use_user_fwhm'],
fof_link = self.par['reduce']['findobj']['fof_link'],
maxdev=self.par['reduce']['findobj']['find_maxdev'],
numiterfit=self.par['reduce']['findobj']['find_numiterfit'],
nperorder=nperorder,
max_snr=self.par['reduce']['findobj']['ech_find_max_snr'],
min_snr=self.par['reduce']['findobj']['ech_find_min_snr'],
Expand Down
8 changes: 6 additions & 2 deletions pypeit/par/pypeitpar.py
Original file line number Diff line number Diff line change
Expand Up @@ -4161,7 +4161,7 @@ class FindObjPar(ParSet):

def __init__(self, trace_npoly=None, snr_thresh=None, find_trim_edge=None,
find_maxdev=None, find_extrap_npoly=None, maxnumber_sci=None, maxnumber_std=None,
find_fwhm=None, ech_find_max_snr=None, ech_find_min_snr=None,
find_fwhm=None, ech_find_max_snr=None, ech_find_min_snr=None, find_numiterfit=None,
ech_find_nabove_min_snr=None, skip_second_find=None, skip_final_global=None,
skip_skysub=None, find_negative=None, find_min_max=None, std_spec1d=None,
use_std_trace=None, fof_link = None):
Expand Down Expand Up @@ -4221,6 +4221,10 @@ def __init__(self, trace_npoly=None, snr_thresh=None, find_trim_edge=None,
dtypes['find_maxdev'] = [int, float]
descr['find_maxdev'] = 'Maximum deviation of pixels from polynomial fit to trace used to reject bad pixels in trace fitting.'

defaults['find_numiterfit'] = 9
dtypes['find_numiterfit'] = int
descr['find_numiterfit'] = 'Number of iterations to perform on the trace fitting.'

defaults['find_fwhm'] = 5.0
dtypes['find_fwhm'] = [int, float]
descr['find_fwhm'] = 'Indicates roughly the fwhm of objects in pixels for object finding'
Expand Down Expand Up @@ -4319,7 +4323,7 @@ def from_dict(cls, cfg):
# Basic keywords
parkeys = ['trace_npoly', 'snr_thresh', 'find_trim_edge',
'find_extrap_npoly', 'maxnumber_sci', 'maxnumber_std',
'find_maxdev', 'find_fwhm', 'ech_find_max_snr',
'find_maxdev', 'find_numiterfit', 'find_fwhm', 'ech_find_max_snr',
'ech_find_min_snr', 'ech_find_nabove_min_snr', 'skip_second_find',
'skip_final_global', 'skip_skysub', 'find_negative', 'find_min_max',
'std_spec1d', 'use_std_trace', 'fof_link']
Expand Down
Loading