MAST: Adding read_product function to mast.observations#3610
MAST: Adding read_product function to mast.observations#3610AlexReedy wants to merge 15 commits into
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #3610 +/- ##
=======================================
Coverage 73.17% 73.18%
=======================================
Files 227 227
Lines 21078 21115 +37
=======================================
+ Hits 15423 15452 +29
- Misses 5655 5663 +8 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
snbianco
left a comment
There was a problem hiding this comment.
I had a few comments, but this looks good!
|
|
||
|
|
||
| @pytest.fixture | ||
| def mock_asdf_open(mocker): |
There was a problem hiding this comment.
If you add:
pytest.importorskip("asdf")
pytest.importorskip("fsspec")
tests that use this fixture will automatically skip if asdf or fsspec are not installed. I think this would be preferable to mocking mock_fsspec_open.
| Observations.read_product("file.fits") | ||
|
|
||
|
|
||
| def test_observations_read_product_asdf_missing(monkeypatch): |
There was a problem hiding this comment.
Could you combine this test with the one before it using parametrization?
| # Forces the path to be lowercase for the extension checks. This is only used for the checks | ||
| path = str(product_path).lower() | ||
|
|
||
| # Checks users enviornment for fsspec, required for both fits and asdf |
There was a problem hiding this comment.
| # Checks users enviornment for fsspec, required for both fits and asdf | |
| # Checks users environment for fsspec, required for both fits and asdf |
| data_product = fits.open(product_path, fsspec_kwargs={"anon": True}, **kwargs) | ||
| log.info(f"Loaded: {product_path}") | ||
| return data_product | ||
| except Exception as e: |
There was a problem hiding this comment.
Can you be more specific about the exception here? Or if you want to catch generally, add a comment explaining why.
|
|
||
| # Logic for reading ASDF files | ||
| elif path.endswith(".asdf"): | ||
| if fsspec is None: |
There was a problem hiding this comment.
Since this package is needed for both FITS and ASDF, can you check that it exists in the environment outside of this block so that it's not there twice?
| raise ImportError('The "asdf" package is required to read ASDF files. Please install it with ' | ||
| '`pip install asdf` or install astroquery with optional dependencies using ' | ||
| '`pip install astroquery[all]`.') | ||
|
|
There was a problem hiding this comment.
I'd also like to raise warnings if the optional packages are not found. Something like this:
for package in ["gwcs", "lz4", "roman_datamodels"]:
if importlib.util.find_spec(package) is None:
warnings.warn(f'The "{package}" package is encouraged when reading ASDF files from the '
'Roman Space Telescope mission. Please install it with `pip install {package}` '
'or install astroquery with optional dependencies using '
'`pip install astroquery[all]`.', ImportWarning)
| data_product = asdf.open(f, ignore_unrecognized_tag=ignore_unrecognized) | ||
| log.info(f"Loaded: {product_path}") | ||
| return data_product | ||
| except Exception as e: |
There was a problem hiding this comment.
Use a more specific exception here if you can
| .. doctest-remote-data:: | ||
|
|
||
| >>> from astroquery.mast import Observations | ||
| >>> fits_product = Observations.read_product(product_path="s3://stpubdata/hst/public/u9o4/u9o40504m/u9o40504m_c3m.fits") |
There was a problem hiding this comment.
Can you add a fits_product.info() and asdf_product.info() just to demonstrate that actual objects with data are being returned?
…reviewer feedback
…t is package is not present
bsipocz
left a comment
There was a problem hiding this comment.
please rebase, and once I have a passing review from Sam I'll come back and do a final review.
| oldestdeps-alldeps: regions==0.5 | ||
| oldestdeps-alldeps: astropy-healpix==0.7 | ||
| oldestdeps-alldeps: roman_datamodels==0.11.0 | ||
| oldestdeps-alldeps: gwcs==0.18 |
There was a problem hiding this comment.
gwcs is not listed as a dependency, so including it here makes little sense to me?
But also, if we add all the 3 packages as optional dependencies we will need to make sure they don't introduce some indirect limitations on supported versions.
| @pytest.mark.parametrize( | ||
| "product_path, expected_type", | ||
| [ | ||
| ( | ||
| "s3://stpubdata/hst/public/u24r/u24r0102t/u24r0102t_c1f.fits", | ||
| fits.HDUList, | ||
| ) | ||
| ], | ||
| ) | ||
| def test_observations_read_product(self, product_path, expected_type): |
There was a problem hiding this comment.
we allow long lines in astroquery, please reformat it back to something less verbose and whitespace-y
| import asdf | ||
| except ImportError: | ||
| asdf = None | ||
|
|
There was a problem hiding this comment.
You already do skipifs, so is this really necessary? or maybe you can use @pytest.mark.skipif instead of the importorskip, so it's more consistent
A function of the Mast.Observations class to read product from S3 to memory.
Observations.read_product() takes both FITS and ASDF file URIs and stores them using astropy.io.fits.open and asdf.open respectively.
Connection to S3 is done using fsspec
Changes made