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

Add ability to load 2D flux arrays in Specviz #3229

Merged
merged 16 commits into from
Nov 1, 2024

Conversation

rosteen
Copy link
Collaborator

@rosteen rosteen commented Oct 18, 2024

Closes #3223, opening as draft to see if this will fix the desired use case based on upstream changes. This splits a Spectrum1D with 2D flux into separate Spectrum1D objects before loading into Specviz.

@rosteen rosteen added the feature Feature request label Oct 18, 2024
@rosteen rosteen added this to the 4.1 milestone Oct 18, 2024
@github-actions github-actions bot added specviz plugin Label for plugins common to multiple configurations labels Oct 18, 2024
Copy link

codecov bot commented Oct 18, 2024

Codecov Report

Attention: Patch coverage is 90.00000% with 4 lines in your changes missing coverage. Please review.

Project coverage is 88.63%. Comparing base (9a1fe09) to head (f5e2f29).
Report is 19 commits behind head on main.

Files with missing lines Patch % Lines
jdaviz/configs/specviz/plugins/parsers.py 90.00% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3229      +/-   ##
==========================================
+ Coverage   88.62%   88.63%   +0.01%     
==========================================
  Files         125      125              
  Lines       18775    18803      +28     
==========================================
+ Hits        16639    16666      +27     
- Misses       2136     2137       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Comment on lines 93 to 97
elif path.is_file():
try:
data = [Spectrum1D.read(str(path), format=format)]
data_label = [app.return_data_label(data_label, alt_name="specviz_data")]
data = Spectrum1D.read(str(path), format=format)
if data.flux.ndim == 2:
data, data_label = split_spectrum_with_2D_flux_array(data, data_label, app)
Copy link
Collaborator

@havok2063 havok2063 Oct 18, 2024

Choose a reason for hiding this comment

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

In our file case, there are 2 data extensions, with the 1st having a 1d flux array, and the 2nd one having the nd flux array. Without the load_as_list flag, this block only loads the first extension and never reaches line 97. With load_as_list set, which is the way I think we need to load these files, I get the error

