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

Plugin: spectral extraction #1514

Merged
merged 37 commits into from
Aug 9, 2022
Merged

Conversation

kecnry
Copy link
Member

@kecnry kecnry commented Jul 20, 2022

Description

This pull request implements a new plugin in specviz2d for spectral extraction via specreduce. It currently only implements the functionality for Trace creation, offsetting, loading from the API, and visualizing in the 2d spectrum viewer. The UI elements for the other "steps" (background, extraction) are implemented (in order to plan for the necessary interaction between the steps), but are currently non-functional. (woops! - that was a nice plan, but planning for how things would interact with each other eventually became just an API call away from actually implementing and devs decided it would be easier to review/merge in a complete form anyways)

IMPORTANT: this PR fixes the units on the x-axis to be shown in pixels instead of erroneously in meters, but by doing so disables the line list and line analysis plugins when in pixels (whenever not manually loading a 1D spectrum in other units). Future work will either need to properly handle plotting in wavelength or update the logic in these plugins to handle converting on-the-fly using the wavelength solution, if available.

view specviz2d barebones docs and the spectral-extraction docs (full specviz2d docs are out-of-scope, but created the plugins page so links from jdaviz work).

NOTE this PR currently requires the following non-merged branches from other dependencies (and will likely fail CI tests until they are merged and pinned here):

Once the upstream PRs above are released, we can re-introduce the functionality in this plugin as a follow-up PR.

Sorry dev-reviewers for another large diff 😬 ! But many of the new lines are just boilerplate new plugin and boilerplate docs for specviz2d, so hopefully it won't be too difficult to parse 🤞

Note: this screen recording was still in pixel space. This has since been updated to show in wavelength, when possible, but the linking from the example notebook is so non-linear that it's almost unusable. We should probably consider switching it out with data that works better and then open follow-up efforts to improve support for more general input data.

Screen.Recording.2022-07-25.at.1.43.13.PM.mov

In addition to the UI, once glue-astronomy#72 is released, we can implement support for importing traces created in the notebook via app.add_data (this functionality has been stripped from the PR so that we're not blocked waiting for that PR to be approved, merged, and released):

from specreduce import tracing
trace = tracing.FlatTrace(spectrum1d.data, 29)

specviz2d.app.add_data(trace, data_label='trace_imported')
specviz2d.app.add_data_to_viewer('spectrum-2d-viewer', 'trace_imported')

You can also use the plugin API to interact with specreduce directly with something like:

ext_plugin = specviz2d.app.get_tray_item_from_name('spectral-extraction')
ext_plugin.trace_pixel = 29
trace = ext_plugin.create_trace()

Note that if the live-preview of the extracted spectrum disappears, that is because an error is being raised by specreduce. When using auto (Kosmos) trace or a manual background, specreduce is often throwing a (probably incorrect) error detecting an overlap in background regions. These cases also result in increased lag as they take a while to compute through specreduce. These cases should be fixed in specreduce and are out-of-scope here.

