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

fix display units moment maps #3169

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ New Features
------------

- Added flux/surface brightness translation and surface brightness
unit conversion in Cubeviz and Specviz. [#2781, #2940, #3088, #3111, #3113, #3129, #3139, #3149, #3155]
unit conversion in Cubeviz and Specviz. [#2781, #2940, #3088, #3111, #3113, #3129, #3139, #3149, #3155, #3169]

- Plugin tray is now open by default. [#2892]

Expand Down
51 changes: 24 additions & 27 deletions jdaviz/configs/cubeviz/plugins/moment_maps/moment_maps.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ class MomentMap(PluginTemplateMixin, DatasetSelectMixin, SpectralSubsetSelectMix
# saving client-side is supported
export_enabled = Bool(True).tag(sync=True)

# for unit conversion, only enabled now for moment 0
moment_0_display_unit = Unicode().tag(sync=True)

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

Expand Down Expand Up @@ -175,6 +178,7 @@ def _set_data_units(self, event={}):
self.send_state("output_unit_selected")

# either 'Flux' or 'Surface Brightness'
# this will eventually always be 'surface brightness'
orig_flux_or_sb = self.output_unit_items[0]['label']

unit_dict = {orig_flux_or_sb: "",
Expand All @@ -197,24 +201,19 @@ def _set_data_units(self, event={}):
self.dataset_spectral_unit = sunit
unit_dict["Spectral Unit"] = sunit

# get flux/SB units
if self.spectrum_viewer and hasattr(self.spectrum_viewer.state, 'y_display_unit'):
if self.spectrum_viewer.state.y_display_unit is not None:
unit_dict[orig_flux_or_sb] = self.spectrum_viewer.state.y_display_unit
else:
# spectrum_viewer.state will only have x/y_display_unit if unit conversion has
# been done if not, get default flux units which should be the units displayed
unit_dict[orig_flux_or_sb] = data.get_component('flux').units
else:
# spectrum_viewer.state will only have x/y_display_unit if unit conversion has
# been done if not, get default flux units which should be the units displayed
unit_dict[orig_flux_or_sb] = data.get_component('flux').units

# figure out if label should say 'Flux' or 'Surface Brightness'
sb_or_flux_label = "Flux"
is_unit_solid_angle = check_if_unit_is_per_solid_angle(unit_dict[orig_flux_or_sb])
if is_unit_solid_angle is True:
# since this is the method subscribed to 'global display unit changed',
# we could get this information from the broadcasted message and not respond
# to every message, but that would require some refactoring,
# so use get_display_unit for now.
comp = data.get_component(self.dataset.selected_dc_item.main_components[0])

# is cube data a flux or sb? this check can go away when cubes are forced to sb
if check_if_unit_is_per_solid_angle(comp.units):
sb_or_flux_label = "Surface Brightness"
unit_dict[orig_flux_or_sb] = self.app._get_display_unit('sb')
else:
sb_or_flux_label = "Flux"
unit_dict[orig_flux_or_sb] = self.app._get_display_unit('flux')

# Update units in selection item dictionary
for item in self.output_unit_items:
Expand Down Expand Up @@ -343,21 +342,19 @@ def calculate_moment(self, add_data=True):
# convert units for moment 0, which is the only currently supported
# moment for using converted units.
if n_moment == 0:
# get flux/SB units
if self.spectrum_viewer and hasattr(self.spectrum_viewer.state, 'y_display_unit'):
if self.spectrum_viewer.state.y_display_unit is not None:
flux_sb_unit = self.spectrum_viewer.state.y_display_unit
else:
flux_sb_unit = data.get_component('flux').units
else:
flux_sb_unit = data.get_component('flux').units

# convert unit string to u.Unit so moment map data can be converted
flux_or_sb_display_unit = u.Unit(flux_sb_unit)
# get display units
moment_0_display_unit = self.output_unit_items[0]['unit_str']

# convert unit string to Unit so moment map data can be converted
flux_or_sb_display_unit = u.Unit(moment_0_display_unit)

# account for extra wavelength factor, depending on specutils version
if SPECUTILS_LT_1_15_1:
moment_new_unit = flux_or_sb_display_unit
else:
moment_new_unit = flux_or_sb_display_unit * self.spectrum_viewer.state.x_display_unit # noqa: E501

self.moment = self.moment.to(moment_new_unit)

# Reattach the WCS so we can load the result
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,31 @@ def test_user_api(cubeviz_helper, spectrum1d_cube):
mm.calculate_moment()


def test_moment_calculation(cubeviz_helper, spectrum1d_cube, tmp_path):
@pytest.mark.parametrize("cube_type", ["Surface Brightness", "Flux"])
def test_moment_calculation(cubeviz_helper, spectrum1d_cube,
spectrum1d_cube_sb_unit, cube_type, tmp_path):

if SPECUTILS_LT_1_15_1:
moment_unit = "Jy"
moment_value_str = "+8.00000e+00"
else:
moment_unit = "Jy m"
moment_value_str = "+6.40166e-10"

if cube_type == 'Surface Brightness':
moment_unit += " / sr"
cube = spectrum1d_cube_sb_unit

elif cube_type == 'Flux':
cube = spectrum1d_cube

cube_unit = cube.unit.to_string()

dc = cubeviz_helper.app.data_collection
with warnings.catch_warnings():
warnings.filterwarnings("ignore", message="No observer defined on WCS.*")
cubeviz_helper.load_data(spectrum1d_cube, data_label='test')
cubeviz_helper.load_data(cube, data_label='test')

flux_viewer = cubeviz_helper.app.get_viewer(cubeviz_helper._default_flux_viewer_reference_name)

# Since we are not really displaying, need this to trigger GUI stuff.
Expand All @@ -73,7 +86,7 @@ def test_moment_calculation(cubeviz_helper, spectrum1d_cube, tmp_path):

mm.n_moment = 0 # Collapsed sum, will get back 2D spatial image
assert mm._obj.results_label == 'moment 0'
assert mm.output_unit == "Flux"
assert mm.output_unit == cube_type # cube data in SB should produce result in SB

mm._obj.add_results.viewer.selected = cubeviz_helper._default_uncert_viewer_reference_name
mm._obj.vue_calculate_moment()
Expand All @@ -93,13 +106,13 @@ def test_moment_calculation(cubeviz_helper, spectrum1d_cube, tmp_path):
assert mm._obj.results_label == 'moment 0'
assert mm._obj.results_label_overwrite is True

# Make sure coordinate display works
# Make sure coordinate display works in flux viewer (loaded data, not the moment map)
label_mouseover = cubeviz_helper.app.session.application._tools['g-coords-info']
label_mouseover._viewer_mouse_event(flux_viewer, {'event': 'mousemove',
'domain': {'x': 0, 'y': 0}})
assert flux_viewer.state.slices == (0, 0, 1)
# Slice 0 has 8 pixels, this is Slice 1
assert label_mouseover.as_text() == ("Pixel x=00.0 y=00.0 Value +8.00000e+00 Jy",
assert label_mouseover.as_text() == (f"Pixel x=00.0 y=00.0 Value +8.00000e+00 {cube_unit}",
"World 13h39m59.9731s +27d00m00.3600s (ICRS)",
"204.9998877673 27.0001000000 (deg)")

Expand Down
5 changes: 5 additions & 0 deletions jdaviz/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,11 @@ def spectrum1d_cube():
return _create_spectrum1d_cube_with_fluxunit(fluxunit=u.Jy)


@pytest.fixture
def spectrum1d_cube_sb_unit():
return _create_spectrum1d_cube_with_fluxunit(fluxunit=u.Jy / u.sr)


@pytest.fixture
def spectrum1d_cube_with_uncerts():
return _create_spectrum1d_cube_with_fluxunit(fluxunit=u.Jy, with_uncerts=True)
Expand Down