Skip to content

Commit

Permalink
Add unit conversion plugin with flux conversion disabled
Browse files Browse the repository at this point in the history
Add message to flux conversion dropdown in cubeviz

Have moment map units update after conversion

Update continuum, moment maps, and spectral extraction

Fix model fitting and aperture plugins and add tests
  • Loading branch information
javerbukh committed Mar 26, 2024
1 parent d007a4b commit 7e64afd
Show file tree
Hide file tree
Showing 11 changed files with 66 additions and 20 deletions.
1 change: 1 addition & 0 deletions jdaviz/configs/cubeviz/cubeviz.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ tray:
- g-subset-plugin
- g-markers
- cubeviz-slice
- g-unit-conversion
- g-gaussian-smooth
- g-collapse
- g-model-fitting
Expand Down
16 changes: 11 additions & 5 deletions jdaviz/configs/cubeviz/plugins/moment_maps/moment_maps.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from specutils import manipulation, analysis, Spectrum1D

from jdaviz.core.custom_traitlets import IntHandleEmpty, FloatHandleEmpty
from jdaviz.core.events import SnackbarMessage
from jdaviz.core.events import SnackbarMessage, GlobalDisplayUnitChanged
from jdaviz.core.registries import tray_registry
from jdaviz.core.template_mixin import (PluginTemplateMixin,
DatasetSelectMixin,
Expand Down Expand Up @@ -96,6 +96,8 @@ def __init__(self, *args, **kwargs):

self.dataset.add_filter('is_cube')
self.add_results.viewer.filters = ['is_image_viewer']
self.session.hub.subscribe(self, GlobalDisplayUnitChanged,
handler=self._set_data_units)

if self.app.state.settings.get('server_is_remote', False):
# when the server is remote, saving the file in python would save on the server, not
Expand Down Expand Up @@ -155,12 +157,16 @@ def _set_data_units(self, event={}):
if self.dataset_selected != "":
# Spectral axis is first in this list
data = self.app.data_collection[self.dataset_selected]
if self.app.data_collection[self.dataset_selected].coords is not None:
if (self.spectrum_viewer and hasattr(self.spectrum_viewer.state, 'x_display_unit')
and self.spectrum_viewer.state.x_display_unit is not None):
sunit = self.spectrum_viewer.state.x_display_unit
elif self.app.data_collection[self.dataset_selected].coords is not None:
sunit = data.coords.world_axis_units[0]
self.dataset_spectral_unit = sunit
unit_dict["Spectral Unit"] = sunit
else:
self.dataset_spectral_unit = ""
sunit = ""
self.dataset_spectral_unit = sunit
unit_dict["Spectral Unit"] = sunit

unit_dict["Flux"] = data.get_component('flux').units

# Update units in selection item dictionary
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,6 @@ def test_moment_velocity_calculation(cubeviz_helper, spectrum1d_cube):
uncert_viewer.state._set_axes_aspect_ratio(1)

mm = cubeviz_helper.plugins["Moment Maps"]
print(mm._obj.dataset_selected)
mm._obj.dataset_selected = 'test[FLUX]'

# Test moment 1 in velocity
Expand All @@ -170,6 +169,13 @@ def test_moment_velocity_calculation(cubeviz_helper, spectrum1d_cube):
"World 13h39m59.9731s +27d00m00.3600s (ICRS)",
"204.9998877673 27.0001000000 (deg)")

# Add test for unit conversion
assert mm._obj.output_radio_items[0]['unit_str'] == 'm'
uc_plugin = cubeviz_helper.plugins['Unit Conversion']._obj
uc_plugin.spectral_unit.selected = 'Angstrom'
assert mm._obj.output_radio_items[0]['unit_str'] == 'Angstrom'
uc_plugin.spectral_unit.selected = 'm'

# Test moment 2 in velocity
mm.n_moment = 2
mm.calculate_moment()
Expand Down
18 changes: 18 additions & 0 deletions jdaviz/configs/cubeviz/plugins/slice/slice.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,24 @@ def _on_add_data(self, msg):
# is updated (if enabled)
self._on_value_updated({'new': self.value})

def _update_slice(self, x_all):
# Also update unit when data is updated
self.value_unit = x_all.unit.to_string()

# force value (wavelength/frequency) to update from the current slider slice
self._on_slider_updated({'new': self.slice})

# update data held inside slice indicator and force reverting to original active status
self.slice_indicator._update_data(x_all)

def _viewer_slices_changed(self, value):
# the slices attribute on the viewer state was changed,
# so we'll update the slider to match which will trigger
# the slider observer (_on_slider_updated) and sync across
# any other applicable viewers
if len(value) == 3:
self.slice = float(value[-1])

def _on_select_slice_message(self, msg):
with warnings.catch_warnings():
warnings.simplefilter('ignore', category=UnitsWarning)
Expand Down
7 changes: 7 additions & 0 deletions jdaviz/configs/cubeviz/plugins/slice/tests/test_slice.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ def test_slice(cubeviz_helper, spectrum1d_cube):
cubeviz_helper.select_wavelength(4.62360028e-07)
assert sl.value == slice_values[1]

# Add test for unit conversion
uc_plugin = cubeviz_helper.plugins['Unit Conversion']._obj
uc_plugin.spectral_unit.selected = 'Angstrom'
assert sl.value_unit == 'Angstrom'
cubeviz_helper.select_wavelength(4623.60028)
assert sl.slice == 1

# Test player buttons API