TODO:

  • layer icon colors for traces (don't currently update when changing colors since they're following image viewer rules)
  • separate icon for traces in layer icons similar to spectral and spatial subsets
  • fix live-preview of Trace offsetting
  • try/except for trace previewing (clear if trace fails)
  • better rules and error handling (example: KosmosTrace requires bins >= 4)
  • better workaround/fix for all range(len(trace.trace)) instances.
  • UI/UX review from @Jenneh
  • trace entries in data-menu to always show check, change spectrum-2d to default to single select for actual images
  • use plugin infrastructure for original spectrum 1d and set defaults in plugin accordingly (see Plugin: spectral extraction #1514 (comment))
  • plugin documentation
  • test coverage
  • PR for glue-astronomy, merged, pinned, or remove support until it is
  • PR for specreduce merged and pinned, or remove support for peak_method until it is
  • remove or finish background/extract support (see list below for what is left to be done for those)

If not removing background/extraction steps into a separate follow-up PR:

  • test coverage for background/extraction steps
  • docs for background/extraction steps
  • fix plotting of background/subtracted image

Potential Future Work:

  • advanced mode toggle (when in simple, hide intermediate export expansion panels as well as all inputs that default to "From Plugin") (ended up partially simplifying the options without losing too much flexibility, a separate toggle at this point is probably overkill)
  • improved trace plot options support (currently shows with markers, but no line, but with line-like choices)
  • default color of trace to be non-gray?
  • can we edit existing entry in place instead of adding new data entry (then would be able to keep plot options)? This would likely need to be done in the AddResults component itself.

Things brought up in other issues/tickets that are not (yet) directly addressed:

  • Parameters can be specified manually in GUI and exported in notebook for reproducibility (like get_model_parameters).
  • Ability to set same parameters for all the spectra in the Mosviz table.
  • spectrum_result= spec2d.extract_spectrum(2dspectrum_background_subtracted_already, trace_object, extractor_object)

Post-merge TODO

  • Add GitHub issue templates for Specviz2d.
  • Update change log template in release instructions to include Specviz2d.

Closes #809

Checklist for package maintainer(s)

This checklist is meant to remind the package maintainer(s) who will review this pull request of some common things to look for. This list is not exhaustive.

  • Are two approvals required? Branch protection rule does not check for the second approval. If a second approval is not necessary, please apply the trivial label.
  • Do the proposed changes actually accomplish desired goals? Also manually run the affected example notebooks, if necessary.
  • Do the proposed changes follow the STScI Style Guides?
  • Are tests added/updated as required? If so, do they follow the STScI Style Guides?
  • Are docs added/updated as required? If so, do they follow the STScI Style Guides?
  • Did the CI pass? If not, are the failures related?
  • Is a change log needed? If yes, is it added to CHANGES.rst?
  • Is a milestone set?
  • After merge, any internal documentations need updating (e.g., JIRA, Innerspace)?

@kecnry kecnry added plugin Label for plugins common to multiple configurations specviz2d labels Jul 20, 2022
@kecnry kecnry added this to the 2.8 milestone Jul 20, 2022
<v-icon style='margin-right: 2px'>{{ data.item.icon }}</v-icon>
<v-icon v-if="data.item.icon" style='margin-right: 2px'>{{ data.item.icon }}</v-icon>
Copy link
Member Author

Choose a reason for hiding this comment

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

this just makes the left of the entries with and without icons line up better. I also applied this across all other instances, even though not all dropdowns use "manual entries".

<j-tooltip :tooltipcontent="'data label: '+item.name" span_style="font-size: 12pt; padding-top: 6px; padding-left: 6px; width: calc(100% - 140px); white-space: nowrap; cursor: default;">
<j-tooltip :tooltipcontent="'data label: '+item.name" span_style="font-size: 12pt; padding-top: 6px; padding-left: 6px; width: calc(100% - 80px); white-space: nowrap; cursor: default;">
Copy link
Member Author

Choose a reason for hiding this comment

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

this fixes an alignment issue with the "x" button. #1491 apparently didn't properly set the alignment for all cases.

Comment on lines -137 to +144
state_filter=is_profile)
state_filter=not_image)
Copy link
Member Author

Choose a reason for hiding this comment

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

Lines used to just be spectra, but now we have a line that is in an image viewer and needs to expose the right plot options.

