-
Notifications
You must be signed in to change notification settings - Fork 74
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
Spatial-Spectral highlighting #1528
Spatial-Spectral highlighting #1528
Conversation
86182da
to
0c734a6
Compare
def _get_id(self, mark): | ||
return getattr(mark, '_model_id', None) | ||
|
||
def _setup_shadowing(self, shadowing, sync_traits=[], other_traits=[]): | ||
self._shadowing = shadowing | ||
self._sync_traits = sync_traits | ||
""" | ||
sync_traits: traits to set now, and mirror any changes to shadowing in the future | ||
other_trait: traits to set now, but not mirror in the future | ||
""" | ||
if not hasattr(self, '_shadowing'): | ||
self._shadowing = {} | ||
self._sync_traits = {} | ||
shadowing_id = self._get_id(shadowing) | ||
self._shadowing[shadowing_id] = shadowing | ||
self._sync_traits[shadowing_id] = sync_traits | ||
|
||
# sync initial values | ||
for attr in sync_traits + other_traits: | ||
self._on_shadowing_changed({'name': attr, 'new': getattr(shadowing, attr)}) | ||
self._on_shadowing_changed({'name': attr, | ||
'new': getattr(shadowing, attr), | ||
'owner': shadowing}) | ||
|
||
# subscribe to future changes | ||
shadowing.observe(self._on_shadowing_changed) | ||
|
||
def _on_shadowing_changed(self, change): | ||
if change['name'] in self._sync_traits: | ||
if change['name'] in self._sync_traits.get(self._get_id(change.get('owner')), []): | ||
setattr(self, change['name'], change['new']) | ||
return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this all extends the existing ShadowMixin to be able to shadow multiple marks simultaneously, the API remains the same, so should not affect other marks that make use of this, but we should thoroughly test those (line analysis continuum marks, slice indicator labels, etc)
ddee9f7
to
23d6d0e
Compare
Codecov Report
@@ Coverage Diff @@
## main #1528 +/- ##
==========================================
+ Coverage 85.64% 85.70% +0.06%
==========================================
Files 94 94
Lines 9216 9271 +55
==========================================
+ Hits 7893 7946 +53
- Misses 1323 1325 +2
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. |
This comment was marked as resolved.
This comment was marked as resolved.
oooo good catch, we definitely need to fix that asap - but that doesn't go through any of the logic changed in this PR and I can confirm its also present on main. I'm guessing that was introduced by the recent linking changes? To reproduce:
Edit: filed as #1530, fixed in #1531, will rebase once that is merged into main. |
Oh dear. I was thinking to myself "I'll check that this isn't on main...omg I hope it isn't in main" and hadn't checked yet. |
#1531 has been merged so once this is rebased I can review, but looks good so far! |
23d6d0e
to
3719753
Compare
Rebased and confirmed that on my end fitting a model to a spatial+spectral subset works as expected. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code is code, nice work! 😄
# use Lines/LinesGL (so an isinstance check won't be sufficient here) | ||
layer_marks = [m for m in self.figure.marks if m.__class__.__name__ in ['Lines', 'LinesGL']] | ||
# and now we'll assume that the marks are in the same order as the layers, this should | ||
# be the case as long as the order isn't manually resorted |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hopefully we remember this when/if we introduce layer reordering.
EDIT: User error, please ignore 😅 Just needed a clean conda environment. |
66015e6
to
b5e7e22
Compare
b5e7e22
to
6336eea
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Works as advertised.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't grok everything here. In a nutshell, looks good. Just some minor comments.
Also a shame the branch isn't called what_we_do_in_the_shadows
. 😉
def _get_spatial_subset_layers(self): | ||
return [ls for ls in self.state.layers | ||
if isinstance(getattr(ls.layer, 'subset_state', None), RoiSubsetState)] | ||
|
||
def _get_spectral_subset_layers(self): | ||
return [ls for ls in self.state.layers | ||
if isinstance(getattr(ls.layer, 'subset_state', None), RangeSubsetState)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't we combine this into one and swap the class to be compared depending on a keyword?
layers_list = list(self.state.layers) | ||
# here we'll assume that all custom marks are subclasses of Lines/GL but don't directly | ||
# use Lines/LinesGL (so an isinstance check won't be sufficient here) | ||
layer_marks = [m for m in self.figure.marks if m.__class__.__name__ in ['Lines', 'LinesGL']] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't @duytnguyendtn write basically the same loop just recently somewhere else? Looks so familiar.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmmm, good point. If that's already in main, I could try to replace both of them with a viewer.custom_marks
property or something 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe I am thinking about #1550 that has been merged.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I created a viewer.native_marks
and viewer.custom_marks
... not really intended for public use, but could be useful for internal use. Not sure how everyone feels about those names though or if its worth the extra property on all viewers?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure that I have a strong opinion here. Though I guess my immediate expectation would be more of a nested structure, like viewer.marks
containing the native marks and then you could get the custom via viewer.marks.custom
. But my opinion isn't strong
# need to add marks for every intersection between THIS spectral subset and ALL spatial | ||
spatial_marks = self._get_marks_for_layers(self._get_spatial_subset_layers()) | ||
for spatial_mark in spatial_marks: | ||
new_marks += [ShadowSpatialSpectral(spatial_mark, this_mark)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the coverage say this is not covered?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah, because the existing test in test_subsets/test_region_spectral_spatial
only does spectral then spatial. I'll add a case for the other order to make sure this line gets covered (and test for the presence of the marks).
Edit: added the test, let's hope it now says this line is covered 🤞
* shadows the spectrum of a spatial subset but the mask and styling of a spectral subset
6acbf40
to
f6808b1
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't try to use it but the code LGTM. Thanks!
Unless @duytnguyendtn has opinions about the new method names, I think this is good to merge.
Description
This pull request implements spectral subset highlighting of automatically-collapsed spectra of spatial subsets in the profile viewer of cubeviz. It does so by a new custom bqplot mark which "shadows" the position of the mark corresponding to the spatial-spectrum, but the nan-mask and styling of the mark corresponding to the spectral-subset on the full spectrum. Everytime a new subset layer is added, a mark is created for each combination of the corresponding subset mark and all marks of the other (spatial vs spectral) type. Everytime a subset is removed, the marks are pruned to remove any where one of the referenced marks no longer exists. Pure hacky dark magic at its ugliest/finest.... and because of that this should be tested thoroughly.
Screen.Recording.2022-07-28.at.4.56.32.PM.mov
Screen.Recording.2022-07-28.at.4.58.06.PM.mov
Fixes #1179
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.
trivial
label.CHANGES.rst
?