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

Export spectral subsets #2843

Merged
merged 17 commits into from
May 2, 2024
Merged

Conversation

rosteen
Copy link
Collaborator

@rosteen rosteen commented May 1, 2024

Implements updating spectral subsets via specutils.SpectralRegion to ECSV files.

@rosteen rosteen added feature Feature request plugin Label for plugins common to multiple configurations labels May 1, 2024
@rosteen rosteen added this to the 3.10 milestone May 1, 2024
@rosteen
Copy link
Collaborator Author

rosteen commented May 1, 2024

Hmm, this was passing locally.

@@ -93,10 +93,6 @@ def test_not_implemented(self, cubeviz_helper, spectral_cube_wcs):

assert export_plugin.subset_invalid_msg == 'Export for composite subsets not yet supported.'

cubeviz_helper.app.session.edit_subset_mode.mode = NewMode
cubeviz_helper.app.get_viewer("spectrum-viewer").apply_roi(XRangeROI(5, 15.5))
assert 'Subset 2' not in export_plugin.subset.choices
Copy link
Contributor

Choose a reason for hiding this comment

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

What does deleting this from the test mean in terms of expected behavior?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It means Subset 2 is allowed to be in the subset choices now.

Copy link
Contributor

Choose a reason for hiding this comment

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

But is it grayed out? If so, is there a way to check?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It is not grayed out, no. The output format choices may be, I can add a check for that.


export_plugin.filename_value = "test_spectral_region"
export_plugin.export()
assert os.path.isfile('test_spectral_region.ecsv')
Copy link
Contributor

Choose a reason for hiding this comment

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

Is roundtripping a requirement? That is, is Jdaviz expected to be able to re-ingest this file and re-creates the same spectral region?

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 don't believe it is.

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 guess checking for the output content is correct or not is the job of specutils, so we don't have to do that here. Thanks for the clarification!

