-
Notifications
You must be signed in to change notification settings - Fork 75
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
Improve coordinates display panel for spectrum viewer #1894
Conversation
This comment was marked as resolved.
This comment was marked as resolved.
3886384
to
b1f465d
Compare
Codecov ReportBase: 91.86% // Head: 91.93% // Increases project coverage by
Additional details and impacted files@@ Coverage Diff @@
## main #1894 +/- ##
==========================================
+ Coverage 91.86% 91.93% +0.07%
==========================================
Files 140 140
Lines 15069 15310 +241
==========================================
+ Hits 13843 14076 +233
- Misses 1226 1234 +8
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. ☔ View full report at Codecov. |
gs = GaussianSmooth(app=app) | ||
gs.dataset_selected = 'test' | ||
gs = cubeviz_helper.plugins['Gaussian Smooth']._obj | ||
gs.dataset_selected = 'test[FLUX]' |
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.
There is slight behavior change when you use the proper route to load the data into Cubeviz. I think this is more correct as a test because this is how user will actually load it.
|
||
@pytest.mark.filterwarnings("ignore::UserWarning") |
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 moved the warning check to the affected line. This way, we won't accidentally ignore warning that we're not supposed to ignore.
p.s. I actually think it is ok to merge this without the marker thingy, but I can also wait if everyone else wants the marker to be part of this PR. |
# TODO: Is there a way to cache this? | ||
sp = lyr.layer.get_object( | ||
cls=Spectrum1D, statistic=getattr(self.state, 'function', None)) |
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 you just use the arrays in the Lines object instead? If that isn't accessible from the layer, we could instead loop through self.figure.marks
(but would then need to filter out marks that are not corresponding to data entries, etc).
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 can try using the marks if you tell me how to properly grab them. I get lost in all the spectrum viewer internals.
Will using marks be compatible with unit conversion (when it finally works) and what is the risk of it breaking if we refactor the display stuff inside spectrum viewer?
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.
Also, would using marks work for Cubeviz and Mosviz?
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.
You should be able to pull the units from the figure as well, but will also need to account for as_steps
similar to how is done for the cubeviz slider
jdaviz/jdaviz/configs/cubeviz/helper.py
Lines 103 to 106 in 66adb92
x_all = sv.native_marks[0].x | |
if sv.state.layers[0].as_steps: | |
# then the marks have been doubled in length (each point duplicated) | |
x_all = x_all[::2] |
Either way, it's probably useful to cache in the plugin and update whenever the underlying data changes, but that might require a significant refactor of the plugin code. Right now, cubeviz is very noticeably laggy, I suspect because of this line and the extra expense of re-collapsing and creating a Spectrum1D
object at every mouse move event)
Screen.Recording.2022-12-30.at.8.44.26.AM.mov
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.
In that case... I wonder if part of this can be refactored out so all the viz with spectrum viewer can reuse this same code. What do you think?
jdaviz/jdaviz/configs/cubeviz/helper.py
Line 89 in 66adb92
def select_wavelength(self, wavelength): |
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 think the logic needs to be quite different here (can't just assume the first marks entry in specviz, for example). But if there is any part that can be refactored to be shared, I'm all for that. But with the complication of as_steps
, I'm beginning to think just caching might be the cleanest way to go.
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.
The cleanest way to cache is probably deep upstream here though I have a feeling they won't want it because of extra memory usage...
The logic for selecting the closest spectrum doesn't behave as I'd expect. See the following example (which uses pllim#8 to display a marker at the currently exposed coordinates): Screen.Recording.2022-12-29.at.3.13.37.PM.mov |
I think I know what is happening. The distance math is pretty basic radius calculation using raw wave and flux values. So in the video, your mouse position results in distance in Y dominating the calculations (flux value is much higher than wave) and my math does not check if the X is outside a spectrum's wave bounds. So I think the fix shouldn't be hard. Good catch! |
Re: #1894 (comment)
import numpy as np
from astropy import units as u
from specutils import Spectrum1D
from jdaviz import Specviz
wave_1 = np.linspace(6000, 7000, 10) * u.AA
flux_1 = ([1200] * wave_1.size) * u.nJy
sp_1 = Spectrum1D(flux=flux_1, spectral_axis=wave_1)
wave_2 = wave_1 + (800 * u.AA)
flux_2 = ([60] * wave_2.size) * u.nJy # corrected
sp_2 = Spectrum1D(flux=flux_2, spectral_axis=wave_2)
specviz_helper = Specviz()
specviz_helper.load_spectrum(sp_1, data_label='left')
specviz_helper.load_spectrum(sp_2, data_label='right')
specviz_helper.show() |
This comment was marked as resolved.
This comment was marked as resolved.
b1f465d
to
bae928f
Compare
I find it quite disorienting to see the jumpy marker and the mouse moving at different rates when I do mouseover. I wonder if @Jenneh has ideas. |
Does pllim#8 (comment) help at all (hiding the marker during zoom/subset actions)? My vote would be to include the marker for now since I think it adds a lot of important context to the mouseover display and avoids confusion/misinterpretation, and if it becomes annoying to us or users we can consider styling tweaks (color, marker, markersize, etc) and/or a toggle somewhere (perhaps directly in the space occupied by the mouseover coordinates since there isn't anything to display there when not hovering over a plot - see #1713 for a similar concept). |
9be2cf4
to
f2600e9
Compare
Display has been updated to show cursor coordinates on the top row and move the index to the spectral axis row, and changing the marker to a vertical rectangle. Any refactoring and ability to "lock" a layer will be deferred for follow-up efforts. Screen.Recording.2023-01-05.at.2.37.37.PM.mov |
644e980
to
9d06095
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.
Looks good to me, the feature works and seems quite performant. I checked that it works for multiple spectra, including a collapsed spatial subset. The "closest spectrum" behavior seems intuitive for well separated spectra, although I can see how it might get annoying with overlapping spectra - but locking is a follow up.
The only quibble I have is that I would prefer the marker (the blue rectangle) to be thinner, but that's not a blocker.
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 looks great! Leaving approval with a few comments.
@@ -53,3 +83,7 @@ def set_coords(self, sky, unreliable_world=False, unreliable_pixel=False): | |||
self.world_dec_deg = world_dec_deg | |||
self.unreliable_world = unreliable_world | |||
self.unreliable_pixel = unreliable_pixel | |||
if unreliable_world: |
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.
Isn't this statement always true? 😏
if _class == Spectrum1D: | ||
layer_data = lyr.get_object(cls=_class, statistic=statistic) | ||
else: | ||
layer_data = lyr.get_object(cls=_class) |
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.
Will this logic ignore any masks associated with the spectrum, which could be accessible via get_subset_object
rather than get_object
?
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 am not familiar with how mask is supposed to work in Jdaviz. What is the workflow I should try to answer this question?
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.
Actually, now that I look at the diff again, these calls also predate the PR, so addressing this comment is out of scope here.
|
||
data_x = layer_state.layer.data.get_object().spectral_axis | ||
data_y = layer_state.layer.data.get_object().flux.value | ||
data_obj = lyr.data.get_object() |
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.
Should we be explicit that cls=Spectrum1D
here, or is that guaranteed elsewhere? When we support translation to/from NDDataArray
from astropy/astropy#14175, we should be prepared to be specific.
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.
Here, I merely cached the get_object()
output. The actual call predates this PR, so addressing this is out of scope here.
if cache_key in self.jdaviz_app._get_object_cache: | ||
sp = self.jdaviz_app._get_object_cache[cache_key] | ||
else: | ||
sp = self.jdaviz_app.get_data_from_viewer('spectrum-viewer', |
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.
Could we change 'spectrum-viewer'
to self.jdaviz_app._default_spectrum_viewer_reference_name
?
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.
Done. Good catch!
in all the configurations supported by Jdaviz.
when out of bounds.
spec1d mouseover. Also remove unnecessary re-computation in the internals. A new internal cache on app level is introduced.
* only used in spectrum profile viewers * currently ALWAYS on
(or default tool - slice in cubeviz, for example)
* including clearing cache when subset is changed and ignoring hidden layers
To me, would be nicer if the marker is semi-transparent or just a simple "x" but I should defer to @Jenneh on this in a follow-up effort after this PR is merged. |
9d06095
to
18c9d34
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.
Description
This pull request is to implement the following feature request:
TODO
PaddedSpectrumWCS
and notSpectralCoordinates
.Change log entry
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, maintainershould 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.
trivial
label.