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

slice: refactor plugin to decouple from cube #2715

Merged
merged 30 commits into from
Mar 8, 2024

Conversation

kecnry
Copy link
Member

@kecnry kecnry commented Feb 19, 2024

Description

This pull request refactors the slice plugin (as a follow-up to #2706) to decouple the slice logic from the cube (so that the slice plugin works with either NO cubes or eventually multiple cubes) and further generalization to disconnect the logic from assumptions about using profile viewers or a spectral axis.

IMPORTANT: This effectively removes exposing and allowing to set a slice by index.

  • allow slice viewer tool to become default when first becoming visible
  • allow downstream to override slice axis at the viewer-level
  • allow for multiple viewers with indicators by using mixins for WithSliceIndicator or WithSliceSelection
  • decouple slice axis from cube and replace with optional (enabled by default, forced to be enabled in cubeviz) "snap to slice" functionality
  • uses scientific notation on the indicator label only if necessary
Screen.Recording.2024-02-20.at.2.10.18.PM.mov

Change log entry

  • Is a change log needed? If yes, is it added to CHANGES.rst? If you want to avoid merge conflicts,
    list the proposed change log here for review and add to CHANGES.rst before merge. If no, maintainer
    should add a no-changelog-entry-needed label.

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 milestone set? Set this to bugfix milestone if this is a bug fix and needs to be released ASAP; otherwise, set this to the next major release milestone. Bugfix milestone also needs an accompanying backport label.
  • After merge, any internal documentations need updating (e.g., JIRA, Innerspace)?

@kecnry kecnry added this to the 3.9 milestone Feb 19, 2024
@github-actions github-actions bot added cubeviz imviz plugin Label for plugins common to multiple configurations labels Feb 19, 2024
@kecnry kecnry force-pushed the slice-refactor branch 7 times, most recently from 6f24ff3 to 13170b8 Compare February 23, 2024 18:46
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.

Still unclear to me how this would work with Baby Shark (and cube without calibration wavelength axis in general).

@@ -305,6 +304,11 @@ def _aperture_selected_changed(self, event={}):
else:
self._background_selected_changed()

@property
def _cubeviz_slice_ind(self):
fv = self.app.get_viewer(self.app._jdaviz_helper._default_flux_viewer_reference_name)
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't know how this would be affected in the future when you allow multiple flux cubes and so on, but I guess we can worry about it in the future.

Copy link
Member Author

Choose a reason for hiding this comment

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

Agreed - for now I was just trying to get the previous behavior in aperture photometry working with the new design. This PR does not allow for multiple cubes, it just helps remove some assumptions in case we want to open that up later.

@kecnry
Copy link
Member Author

kecnry commented Feb 26, 2024

Still unclear to me how this would work with Baby Shark (and cube without calibration wavelength axis in general).

I have not tested this yet (the PR is still in draft - I'm working to fix existing test cases first), but the slicing axis must be in some units, even if it is pixels or dimensionless. So I don't see any design issues that would conflict with this generality - we may just need to make sure the empty unit is handled correctly in the UI and indicator label.

Copy link

codecov bot commented Mar 4, 2024

Codecov Report

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

Project coverage is 88.72%. Comparing base (af8d1b8) to head (d5a732f).
Report is 9 commits behind head on main.

❗ Current head d5a732f differs from pull request most recent head 2eea290. Consider uploading reports for the commit 2eea290 to get more accurate results

Files Patch % Lines
jdaviz/configs/cubeviz/plugins/slice/slice.py 73.74% 47 Missing ⚠️
jdaviz/core/marks.py 91.11% 4 Missing ⚠️
jdaviz/configs/cubeviz/plugins/viewers.py 94.64% 3 Missing ⚠️
...configs/default/plugins/export_plot/export_plot.py 50.00% 2 Missing ⚠️
jdaviz/configs/cubeviz/helper.py 80.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2715      +/-   ##
==========================================
- Coverage   88.85%   88.72%   -0.13%     
==========================================
  Files         108      108              
  Lines       15920    16138     +218     
==========================================
+ Hits        14145    14319     +174     
- Misses       1775     1819      +44     

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

@kecnry kecnry marked this pull request as ready for review March 5, 2024 16:07
Comment on lines 10 to 11
sl = Slice(app=app)
# sl = cubeviz_helper.plugins['Slice']._obj
Copy link
Contributor

Choose a reason for hiding this comment

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

Which one of these makes more sense to use here?

Copy link
Member Author

Choose a reason for hiding this comment

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

I can remove the commented line if we want... I wanted to test to make sure it works both ways. I think in the future we may want to run all tests both ways since they do go through different logic routes... but that's a story for another day.

min_slice = Int(0).tag(sync=True)
max_slice = Int(100).tag(sync=True)
wait = Int(200).tag(sync=True)
slider_throttle = Int(200).tag(sync=True) # milliseconds
Copy link
Contributor

Choose a reason for hiding this comment

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

I noticed that clicking and dragging the slice indicator leaves it a fraction of a second behind my cursor, does that come from this throttle? Is there a particular reason 200 ms was chosen instead of something smaller?

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 throttle was already there (I just renamed it from wait). This definitely will add a floor to the lag that is seen, but if the lag increases beyond this, we definitely should try to optimize the code so that it is more responsive. Is this PR noticeably less responsive than main for you?

Copy link
Contributor

Choose a reason for hiding this comment

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

No it's the same as main. Agreed on your point about coming back to this later and trying to optimize the code.

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.

I left a couple comments but overall the code looks very clean and the slice plugin runs without any issues, nice work! Looking forward to seeing the multiple WithSliceIndicator viewers in LCViz and how that functionality is handled there.

@kecnry
Copy link
Member Author

kecnry commented Mar 6, 2024

Looking forward to seeing the multiple WithSliceIndicator viewers in LCViz and how that functionality is handled there.

Feel free to look at spacetelescope/lcviz#85!

Comment on lines 10 to 11
sl = Slice(app=app)
# sl = cubeviz_helper.plugins['Slice']._obj
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't we prefer cubeviz_helper.plugins['Slice'] since that is the API we are advertising?

Suggested change
sl = Slice(app=app)
# sl = cubeviz_helper.plugins['Slice']._obj
sl = cubeviz_helper.plugins['Slice']._obj

Copy link
Member Author

Choose a reason for hiding this comment

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

One is instantiated at app startup and the other when called. So they run through different logic routes, see my reply above. We really should test both for all cases, but that would take some work. Here I ultimately don't care, I tested both by toggling the comment and it works.

Copy link
Contributor

Choose a reason for hiding this comment

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

But CI cannot do manual toggle like you did. If you want to test them both, then please use pytest.mark.parametrize. Thanks!

Copy link
Member Author

@kecnry kecnry Mar 7, 2024

Choose a reason for hiding this comment

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

ok, I'll just remove the comment then and make a tech debt ticket 🐱 to consider parameterizing over this in all tests. I just had this for convenience to test myself.

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.

Running through concepts/cubeviz_ndarray_gif.ipynb, the behavior isn't quite right. The concepts/cubeviz_wfc3ir_ramp.ipynb has all the problems described in "From array".

From array

X-axis label is called Pixel Axis 2 [x]; a little ugly but I can live with that. However, the Slice plugin says "Wavelength" that is clearly wrong. The play/pause buttons are all broken. Spectrum viewer mouseover is also broken.

Sometimes (seems non-deterministic), the text box under "Wavelength" seems to flash quickly to some float value before "snapping" to an integer index value. For example, I would see something like 2.0344243242 flashed real quick before it settles to 2. Not a show stopper though.

From GIF

Play/pause buttons work but mouseover on spectrum viewer still broken as above.

More shark!

At this point, the play/pause buttons stopped working (after I ran slice_plg.value = 0) but I am not sure why. Four of the buttons are disabled when they are not supposed to (accidentally flipped state?) and the play does not do anything.

Conclusion

Our regression test for "raw numpy cube" is too simple to catch all the subtle problems I saw above.

def test_numpy_cube(cubeviz_helper):

This PR may have made things better for lcviz but it made Cubeviz much less flexible. With this in place, re-using Cubeviz for ramp visualization would be a bit harder because we have to go back and fix the things mentioned above.

If you insist that these cases only exists in "concepts" and so not supported, then I rather we just officially drop support than to have them still load but not work as well as before.

* can always change to be more intelligent based on data and x-display-unit later
@kecnry kecnry requested a review from pllim March 8, 2024 16:52
@pllim
Copy link
Contributor

pllim commented Mar 8, 2024

Failure seems related:

        # Make sure nothing crashes if plugin used without data]
        sl.vue_play_next()
        sl.vue_play_start_stop()
>       assert not sl.is_playing
E       AssertionError: assert not True
...
slice/tests/test_slice.py::test_slice - AssertionError: assert not True
 +  where True = Slice(config='cubeviz', events=[
'create_cube_viewer', 'goto_first', 'goto_last', 'play_next', 'play_prev', 'play_start...le);\n
},\n  }\n</script>\n\n<style>\n  .v-slider {\n    margin: 0px !important;\n  }\n</style>\n'),
vdocs='latest').is_playing

(this would have quite immediately after otherwise, but is hard to reliably test since that is threaded)
@kecnry
Copy link
Member Author

kecnry commented Mar 8, 2024

hmmm, I think that was just because the check was in the thread before and sometimes returned in time to be caught by the assert, but apparently not always. I now duplicated the check before the thread starts so hopefully the test is more reliable 🤞

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.

I pushed a commit to update baby shark concept notebook but there is no need to rerun CI. I will merge now. Thanks!

@pllim pllim merged commit b4cdd08 into spacetelescope:main Mar 8, 2024
2 checks passed
@kecnry kecnry deleted the slice-refactor branch March 8, 2024 20:09
kecnry added a commit to kecnry/jdaviz that referenced this pull request Mar 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cubeviz imviz 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