sl.vue_goto_first()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -354,8 +354,7 @@ def get_aperture(self):
# Retrieve flux cube and create an array to represent the cone mask
flux_cube = self._app._jdaviz_helper._loaded_flux_cube.get_object(cls=Spectrum1D,
statistic=None)
# TODO: Replace with code for retrieving display_unit in cubeviz when it is available
display_unit = flux_cube.spectral_axis.unit
display_unit = astropy.units.Unit(self.app._get_display_unit('spectral'))

# Center is reverse coordinates
center = (self.aperture.selected_spatial_region.center.y,
Expand All @@ -372,7 +371,7 @@ def get_aperture(self):
f'Spectral axis unit physical type is {display_unit.physical_type}, '
'must be length for cone aperture')

fac = flux_cube.spectral_axis.value / self.reference_wavelength
fac = flux_cube.spectral_axis.to(display_unit).value / self.reference_wavelength

# TODO: Use flux_cube.spectral_axis.to_value(display_unit) when we have unit conversion.
if isinstance(aperture, CircularAperture):
Expand Down
5 changes: 3 additions & 2 deletions jdaviz/configs/default/plugins/model_fitting/model_fitting.py
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,8 @@ def _warn_if_no_equation(self):

def _get_1d_spectrum(self):
# retrieves the 1d spectrum (accounting for spatial subset for cubeviz, if necessary)
return self.dataset.selected_spectrum_for_spatial_subset(self.spatial_subset_selected) # noqa
return self.dataset.selected_spectrum_for_spatial_subset(self.spatial_subset_selected,
use_display_units=True) # noqa

@observe("dataset_selected", "spatial_subset_selected")
def _dataset_selected_changed(self, event=None):
Expand Down Expand Up @@ -343,7 +344,6 @@ def _dataset_selected_changed(self, event=None):
# Replace NaNs from collapsed Spectrum1D in Cubeviz
# (won't affect calculations because these locations are masked)
selected_spec.flux[np.isnan(selected_spec.flux)] = 0.0

# TODO: can we simplify this logic?
self._units["x"] = str(
selected_spec.spectral_axis.unit)
Expand Down Expand Up @@ -518,6 +518,7 @@ def _initialize_model_component(self, model_comp, comp_label, poly_order=None):
return new_model

def _check_model_component_compat(self, axes=['x', 'y'], display_units=None):
print(display_units, self._units)
if display_units is None:
display_units = [u.Unit(self._units[ax]) for ax in axes]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,18 +127,18 @@ def _on_glue_y_display_unit_changed(self, y_unit):

@observe('spectral_unit_selected')
def _on_spectral_unit_changed(self, *args):
self.hub.broadcast(GlobalDisplayUnitChanged('spectral',
self.spectral_unit.selected,
sender=self))
xunit = _valid_glue_display_unit(self.spectral_unit.selected, self.spectrum_viewer, 'x')
if self.spectrum_viewer.state.x_display_unit != xunit:
self.spectrum_viewer.state.x_display_unit = xunit
self.hub.broadcast(GlobalDisplayUnitChanged('spectral',
self.spectral_unit.selected,
sender=self))

@observe('flux_unit_selected')
def _on_flux_unit_changed(self, *args):
self.hub.broadcast(GlobalDisplayUnitChanged('flux',
self.flux_unit.selected,
sender=self))
yunit = _valid_glue_display_unit(self.flux_unit.selected, self.spectrum_viewer, 'y')
if self.spectrum_viewer.state.y_display_unit != yunit:
self.spectrum_viewer.state.y_display_unit = yunit
self.hub.broadcast(GlobalDisplayUnitChanged('flux',
self.flux_unit.selected,
sender=self))
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,13 @@
label="Flux Unit"
hint="Global display unit for flux."
persistent-hint
:disabled="config === 'cubeviz'"
></v-select>
</v-row>
<v-row v-if="config === 'cubeviz'">
<span class="v-messages v-messages__message text--secondary" style="color: red !important">
Flux conversion is not yet implemented in cubeviz
</span>
</v-row>
</j-tray-plugin>
</template>
3 changes: 2 additions & 1 deletion jdaviz/core/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,8 @@ def _handle_display_units(data, use_display_units):
u.spectral()),
flux=data.flux.to(flux_unit,
u.spectral_density(data.spectral_axis)),
uncertainty=new_uncert)
uncertainty=new_uncert,
mask=data.mask)
else: # pragma: nocover
raise NotImplementedError(f"converting {data.__class__.__name__} to display units is not supported") # noqa
return data
Expand Down
5 changes: 3 additions & 2 deletions jdaviz/core/template_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -2632,7 +2632,8 @@ def _get_continuum(self, dataset, spatial_subset, spectral_subset, update_marks=
if spatial_subset == 'per-pixel':
if self.app.config != 'cubeviz':
raise ValueError("per-pixel only supported for cubeviz")
full_spectrum = self.dataset.selected_obj
full_spectrum = self.app._jdaviz_helper.get_data(self.dataset.selected,
use_display_units=True)
else:
full_spectrum = dataset.selected_spectrum_for_spatial_subset(spatial_subset.selected if spatial_subset is not None else None, # noqa
use_display_units=True)
Expand Down Expand Up @@ -2719,7 +2720,7 @@ def _get_continuum(self, dataset, spatial_subset, spectral_subset, update_marks=
continuum_mask = ~self._specviz_helper.get_data(
dataset.selected,
spectral_subset=self.continuum_subset_selected,
use_display_units=False).mask
use_display_units=True).mask
spectral_axis_nanmasked = spectral_axis.value.copy()
spectral_axis_nanmasked[~continuum_mask] = np.nan
if not update_marks:
Expand Down

0 comments on commit 7e64afd

Please sign in to comment.