Skip to content

Commit

Permalink
Improved spectrum info panel for spectrum viewers
Browse files Browse the repository at this point in the history
in all the configurations supported by Jdaviz.
  • Loading branch information
pllim committed Dec 21, 2022
1 parent ecc2658 commit b1f465d
Show file tree
Hide file tree
Showing 10 changed files with 273 additions and 42 deletions.
8 changes: 8 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ Cubeviz

- Added Slice plugin player control buttons. [#1848]

- Improved mouseover info display for spectrum viewer. [#1894]

Imviz
^^^^^

Expand All @@ -41,13 +43,17 @@ Mosviz

- ``load_data`` method can now load JWST NIRCam and NIRSpec level 2 data. [#1835]

- Improved mouseover info display for spectrum viewer. [#1894]

Specviz
^^^^^^^

- Spectrum viewer now shows X and Y values under cursor. [#1759]

- Switch to opt-in concatenation for multi-order x1d spectra. [#1659]

- Improved mouseover info display for spectrum viewer. [#1894]

Specviz2d
^^^^^^^^^

Expand All @@ -56,6 +62,8 @@ Specviz2d

- Add dropdown for choosing background statistic (average or median). [#1922]

- Improved mouseover info display for spectrum viewer. [#1894]

API Changes
-----------

Expand Down
10 changes: 10 additions & 0 deletions docs/specviz/displaying.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ data menu.

.. image:: img/data_tab.png

.. _specviz_cursor_info:

Cursor Information
==================

By moving your cursor along the spectrum viewer, you will be able to see information on the
index, spectral axis value, and flux value of the closest data point to the cursor
(not to be confused with the actual cursor position).
This information is displayed in the top bar of the UI, on the middle-right side.

Home
====

Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
import pytest
from jdaviz import Application
from astropy.utils.exceptions import AstropyUserWarning
from specutils import Spectrum1D

from jdaviz.configs.default.plugins.gaussian_smooth.gaussian_smooth import GaussianSmooth


def test_linking_after_spectral_smooth(spectrum1d_cube):

app = Application(configuration="cubeviz")
def test_linking_after_spectral_smooth(cubeviz_helper, spectrum1d_cube):
app = cubeviz_helper.app
dc = app.data_collection
app.add_data(spectrum1d_cube, 'test')
app.add_data_to_viewer('flux-viewer', 'test')
cubeviz_helper.load_data(spectrum1d_cube, data_label='test')
spec_viewer = cubeviz_helper.app.get_viewer('spectrum-viewer')

assert len(dc) == 1

gs = GaussianSmooth(app=app)
gs.dataset_selected = 'test'
gs = cubeviz_helper.plugins['Gaussian Smooth']._obj
gs.dataset_selected = 'test[FLUX]'
gs.mode_selected = 'Spectral'
gs.stddev = 3.2
gs.add_to_viewer_selected = 'None'
Expand All @@ -40,8 +37,8 @@ def test_linking_after_spectral_smooth(spectrum1d_cube):
# itself is prepended to the default label, and there is no longer
# an overwrite warning.
assert len(gs.dataset_items) == 2
assert gs.dataset_selected == 'test'
assert gs.results_label == 'test spectral-smooth stddev-3.2'
assert gs.dataset_selected == 'test[FLUX]'
assert gs.results_label == 'test[FLUX] spectral-smooth stddev-3.2'
assert gs.results_label_overwrite is False

assert len(dc) == 2
Expand All @@ -68,21 +65,109 @@ def test_linking_after_spectral_smooth(spectrum1d_cube):
assert dc.external_links[2].cids1[0] == dc[0].pixel_component_ids[2]
assert dc.external_links[2].cids2[0] == dc[-1].pixel_component_ids[2]

# Mouseover should automatically jump from one spectrum
# to another, depending on which one is closer.

spec_viewer.on_mouse_or_key_event({'event': 'mousemove', 'domain': {'x': 4.633e-7, 'y': 60}})
assert spec_viewer.label_mouseover.pixel == 'x=01.0'
assert spec_viewer.label_mouseover.world_label_prefix == 'Wave'
assert spec_viewer.label_mouseover.world_ra == '4.62360e-07'
assert spec_viewer.label_mouseover.world_dec == 'm'
assert spec_viewer.label_mouseover.world_label_prefix_2 == 'Flux'
assert spec_viewer.label_mouseover.world_ra_deg == '9.20000e+01'
assert spec_viewer.label_mouseover.world_dec_deg == 'Jy'
assert spec_viewer.label_mouseover.icon == 'a'

spec_viewer.on_mouse_or_key_event({'event': 'mousemove', 'domain': {'x': 4.633e-7, 'y': 20}})
assert spec_viewer.label_mouseover.pixel == 'x=01.0'
assert spec_viewer.label_mouseover.world_label_prefix == 'Wave'
assert spec_viewer.label_mouseover.world_ra == '4.62360e-07'
assert spec_viewer.label_mouseover.world_dec == 'm'
assert spec_viewer.label_mouseover.world_label_prefix_2 == 'Flux'
assert spec_viewer.label_mouseover.world_ra_deg == '1.47943e+01'
assert spec_viewer.label_mouseover.world_dec_deg == 'Jy'
assert spec_viewer.label_mouseover.icon == 'b'

# Check mouseover behavior when we hide everything.
for lyr in spec_viewer.layers:
lyr.visible = False

spec_viewer.on_mouse_or_key_event({'event': 'mousemove', 'domain': {'x': 4.633e-7, 'y': 60}})
assert spec_viewer.label_mouseover.pixel == ''
assert spec_viewer.label_mouseover.world_label_prefix == '\xa0'
assert spec_viewer.label_mouseover.world_ra == ''
assert spec_viewer.label_mouseover.world_dec == ''
assert spec_viewer.label_mouseover.world_label_prefix_2 == '\xa0'
assert spec_viewer.label_mouseover.world_ra_deg == ''
assert spec_viewer.label_mouseover.world_dec_deg == ''
assert spec_viewer.label_mouseover.icon == ''


@pytest.mark.filterwarnings("ignore::UserWarning")
def test_spatial_convolution(cubeviz_helper, spectrum1d_cube):
dc = cubeviz_helper.app.data_collection
cubeviz_helper.app.add_data(spectrum1d_cube, 'test')
cubeviz_helper.app.add_data_to_viewer('flux-viewer', 'test')
cubeviz_helper.load_data(spectrum1d_cube, data_label='test')

gs = GaussianSmooth(app=cubeviz_helper.app)
gs.dataset_selected = 'test'
gs = cubeviz_helper.plugins['Gaussian Smooth']._obj
gs.dataset_selected = 'test[FLUX]'
gs.mode_selected = 'Spatial'
gs.stddev = 3
assert gs.results_label == 'spatial-smooth stddev-3.0'
gs.vue_apply()
with pytest.warns(
AstropyUserWarning,
match='The following attributes were set on the data object, but will be ignored'):
gs.vue_apply()

assert len(dc) == 2
assert dc[1].label == "spatial-smooth stddev-3.0"
assert dc[1].shape == (2, 4, 2) # specutils moved spectral axis to last
assert (dc["spatial-smooth stddev-3.0"].get_object(cls=Spectrum1D, statistic=None).shape
== (4, 2, 2))
== (2, 4, 2))


def test_spectrum1d_smooth(specviz_helper, spectrum1d):
dc = specviz_helper.app.data_collection
specviz_helper.load_data(spectrum1d, data_label='test')
spec_viewer = specviz_helper.app.get_viewer('spectrum-viewer')

gs = specviz_helper.plugins['Gaussian Smooth']._obj
gs.dataset_selected = 'test'
gs.mode_selected = 'Spectral'
gs.stddev = 10
gs.vue_apply()

assert len(dc) == 2
assert dc[1].label == 'smooth stddev-10.0'

# Mouseover should automatically jump from one spectrum
# to another, depending on which one is closer.

spec_viewer.on_mouse_or_key_event({'event': 'mousemove', 'domain': {'x': 6400, 'y': 120}})
assert spec_viewer.label_mouseover.pixel == 'x=02.0'
assert spec_viewer.label_mouseover.world_label_prefix == 'Wave'
assert spec_viewer.label_mouseover.world_ra == '6.44444e+03'
assert spec_viewer.label_mouseover.world_dec == 'Angstrom'
assert spec_viewer.label_mouseover.world_label_prefix_2 == 'Flux'
assert spec_viewer.label_mouseover.world_ra_deg == '1.35366e+01'
assert spec_viewer.label_mouseover.world_dec_deg == 'Jy'
assert spec_viewer.label_mouseover.icon == 'a'

spec_viewer.on_mouse_or_key_event({'event': 'mousemove', 'domain': {'x': 6400, 'y': 5}})
assert spec_viewer.label_mouseover.pixel == 'x=02.0'
assert spec_viewer.label_mouseover.world_label_prefix == 'Wave'
assert spec_viewer.label_mouseover.world_ra == '6.44444e+03'
assert spec_viewer.label_mouseover.world_dec == 'Angstrom'
assert spec_viewer.label_mouseover.world_label_prefix_2 == 'Flux'
assert spec_viewer.label_mouseover.world_ra_deg == '5.34688e+00'
assert spec_viewer.label_mouseover.world_dec_deg == 'Jy'
assert spec_viewer.label_mouseover.icon == 'b'

# Out-of-bounds should lock to closest edge value.
spec_viewer.on_mouse_or_key_event({'event': 'mousemove', 'domain': {'x': 5500, 'y': 120}})
assert spec_viewer.label_mouseover.pixel == 'x=00.0'
assert spec_viewer.label_mouseover.world_label_prefix == 'Wave'
assert spec_viewer.label_mouseover.world_ra == '6.00000e+03'
assert spec_viewer.label_mouseover.world_dec == 'Angstrom'
assert spec_viewer.label_mouseover.world_label_prefix_2 == 'Flux'
assert spec_viewer.label_mouseover.world_ra_deg == '1.24967e+01'
assert spec_viewer.label_mouseover.world_dec_deg == 'Jy'
assert spec_viewer.label_mouseover.icon == 'a'
6 changes: 6 additions & 0 deletions jdaviz/configs/imviz/plugins/coords_info/coords_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class CoordsInfo(TemplateMixin):
pixel = Unicode("").tag(sync=True)
value = Unicode("").tag(sync=True)
world_label_prefix = Unicode("\u00A0").tag(sync=True)
world_label_prefix_2 = Unicode("\u00A0").tag(sync=True)
world_label_icrs = Unicode("\u00A0").tag(sync=True)
world_label_deg = Unicode("\u00A0").tag(sync=True)
world_ra = Unicode("").tag(sync=True)
Expand All @@ -24,6 +25,7 @@ class CoordsInfo(TemplateMixin):

def reset_coords_display(self):
self.world_label_prefix = '\u00A0'
self.world_label_prefix_2 = '\u00A0'
self.world_label_icrs = '\u00A0'
self.world_label_deg = '\u00A0'
self.world_ra = ''
Expand Down Expand Up @@ -53,3 +55,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:
self.world_label_prefix_2 = '(est.)'
else:
self.world_label_prefix_2 = '\u00A0'
6 changes: 3 additions & 3 deletions jdaviz/configs/imviz/plugins/coords_info/coords_info.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@
</tr>
<tr :style="unreliable_world ? 'color: #B8B8B8' : ''">
<td width="42"><b>{{ world_label_prefix }}</b></td>
<td width="115">{{ world_ra }}</td>
<td :width="world_label_prefix == 'Wave' ? 85 : 115">{{ world_ra }}</td>
<td width="120">{{ world_dec }}</td>
<td>{{ world_label_icrs }}</td>
</tr>
<tr :style="unreliable_world ? 'color: #B8B8B8' : ''">
<td width="42">{{ unreliable_world ? '(est.)' : '' }}</td>
<td width="115">{{ world_ra_deg }}</td>
<td width="42" :style="unreliable_world ? '' : 'font-weight: bold'">{{ world_label_prefix_2 }}</td>
<td :width="world_label_prefix == 'Wave' ? 85 : 115">{{ world_ra_deg }}</td>
<td width="120">{{ world_dec_deg }}</td>
<td>{{ world_label_deg }}</td>
</tr>
Expand Down
1 change: 1 addition & 0 deletions jdaviz/configs/imviz/tests/test_linking.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ def test_wcslink_rotated(self):
# but cursor is outside GWCS bounding box
assert self.viewer.label_mouseover.unreliable_world
assert self.viewer.label_mouseover.unreliable_pixel
assert self.viewer.label_mouseover.world_label_prefix_2 == '(est.)'


class TestLink_GWCS_GWCS(BaseImviz_GWCS_GWCS):
Expand Down
24 changes: 22 additions & 2 deletions jdaviz/configs/mosviz/tests/test_data_loading.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ def test_load_single_image_multi_spec(mosviz_helper, mos_image, spectrum1d, mos_
spectra2d = [mos_spectrum2d] * 3

image_viewer = mosviz_helper.app.get_viewer('image-viewer')
spec1d_viewer = mosviz_helper.app.get_viewer('spectrum-viewer')
spec2d_viewer = mosviz_helper.app.get_viewer('spectrum-2d-viewer')

# Coordinates info panel should not crash even when nothing is loaded.
image_viewer.on_mouse_or_key_event({'event': 'mouseover'})
Expand All @@ -176,14 +178,15 @@ def test_load_single_image_multi_spec(mosviz_helper, mos_image, spectrum1d, mos_
assert len(qtable) == 3

# Also check coordinates info panels for Mosviz image viewer.
# 1D spectrum viewer panel is already tested in Specviz.
# 2D spectrum viewer panel is already tested in Specviz2d.
# 1D spectrum viewer panel is also tested in Specviz.
# 2D spectrum viewer panel is also tested in Specviz2d.

image_viewer.on_mouse_or_key_event({'event': 'mousemove', 'domain': {'x': 0, 'y': 0}})
assert image_viewer.label_mouseover.pixel == 'x=000.0 y=000.0'
assert image_viewer.label_mouseover.value == '+3.74540e-01 Jy'
assert image_viewer.label_mouseover.world_ra_deg == '5.0297844783'
assert image_viewer.label_mouseover.world_dec_deg == '4.9918991917'
assert image_viewer.label_mouseover.icon == 'a'

image_viewer.on_mouse_or_key_event({'event': 'mousemove', 'domain': {'x': None, 'y': 0}})
assert image_viewer.label_mouseover.pixel == ''
Expand All @@ -203,6 +206,23 @@ def test_load_single_image_multi_spec(mosviz_helper, mos_image, spectrum1d, mos_
assert image_viewer.label_mouseover.world_ra_deg == ''
assert image_viewer.label_mouseover.world_dec_deg == ''

spec2d_viewer.on_mouse_or_key_event({'event': 'mousemove', 'domain': {'x': 10, 'y': 100}})
assert spec2d_viewer.label_mouseover.pixel == 'x=00010.0 y=00100.0'
assert spec2d_viewer.label_mouseover.value == '+8.12986e-01 '
assert spec2d_viewer.label_mouseover.world_ra_deg == ''
assert spec2d_viewer.label_mouseover.world_dec_deg == ''
assert spec2d_viewer.label_mouseover.icon == 'b'

spec1d_viewer.on_mouse_or_key_event({'event': 'mousemove', 'domain': {'x': 7000, 'y': 170}})
assert spec1d_viewer.label_mouseover.pixel == 'x=04.0'
assert spec1d_viewer.label_mouseover.world_label_prefix == 'Wave'
assert spec1d_viewer.label_mouseover.world_ra == '6.88889e+03'
assert spec1d_viewer.label_mouseover.world_dec == 'Angstrom'
assert spec1d_viewer.label_mouseover.world_label_prefix_2 == 'Flux'
assert spec1d_viewer.label_mouseover.world_ra_deg == '1.35436e+01'
assert spec1d_viewer.label_mouseover.world_dec_deg == 'Jy'
assert spec1d_viewer.label_mouseover.icon == 'c'


def test_zip_error(mosviz_helper, tmp_path):
'''
Expand Down
Loading

0 comments on commit b1f465d

Please sign in to comment.