Skip to content

Commit

Permalink
resolve UnitConversionError tracebacks in notebook
Browse files Browse the repository at this point in the history
  • Loading branch information
gibsongreen committed May 1, 2024
1 parent 3ed96dd commit c158bcc
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 45 deletions.
34 changes: 15 additions & 19 deletions jdaviz/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,7 @@

@unit_converter('custom-jdaviz')
class UnitConverterWithSpectral:

def equivalent_units(self, data, cid, units):
# to debug
# print("eqv unit cid : ", cid, ", units : ", units)

if cid.label == "flux":
eqv = u.spectral_density(1 * u.m) # Value does not matter here.
list_of_units = set(list(map(str, u.Unit(units).find_equivalent_units(
Expand All @@ -80,18 +76,19 @@ def equivalent_units(self, data, cid, units):
'W / (m2 Hz)', 'W / (Hz m2)', # Order is different in astropy v5.3
'eV / (s m2 Hz)', 'eV / (Hz s m2)',
'erg / (s cm2)',
'erg / (s cm2 Angstrom)', 'erg / (Angstrom s cm2)',
'erg / (s cm2 Angstrom)', 'erg / (s cm2 Angstrom)',
'erg / (s cm2 Hz)', 'erg / (Hz s cm2)',
'ph / (s cm2 Angstrom)', 'ph / (Angstrom s cm2)',
'ph / (s cm2 Angstrom)', 'ph / (s cm2 Angstrom)',
'ph / (Hz s cm2)', 'ph / (Hz s cm2)', 'bol', 'AB', 'ST'
]
+ [
'Jy / sr', 'mJy / sr', 'uJy / sr', 'MJy / sr',
'W / (m2 Hz sr)',
'W / (Hz sr m2)',
'eV / (s m2 Hz sr)',
'erg / (s cm2 sr)',
'erg / (s cm2 Angstrom sr)', 'erg / (s cm2 Hz sr)',
'ph / (s cm2 Angstrom sr)', 'ph / (s cm2 Hz sr)'
'ph / (s cm2 Angstrom sr)', 'ph / (s cm2 Hz sr)',
'bol / sr', 'AB / sr', 'ST / sr'
])
else: # spectral axis
# prefer Hz over Bq and um over micron
Expand All @@ -111,27 +108,22 @@ def to_unit(self, data, cid, values, original_units, target_units):
spec = data.get_object(cls=Spectrum1D)
except RuntimeError:
eqv = []
if len(values) == 2:
# Need this for setting the y-limits
spec_limits = [spec.spectral_axis[0].value, spec.spectral_axis[-1].value]
eqv = u.spectral_density(spec_limits * spec.spectral_axis.unit)

# Ensure a spectrum passed through Spectral Extraction plugin
elif '_pixel_scale_factor' in spec.meta:
if '_pixel_scale_factor' in spec.meta:
# if spectrum data collection item is in Surface Brightness units
if u.sr in spec.unit.bases:
# Data item in data collection does not update from conversion/translation.
# App wide orginal data units are used for conversion, orginal_units and
# target_units dicate the conversion to take place.
if (u.sr in u.Unit(original_units).bases) and \
(u.sr not in u.Unit(target_units).bases) and \
(target_units not in ["AB", "bol", "ST"]): # astropy supported equivalency
(u.sr not in u.Unit(target_units).bases):
# Surface Brightness -> Flux
eqv = [(u.MJy / u.sr,
u.MJy,
lambda x: (x * spec.meta['_pixel_scale_factor']),
lambda x: x)]

# below is the generalized version
'''
eqv = [(u.Unit(original_units),
Expand All @@ -149,14 +141,13 @@ def to_unit(self, data, cid, values, original_units, target_units):
# App wide orginal data units are used for conversion, orginal_units and
# target_units dicate the conversion to take place.
if (u.sr not in u.Unit(original_units).bases) and \
(u.sr in u.Unit(target_units).bases) and \
(target_units not in ["AB", "bol", "ST"]): # astropy supported equivalency
(u.sr in u.Unit(target_units).bases):
# Flux -> Surface Brightness
eqv = [(u.MJy,
u.MJy / u.sr,
lambda x: (x / spec.meta['_pixel_scale_factor']),
lambda x: x)]

# below is the generalized version
'''
eqv = [(u.Unit(original_units),
Expand All @@ -171,6 +162,11 @@ def to_unit(self, data, cid, values, original_units, target_units):
# flux cid, but neither Surface Brightness nor Flux units
else:
raise ValueError('flux cid, but not a flux nor surface brightness unit.')
elif len(values) == 2:
# Need this for setting the y-limits
spec_limits = [spec.spectral_axis[0].value, spec.spectral_axis[-1].value]
eqv = u.spectral_density(spec_limits * spec.spectral_axis.unit)

else:
eqv = u.spectral_density(spec.spectral_axis)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@ def test_unit_translation(cubeviz_helper):
center = PixCoord(5, 10)
cubeviz_helper.load_regions(CirclePixelRegion(center, radius=2.5))

uc_plg = cubeviz_helper.plugins['Unit Conversion']
uc_plg.open_in_tray()

extract_plg = cubeviz_helper.plugins['Spectral Extraction']

extract_plg.aperture = extract_plg.aperture.choices[-1]
Expand All @@ -157,7 +160,6 @@ def test_unit_translation(cubeviz_helper):
# test that the scale factor was set
assert collapsed_spec.meta['_pixel_scale_factor'] != 1

uc_plg = cubeviz_helper.plugins['Unit Conversion']
# When the dropdown is displayed, this ensures the loaded
# data collection item units will be used for translations.
uc_plg._obj.show_translator = True
Expand All @@ -174,13 +176,13 @@ def test_unit_translation(cubeviz_helper):
assert y_display_unit == u.MJy / u.sr

# Surface Brightness conversion
uc_plg.flux_unit_selected = 'W / (Hz sr m2)'
assert y_display_unit == u.W / (u.m**2 * u.sr * u.Hz)

# A second Surface Brightness conversion
uc_plg.flux_unit_selected = 'Jy / sr'
assert y_display_unit == u.Jy / u.sr

# A second Surface Brightness conversion
# uc_plg.flux_unit_selected = 'Jy / sr'
# assert y_display_unit == u.Jy / u.sr

# Translate back to Flux
uc_plg._obj.flux_or_sb_selected = 'Flux'
y_display_unit = u.Unit(viewer_1d.state.y_display_unit)
Expand Down
36 changes: 19 additions & 17 deletions jdaviz/configs/specviz/plugins/unit_conversion/unit_conversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,14 @@ class UnitConversion(PluginTemplateMixin):
* :meth:`~jdaviz.core.template_mixin.PluginTemplateMixin.close_in_tray`
* ``spectral_unit`` (:class:`~jdaviz.core.template_mixin.SelectPluginComponent`):
Global unit to use for all spectral axes.
* ``flux_unit`` (:class:`~jdaviz.core.template_mixin.SelectPluginComponent`):
* ``flux_or_sb_unit`` (:class:`~jdaviz.core.template_mixin.SelectPluginComponent`):
Global unit to use for all flux axes.
"""
template_file = __file__, "unit_conversion.vue"

spectral_unit_items = List().tag(sync=True)
spectral_unit_selected = Unicode().tag(sync=True)

flux_unit_items = List().tag(sync=True)
flux_unit_selected = Unicode().tag(sync=True)

Expand Down Expand Up @@ -78,17 +79,17 @@ def __init__(self, *args, **kwargs):
self.spectral_unit = UnitSelectPluginComponent(self,
items='spectral_unit_items',
selected='spectral_unit_selected')
self.flux_unit = UnitSelectPluginComponent(self,
items='flux_unit_items',
selected='flux_unit_selected')
self.flux_or_sb_unit = UnitSelectPluginComponent(self,
items='flux_unit_items',
selected='flux_unit_selected')
self.flux_or_sb = SelectPluginComponent(self,
items='flux_or_sb_items',
selected='flux_or_sb_selected',
manual_options=['Surface Brightness', 'Flux'])

@property
def user_api(self):
return PluginUserApi(self, expose=('spectral_unit', 'flux_unit'))
return PluginUserApi(self, expose=('spectral_unit', 'flux_or_sb_unit', 'flux_or_sb'))

def _on_glue_x_display_unit_changed(self, x_unit):
if x_unit is None:
Expand All @@ -109,7 +110,7 @@ def _on_glue_x_display_unit_changed(self, x_unit):
# which would then be appended on to the list of choices going forward
self.spectral_unit._addl_unit_strings = self.spectrum_viewer.state.__class__.x_display_unit.get_choices(self.spectrum_viewer.state) # noqa
self.spectral_unit.selected = x_unit
if not len(self.flux_unit.choices):
if not len(self.flux_or_sb_unit.choices):
# in case flux_unit was triggered first (but could not be set because there
# as no spectral_unit to determine valid equivalencies)
self._on_glue_y_display_unit_changed(self.spectrum_viewer.state.y_display_unit)
Expand All @@ -119,23 +120,24 @@ def _on_glue_y_display_unit_changed(self, y_unit):
return
if self.spectral_unit.selected == "":
# no spectral unit set yet, cannot determine equivalencies
# setting the spectral unit will check len(flux_unit.choices) and call this manually
# in the case that that is triggered second.
# setting the spectral unit will check len(flux_or_sb_unit.choices)
# and call this manually in the case that that is triggered second.
return
self.spectrum_viewer.set_plot_axes()
if y_unit != self.flux_unit.selected:
if y_unit != self.flux_or_sb_unit.selected:
x_u = u.Unit(self.spectral_unit.selected)
y_unit = _valid_glue_display_unit(y_unit, self.spectrum_viewer, 'y')
y_u = u.Unit(y_unit)
choices = create_flux_equivalencies_list(y_u, x_u)
# ensure that original entry is in the list of choices
if not np.any([y_u == u.Unit(choice) for choice in choices]):
choices = [y_unit] + choices
self.flux_unit.choices = choices
self.flux_unit.selected = y_unit
self.flux_or_sb_unit.choices = choices
self.flux_or_sb_unit.selected = y_unit

def translate_units(self, flux_or_sb_selected):
spec_units = u.Unit(self.spectrum_viewer.state.y_display_unit)
print('spec units ', spec_units, ' f or sb ', flux_or_sb_selected)
# Surface Brightness -> Flux
if u.sr in spec_units.bases and flux_or_sb_selected == 'Flux':
spec_units *= u.sr
Expand All @@ -148,10 +150,6 @@ def translate_units(self, flux_or_sb_selected):
# update display units
self.spectrum_viewer.state.y_display_unit = str(spec_units)

else:
raise ValueError("Unrecognized unit translation, \
please ensure y-unit is in Surface Brightness or Flux.")

@observe('spectral_unit_selected')
def _on_spectral_unit_changed(self, *args):
self.hub.broadcast(GlobalDisplayUnitChanged('spectral',
Expand All @@ -163,11 +161,11 @@ def _on_spectral_unit_changed(self, *args):

@observe('flux_unit_selected')
def _on_flux_unit_changed(self, *args):
yunit = _valid_glue_display_unit(self.flux_unit.selected, self.spectrum_viewer, 'y')
yunit = _valid_glue_display_unit(self.flux_or_sb_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,
self.flux_or_sb_unit.selected,
sender=self))

# Ensure first dropdown selection for Flux/Surface Brightness
Expand All @@ -183,6 +181,10 @@ def _set_flux_or_sb(self, *args):

@observe('flux_or_sb_selected')
def _translate(self, *args):
# currently unsupported, can be supported with a scale factor
if self.app.config == 'specviz':
return

# Check for a scale factor/data passed through spectral extraction plugin.
specs_w_factor = [spec for spec in self.app.data_collection
if "_pixel_scale_factor" in spec.meta]
Expand Down
3 changes: 2 additions & 1 deletion jdaviz/configs/specviz/plugins/viewers.py
Original file line number Diff line number Diff line change
Expand Up @@ -568,7 +568,8 @@ def set_plot_axes(self):
u.erg / (u.s * u.cm**2 * u.Angstrom),
u.erg / (u.s * u.cm**2 * u.Hz),
u.ph / (u.s * u.cm**2 * u.Angstrom),
u.ph / (u.s * u.cm**2 * u.Hz)
u.ph / (u.s * u.cm**2 * u.Hz),
u.bol, u.AB, u.ST
]

locally_defined_sb_units = [
Expand Down
7 changes: 4 additions & 3 deletions jdaviz/core/validunits.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def create_flux_equivalencies_list(flux_unit, spectral_axis_unit):
# Get local units.
if u.sr not in flux_unit.bases:
locally_defined_flux_units = ['Jy', 'mJy', 'uJy', 'MJy', 'Jy',
'W / (m2 Hz)',
'W / (Hz m2)',
'eV / (s m2 Hz)',
'erg / (s cm2)',
'erg / (s cm2 Angstrom)',
Expand All @@ -79,13 +79,14 @@ def create_flux_equivalencies_list(flux_unit, spectral_axis_unit):
local_units = [u.Unit(unit) for unit in locally_defined_flux_units]
else:
locally_defined_flux_units = ['Jy / sr', 'mJy / sr', 'uJy / sr', 'MJy / sr', 'Jy / sr',
'W / (m2 Hz sr)',
'W / (Hz sr m2)',
'eV / (s m2 Hz sr)',
'erg / (s cm2 sr)',
'erg / (s cm2 Angstrom sr)',
'erg / (s cm2 Hz sr)',
'ph / (s cm2 Angstrom sr)',
'ph / (s cm2 Hz sr)']
'ph / (s cm2 Hz sr)',
'bol / sr', 'AB / sr', 'ST / sr']
local_units = [u.Unit(unit) for unit in locally_defined_flux_units]

# Remove overlap units.
Expand Down

0 comments on commit c158bcc

Please sign in to comment.