Skip to content

Wavelength template line detection - #2133

Open
kbwestfall wants to merge 16 commits into
developfrom
arxiv_line_detect
Open

Wavelength template line detection#2133
kbwestfall wants to merge 16 commits into
developfrom
arxiv_line_detect

Conversation

@kbwestfall

@kbwestfall kbwestfall commented May 22, 2026

Copy link
Copy Markdown
Collaborator

I wanted to reduce the data in the RAW_DATA/keck_deimos/830G_L_8410 directory as a way of producing a test for flux calibration that would use the multi_spec_det option. Wavelength calibration on detector 3 was failing because pypeit.core.wavecal.wvutils.arc_lines_from_spec was not detecting lines in the template spectrum keck_deimos_830G.fits. This is because the FWHM is too small. I.e., the FWHM of the observed data is smaller than in the template, which is causing the lines in the template to be rejected.

This is a short term fix that adds a loop that iteratively increments the FWHM until the number of good template lines reaches some minimum fraction of all lines detected. This works for this data set, but we'll need to run the dev-suite to check how this affects other instruments.

In the longer term, I think we should

  • only detect the lines in the template once
  • or, better yet, require that the pixel and wavelength coordinates of the lines used in calibrating the template be included in the template file. I.e., we shouldn't need to re-detect the lines.

The primary changes are in pypeit.core.wavecal.wvutils.arc_lines_from_spec and pypeit.core.wavecal.autoid.reidentify. Particularly for the latter, I took the opportunity to clean-up the code and docs a bit.

@kbwestfall kbwestfall added the bug Bug fix. label May 22, 2026
@kbwestfall
kbwestfall requested review from profxj and tbowers7 May 22, 2026 00:25

@profxj profxj left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Excellent addition. I might give Debora a head's up about it too
If you haven't already

Comment thread pypeit/core/wavecal/autoid.py
Comment thread pypeit/core/wavecal/autoid.py
@tbowers7 tbowers7 added this to the v2.1.0 milestone Jun 1, 2026

@tbowers7 tbowers7 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for figuring out this issue. There is only one place that needs an actual change -- the rest are questions and comments. Approving now.

Comment thread pypeit/core/wavecal/autoid.py
Comment on lines +584 to +586
# NOTE: I've hard-coded the values for good_frac, fwhm_incr, and
# max_good_iter. We may want to revisit this during testing and/or as
# we continue to develop.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Is there any reason at all to expose these as user-tunable parameters, or are they strictly algorithm-specific parameters that need to be tested and set for good?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

My hope is that these are actually (somewhat) temporary parameters, so I think the answer to your first question is no. Particularly because it's would be difficult to add a way for a user to assess what the parameters should be without digging into the code.

Comment thread pypeit/core/wavecal/autoid.py Outdated
Comment on lines +648 to +649
f'shift = {shift_vec[iarxiv]:5.3f}, stretch = {stretch_vec[iarxiv]:5.3f}, cc = '
f'{ccorr_vec[iarxiv]:5.3f}'

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Formatting annoyance: place the "cc =" on the next line -- doesn't affect anything other than me reading the code.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done!

Comment thread pypeit/core/wavecal/autoid.py Outdated
# Grab the observed arc spectrum
obs_spec_i = spec[:,slit]
# get FWHM for this slit
# TODO: Doesn't this mean measured_fwhms *cannot* be None?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

That's how I read it. Maybe add a defensive check for None?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Instead of checking for None, I made it a positional argument.

Comment thread pypeit/core/wavecal/autoid.py Outdated

# TODO: JFH This continue statement deals with the case when the
# msnippet derives from *entirely* zero-padded pixels, and allows
# the code to continue with crashing. This code is constantly

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

without crashing?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Good catch! Fixed.

if all(iter_args) and len(w)/len(tampl) < good_frac:
# Iteratively increase the FWHM in an attempt to improve the line detection
for i in range(max_good_iter):
_fwhm = fwhm*fwhm_incr**(i+1)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

So, if fwhm_incr were less than 1, we would be decreasing the FWHM with each iteration. Is there a case where this would be useful at all?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

In the limited testing I've done, it seems like you tend to miss lines if the FWHM is too small, but not if it is too big. That means there is not much to be gained by iteratively making the FWHM smaller. But, I didn't think it was worth imposing that fwhm_incr be greater than 1, particularly given that it's effectively a developer-only parameter in the current workflow. I've added a comment along these lines.