@@ -1018,8 +1021,27 @@ class DatasetSelect(BaseSelectPluginComponent):
"""
def __init__(self, plugin, items, selected,
filters=['not_from_plugin_model_fitting', 'layer_in_viewers'],
default_text=None, manual_options=[],
Copy link
Member Author

Choose a reason for hiding this comment

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

We didn't have a use for manual options in dataset dropdowns until now, so they weren't exposed. This works the same way as all other Select components that inherit from BaseSelectPluginComponent.

Comment on lines -1326 to +1356
replace = self.viewer.selected_reference != 'spectrum-viewer'
if replace is None:
replace = self.viewer.selected_reference != 'spectrum-viewer'
Copy link
Member Author

Choose a reason for hiding this comment

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

replace used to be hardcoded to True for viewers other than spectrum-viewer, but in this new plugin, we definitely want to plot the trace on top of the existing image, not replacing it.

@@ -34,6 +34,7 @@ install_requires =
voila>=0.3.5
pyyaml>=5.4.1
specutils>=1.7.0
specreduce>=1.0.0
Copy link
Member Author

Choose a reason for hiding this comment

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

specreduce will be an added dependency (although we might need to pin a newer version).

Copy link
Contributor

Choose a reason for hiding this comment

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

Yet another required dependency... Is @havok2063 okay with this?

Copy link
Member Author

Choose a reason for hiding this comment

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

If not, we could have it be required for the plugin to show up, but then users would need to install additional dependencies depending on which plugins they want.

Copy link
Contributor

Choose a reason for hiding this comment

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

Tricky business: #1399

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think I'm ok with it, since we will use this plugin in MAST. Does this plugin also provide users information on the default spectral extraction that occurs when I load a single s2d file? Or is it only for performing custom extractions?

Copy link
Member Author

Choose a reason for hiding this comment

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

As far as I know, the (current) plan is only for custom extraction and using jdaviz as a visualization layer to existing and upcoming functionality in specreduce.

Copy link
Collaborator

Choose a reason for hiding this comment

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

User feedback said they wanted to know how the default extraction was made. If we switch the default extraction to use this plugin to perform the extraction on initial load, would that provide that info and satisfy this feedback?

Copy link
Member Author

Choose a reason for hiding this comment

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

That's an interesting idea. I think the current displayed spectrum is just collapsed across the entire image. But if we could come up with automated defaults as input into the specreduce functionality, use those for the initial collapse instead, and have those set as the default in the plugin, that would be slick! I'm guessing even if that extraction isn't perfect, it would be better than just the full collapse?

There already is a snackbar warning that says: "The collapsed 1D spectrum is for quicklook purposes only. A robust extraction should be used for scientific use cases." Perhaps this text should also be updated to direct the user to this new plugin? Or maybe the "Spectrum 1D" data label should be changed to "Collapsed Spectrum"?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah I think it would be fine to define some reasonable defaults to perform a default extraction. We would still display the snackbar warning message. Yeah it's also a good idea to update the message to point people to the plugin. If it's too much work to switch over, then I am also ok just updating the label to say "Collapsed Spectrum" and updating the message to point people to the plugin.

@pllim pllim requested a review from eteq July 20, 2022 18:47
@kecnry kecnry force-pushed the plugin-specreduce-trace branch 4 times, most recently from 7693b7a to 10eee9e Compare July 20, 2022 19:43
@PatrickOgle
Copy link
Contributor

@kecnry This looks really good. My biggest suggestion would be to make the trace and extraction update automatically as you change the parameters, the products should then only be written out at the end (bottom of extraction workflow), similar to other plugins. Background subtraction might be more difficult to dynamically update, since it involves a 2D rather than 1D product, but that is just my guess.

@kecnry
Copy link
Member Author

kecnry commented Jul 21, 2022

@PatrickOgle

My biggest suggestion would be to make the trace and extraction update automatically as you change the parameters

This is definitely do-able (maybe using the same blue we do in line analysis to make a clear distinction between the live preview and actual result), but I'm a bit worried about all the things we'll want to visualize as we implement the rest of the plugin: the trace, the adopted regions for the background (some width and separation around the trace), the background image and/or subtracted image, the region adopted for the extraction (some width around the trace), and finally the extracted spectrum. Showing all of these at once in an intuitive way might be not be possible with our limited real estate.

I think the regions for background and extraction might be the most important to show in real-time since they're just visualizing the inputs rather than the outputs and would really help the user to understand what the parameters mean. But which of the others do we want to show without making it too cluttered?

One option might be to have the visual feedback be temporary - so that when you change options for the trace, there is some live visual "preview" feedback but that only stays on the screen for 5 seconds, or maybe stays until you make changes to one of the other steps, and then goes away so you can see feedback from the current step. I'd be happy to give this a try if people like the idea, but it'll take some framework implementation first.

the products should then only be written out at the end (bottom of extraction workflow)

I see and agree with your point that for simple cases this would be more convenient. But unless we really don't want to support more complex workflows (few cases I have in mind listed below), I'd like to try to keep support for importing/exporting at each intermediate step. What about something like this to make the simpler case the default while still having the flexibility for interacting in the UI or notebook at each step? If we wanted to simplify it even more, we could have an "simple/advanced" toggle at the top which hides the export expandable sections and all the dropdowns that default to "From Plugin" which would effectively enforce a flow from top to bottom without all the clutter.

Screen.Recording.2022-07-21.at.1.07.12.PM.mov

Cases where the more advanced workflow might be useful:

  1. The point you brought up about the background/subtracted image. Won't the user want to inspect these before finalizing extraction? I'm not sure we can visualize those images on the fly since they'll need to be loaded as data entries into the app and manually toggled in the data menu or have their opacities changed to view multiple layers at once. I suppose these images could still be added to the app when pressing the final "extract" button at the end and just inspected by the user to make sure they make sense, but then the user can't visually see the extraction region on top of the subtracted image ever (unless maybe by re-running the plugin, choosing the subtracted image from the previous run as input, and then choosing to skip doing another round of background subtraction).

  2. Complex UI workflows: outputting the trace to a data entry enables the workflow of using one trace to create the background subtracted image and then refining the trace from that subtracted image (and similar complex, non-linear, workflows). Having everything automatically update linearly from the top to the bottom of the plugin without manual outputs, probably prevents this type of (advanced) workflow.

  3. Notebook workflows: part of the original criteria was to support loading/exporting a trace object via the API. I think we could still support that with a linear/automatic flow in the plugin, but it would then be the only reason to need support for trace objects as data entries. If we went in this direction, I'd probably suggest loading the trace directly into the plugin itself, but that seems a bit at odds with @eteq's request for high-level API access to loading/visualizing traces.

@rosteen rosteen modified the milestones: 2.8, 2.9 Jul 21, 2022
@kecnry
Copy link
Member Author

kecnry commented Jul 21, 2022

@PatrickOgle - this is what I've managed to come up with as a prototype from your suggestions (both for an easier linear-flow and for visual feedback) - let me know what you think! Unfortunately, I don't think this will be capable of live-preview of the background/subtracted images, but does visualize all of the various input parameters and does so in a way that isn't too cluttered (and hopefully is still intuitive - cc @Jenneh?).

Screen.Recording.2022-07-21.at.4.12.00.PM.mov

A slightly more complex workflow where you might want to use separate traces for the background and extraction would then look something like this

Screen.Recording.2022-07-21.at.4.20.33.PM.mov

@PatrickOgle
Copy link
Contributor

PatrickOgle commented Jul 21, 2022

Here is an example of static matplotlib visualizations that I find useful when performing an extraction, top to bottom:

  1. Trace and extraction window on original 2D spectrum. Background locations (not shown) would be useful here too.
  2. Trace and extraction window on background-subtracted 2D spectrum
  3. Left: Spatial (cross-dispersion profile, with median trace location indicated (KosmosTrace dotted vs. PolyTrace (solid)).
    3: Right: Trace y location vs x-pixel (for 4 different traces).
  4. The extracted spectrum (1D
    spectral_extraction_visualization
    spectrum viewer).
  5. Ignore--specific to my use case.

We will want at minimum 1 and 2, with 3 as nice-to have. 4. is already implemented.

@kecnry
Copy link
Member Author

kecnry commented Jul 21, 2022

Ok, that's very useful as a reference, thanks!

(1) is implemented above in the comment I posted almost exactly as you posted.
(2) is possible, but probably will require the user to export the subtracted image into the viewer and select the layer manually (or maybe we can have some control in the plugin to do that in one step).
(3) would probably require a small plot in the plugin (similar to Imviz's line profiles). Or maybe we just need a more general plugin/viewer for plotting the cross-dispersion in general? I can see how this would be quite useful though and specviz2d being restricted to the two viewers will be limiting to the user.

Comment on lines 255 to 256
# TODO: range(len(...)) is a temporary hack for this data displaying in meters instead of pixels
self.marks['trace'].update_xy(range(len(trace.trace)), trace.trace)
Copy link
Member Author

Choose a reason for hiding this comment

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

will definitely want to fix this or find a workaround so that the underlying bug doesn't become a blocker to this PR 🐱

@kecnry kecnry force-pushed the plugin-specreduce-trace branch 4 times, most recently from 8f420b4 to 98f89a8 Compare July 22, 2022 16:52
@kecnry kecnry changed the title Plugin: spectral extraction (trace) Plugin: spectral extraction Jul 22, 2022
@kecnry
Copy link
Member Author

kecnry commented Jul 22, 2022

@havok2063 - I managed to implement your suggestion to use this as the default extraction method (if the user only loads a 2D spectrum). It currently defaults to a simple extraction with the trace set somewhat intelligently based on median of the row number of the brightest pixel in each column and with a width of 10% the full image height. When you open the plugin, you'll then see the settings that were used to extract that spectrum, and the snackbar is updated to state: "The collapsed 1D spectrum was generated automatically. Use the spectral extraction plugin for custom extraction."

Screen.Recording.2022-07-22.at.2.25.29.PM.mov

@kecnry kecnry force-pushed the plugin-specreduce-trace branch 2 times, most recently from c9011d3 to 4e65f50 Compare July 22, 2022 18:48
@havok2063
Copy link
Collaborator

@kecnry That looks great! This plugin vastly improves the reasons for using Specviz2d. Can we change the snackbar message to the following? "The collapsed 1D spectrum was generated automatically. See the spectral extraction plugin for details or to perform a custom extraction."

One follow-up question, if someone performs a custom extraction in the GUI, is there a GUI way to save/download it as a file. Thinking about the use case of using this in MAST.

@pllim
Copy link
Contributor

pllim commented Jul 22, 2022

I thought Specviz2D was a temporarily solution until "something" happens? We don't even really document it in the user docs. Should we start?

@@ -174,6 +174,7 @@ Using Jdaviz
imviz/index.rst
specviz/index.rst
cubeviz/index.rst
specviz2d/index.rst
Copy link
Contributor

Choose a reason for hiding this comment

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

Need to add specviz2d stuff to API docs too?

Also add new Specviz2D section to change log template in the release instructions?

On GitHub itself, should I create a new Specviz2D label and add corresponding Issue and Bug templates?

Copy link
Member Author

Choose a reason for hiding this comment

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

Since specviz2d is currently used by MAST (which links to a non-existent RTD page), I think we should... and we can always merge with mosviz later if we decide to go that route. Full docs are out-of-scope for this PR, I think/hope, but I just put the bare minimum so that all the plugin links point somewhere appropriate.

I added a specviz2d label in GitHub already (for this PR) and added a custom section in the change log (but not the template). The helper was already in the docs, but I'll add this plugin as well, thanks for catching that!

Copy link
Contributor

Choose a reason for hiding this comment

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

The book-keeping stuff (templates, release instructions) can be done after this is merged. Thanks!

Copy link
Contributor

Choose a reason for hiding this comment

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

I'll let @rosteen decide if anything in JIRA needs updating to include specviz2d...

kecnry and others added 12 commits August 5, 2022 09:07
* plotting the 1D spectrum in wavelength/frequency and linking to the 2D spectrum viewer can have adverse affects when the mapping is highly non-linear
* previous behavior in main was to plot in pixel-space but had incorrect wavelength label/units on the x-axis (and in the accessed spectrum1d object).  This PR will partly fix that by being consistent with units, but no longer attempts to plot in actual wavelengths until a more general solution is implemented.
* UserWarning from traitlets was being caused by setting the x/y values on the bqplot line, by casting to an array, this goes away
* now that extraction replaces collapse, the NAXIS meta is no longer set.  As far as I can tell, this is unused so can be safely removed from the test.  If that isn't the case, we can manually add to the meta-data when extracting instead.
* for now setting to False, but could see the argument that they should default to True to mimic the behavior of the UI buttons which do add data to the app
* can be re-implemented once the glue-astronomy PR is merged and released
Co-authored-by: Ricky O'Steen <39831871+rosteen@users.noreply.github.com>
* could cause confusion with the actual spectral line in the 2d spectrum viewer
* the "accordion" container and the mouseover text includes the necessary context
@kecnry
Copy link
Member Author

kecnry commented Aug 5, 2022

Rebased on top of #1538 which should fix the bug found by @rosteen and @javerbukh.

@rosteen
Copy link
Collaborator

rosteen commented Aug 9, 2022

I think this looks good to me now, thanks for addressing those comments.

@pllim
Copy link
Contributor

pllim commented Aug 9, 2022

I feel like @ojustino should give the second approval since he has been very involved in specreduce.

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.

Looks good to me, thanks for addressing all the feedback! I'm OK with @ojustino at least taking a look at this monster of a PR before merging 😄

@kecnry kecnry mentioned this pull request Aug 9, 2022
10 tasks
@ojustino
Copy link
Contributor

ojustino commented Aug 9, 2022

Even though it uses specreduce, my understanding of the point of constructing the plugin this way was that this step's development focus would solely be on the jdaviz side. Given that, and a low likelihood that I'll be able to review it today (though I do plan to catch up soon), please don't delay a merge on my account.

@kecnry
Copy link
Member Author

kecnry commented Aug 9, 2022

Thanks for the thorough reviews! @ojustino - I'll go ahead and merge then - I know the plan is to continue to iterate on this, so whenever you do get a chance to try it, feel free to recommend or make any changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
plugin Label for plugins common to multiple configurations Ready for final review specviz specviz2d
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Provide info on 1d extraction for Specviz2d
7 participants