File [~/Work/jdaviz/jdaviz/configs/specviz/plugins/parsers.py:129](http://localhost:8888/lab/workspaces/auto-b/tree/~/Work/jdaviz/jdaviz/configs/specviz/plugins/parsers.py#line=128), in specviz_spectrum1d_parser(app, data, data_label, format, show_in_viewer, concat_by_file, cache, local_path, timeout, load_as_list)
    127 for wlind in range(len(spec.spectral_axis)):
    128     wlallorig.append(spec.spectral_axis[wlind].value)
--> 129     fnuallorig.append(spec.flux[wlind].value)
    131     # because some spec in the list might have uncertainties and
    132     # others may not, if uncert is None, set to list of NaN. later,
    133     # if the concatenated list of uncertanties is all nan (meaning
    134     # they were all nan to begin with, or all None), it will be set
    135     # to None on the final Spectrum1D
    136     if spec.uncertainty[wlind] is not None:

File [~/anaconda3/envs/newsv/lib/python3.11/site-packages/astropy/units/quantity.py:1302](http://localhost:8888/lab/workspaces/auto-b/tree/~/anaconda3/envs/newsv/lib/python3.11/site-packages/astropy/units/quantity.py#line=1301), in Quantity.__getitem__(self, key)
   1297     return self._new_view(
   1298         self.view(np.ndarray)[key], self.unit[key], propagate_info=False
   1299     )
   1301 try:
-> 1302     out = super().__getitem__(key)
   1303 except IndexError:
   1304     # We want zero-dimensional Quantity objects to behave like scalars,
   1305     # so they should raise a TypeError rather than an IndexError.
   1306     if self.isscalar:

IndexError: index 1 is out of bounds for axis 0 with size 1

Copy link
Contributor

Choose a reason for hiding this comment

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

I think what I've done should fix this bug. It occurs when there's 2D spectra in a SpectrumList.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes, with your PR it loads correctly, but your PR is basically unpacking the nd arrays into individual Spectrum1D objects, which this draft code is also doing. In principle, with the change here, we don't need to manually unpack the nd fluxes inside the loader.

This draft code should work loading nd-flux data more generally, outside of the specific mwm loader

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, I've already reverted that back to how it was initially, see specutils#1185, ca4d8c

@rileythai
Copy link
Contributor

rileythai commented Oct 19, 2024

Should Specviz instead just always try to load as SpectrumList first when reading single files? Given the jdaviz webapp usecase, users probably want to load all spectra in a file.

Most of the multi-extension default loaders are only implemented as SpectrumList (JWST, DESI, GALAH, SDSS), so it should try to autoload everything, right? And if it throws an IORegistryError error or can't autodetect it then it can always jump ship to the Spectrum1D case instead.

@rileythai
Copy link
Contributor

rileythai commented Oct 19, 2024

Also on metadata -- we could make the 2D-to-1D converter split list-like metadata objects with the same length as spectrum1d.flux.shape[0] across unique metadata dicts to each split Spectrum1D, and otherwise just copy everything else.

@rosteen
Copy link
Collaborator Author

rosteen commented Oct 22, 2024

@havok2063 @rileythai I pulled in Riley's code from rosteen#6 handling the case of SpectrumList containing 2D spectra (and a couple other small fixes). I didn't pull in some changes I didn't agree with (some autoformatting and a couple changes to the Spectrum1D handling) but I think I got everything that was strictly necessary.

@rosteen
Copy link
Collaborator Author

rosteen commented Oct 22, 2024

Whoops, messed up one thing, stand by...

@rosteen
Copy link
Collaborator Author

rosteen commented Oct 22, 2024

Alright, I debugged the previous commit and added some more test coverage, this is ready for another look.

@rosteen rosteen closed this Oct 22, 2024
@rosteen rosteen reopened this Oct 22, 2024
@havok2063
Copy link
Collaborator

@rosteen @rileythai I've tested this PR with the latest version of astropy/specutils#1185 against the following file types: mwmStar, mwmVisit, spec-lite, spec-full, apStar and I was able to load all the expected extensions viz Specviz using the right format and the new load_as_list keyword as needed. Everything seems to work! Thanks to both of you for your help! I think we've converged on a working solution we're all on board with.

@rosteen
Copy link
Collaborator Author

rosteen commented Oct 24, 2024

@havok2063 Great, I'll mark this as ready for review then.

@rosteen rosteen marked this pull request as ready for review October 24, 2024 13:53
unc = data.uncertainty[i, :]
if data.mask is not None:
mask = data.mask[i, :]
new_data.append(Spectrum1D(flux=data.flux[i, :], spectral_axis=data.spectral_axis,
Copy link
Contributor

Choose a reason for hiding this comment

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

What about the other properties like redshift, metadata, etc? Do they not have to be propagated?

Copy link
Contributor

Choose a reason for hiding this comment

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

Also... is an utility function like this better suited for specutils upstream?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I just added the meta, I had discussed with Brian and we agreed that it's ok to attach the meta from the original to each split spectrum at least for now. Redshift comes along with the spectral_axis.

I think I'd prefer to keep this here for now, but we could potentially upstream it at some point. I don't know exactly where I'd want to put it in specutils.

Copy link
Contributor

Choose a reason for hiding this comment

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

OK, I opened astropy/specutils#1188

@@ -405,6 +405,24 @@ def test_load_spectrum_list_directory_concat(tmpdir, specviz_helper):
assert len(specviz_helper.app.data_collection) == 41


def test_load_2d_flux(specviz_helper):
spec = Spectrum1D(spectral_axis=np.linspace(4000, 6000, 10)*u.Angstrom,
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe add comments to explain what is going on here for future devs. Hard to tell from reading the code without more context.

CHANGES.rst Outdated
@@ -15,6 +15,7 @@ Mosviz

Specviz
^^^^^^^
- Specviz parser will now split a spectrum with a 2D flux array into multiple spectra on load. [#3229]
Copy link
Contributor

Choose a reason for hiding this comment

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

If this is added to support a specific telescope/instrument, please state also.

Copy link
Contributor

@pllim pllim left a comment

Choose a reason for hiding this comment

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

Since MAST is happy, I am approving by proxy and also the fact that the test added passes CI. Thanks!

Copy link
Contributor

@javerbukh javerbukh left a comment

Choose a reason for hiding this comment

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

Tested this branch and could not replicate the bug. Code looks good as well so LGTM!

@rosteen
Copy link
Collaborator Author

rosteen commented Nov 1, 2024

Thanks for the reviews!

@rosteen rosteen merged commit 3c14001 into spacetelescope:main Nov 1, 2024
25 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Feature request plugin Label for plugins common to multiple configurations Ready for final review specviz
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[FEAT] support Spectrum1D objects with 2D flux arrays in Specviz
5 participants