diff --git a/CHANGES.rst b/CHANGES.rst index aefd4bc564..45a3ba7668 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -69,6 +69,9 @@ Cubeviz - Spectral Extraction: renamed ``collapse_to_spectrum(...)`` to ``extract(...)``. [#2859] +- Custom Spectrum1D writer format ``jdaviz-cube`` is removed. Use ``wcs1d-fits`` from + ``specutils`` instead. [#2094] + Imviz ^^^^^ diff --git a/docs/cubeviz/export_data.rst b/docs/cubeviz/export_data.rst index 3053ca65e9..976e204d4d 100644 --- a/docs/cubeviz/export_data.rst +++ b/docs/cubeviz/export_data.rst @@ -74,7 +74,7 @@ where the mask (if available) is as defined in .. code-block:: python - mydata.write("mydata.fits", format="jdaviz-cube") + mydata.write("mydata.fits", format="wcs1d-fits", hdu=1) .. _cubeviz-export-model: diff --git a/jdaviz/configs/cubeviz/helper.py b/jdaviz/configs/cubeviz/helper.py index 41de2f5a29..36caca8029 100644 --- a/jdaviz/configs/cubeviz/helper.py +++ b/jdaviz/configs/cubeviz/helper.py @@ -1,9 +1,3 @@ -import numpy as np -from astropy.io import fits -from astropy.io import registry as io_registry -from specutils import Spectrum1D -from specutils.io.registers import _astropy_has_priorities - from jdaviz.core.events import SnackbarMessage from jdaviz.core.helpers import ImageConfigHelper from jdaviz.configs.default.plugins.line_lists.line_list_mixin import LineListMixin @@ -166,63 +160,3 @@ def get_aperture_photometry_results(self): """ return self.plugins['Aperture Photometry']._obj.export_table() - - -# TODO: We can remove this when specutils supports it, i.e., -# https://github.com/astropy/specutils/issues/592 and -# https://github.com/astropy/specutils/pull/1009 -# NOTE: Cannot use custom_write decorator from specutils because -# that involves asking user to manually put something in -# their ~/.specutils directory. - -def jdaviz_cube_fitswriter(spectrum, file_name, **kwargs): - """This is a custom writer for Spectrum1D data cube. - This writer is specifically targetting data cube - generated from Cubeviz plugins (e.g., cube fitting) - with FITS WCS. It writes out data in the following format - (with MASK only exist when applicable):: - - No. Name Ver Type - 0 PRIMARY 1 PrimaryHDU - 1 SCI 1 ImageHDU (float32) - 2 MASK 1 ImageHDU (uint16) - - The FITS file generated by this writer does not need a - custom reader to be read back into Spectrum1D. - - Examples - -------- - To write out a Spectrum1D cube using this writer: - - >>> spec.write("my_output.fits", format="jdaviz-cube", overwrite=True) # doctest: +SKIP - - """ - pri_hdu = fits.PrimaryHDU() - - flux = spectrum.flux - sci_hdu = fits.ImageHDU(flux.value.astype(np.float32)) - sci_hdu.name = "SCI" - sci_hdu.header.update(spectrum.meta) - sci_hdu.header.update(spectrum.wcs.to_header()) - sci_hdu.header['BUNIT'] = flux.unit.to_string(format='fits') - - hlist = [pri_hdu, sci_hdu] - - # https://specutils.readthedocs.io/en/latest/spectrum1d.html#including-masks - # Good: False or 0 - # Bad: True or non-zero - if spectrum.mask is not None: - mask_hdu = fits.ImageHDU(spectrum.mask.astype(np.uint16)) - mask_hdu.name = "MASK" - hlist.append(mask_hdu) - - hdulist = fits.HDUList(hlist) - hdulist.writeto(file_name, **kwargs) - - -if _astropy_has_priorities(): - kwargs = {"priority": 0} -else: # pragma: no cover - kwargs = {} -io_registry.register_writer( - "jdaviz-cube", Spectrum1D, jdaviz_cube_fitswriter, force=False, **kwargs) diff --git a/jdaviz/configs/default/plugins/model_fitting/tests/test_fitting.py b/jdaviz/configs/default/plugins/model_fitting/tests/test_fitting.py index 334816029c..49f2d0715d 100644 --- a/jdaviz/configs/default/plugins/model_fitting/tests/test_fitting.py +++ b/jdaviz/configs/default/plugins/model_fitting/tests/test_fitting.py @@ -4,7 +4,6 @@ import pytest from astropy import units as u from astropy.io import fits -from astropy.io.registry.base import IORegistryError from astropy.modeling import models from astropy.nddata import StdDevUncertainty from astropy.tests.helper import assert_quantity_allclose @@ -251,7 +250,7 @@ def test_cube_fitting_backend(cubeviz_helper, unc, tmp_path): # Check I/O roundtrip. out_fn = tmp_path / "fitted_cube.fits" - fitted_spectrum.write(out_fn, format="jdaviz-cube", overwrite=True) + fitted_spectrum.write(out_fn, format="wcs1d-fits", hdu=1, flux_name="SCI", overwrite=True) flux_unit_str = fitted_spectrum.flux.unit.to_string(format="fits") coo_expected = fitted_spectrum.wcs.pixel_to_world(1, 0, 2) with fits.open(out_fn) as pf: @@ -268,12 +267,7 @@ def test_cube_fitting_backend(cubeviz_helper, unc, tmp_path): assert_allclose([coo[1].ra.deg, coo[1].dec.deg], [coo_expected[1].ra.deg, coo_expected[1].dec.deg]) - # Our custom format is not registered to readers, just writers. - # You can read it back in without custom read. See "Cubeviz roundtrip" below. - with pytest.raises(IORegistryError, match="No reader defined"): - Spectrum1D.read(out_fn, format="jdaviz-cube") - - # Check Cubeviz roundtrip. + # Check Cubeviz roundtrip. This should automatically go through wcs1d-fits reader. cubeviz_helper.load_data(out_fn) assert len(cubeviz_helper.app.data_collection) == 3 data_sci = cubeviz_helper.app.data_collection["fitted_cube.fits[SCI]"]