diff --git a/CHANGES.rst b/CHANGES.rst index eea2516be7..6b7003dad2 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -69,6 +69,9 @@ Cubeviz - Spectral Extraction: renamed ``collapse_to_spectrum(...)`` to ``extract(...)``. [#2859] +- Generic FITS parsing now goes through ``specutils`` loaders first, if possible. + If a ``specutils`` loader is used, uncertainty is converted to standard deviation type. [#3119] + Imviz ^^^^^ @@ -105,6 +108,11 @@ Cubeviz - Flux units are now correct for collapsed spectra when using the sum function when units are in per steradian. [#2873] +- Fixed MaNGA cube loading. Uncertainty type is also handled properly now. [#3119] + +- Fixed spectral axis value display in Markers plugin. Previously, it failed to display + very small values, resulting in zeroes. [#3119] + Imviz ^^^^^ diff --git a/jdaviz/configs/cubeviz/plugins/parsers.py b/jdaviz/configs/cubeviz/plugins/parsers.py index a565ba36e1..224b84d85c 100644 --- a/jdaviz/configs/cubeviz/plugins/parsers.py +++ b/jdaviz/configs/cubeviz/plugins/parsers.py @@ -5,7 +5,7 @@ import numpy as np from astropy import units as u from astropy.io import fits - +from astropy.nddata import StdDevUncertainty from astropy.time import Time from astropy.wcs import WCS from specutils import Spectrum1D @@ -68,11 +68,18 @@ def parse_data(app, file_obj, data_type=None, data_label=None, # generic enough to work with other file types (e.g. ASDF). For now, this # supports MaNGA and JWST data. if isinstance(file_obj, fits.hdu.hdulist.HDUList): - _parse_hdulist( - app, file_obj, file_name=data_label, - flux_viewer_reference_name=flux_viewer_reference_name, - uncert_viewer_reference_name=uncert_viewer_reference_name - ) + try: + _parse_spectrum1d_3d( + app, Spectrum1D.read(file_obj), data_label=data_label, + flux_viewer_reference_name=flux_viewer_reference_name, + uncert_viewer_reference_name=uncert_viewer_reference_name + ) + except Exception: # nosec + _parse_hdulist( + app, file_obj, file_name=data_label, + flux_viewer_reference_name=flux_viewer_reference_name, + uncert_viewer_reference_name=uncert_viewer_reference_name + ) app.get_tray_item_from_name("Spectral Extraction").disabled_msg = "" elif isinstance(file_obj, str): if file_obj.lower().endswith('.gif'): # pragma: no cover @@ -130,11 +137,18 @@ def parse_data(app, file_obj, data_type=None, data_label=None, flux_viewer_reference_name=flux_viewer_reference_name, ) else: - _parse_hdulist( - app, hdulist, file_name=data_label or file_name, - flux_viewer_reference_name=flux_viewer_reference_name, - uncert_viewer_reference_name=uncert_viewer_reference_name - ) + try: + _parse_spectrum1d_3d( + app, Spectrum1D.read(hdulist), data_label=data_label or file_name, + flux_viewer_reference_name=flux_viewer_reference_name, + uncert_viewer_reference_name=uncert_viewer_reference_name + ) + except Exception: # nosec + _parse_hdulist( + app, hdulist, file_name=data_label or file_name, + flux_viewer_reference_name=flux_viewer_reference_name, + uncert_viewer_reference_name=uncert_viewer_reference_name + ) app.get_tray_item_from_name("Spectral Extraction").disabled_msg = "" # If the data types are custom data objects, use explicit parsers. Note @@ -416,10 +430,7 @@ def _parse_spectrum1d_3d(app, file_obj, data_label=None, if attr == "mask": flux = val << u.dimensionless_unscaled # DQ flags have no unit elif attr == "uncertainty": - if hasattr(val, "array"): - flux = u.Quantity(val.array, file_obj.flux.unit) - else: - continue + flux = val.represent_as(StdDevUncertainty).quantity else: flux = val diff --git a/jdaviz/core/template_mixin.py b/jdaviz/core/template_mixin.py index 51222a639f..272f976afc 100644 --- a/jdaviz/core/template_mixin.py +++ b/jdaviz/core/template_mixin.py @@ -4527,24 +4527,24 @@ def float_precision(column, item): return f"{item:0.3f}" elif column in ('xcenter', 'ycenter'): return f"{item:0.1f}" - elif column in ('sum', ): + elif column in ('sum', 'spectral_axis'): return f"{item:.3e}" else: return f"{item:0.5f}" if isinstance(item, SkyCoord): return item.to_string('hmsdms', precision=4) - if isinstance(item, u.Quantity) and not np.isnan(item): + elif isinstance(item, u.Quantity) and not np.isnan(item): return f"{float_precision(column, item.value)} {item.unit.to_string()}" - if hasattr(item, 'to_string'): + elif hasattr(item, 'to_string'): return item.to_string() - if isinstance(item, float) and np.isnan(item): + elif isinstance(item, float) and np.isnan(item): return '' - if isinstance(item, tuple) and np.all([np.isnan(i) for i in item]): + elif isinstance(item, tuple) and np.all([np.isnan(i) for i in item]): return '' - if isinstance(item, float): + elif isinstance(item, float): return float_precision(column, item) elif isinstance(item, (list, tuple)): return [float_precision(column, i) if isinstance(i, float) else i for i in item]