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 SB/flux scale factor #2860

Merged
merged 5 commits into from
May 31, 2024
Merged
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
3 changes: 3 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
^^^^^

Expand Down
29 changes: 26 additions & 3 deletions jdaviz/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -106,11 +107,13 @@ 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:
if '_pixel_scale_factor' in spec.meta and len(values) != 2:

# Data item in data collection does not update from conversion/translation.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# Data item in data collection does not update from conversion/translation.
# Data item in data collection will not be updated by conversion/translation.

# App wide original data units are used for conversion, original and
Expand All @@ -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)
Expand All @@ -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(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 \
(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)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
16 changes: 4 additions & 12 deletions jdaviz/tests/test_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Loading