diff --git a/jdaviz/app.py b/jdaviz/app.py index 2f2bfa2d74..2620ef5357 100644 --- a/jdaviz/app.py +++ b/jdaviz/app.py @@ -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( @@ -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 @@ -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), @@ -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), @@ -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) diff --git a/jdaviz/configs/specviz/plugins/unit_conversion/tests/test_unit_conversion.py b/jdaviz/configs/specviz/plugins/unit_conversion/tests/test_unit_conversion.py index dfee17acbd..883722e0b0 100644 --- a/jdaviz/configs/specviz/plugins/unit_conversion/tests/test_unit_conversion.py +++ b/jdaviz/configs/specviz/plugins/unit_conversion/tests/test_unit_conversion.py @@ -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] @@ -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 @@ -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) diff --git a/jdaviz/configs/specviz/plugins/unit_conversion/unit_conversion.py b/jdaviz/configs/specviz/plugins/unit_conversion/unit_conversion.py index 805393d763..baadf70d6e 100644 --- a/jdaviz/configs/specviz/plugins/unit_conversion/unit_conversion.py +++ b/jdaviz/configs/specviz/plugins/unit_conversion/unit_conversion.py @@ -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) @@ -78,9 +79,9 @@ 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', @@ -88,7 +89,7 @@ def __init__(self, *args, **kwargs): @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: @@ -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) @@ -119,11 +120,11 @@ 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) @@ -131,11 +132,12 @@ def _on_glue_y_display_unit_changed(self, y_unit): # 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 @@ -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', @@ -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 @@ -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] diff --git a/jdaviz/configs/specviz/plugins/viewers.py b/jdaviz/configs/specviz/plugins/viewers.py index 2205fdcf58..a228c2b026 100644 --- a/jdaviz/configs/specviz/plugins/viewers.py +++ b/jdaviz/configs/specviz/plugins/viewers.py @@ -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 = [ diff --git a/jdaviz/core/validunits.py b/jdaviz/core/validunits.py index ced8ef4f99..378cf755eb 100644 --- a/jdaviz/core/validunits.py +++ b/jdaviz/core/validunits.py @@ -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)', @@ -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.