Comment thread pypeit/core/wavecal/wvutils.py Outdated
zerolag_shift_stretch, args=(y1,y2), x0=x0_guess, tol=toler,
bounds=bounds, disp=False, polish=True, seed=seed)
zerolag_shift_stretch, args=(y1,y2), x0=x0_guess, tol=toler, bounds=bounds, disp=False,
polish=True, rng=seed

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

seed = rng instead?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

The seed keyword is being deprecated by scipy, in favor of rng.

continue
# Detect lines and store the spectral FWHM
_, _, cent, wdth, _, best, _, nsig = arc.detect_lines(arc_spec.squeeze(), sigdetect=sigdetect, fwhm=fwhm, bpm=arc_spec_bpm.squeeze())
# NOTE: "best" is a list of line indices, NOT a boolean array!

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This kind of NOTE occurs often in this PR...

This indicates that a boolean array is expected for this kind of variable... is there a good reason it is not and/or would it be prohibitively expensive (code changes / in-process computation / etc.) to make it thus?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Personally, I often expect that these kinds of arrays are boolean. So I added these (admittedly obnoxious) notes mostly as a reminder to me. At the same time, I didn't think it was worth actually trying to change the object from an int array to a bool array. Punting...

@kbwestfall kbwestfall left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Thanks for the reviews! All comments addressed. Next is to run the tests!

Comment on lines +584 to +586
# NOTE: I've hard-coded the values for good_frac, fwhm_incr, and
# max_good_iter. We may want to revisit this during testing and/or as
# we continue to develop.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

My hope is that these are actually (somewhat) temporary parameters, so I think the answer to your first question is no. Particularly because it's would be difficult to add a way for a user to assess what the parameters should be without digging into the code.

Comment thread pypeit/core/wavecal/autoid.py Outdated
Comment on lines +648 to +649
f'shift = {shift_vec[iarxiv]:5.3f}, stretch = {stretch_vec[iarxiv]:5.3f}, cc = '
f'{ccorr_vec[iarxiv]:5.3f}'

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done!

continue
# Detect lines and store the spectral FWHM
_, _, cent, wdth, _, best, _, nsig = arc.detect_lines(arc_spec.squeeze(), sigdetect=sigdetect, fwhm=fwhm, bpm=arc_spec_bpm.squeeze())
# NOTE: "best" is a list of line indices, NOT a boolean array!

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Personally, I often expect that these kinds of arrays are boolean. So I added these (admittedly obnoxious) notes mostly as a reminder to me. At the same time, I didn't think it was worth actually trying to change the object from an int array to a bool array. Punting...

Comment thread pypeit/core/wavecal/autoid.py Outdated
# Grab the observed arc spectrum
obs_spec_i = spec[:,slit]
# get FWHM for this slit
# TODO: Doesn't this mean measured_fwhms *cannot* be None?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Instead of checking for None, I made it a positional argument.

Comment thread pypeit/core/wavecal/autoid.py Outdated

# TODO: JFH This continue statement deals with the case when the
# msnippet derives from *entirely* zero-padded pixels, and allows
# the code to continue with crashing. This code is constantly

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Good catch! Fixed.

if all(iter_args) and len(w)/len(tampl) < good_frac:
# Iteratively increase the FWHM in an attempt to improve the line detection
for i in range(max_good_iter):
_fwhm = fwhm*fwhm_incr**(i+1)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

In the limited testing I've done, it seems like you tend to miss lines if the FWHM is too small, but not if it is too big. That means there is not much to be gained by iteratively making the FWHM smaller. But, I didn't think it was worth imposing that fwhm_incr be greater than 1, particularly given that it's effectively a developer-only parameter in the current workflow. I've added a comment along these lines.

Comment thread pypeit/core/wavecal/wvutils.py Outdated
zerolag_shift_stretch, args=(y1,y2), x0=x0_guess, tol=toler,
bounds=bounds, disp=False, polish=True, seed=seed)
zerolag_shift_stretch, args=(y1,y2), x0=x0_guess, tol=toler, bounds=bounds, disp=False,
polish=True, rng=seed

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

The seed keyword is being deprecated by scipy, in favor of rng.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Bug fix.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants