From b97243c3c76f4ab59ba2251feaa2008b3b13e9d9 Mon Sep 17 00:00:00 2001 From: Kyle Conroy Date: Wed, 8 May 2024 09:09:09 -0400 Subject: [PATCH 1/5] fix pixel scale factor to use wavelength-dependent aperture areas --- .../cubeviz/plugins/spectral_extraction/spectral_extraction.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jdaviz/configs/cubeviz/plugins/spectral_extraction/spectral_extraction.py b/jdaviz/configs/cubeviz/plugins/spectral_extraction/spectral_extraction.py index 32e50c2814..ea1b5c3d0f 100644 --- a/jdaviz/configs/cubeviz/plugins/spectral_extraction/spectral_extraction.py +++ b/jdaviz/configs/cubeviz/plugins/spectral_extraction/spectral_extraction.py @@ -341,6 +341,7 @@ def bg_weight_mask(self): def aperture_area_along_spectral(self): # Weight mask summed along the spatial axes so that we get area of the aperture, in pixels, # as a function of wavelength. + # To convert to steradians, multiply by self.spectral_cube.meta.get('PIXAR_SR', 1.0) return np.sum(self.aperture_weight_mask, axis=(0, 1)) @property @@ -483,7 +484,7 @@ def extract(self, return_bg=False, add_data=True, **kwargs): spec = spec - bg_spec # per https://jwst-docs.stsci.edu/jwst-near-infrared-camera/nircam-performance/nircam-absolute-flux-calibration-and-zeropoints # noqa - pix_scale_factor = self.aperture.scale_factor * self.spectral_cube.meta.get('PIXAR_SR', 1.0) + pix_scale_factor = self.aperture_area_along_spectral * self.spectral_cube.meta.get('PIXAR_SR', 1.0) # noqa spec.meta['_pixel_scale_factor'] = pix_scale_factor # stuff for exporting to file From afcdcb694a8ad8d259e710e549a016faa302e9b6 Mon Sep 17 00:00:00 2001 From: gibsongreen Date: Thu, 23 May 2024 15:59:45 -0400 Subject: [PATCH 2/5] adjust from incorrect scalar scale factor to correct array implementation --- jdaviz/app.py | 27 +++++++++++++++++-- .../tests/test_unit_conversion.py | 2 +- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/jdaviz/app.py b/jdaviz/app.py index 57590bcf5e..4d4b2bdae0 100644 --- a/jdaviz/app.py +++ b/jdaviz/app.py @@ -9,6 +9,7 @@ from astropy.nddata import NDData from astropy.io import fits from astropy.time import Time +from astropy.units import Quantity from echo import CallbackProperty, DictCallbackProperty, ListCallbackProperty from ipygoldenlayout import GoldenLayout from ipysplitpanes import SplitPanes @@ -106,9 +107,11 @@ def to_unit(self, data, cid, values, original_units, target_units): if cid.label == "flux": try: spec = data.get_object(cls=Spectrum1D) + except RuntimeError: eqv = [] else: + eqv = [] # Ensure a spectrum passed through Spectral Extraction plugin if '_pixel_scale_factor' in spec.meta: @@ -121,14 +124,14 @@ def to_unit(self, data, cid, values, original_units, target_units): # Surface Brightness -> Flux eqv = [(u.MJy / u.sr, u.MJy, - lambda x: (x * spec.meta['_pixel_scale_factor']), + lambda x: (x * np.array(spec.meta['_pixel_scale_factor'])), lambda x: x)] elif (u.sr not in u.Unit(original_units).bases) and \ (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 / np.array(spec.meta['_pixel_scale_factor'])), lambda x: x)] else: eqv = u.spectral_density(spec.spectral_axis) @@ -138,6 +141,26 @@ def to_unit(self, data, cid, values, original_units, target_units): spec_limits = [spec.spectral_axis[0].value, spec.spectral_axis[-1].value] eqv = u.spectral_density(spec_limits * spec.spectral_axis.unit) + if '_pixel_scale_factor' in spec.meta: + # get min and max scale factors, to use with min and max of spec for + # y-limits. Make sure they are Quantities (can be numpy.float64). + pixel_scale_min = (Quantity(spec.meta['_pixel_scale_factor'][0])).value + pixel_scale_max = (Quantity(spec.meta['_pixel_scale_factor'][-1])).value + min_max = [pixel_scale_min, pixel_scale_max] + + if (u.sr in u.Unit(original_units).bases) and \ + (u.sr not in u.Unit(target_units).bases): + eqv += [(u.MJy, + u.MJy / u.sr, + lambda x: x * np.array(min_max), + lambda x: x)] + elif (u.sr not in u.Unit(original_units).bases) and \ + (u.sr in u.Unit(target_units).bases): + eqv += [(u.MJy / u.sr, + u.MJy, + lambda x: x / np.array(min_max), + lambda x: x)] + 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 117ebb704d..12ce333b35 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 @@ -156,7 +156,7 @@ def test_unit_translation(cubeviz_helper): collapsed_spec = extract_plg.extract() # test that the scale factor was set - assert collapsed_spec.meta['_pixel_scale_factor'] != 1 + assert np.all(collapsed_spec.meta['_pixel_scale_factor'] != 1) # When the dropdown is displayed, this ensures the loaded # data collection item units will be used for translations. From 88dd540618690cb140795e21a158c58b46a7545e Mon Sep 17 00:00:00 2001 From: gibsongreen Date: Thu, 23 May 2024 16:28:39 -0400 Subject: [PATCH 3/5] update to_unit test after change from scalar to array scale factor --- jdaviz/tests/test_app.py | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/jdaviz/tests/test_app.py b/jdaviz/tests/test_app.py index 48adfe4035..9327198695 100644 --- a/jdaviz/tests/test_app.py +++ b/jdaviz/tests/test_app.py @@ -224,20 +224,12 @@ def test_to_unit(cubeviz_helper): cid = cubeviz_helper.app.data_collection[0].data.find_component_id('flux') data = cubeviz_helper.app.data_collection[-1].data - values = 1 - - # Surface brightness to flux - + values = [1] original_units = u.MJy / u.sr target_units = u.MJy value = uc.to_unit(cubeviz_helper, data, cid, values, original_units, target_units) - assert np.allclose(value, 4.7945742429049767e-11) - - # Flux to surface brightness - - original_units = u.MJy - target_units = u.MJy / u.sr - - value = uc.to_unit(cubeviz_helper, data, cid, values, original_units, target_units) + # will be a uniform array since not wavelength dependent + # so test first value in array + assert np.allclose(value[0], 4.800000041882413e-08) From e1401ba02ba233bb46e6a06b8aa9b684aa5735be Mon Sep 17 00:00:00 2001 From: gibsongreen Date: Tue, 28 May 2024 13:16:34 -0400 Subject: [PATCH 4/5] update comments, add changelog, use min/max instead of array indexing for y-limits --- CHANGES.rst | 3 +++ jdaviz/app.py | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 739e887368..3c960570a6 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -88,6 +88,9 @@ Cubeviz - Moment map plugin now reflects selected flux / surface brightness unit for moment zero. [#2877] +- Update the scale factor used to convert a spectrum between surface brightness and flux + to use wavelength-dependent aperture area instead of the cone slice scale factor. [#2860] + Imviz ^^^^^ diff --git a/jdaviz/app.py b/jdaviz/app.py index 4d4b2bdae0..f52ded75ec 100644 --- a/jdaviz/app.py +++ b/jdaviz/app.py @@ -144,8 +144,8 @@ def to_unit(self, data, cid, values, original_units, target_units): if '_pixel_scale_factor' in spec.meta: # get min and max scale factors, to use with min and max of spec for # y-limits. Make sure they are Quantities (can be numpy.float64). - pixel_scale_min = (Quantity(spec.meta['_pixel_scale_factor'][0])).value - pixel_scale_max = (Quantity(spec.meta['_pixel_scale_factor'][-1])).value + pixel_scale_min = (Quantity(min(spec.meta['_pixel_scale_factor']))).value + pixel_scale_max = (Quantity(max(spec.meta['_pixel_scale_factor']))).value min_max = [pixel_scale_min, pixel_scale_max] if (u.sr in u.Unit(original_units).bases) and \ From 462df2430ab5e0e4879f58de95d6a89970fd9704 Mon Sep 17 00:00:00 2001 From: gibsongreen Date: Thu, 30 May 2024 11:41:05 -0400 Subject: [PATCH 5/5] update conditional post-rebase to ensure limit updates don't enter spectrum wide conversion condition --- jdaviz/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdaviz/app.py b/jdaviz/app.py index f52ded75ec..ee2bdcc67f 100644 --- a/jdaviz/app.py +++ b/jdaviz/app.py @@ -113,7 +113,7 @@ def to_unit(self, data, cid, values, original_units, target_units): else: eqv = [] # Ensure a spectrum passed through Spectral Extraction plugin - if '_pixel_scale_factor' in spec.meta: + if '_pixel_scale_factor' in spec.meta and len(values) != 2: # Data item in data collection does not update from conversion/translation. # App wide original data units are used for conversion, original and