-
-
Notifications
You must be signed in to change notification settings - Fork 39
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
Initial implementation of line matching #182
Conversation
…d-coding Moffat1D. need Gaussian1D for some test cases
…ct that types/defaults are now self-documented by the code
…input as np.array which needs to happen, anyway
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #182 +/- ##
==========================================
+ Coverage 81.91% 83.37% +1.45%
==========================================
Files 10 13 +3
Lines 1001 1137 +136
==========================================
+ Hits 820 948 +128
- Misses 181 189 +8 ☔ View full report in Codecov by Sentry. |
i think i successfully merged in the significant changes from #202. the python 3.8 and 3.9 tests did fail as expected so i bumped |
this PR has been languishing for a while. i'd like to finally get this in to at least add the type annotation work and up the minimum python to 3.10. there's more work to be done on the line matching and especially wavelength calibration, but at this point it's better off done in new PRs. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
still testing out the functionality, but some initial comments on code.
I noticed that throughout, you've removed some of the numpy style docstrings that describe input parameter type and default, and are instead annotating the function. I think that the annotations are a helpful addition, but that the docstrings should retain the same format as before, making sure defaults are also described.
from specreduce.core import * # noqa | ||
from specreduce.wavelength_calibration import * # noqa | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this necessary? specreduce.__version__ seems to be correct already
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it may not be. i just moved it over from _astropy_init.py
as-is so there'd be no surprises. kind of a vestige of the old astropy-helpers
, but other coordinated packages like photutils
have this in their __init__.py
as well, fwiw.
# Extra sanity handling to make sure the input Sequence can be converted to an np.array | ||
try: | ||
pixel_positions = np.array(pixel_positions, dtype=float) | ||
except ValueError as e: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add a small test for this case to raise the error. Also, as part of sanity checking, maybe add in a check that wcs exists and its spectral.
widths = [] | ||
amplitudes = [] | ||
for r in detected_lines: | ||
g_init = models.Gaussian1D( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this will cause an error when the model is evaluated unless stddev, mean, and amp are all in the same unit. Stddev is in pixels but it looks like amplitude will have the same unit as flux?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's units-aware and is ultimately getting the unit information from the Spectrum1D
instance. i was, however, incorrect to assume fwhm
should be pixels if not specified. it should be in whatever the spectral_axis
unit is in the input spectrum.
@@ -88,44 +90,47 @@ | |||
] | |||
|
|||
|
|||
def get_available_line_catalogs() -> dict: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would maybe add a call to this to one of the existing tests (like in test_line_matching.py) to make sure this function is covered in tests.
@@ -2,21 +2,23 @@ | |||
Utilities for defining, loading, and handling spectroscopic calibration data | |||
""" | |||
|
|||
import os | |||
import warnings |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sort import alphabetically (move warnings import down, and astropy.coordinates up)
'pypeit': PYPEIT_CALIBRATION_LINELISTS | ||
} | ||
|
||
|
||
def get_reference_file_path( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a bit confused by this function. If you don't give it a path, it quietly does nothing. It's also not clear if something is being overwritten or not. Also, it seems to only allow you to download something to a .specreduce directory (which it creates), or if you set cache to False it puts it in /var/. Would it make sense to allow specifying an output directory? Probably out of the scope of this, but I had never used this before reviewing this PR and it stood out to me as confusing.
|
||
catalog_pixels = spectral_wcs.world_to_pixel(catalog_wavelengths) | ||
separations = pixel_positions[:, np.newaxis] - catalog_pixels | ||
matched_loc = np.where(np.abs(separations) < tolerance) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe raise a warning when there are no matches? it might be more informative than just returning an empty table
@@ -0,0 +1,110 @@ | |||
import pytest |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
alphabetize imports
'CRVAL2': 0, # Reference value | ||
'CDELT2': 1 # Spatial units per pixel | ||
} | ||
non_linear_wcs = WCS(header=non_linear_header) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does it make sense to also test this with GWCS since the function can accept either? im not sure if thats overkill
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i am working on a draft PR to formally add gwcs
as a dependency (it is currently an import
in one place, but not a defined dependency in pyproject.toml
), add tests to cover its use in addition to astropy.wcs
, and add better examples of its use in contexts like this. so, yes, it definitely makes sense, but it's out of scope for this PR.
this was a very intentional change. now that type annotations are supported, they should be the preferred way to document typing and defaults. it is a much more flexible and powerful way of doing so. e.g., it empowers compilers to optimize the code using the given information which is important in contexts such as GPUs. what we definitely DO NOT WANT is to have redundant information in two places because it is guaranteed to create inconsistencies in the future. |
That makes sense not to keep in in two places. So this is the new best practice then? If so maybe we can make a PR to do this across the whole package so its not in the diff here, that should be fairly quick to do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tests are passing so I'm going to merge this, thanks!
This PR adds functions to find and centroid lines in a calibration, e.g. arc lamp, spectrum and then match pixel positions to wavelengths using an input WCS. More work is needed to close the loop between this and the fitting process for wavelength calibration, but this is a start.
This PR also contains come code cleanups and the addition of typing in several places. To take advantage of the significant improvements in typing and type handling in newer versions of python, the minimum python version has been upped to 3.10. The CI and
tox
configuration has been updated to reflect this.