@@ -23,7 +23,7 @@ dependencies = [
"ipywidgets>=8.0.6",
"voila>=0.4,<0.5",
"pyyaml>=5.4.1",
"specutils>=1.9",
"specutils>=1.15",
Copy link
Contributor

Choose a reason for hiding this comment

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

That is quite a jump. Do we need a change log for this?

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 would be happy to add it to the change log if you think so.

Copy link
Contributor

Choose a reason for hiding this comment

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

Doesn't hurt?

Copy link

codecov bot commented May 1, 2024

Codecov Report

Attention: Patch coverage is 97.67442% with 1 lines in your changes are missing coverage. Please review.

Project coverage is 88.99%. Comparing base (9b4817d) to head (3a415ec).
Report is 10 commits behind head on main.

Files Patch % Lines
jdaviz/configs/default/plugins/export/export.py 97.61% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2843      +/-   ##
==========================================
+ Coverage   88.95%   88.99%   +0.03%     
==========================================
  Files         111      111              
  Lines       17101    17148      +47     
==========================================
+ Hits        15213    15261      +48     
+ Misses       1888     1887       -1     

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

@@ -655,6 +696,10 @@ def save_subset_as_region(self, selected_subset_label, filename):

region.write(filename, overwrite=True)

def save_subset_as_table(self, filename):
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we want an option to overwrite? Also does this need some path wrangling magic for the "standalone app"? For example, see implementation in this method:

def _write_moment_to_fits(self, overwrite=False, *args):

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually I see that this plugin already has _normalize_filename method that you wrote recently. Should that be used explicitly?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

_normalize_filename is already used before we get to this point, and handling overwrite is also handled in that method.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah OK, hard to tell from the diff. Thanks for the clarification!

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.

Works as advertised but some feedback for possible future work as follows.

When I have multiple spectral regions, I would like the option to save all or some of them in the same file. Currently, I can only save one Subset per file. But what would be nice is something like this in the same file:

lower_bound upper_bound
7.030608671135324 7.168932092864794
5.701354428693486 5.876789012350375

I have checked that both astropy.table.QTable and specutils.SpectralRegion could read multi-row ECSV back in.

Even better (and probably only makes sense when we support Subset renaming; also double check how ECSV really store fields with whitespace, this is just pseudocode):

name lower_bound upper_bound
"My fav line 1" 7.030608671135324 7.168932092864794
"My other fav line" 5.701354428693486 5.876789012350375

@pllim
Copy link
Contributor

pllim commented May 1, 2024

p.s. Not sure if there are any other relevant info you want to also store, like the dataset it was tied to, or the redshift. Again, ideas for future work, not this PR.

@rosteen
Copy link
Collaborator Author

rosteen commented May 1, 2024

@pllim Thanks for the comments. This can save out multiple lines to the same file, but it has to be a single subset with multiple subregions rather than multiple independent spectral subsets.

@pllim
Copy link
Contributor

pllim commented May 1, 2024

Re: #2843 (comment)

Do you think such a distinction should be documented in user doc, maybe at https://jdaviz.readthedocs.io/en/latest/specviz/export_data.html#spectral-regions ? 🤔

Copy link
Member

@kecnry kecnry left a comment

Choose a reason for hiding this comment

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

I was worried about how the automatic changing of format would work wrt the API, but in playing with it, I actually think its ok and quite convenient! One caveat explained below where the API can still get into trouble, but I think we can find ways around that.

I do think it would then be worth looking into what other places this pattern could be used. In some cases, I think the red text is still the better choice because it can explain why, but in cases where it is more obvious like this, this really is a nice UX improvement!

Another thing to consider: instead of bumping specutils, we could just have spectral subsets disabled entirely based on the imported version (in this case it probably would make sense to allow selecting the spectral subset but then have the red text say that upgrading specutils is necessary). I'm ok with the bump though if that keeps things simpler and has other advantages as well.

@@ -126,7 +126,7 @@
</div>

<div v-if="subset_items.length > 0">
<span class="export-category">Spatial Subsets</span>
<span class="export-category">Subsets</span>
<v-row>
<span class="category-content v-messages v-messages__message text--secondary">Export spatial subset as astropy region.</span>
Copy link
Member

Choose a reason for hiding this comment

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

this description definitely needs generalizing now (while still keeping this information since that was explicitly requested).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Whoops, good catch. I'll update.

Comment on lines 294 to 296
if bad_combo:
raise ValueError(f"Cannot export {self.subset.selected} in "
f"{self.subset_format.selected.upper()} format")
Copy link
Member

Choose a reason for hiding this comment

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

This doesn't revert the actual value, and so leaves the plugin in a broken state at which point clicking export or calling export() gives an uninformative traceback. I suspect the code to revert the selection would be messy and perhaps confusing behavior, but maybe we can keep this error message, still show the red text and disable the export button, and then raise that red text as an error on export (all that infrastructure should already exist for the other cases already 🤞 )

To reproduce:

  • create a spectral subset and select in the UI
  • using the API, request 'fits' as the format. This error is raised but the value is still set.
  • (subsequent attempts to set would not raise an error since the value hasn't changed)
  • click or call export

Comment on lines +299 to +300
raise ValueError(f"Cannot export {self.subset.selected} in {event['new']}"
f" format, reverting selection to {self.subset_format.selected}")
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@kecnry, do you think this error message makes clear enough what is happening?

Copy link
Member

Choose a reason for hiding this comment

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

if you want to go the revert route, you could also use self.subset_format.select_previous() (which hopefully should be valid still... I can't think of a case where it wouldn't)

Copy link
Member

Choose a reason for hiding this comment

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

but the message makes sense to me, let me test it to see if I can find a way to break it and otherwise should be good to approve.

@rosteen
Copy link
Collaborator Author

rosteen commented May 2, 2024

@pllim I updated the docs. It actually looks like the export section in plugins.rst hadn't been updated since we added more things in addition to viewers, so I added a mention of plugin plots as well.

@pllim
Copy link
Contributor

pllim commented May 2, 2024

Re: docs -- LGTM. Thanks!

docs/specviz/plugins.rst Outdated Show resolved Hide resolved
docs/specviz/plugins.rst Outdated Show resolved Hide resolved
Copy link
Member

@kecnry kecnry left a comment

Choose a reason for hiding this comment

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

LGTM now - thanks!

@rosteen rosteen merged commit 815bce7 into spacetelescope:main May 2, 2024
16 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
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants