diff --git a/docs/create_products.rst b/docs/create_products.rst index 3a78bd6991..ebd7c62a9f 100644 --- a/docs/create_products.rst +++ b/docs/create_products.rst @@ -5,14 +5,14 @@ Creating Jdaviz-readable Products Spectroscopic data products (1D, 2D, and 3D) can be loaded in the different ``jdaviz`` configurations using -essentially two methods, i.e., loading :class:`~specutils.Spectrum1D` objects or +essentially two methods, i.e., loading :class:`~specutils.Spectrum` objects or from FITS files. Here, we list a few ways in which data can be packaged to be easily loaded into a ``jdaviz`` configuration. Data in a database ------------------ -If the data are stored in a database, we recommend storing a :class:`~specutils.Spectrum1D` object +If the data are stored in a database, we recommend storing a :class:`~specutils.Spectrum` object per entry. This would allow the user to query the data and visualize it in ``jdaviz`` with few lines of code; also see :ref:`create_product_spectrum1d_obj`. @@ -34,8 +34,8 @@ Available loaders can be listed with the following commands: .. code-block:: python - from specutils import Spectrum1D - Spectrum1D.read.list_formats() + from specutils import Spectrum + Spectrum.read.list_formats() The majority are fairly specific to missions and instruments. Four formats are more generic and adaptable: ``ASCII``, ``ECSV``, ``tabular-fits``, and @@ -55,14 +55,14 @@ is available. We are working on the necessary documentation to prompt .. _create_product_spectrum1d_obj: -Providing scripts to load the data as Spectrum1D objects +Providing scripts to load the data as Spectrum objects ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ If none of the above is an acceptable option, the user can create the data products with their custom format and provide scripts or Jupyter Notebooks -that show how to read the products and create :class:`~specutils.Spectrum1D` objects +that show how to read the products and create :class:`~specutils.Spectrum` objects that can be read into ``jdaviz``. More about -how to create :class:`~specutils.Spectrum1D` objects for the 1D, 2D, and 3D cases can be +how to create :class:`~specutils.Spectrum` objects for the 1D, 2D, and 3D cases can be found in the corresponding "Importing data" sections of the various configurations: * :ref:`specviz-import-data` diff --git a/docs/cubeviz/export_data.rst b/docs/cubeviz/export_data.rst index fb860fd915..600d589ad7 100644 --- a/docs/cubeviz/export_data.rst +++ b/docs/cubeviz/export_data.rst @@ -74,12 +74,12 @@ with the name of the data you want to extract): mydata = cubeviz.get_data(data_label="data_name") -The data is returned as a 3D `specutils.Spectrum1D` object. +The data is returned as a 3D `specutils.Spectrum` object. -To write out a `specutils.Spectrum1D` cube from Cubeviz +To write out a `specutils.Spectrum` cube from Cubeviz (e.g., a fitted cube from :ref:`model-fitting`), where the mask (if available) is as defined in -`Spectrum1D masks `_: +`Spectrum masks `_: .. code-block:: python diff --git a/docs/cubeviz/import_data.rst b/docs/cubeviz/import_data.rst index 47fbe08863..b2a1c34025 100644 --- a/docs/cubeviz/import_data.rst +++ b/docs/cubeviz/import_data.rst @@ -5,24 +5,24 @@ Importing Data into Cubeviz *************************** By design, Cubeviz only supports data that can be parsed as -:class:`~specutils.Spectrum1D` objects. Despite the name, :class:`~specutils.Spectrum1D` -supports 3D cubes and allows the Python-level interface and parsing tools to +:class:`~specutils.Spectrum` objects. :class:`~specutils.Spectrum` supports 3D cubes +and allows the Python-level interface and parsing tools to be defined in ``specutils`` instead of being duplicated in Jdaviz. -:class:`~specutils.Spectrum1D` objects are very flexible in their capabilities, however, +:class:`~specutils.Spectrum` objects are very flexible in their capabilities, however, and hence should address most astronomical spectrum use cases. If you are creating your own data products, please read the page :ref:`create_products`. Cubeviz will automatically parse the data into the multiple viewers as described in :ref:`cubeviz-display-cubes`. For the best experience, data loaded into Cubeviz should contain valid WCS -keywords. For more information on how :class:`~specutils.Spectrum1D` -uses WCS, please go to the `Spectrum1D defining WCS section `_. +keywords. For more information on how :class:`~specutils.Spectrum` +uses WCS, please go to the `Spectrum defining WCS section `_. To check if your FITS file contains valid WCS keywords, please use `Astropy WCS validate `. For an example on loading a cube with valid WCS keywords, please see the :ref:`cubeviz-import-api` section below. Loading data without WCS is also possible as long as they are compatible -with :class:`~specutils.Spectrum1D`. However, not all plugins will work with this data. +with :class:`~specutils.Spectrum`. However, not all plugins will work with this data. .. _cubeviz-viewers: @@ -60,7 +60,7 @@ Importing data through the GUI Users may load data into the Cubeviz application by clicking the :guilabel:`Import Data` button at the top left of the application's user interface. This opens a dialogue with a prompt to select a file -that can be parsed as a :class:`~specutils.Spectrum1D` object. +that can be parsed as a :class:`~specutils.Spectrum` object. After clicking :guilabel:`Import`, the data file will be parsed and loaded into the application. A notification will appear to confirm whether the data import @@ -75,7 +75,7 @@ Importing data via the API Alternatively, users who work in a coding environment like a Jupyter notebook can access the Cubeviz helper class API. Using this API, users can load data into the application through code with the :py:meth:`~jdaviz.configs.specviz.helper.Specviz.load_data` -method, which takes as input a :class:`~specutils.Spectrum1D` object. +method, which takes as input a :class:`~specutils.Spectrum` object. FITS Files ---------- @@ -89,33 +89,33 @@ The example below loads a FITS file into Cubeviz: cubeviz.load_data("/path/to/data/file.fits") cubeviz.show() -Spectrum1D (from file) +Spectrum (from file) ---------------------- For cases where the built-in parser is unable to understand your file format, -you can try the `~specutils.Spectrum1D` parser directly and then pass the object to the +you can try the `~specutils.Spectrum` parser directly and then pass the object to the :py:meth:`~jdaviz.core.helpers.ConfigHelper.load_data` method: .. code-block:: python - from specutils import Spectrum1D + from specutils import Spectrum from jdaviz import Cubeviz - spec3d = Spectrum1D.read("/path/to/data/file.fits") + spec3d = Spectrum.read("/path/to/data/file.fits") cubeviz = Cubeviz() cubeviz.load_data(spec3d, data_label='My Cube') cubeviz.show() -Spectrum1D (from array) +Spectrum (from array) ----------------------- -You can create your own :class:`~specutils.Spectrum1D` object by hand to load into Cubeviz: +You can create your own :class:`~specutils.Spectrum` object by hand to load into Cubeviz: .. code-block:: python import numpy as np from astropy import units as u from astropy.wcs import WCS - from specutils import Spectrum1D + from specutils import Spectrum from jdaviz import Cubeviz flux = np.arange(16).reshape((2, 2, 4)) * u.Jy @@ -125,7 +125,7 @@ You can create your own :class:`~specutils.Spectrum1D` object by hand to load in "CRPIX1": 0, "CRPIX2": 0, "CRPIX3": 0} w = WCS(wcs_dict) - cube = Spectrum1D(flux=flux, wcs=w) + cube = Spectrum(flux=flux, wcs=w) cubeviz = Cubeviz() cubeviz.load_data(cube, data_label='My Cube') cubeviz.show() @@ -149,7 +149,7 @@ object, you can load it into Cubeviz as follows: mydatamodel = datamodels.open(file) # mydatamodel is a jwst.datamodels object - # Due to current schema in jwst.datamodels, you'll need to create your own WCS object before you create your Spectrum1D object + # Due to current schema in jwst.datamodels, you'll need to create your own WCS object before you create your Spectrum object wcs_dict = {"CTYPE1": mydatamodel.meta.wcsinfo.ctype3, "CTYPE2": mydatamodel.meta.wcsinfo.ctype2, "CTYPE3": mydatamodel.meta.wcsinfo.ctype1, "CRVAL1": mydatamodel.meta.wcsinfo.crval3, "CRVAL2": mydatamodel.meta.wcsinfo.crval2, @@ -166,7 +166,7 @@ object, you can load it into Cubeviz as follows: data = np.swapaxes(data, 1, 2) # Create your spectrum1 - spec3d = Spectrum1D(data, wcs=my_wcs) + spec3d = Spectrum(data, wcs=my_wcs) cubeviz = Cubeviz() cubeviz.load_data(spec3d, data_label='My Cube') cubeviz.show() diff --git a/docs/cubeviz/plugins.rst b/docs/cubeviz/plugins.rst index 06cf9087a2..3c3f4f1429 100644 --- a/docs/cubeviz/plugins.rst +++ b/docs/cubeviz/plugins.rst @@ -12,7 +12,7 @@ icon in the upper right corner of the Cubeviz application. The data analysis plugins are meant to aid quick-look analysis of both 3D and 1D spectroscopic data. In many cases, functions can be applied to -`~specutils.Spectrum1D` objects, which include both 3D and 1D datasets. +`~specutils.Spectrum` objects, which include both 3D and 1D datasets. Plugins that are specific to 1D spectra are described in more detail under :ref:`Specviz: Data Analysis Plugins `. In many cases, these capabilities can be further applied on a per spaxel basis diff --git a/docs/mosviz/plugins.rst b/docs/mosviz/plugins.rst index c49ba83f67..2b99238a41 100644 --- a/docs/mosviz/plugins.rst +++ b/docs/mosviz/plugins.rst @@ -3,7 +3,7 @@ Data Analysis Plugins ********************* The Mosviz data analysis plugins include operations on both -2D images and Spectrum1D one dimensional datasets. +2D images and Spectrum one dimensional datasets. Plugins that are specific to 1D spectra are described in more detail under Specviz:Data Analysis Plugins. All plugins are accessed via the plugin icon in the upper right corner @@ -120,5 +120,5 @@ The :guilabel:`Remove` button can be used to remove a slit once it has been appl In order to plot a slit onto the image viewer, we need WCS information from an image and slit position from a 2D spectrum. The slit position is calculated using the ``S_REGION`` header extension value, located in the -`~specutils.Spectrum1D.meta` attribute of the :class:`~specutils.Spectrum1D` object +`~specutils.Spectrum.meta` attribute of the :class:`~specutils.Spectrum` object that is active in the 2D spectrum viewer. diff --git a/docs/specviz/export_data.rst b/docs/specviz/export_data.rst index 5f7111bad0..d133c43258 100644 --- a/docs/specviz/export_data.rst +++ b/docs/specviz/export_data.rst @@ -14,8 +14,8 @@ those data currently back into your Jupyter notebook: specviz.get_spectra() -which yields a either a single `specutils.Spectrum1D` object or a dictionary of -`specutils.Spectrum1D` (if there are multiple displayed spectra) that you can +which yields a either a single `specutils.Spectrum` object or a dictionary of +`specutils.Spectrum` (if there are multiple displayed spectra) that you can manipulate however you wish. You can then load the modified spectrum back into the notebook via the API described in :ref:`specviz-import-api`. @@ -35,7 +35,7 @@ To extract a spectrum with a spectral subset applied: specviz.get_data(spectral_subset='Subset 1') -In this case, the returned `specutils.Spectrum1D` object will have a ``mask`` +In this case, the returned `specutils.Spectrum` object will have a ``mask`` attribute, where ``True`` corresponds to the region outside the selected subset (i.e., the region that has been masked out). You could load back in a copy of the spectrum containing only your subset by running: @@ -43,7 +43,7 @@ spectrum containing only your subset by running: .. code-block:: python spec = specviz.get_data(spectral_subset='Subset 1') - subset_spec = Spectrum1D(flux=spec.flux[~spec.mask], + subset_spec = Spectrum(flux=spec.flux[~spec.mask], spectral_axis=spec.spectral_axis[~spec.mask]) specviz.load_data(subset_spec) diff --git a/docs/specviz/import_data.rst b/docs/specviz/import_data.rst index 1e281a9baf..d579d22ef9 100644 --- a/docs/specviz/import_data.rst +++ b/docs/specviz/import_data.rst @@ -4,17 +4,17 @@ Importing Data Into Specviz *************************** -By design, Specviz only supports data that can be parsed as :class:`~specutils.Spectrum1D` objects, +By design, Specviz only supports data that can be parsed as :class:`~specutils.Spectrum` objects, as that allows the Python-level interface and parsing tools to be defined in ``specutils`` instead of being duplicated in Jdaviz. -:class:`~specutils.Spectrum1D` objects are very flexible in their capabilities, however, +:class:`~specutils.Spectrum` objects are very flexible in their capabilities, however, and hence should address most astronomical spectrum use cases. If you are creating your own data products, please read the page :ref:`create_products`. .. seealso:: `Reading from a File `_ - Specutils documentation on loading data as :class:`~specutils.Spectrum1D` objects. + Specutils documentation on loading data as :class:`~specutils.Spectrum` objects. .. _specviz-import-commandline: @@ -36,7 +36,7 @@ Importing data through the GUI You can load your data into the Specviz application by clicking the :guilabel:`Import Data` button at the top left of the application's user interface. This opens a dialogue where the user can select a file -that can be parsed as a :class:`~specutils.Spectrum1D`. +that can be parsed as a :class:`~specutils.Spectrum`. After clicking :guilabel:`Import`, the data file will be parsed and loaded into the application. A notification will appear to let users know if the data import @@ -52,7 +52,7 @@ Alternatively, users who work in a coding environment like a Jupyter notebook can access the Specviz helper class API. Using this API, users can load data into the application through code with the :py:meth:`~jdaviz.configs.specviz.helper.Specviz.load_data` -method, which takes as input a :class:`~specutils.Spectrum1D` object. +method, which takes as input a :class:`~specutils.Spectrum` object. FITS Files ---------- @@ -61,13 +61,13 @@ The example below loads a FITS file into Specviz: .. code-block:: python - from specutils import Spectrum1D - spec1d = Spectrum1D.read("/path/to/data/file") + from specutils import Spectrum + spec1d = Spectrum.read("/path/to/data/file") specviz = Specviz() specviz.load_data(spec1d, data_label="my_spec") specviz.show() -You can also pass the path to a file that `~specutils.Spectrum1D` understands directly to the +You can also pass the path to a file that `~specutils.Spectrum` understands directly to the :py:meth:`~jdaviz.configs.specviz.helper.Specviz.load_data` method: .. code-block:: python @@ -83,12 +83,12 @@ You can create your own array to load into Specviz: import numpy as np import astropy.units as u - from specutils import Spectrum1D + from specutils import Spectrum from jdaviz import Specviz flux = np.random.randn(200) * u.Jy wavelength = np.arange(5100, 5300) * u.AA - spec1d = Spectrum1D(spectral_axis=wavelength, flux=flux) + spec1d = Spectrum(spectral_axis=wavelength, flux=flux) specviz = Specviz() specviz.load_data(spec1d, data_label="my_spec") specviz.show() @@ -101,7 +101,7 @@ object, you can load it into Specviz as follows: .. code-block:: python - from specutils import Spectrum1D + from specutils import Spectrum from jdaviz import Specviz # mydatamodel is a jwst.datamodels.MultiSpecModel object @@ -109,7 +109,7 @@ object, you can load it into Specviz as follows: flux = a.spec_table['FLUX'] wave = a.spec_table['WAVELENGTH'] - spec1d = Spectrum1D(flux=flux, spectral_axis=wave) + spec1d = Spectrum(flux=flux, spectral_axis=wave) specviz = Specviz() specviz.load_data(spec1d, data_label="MultiSpecModel") specviz.show() @@ -124,7 +124,7 @@ Importing a SpectrumList The :py:meth:`~jdaviz.configs.specviz.helper.Specviz.load_data` also accepts a `~specutils.SpectrumList` object, in which case it will both load the -individual `~specutils.Spectrum1D` objects in the list and additionally attempt +individual `~specutils.Spectrum` objects in the list and additionally attempt to stitch together the spectra into a single data object so that they can be manipulated and analyzed in the application as a single entity: diff --git a/docs/specviz/plugins.rst b/docs/specviz/plugins.rst index 72d0c1ebd3..6b9ae6ff1c 100644 --- a/docs/specviz/plugins.rst +++ b/docs/specviz/plugins.rst @@ -65,12 +65,12 @@ Markers Gaussian Smooth =============== -Gaussian Smooth is performed on a Spectrum1D data object. +Gaussian Smooth is performed on a Spectrum data object. The spectrum is convolved with a Gaussian function. The Gaussian standard deviation in pixels must be entered into the :guilabel:`Standard deviation` field in the plugin. -A new Spectrum1D object is generated and is added to the spectrum +A new Spectrum object is generated and is added to the spectrum viewer. It can be selected and shown in the viewer via the :guilabel:`Data` icon in the viewer toolbar. diff --git a/docs/specviz2d/export_data.rst b/docs/specviz2d/export_data.rst index 4fc2ecd8bc..a91d67b222 100644 --- a/docs/specviz2d/export_data.rst +++ b/docs/specviz2d/export_data.rst @@ -9,7 +9,7 @@ Exporting Data From Specviz2D 2D Spectra ========== -Images in the 2D spectrum viewer can be exported as `specutils.Spectrum1D` objects into +Images in the 2D spectrum viewer can be exported as `specutils.Spectrum` objects into the notebook (replace "2D data" with the label of the desired data): .. code-block:: python diff --git a/docs/specviz2d/import_data.rst b/docs/specviz2d/import_data.rst index ddb71e2db1..0a4fbf210c 100644 --- a/docs/specviz2d/import_data.rst +++ b/docs/specviz2d/import_data.rst @@ -4,17 +4,17 @@ Importing Data Into Specviz2D ***************************** -By design, Specviz2D only supports data that can be parsed as :class:`~specutils.Spectrum1D` objects, +By design, Specviz2D only supports data that can be parsed as :class:`~specutils.Spectrum` objects, as that allows the Python-level interface and parsing tools to be defined in ``specutils`` instead of being duplicated in Jdaviz. -:class:`~specutils.Spectrum1D` objects are very flexible in their capabilities, however, +:class:`~specutils.Spectrum` objects are very flexible in their capabilities, however, and hence should address most astronomical spectrum use cases. If you are creating your own data products, please read the page :ref:`create_products`. .. seealso:: `Reading from a File `_ - Specutils documentation on loading data as :class:`~specutils.Spectrum1D` objects. + Specutils documentation on loading data as :class:`~specutils.Spectrum` objects. Specviz2D can either take both a 2D and 1D spectrum as input, or can automatically extract a 1D spectrum if only a 2D spectrum is provided. To view the extraction parameters and override the @@ -42,7 +42,7 @@ Importing data through the GUI You can load your data into the Specviz2D application by clicking the :guilabel:`Import Data` button at the top left of the application's user interface. This opens a dialogue where the user can select a file -that can be parsed as a :class:`~specutils.Spectrum1D`. +that can be parsed as a :class:`~specutils.Spectrum`. After clicking :guilabel:`Import`, the data file will be parsed and loaded into the application. @@ -56,7 +56,7 @@ Alternatively, users who work in a coding environment like a Jupyter notebook can access the Specviz2D helper class API. Using this API, users can load data into the application through code with the :meth:`~jdaviz.configs.specviz2d.helper.Specviz2d.load_data` -method, which takes as input a :class:`~specutils.Spectrum1D` object or filename for the +method, which takes as input a :class:`~specutils.Spectrum` object or filename for the 2D spectrum and (optionally) the 1D spectrum. .. code-block:: python diff --git a/docs/specviz2d/plugins.rst b/docs/specviz2d/plugins.rst index d7639dd97e..7ec9206b9b 100644 --- a/docs/specviz2d/plugins.rst +++ b/docs/specviz2d/plugins.rst @@ -156,7 +156,7 @@ To export and access the specreduce Background object defined in the plugin, cal bg = sp_ext.export_bg() -To access the background image, background spectrum, or background-subtracted image as a :class:`~specutils.Spectrum1D` object, +To access the background image, background spectrum, or background-subtracted image as a :class:`~specutils.Spectrum` object, call :py:meth:`~jdaviz.configs.specviz2d.plugins.spectral_extraction.spectral_extraction.SpectralExtraction.export_bg_img`, :py:meth:`~jdaviz.configs.specviz2d.plugins.spectral_extraction.spectral_extraction.SpectralExtraction.export_bg_spectrum`, or :py:meth:`~jdaviz.configs.specviz2d.plugins.spectral_extraction.spectral_extraction.SpectralExtraction.export_bg_sub`, respectively. @@ -203,7 +203,7 @@ To export and access the specreduce extraction object defined in the plugin, cal ext = sp_ext.export_extract() -To access the extracted spectrum as a :class:`~specutils.Spectrum1D` object, call :py:meth:`~jdaviz.configs.specviz2d.plugins.spectral_extraction.spectral_extraction.SpectralExtraction.export_extract_spectrum`. +To access the extracted spectrum as a :class:`~specutils.Spectrum` object, call :py:meth:`~jdaviz.configs.specviz2d.plugins.spectral_extraction.spectral_extraction.SpectralExtraction.export_extract_spectrum`. To import the parameters from a specreduce extraction object (either a new object, or an exported one modified in the notebook) into the plugin, call :py:meth:`~jdaviz.configs.specviz2d.plugins.spectral_extraction.spectral_extraction.SpectralExtraction.import_extract`: diff --git a/jdaviz/app.py b/jdaviz/app.py index 2a8d3ed761..cc66e180dd 100644 --- a/jdaviz/app.py +++ b/jdaviz/app.py @@ -36,7 +36,7 @@ from ipyvuetify import VuetifyTemplate from ipywidgets import widget_serialization from traitlets import Dict, Bool, Unicode, Any -from specutils import Spectrum1D, SpectralRegion +from specutils import Spectrum, SpectralRegion from jdaviz import __version__ from jdaviz import style_registry @@ -95,7 +95,7 @@ def to_unit(self, data, cid, values, original_units, target_units): # gives the units of the values array, which might not be the same # as the original native units of the component in the data. if cid.label == "flux": - spec = data.get_object(cls=Spectrum1D) + spec = data.get_object(cls=Spectrum) if len(values) == 2: # Need this for setting the y-limits spec_limits = [spec.spectral_axis[0].value, spec.spectral_axis[-1].value] @@ -692,17 +692,11 @@ def _link_new_data(self, reference_data=None, data_to_be_linked=None): return elif self.config == 'cubeviz' and linked_data.ndim == 1: - ref_wavelength_component = dc[0].components[-2] - ref_flux_component = dc[0].components[-1] - linked_wavelength_component = dc[-1].components[1] - linked_flux_component = dc[-1].components[-1] + spectral_axis_index = dc[0].meta['spectral_axis_index'] + ref_wavelength_component = dc[0].components[spectral_axis_index] + linked_wavelength_component = dc[-1].components[0] - links = [ - LinkSameWithUnits(ref_wavelength_component, linked_wavelength_component), - LinkSame(ref_flux_component, linked_flux_component) - ] - - dc.add_link(links) + dc.add_link(LinkSame(ref_wavelength_component, linked_wavelength_component)) return elif (linked_data.meta.get('Plugin', None) == 'SpectralExtraction' or @@ -1027,7 +1021,7 @@ def _get_range_subset_bounds(self, subset_state, # units = dc[0].data.coords.spectral_axis.unit viewer = self.get_viewer(self._jdaviz_helper. _default_spectrum_viewer_reference_name) data = viewer.data() - if data and len(data) > 0 and isinstance(data[0], Spectrum1D): + if data and len(data) > 0 and isinstance(data[0], Spectrum): units = data[0].spectral_axis.unit else: raise ValueError("Unable to find spectral axis units") @@ -1402,7 +1396,7 @@ def return_data_label(self, loaded_object, ext=None, alt_name=None, check_unique Parameters ---------- loaded_object : str or object - The path to a data file or FITS HDUList or image object or Spectrum1D or + The path to a data file or FITS HDUList or image object or Spectrum or NDData array or numpy.ndarray. ext : str, optional The extension (or other distinguishing feature) of data used to identify it. @@ -1440,8 +1434,8 @@ def return_data_label(self, loaded_object, ext=None, alt_name=None, check_unique data_label = f"{loaded_object.file_name}[HDU object]" else: data_label = "Unknown HDU object" - elif isinstance(loaded_object, Spectrum1D): - data_label = "Spectrum1D" + elif isinstance(loaded_object, Spectrum): + data_label = "Spectrum" elif isinstance(loaded_object, NDData): data_label = "NDData" elif isinstance(loaded_object, np.ndarray): diff --git a/jdaviz/configs/cubeviz/helper.py b/jdaviz/configs/cubeviz/helper.py index d0f5f2c89e..4dad20cb49 100644 --- a/jdaviz/configs/cubeviz/helper.py +++ b/jdaviz/configs/cubeviz/helper.py @@ -3,7 +3,7 @@ from astropy.io import registry as io_registry from astropy.utils.decorators import deprecated from glue.core import BaseData -from specutils import Spectrum1D +from specutils import Spectrum from specutils.io.registers import _astropy_has_priorities from jdaviz.core.helpers import ImageConfigHelper @@ -58,7 +58,7 @@ def load_data(self, data, data_label=None, override_cube_limit=False, **kwargs): Parameters ---------- - data : str, `~astropy.io.fits.HDUList`, `~specutils.Spectrum1D`, or ndarray + data : str, `~astropy.io.fits.HDUList`, `~specutils.Spectrum`, or ndarray A string file path, astropy FITS object pointing to the data cube, a spectrum object, or a Numpy array cube. If plain array is given, axes order must be ``(x, y, z)``. @@ -141,7 +141,7 @@ def get_data(self, data_label=None, spatial_subset=None, spectral_subset=None, f spectrum viewer. If provided as a string, the cube will be collapsed with the provided function. If False, None, or not passed, the entire cube will be returned (unless there are values for ``spatial_subset`` and ``spectral_subset``). - cls : `~specutils.Spectrum1D`, `~astropy.nddata.CCDData`, optional + cls : `~specutils.Spectrum`, `~astropy.nddata.CCDData`, optional The type that data will be returned as. Returns @@ -193,7 +193,7 @@ def layer_is_cube_image_data(layer): # their ~/.specutils directory. def jdaviz_cube_fitswriter(spectrum, file_name, **kwargs): - """This is a custom writer for Spectrum1D data cube. + """This is a custom writer for Spectrum 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 @@ -205,11 +205,11 @@ def jdaviz_cube_fitswriter(spectrum, file_name, **kwargs): 2 MASK 1 ImageHDU (uint16) The FITS file generated by this writer does not need a - custom reader to be read back into Spectrum1D. + custom reader to be read back into Spectrum. Examples -------- - To write out a Spectrum1D cube using this writer: + To write out a Spectrum cube using this writer: >>> spec.write("my_output.fits", format="jdaviz-cube", overwrite=True) # doctest: +SKIP @@ -242,4 +242,4 @@ def jdaviz_cube_fitswriter(spectrum, file_name, **kwargs): else: # pragma: no cover kwargs = {} io_registry.register_writer( - "jdaviz-cube", Spectrum1D, jdaviz_cube_fitswriter, force=False, **kwargs) + "jdaviz-cube", Spectrum, jdaviz_cube_fitswriter, force=False, **kwargs) diff --git a/jdaviz/configs/cubeviz/plugins/moment_maps/moment_maps.py b/jdaviz/configs/cubeviz/plugins/moment_maps/moment_maps.py index ac98d7cbcc..155d87abab 100644 --- a/jdaviz/configs/cubeviz/plugins/moment_maps/moment_maps.py +++ b/jdaviz/configs/cubeviz/plugins/moment_maps/moment_maps.py @@ -6,7 +6,7 @@ import numpy as np from traitlets import Bool, List, Unicode, observe -from specutils import manipulation, analysis, Spectrum1D +from specutils import manipulation, analysis, Spectrum from jdaviz.core.custom_traitlets import IntHandleEmpty, FloatHandleEmpty from jdaviz.core.events import SnackbarMessage, GlobalDisplayUnitChanged @@ -276,7 +276,7 @@ def calculate_moment(self, add_data=True): ref_wavelength = self.reference_wavelength * u.Unit(self.dataset_spectral_unit) slab_sa = slab.spectral_axis.to("km/s", doppler_convention="relativistic", doppler_rest=ref_wavelength) - slab = Spectrum1D(slab.flux, slab_sa) + slab = Spectrum(slab.flux, slab_sa) # Finally actually calculate the moment self.moment = analysis.moment(slab, order=n_moment).T diff --git a/jdaviz/configs/cubeviz/plugins/parsers.py b/jdaviz/configs/cubeviz/plugins/parsers.py index 8d14a575ac..6f5e160928 100644 --- a/jdaviz/configs/cubeviz/plugins/parsers.py +++ b/jdaviz/configs/cubeviz/plugins/parsers.py @@ -6,9 +6,8 @@ from astropy import units as u from astropy.io import fits -from astropy.time import Time from astropy.wcs import WCS -from specutils import Spectrum1D +from specutils import Spectrum from jdaviz.core.registries import data_parser_registry from jdaviz.utils import standardize_metadata, PRIHDR_KEY @@ -22,7 +21,7 @@ @data_parser_registry("cubeviz-data-parser") -def parse_data(app, file_obj, data_type=None, data_label=None): +def parse_data(app, file_obj, data_type=None, data_label=None, specutils_format=None): """ Attempts to parse a data file and auto-populate available viewers in cubeviz. @@ -37,6 +36,11 @@ def parse_data(app, file_obj, data_type=None, data_label=None): The data type used to explicitly differentiate parsed data. data_label : str, optional The label to be applied to the Glue data component. + specutils_format : str, optional + Optional format string to pass to Spectrum.read(), see + https://specutils.readthedocs.io/en/stable/spectrum1d.html#list-of-loaders + for valid format strings. Useful for processed files that may not include + the original headers with information used to auto-identify. """ flux_viewer_reference_name = app._jdaviz_helper._default_flux_viewer_reference_name @@ -67,6 +71,17 @@ def parse_data(app, file_obj, data_type=None, data_label=None): spectrum_viewer_reference_name=spectrum_viewer_reference_name) return + elif specutils_format is not None: + sc = Spectrum.read(file_obj, format=specutils_format) + _parse_spectrum1d_3d( + app, sc, data_label=data_label, + flux_viewer_reference_name=flux_viewer_reference_name, + spectrum_viewer_reference_name=spectrum_viewer_reference_name, + uncert_viewer_reference_name=uncert_viewer_reference_name + ) + app.get_tray_item_from_name("Spectral Extraction").disabled_msg = "" + return + file_name = os.path.basename(file_obj) with fits.open(file_obj) as hdulist: @@ -76,29 +91,17 @@ def parse_data(app, file_obj, data_type=None, data_label=None): # NOTE: Alerted to deprecation of FILETYPE keyword from pipeline on 2022-07-08 # Kept for posterity in for data processed prior to this date. Use EXP_TYPE instead filetype = prihdr.get('FILETYPE', '').lower() - system = prihdr.get('SYSTEM', '').lower() if telescop == 'jwst' and ('ifu' in exptype or 'mrs' in exptype or filetype == '3d ifu cube'): - for ext, viewer_name in (('SCI', flux_viewer_reference_name), - ('ERR', uncert_viewer_reference_name), - ('DQ', None)): - data_label = app.return_data_label(file_name, ext) - _parse_jwst_s3d( - app, hdulist, data_label, ext=ext, viewer_name=viewer_name, - flux_viewer_reference_name=flux_viewer_reference_name, - spectrum_viewer_reference_name=spectrum_viewer_reference_name - ) - elif telescop == 'jwst' and filetype == 'r3d' and system == 'esa-pipeline': - for ext, viewer_name in (('DATA', flux_viewer_reference_name), - ('ERR', uncert_viewer_reference_name), - ('QUALITY', None)): - data_label = app.return_data_label(file_name, ext) - _parse_esa_s3d( - app, hdulist, data_label, ext=ext, viewer_name=viewer_name, - flux_viewer_reference_name=flux_viewer_reference_name, - spectrum_viewer_reference_name=spectrum_viewer_reference_name - ) + sc = Spectrum.read(file_obj) + data_label = app.return_data_label(file_name) + _parse_spectrum1d_3d( + app, sc, data_label=data_label, + flux_viewer_reference_name=flux_viewer_reference_name, + spectrum_viewer_reference_name=spectrum_viewer_reference_name, + uncert_viewer_reference_name=uncert_viewer_reference_name + ) else: _parse_hdulist( app, hdulist, file_name=data_label or file_name, @@ -111,8 +114,9 @@ def parse_data(app, file_obj, data_type=None, data_label=None): # If the data types are custom data objects, use explicit parsers. Note # that this relies on the glue-astronomy machinery to turn the data object # into something glue can understand. - elif isinstance(file_obj, Spectrum1D) and file_obj.flux.ndim in (1, 3): + elif isinstance(file_obj, Spectrum) and file_obj.flux.ndim in (1, 3): if file_obj.flux.ndim == 3: + print("Parsing 3D Spectrum") _parse_spectrum1d_3d( app, file_obj, data_label=data_label, flux_viewer_reference_name=flux_viewer_reference_name, @@ -142,7 +146,8 @@ def _get_celestial_wcs(wcs): def _return_spectrum_with_correct_units(flux, wcs, metadata, data_type, target_wave_unit=None, - hdulist=None, uncertainty=None, mask=None): + hdulist=None, uncertainty=None, mask=None, + spectral_axis=None): """Upstream issue of WCS not using the correct units for data must be fixed here. Issue: https://github.com/astropy/astropy/issues/3658 """ @@ -150,7 +155,11 @@ def _return_spectrum_with_correct_units(flux, wcs, metadata, data_type, target_w warnings.filterwarnings( 'ignore', message='Input WCS indicates that the spectral axis is not last', category=UserWarning) - sc = Spectrum1D(flux=flux, wcs=wcs, uncertainty=uncertainty, mask=mask) + if spectral_axis is None: + sc = Spectrum(flux=flux, wcs=wcs, uncertainty=uncertainty, mask=mask) + else: + sc = Spectrum(flux=flux, spectral_axis=spectral_axis, + uncertainty=uncertainty, mask=mask) if target_wave_unit is None and hdulist is not None: found_target = False @@ -176,7 +185,7 @@ def _return_spectrum_with_correct_units(flux, wcs, metadata, data_type, target_w warnings.filterwarnings( 'ignore', message='Input WCS indicates that the spectral axis is not last', category=UserWarning) - new_sc = Spectrum1D( + new_sc = Spectrum( flux=sc.flux, spectral_axis=sc.spectral_axis.to(target_wave_unit, u.spectral()), meta=metadata, @@ -268,110 +277,6 @@ def _parse_hdulist(app, hdulist, file_name=None, app._jdaviz_helper._loaded_flux_cube = app.data_collection[data_label] -def _parse_jwst_s3d(app, hdulist, data_label, ext='SCI', - viewer_name=None, flux_viewer_reference_name=None, - spectrum_viewer_reference_name=None): - hdu = hdulist[ext] - data_type = _get_data_type_by_hdu(hdu) - - # Manually inject MJD-OBS until we can support GWCS, see - # https://github.com/spacetelescope/jdaviz/issues/690 and - # https://github.com/glue-viz/glue-astronomy/issues/59 - if ext == 'SCI' and 'MJD-OBS' not in hdu.header: - for key in ('MJD-BEG', 'DATE-OBS'): # Possible alternatives - if key in hdu.header: - if key.startswith('MJD'): - hdu.header['MJD-OBS'] = hdu.header[key] - break - else: - t = Time(hdu.header[key]) - hdu.header['MJD-OBS'] = t.mjd - break - - if ext == 'DQ': # DQ flags have no unit - flux = hdu.data << u.dimensionless_unscaled - else: - unit = u.Unit(hdu.header.get('BUNIT', 'count')) - flux = hdu.data << unit - wcs = WCS(hdulist['SCI'].header, hdulist) # Everything uses SCI WCS - - metadata = standardize_metadata(hdu.header) - - # store original WCS in metadata. this is a hacky workaround for converting subsets - # to sky regions, where the parent data of the subset might have dropped spatial WCS info - metadata['_orig_spatial_wcs'] = _get_celestial_wcs(wcs) - - if hdu.name != 'PRIMARY' and 'PRIMARY' in hdulist: - metadata[PRIHDR_KEY] = standardize_metadata(hdulist['PRIMARY'].header) - - data = _return_spectrum_with_correct_units(flux, wcs, metadata, data_type, hdulist=hdulist) - app.add_data(data, data_label) - if data_type == 'flux': # Forced wave unit conversion made it lose stuff, so re-add - app.data_collection[-1].get_component("flux").units = flux.unit - - if viewer_name is not None: - app.add_data_to_viewer(viewer_name, data_label) - # Also add the collapsed flux to the spectrum viewer - if viewer_name == flux_viewer_reference_name: - app.add_data_to_viewer(spectrum_viewer_reference_name, data_label) - - if data_type == 'flux': - app._jdaviz_helper._loaded_flux_cube = app.data_collection[data_label] - elif data_type == 'uncert': - app._jdaviz_helper._loaded_uncert_cube = app.data_collection[data_label] - - -def _parse_esa_s3d(app, hdulist, data_label, ext='DATA', flux_viewer_reference_name=None, - spectrum_viewer_reference_name=None): - hdu = hdulist[ext] - data_type = _get_data_type_by_hdu(hdu) - - if ext == 'QUALITY': # QUALITY flags have no unit - flux = hdu.data << u.dimensionless_unscaled - else: - unit = u.Unit(hdu.header.get('BUNIT', 'count')) - flux = hdu.data << unit - - hdr = hdulist[1].header - - wcs_dict = { - 'CTYPE1': 'WAVE ', 'CUNIT1': 'um', 'CDELT1': hdr['CDELT3'] * 1E6, - 'CRPIX1': hdr['CRPIX3'], - 'CRVAL1': hdr['CRVAL3'] * 1E6, 'NAXIS1': hdr['NAXIS3'], - 'CTYPE2': 'DEC--TAN', 'CUNIT2': 'deg', 'CDELT2': hdr['CDELT1'], 'CRPIX2': hdr['CRPIX1'], - 'CRVAL2': hdr['CRVAL1'], 'NAXIS2': hdr['NAXIS1'], - 'CTYPE3': 'RA---TAN', 'CUNIT3': 'deg', 'CDELT3': hdr['CDELT2'], 'CRPIX3': hdr['CRPIX2'], - 'CRVAL3': hdr['CRVAL2'], 'NAXIS3': hdr['NAXIS2']} - - wcs = WCS(wcs_dict) - flux = np.moveaxis(flux, 0, -1) - flux = np.swapaxes(flux, 0, 1) - - metadata = standardize_metadata(hdu.header) - metadata.update(wcs_dict) # To be internally consistent - if hdu.name != 'PRIMARY' and 'PRIMARY' in hdulist: - metadata[PRIHDR_KEY] = standardize_metadata(hdulist['PRIMARY'].header) - - # store original WCS in metadata. this is a hacky workaround for converting subsets - # to sky regions, where the parent data of the subset might have dropped spatial WCS info - metadata['_orig_spatial_wcs'] = _get_celestial_wcs(wcs) - - data = _return_spectrum_with_correct_units(flux, wcs, metadata, data_type, hdulist=hdulist) - - app.add_data(data, data_label) - - if data_type == 'flux': # Forced wave unit conversion made it lose stuff, so re-add - app.data_collection[-1].get_component("flux").units = flux.unit - - app.add_data_to_viewer(flux_viewer_reference_name, data_label) - app.add_data_to_viewer(spectrum_viewer_reference_name, data_label) - - if data_type == 'flux': - app._jdaviz_helper._loaded_flux_cube = app.data_collection[data_label] - if data_type == 'uncert': - app._jdaviz_helper._loaded_uncert_cube = app.data_collection[data_label] - - def _parse_spectrum1d_3d(app, file_obj, data_label=None, flux_viewer_reference_name=None, spectrum_viewer_reference_name=None, uncert_viewer_reference_name=None): @@ -395,8 +300,6 @@ def _parse_spectrum1d_3d(app, file_obj, data_label=None, else: flux = val - flux = np.moveaxis(flux, 1, 0) - with warnings.catch_warnings(): warnings.filterwarnings( 'ignore', message='Input WCS indicates that the spectral axis is not last', @@ -410,7 +313,7 @@ def _parse_spectrum1d_3d(app, file_obj, data_label=None, if hasattr(file_obj, 'wcs'): meta['_orig_spatial_wcs'] = _get_celestial_wcs(file_obj.wcs) - s1d = Spectrum1D(flux=flux, wcs=file_obj.wcs, meta=meta) + s1d = Spectrum(flux=flux, wcs=file_obj.wcs, meta=meta) cur_data_label = app.return_data_label(data_label, attr.upper()) app.add_data(s1d, cur_data_label) @@ -427,7 +330,7 @@ def _parse_spectrum1d_3d(app, file_obj, data_label=None, def _parse_spectrum1d(app, file_obj, data_label=None, spectrum_viewer_reference_name=None): - # Here 'file_obj' is a Spectrum1D + # Here 'file_obj' is a Spectrum if data_label is None: data_label = app.return_data_label(file_obj) @@ -437,7 +340,7 @@ def _parse_spectrum1d(app, file_obj, data_label=None, spectrum_viewer_reference_ file_obj.meta['_orig_spatial_wcs'] = _get_celestial_wcs(file_obj.wcs) if hasattr(file_obj, 'wcs') else None # noqa: E501 # TODO: glue-astronomy translators only look at the flux property of - # specutils Spectrum1D objects. Fix to support uncertainties and masks. + # specutils Spectrum objects. Fix to support uncertainties and masks. app.add_data(file_obj, data_label) app.add_data_to_viewer(spectrum_viewer_reference_name, data_label) @@ -460,7 +363,7 @@ def _parse_ndarray(app, file_obj, data_label=None, data_type=None, flux = flux << u.count meta = standardize_metadata({'_orig_spatial_wcs': None}) - s3d = Spectrum1D(flux=flux, meta=meta) + s3d = Spectrum(flux=flux, meta=meta) app.add_data(s3d, data_label) if data_type == 'flux': @@ -487,7 +390,7 @@ def _parse_gif(app, file_obj, data_label=None, flux_viewer_reference_name=None, flux = np.rot90(np.moveaxis(flux, 0, 2), k=-1, axes=(0, 1)) meta = {'filename': file_name, '_orig_spatial_wcs': None} - s3d = Spectrum1D(flux=flux * u.count, meta=standardize_metadata(meta)) + s3d = Spectrum(flux=flux * u.count, meta=standardize_metadata(meta)) app.add_data(s3d, data_label) app.add_data_to_viewer(flux_viewer_reference_name, data_label) diff --git a/jdaviz/configs/cubeviz/plugins/spectral_extraction/spectral_extraction.py b/jdaviz/configs/cubeviz/plugins/spectral_extraction/spectral_extraction.py index 2cacd749b0..93420f8140 100644 --- a/jdaviz/configs/cubeviz/plugins/spectral_extraction/spectral_extraction.py +++ b/jdaviz/configs/cubeviz/plugins/spectral_extraction/spectral_extraction.py @@ -4,6 +4,7 @@ import numpy as np import astropy from astropy import units as u +from astropy.coordinates import SpectralCoord from astropy.utils.decorators import deprecated from astropy.nddata import ( NDDataArray, StdDevUncertainty @@ -11,7 +12,7 @@ from traitlets import Any, Bool, Dict, Float, List, Unicode, observe from packaging.version import Version from photutils.aperture import CircularAperture, EllipticalAperture, RectangularAperture -from specutils import Spectrum1D +from specutils import Spectrum from jdaviz.core.custom_traitlets import FloatHandleEmpty from jdaviz.core.events import SnackbarMessage, SliceValueUpdatedMessage @@ -119,6 +120,8 @@ def __init__(self, *args, **kwargs): self.aperture._initialize_choices() self.aperture.select_default() + self.spectral_axis_index = 0 + self.background = ApertureSubsetSelect(self, 'bg_items', 'bg_selected', @@ -262,7 +265,7 @@ def collapse_to_spectrum(self, add_data=True, **kwargs): uncert_cube = self._app._jdaviz_helper._loaded_uncert_cube uncertainties = None selected_func = self.function_selected.lower() - + self.spectral_axis_index = spectral_cube.meta["spectral_axis_index"] # This plugin collapses over the *spatial axes* (optionally over a spatial subset, # defaults to ``No Subset``). Since the Cubeviz parser puts the fluxes # and uncertainties in different glue Data objects, we translate the spectral @@ -273,7 +276,7 @@ def collapse_to_spectrum(self, add_data=True, **kwargs): ) if uncert_cube: uncertainties = uncert_cube.get_subset_object( - subset_id=self.aperture.selected, cls=StdDevUncertainty + subset_id=self.aperture.selected, cls=StdDevUncertainty, attribute="flux" ) # Exact slice mask of cone or cylindrical aperture through the cube. `shape_mask` is # a 3D array with fractions of each pixel within an aperture at each @@ -295,10 +298,16 @@ def collapse_to_spectrum(self, add_data=True, **kwargs): flux = nddata.data << nddata.unit mask = nddata.mask # Use the spectral coordinate from the WCS: + pass_spectral_axis = False + spectral_axis = None if '_orig_spec' in spectral_cube.meta: wcs = spectral_cube.meta['_orig_spec'].wcs.spectral - else: + elif hasattr(spectral_cube.coords, "spectral"): wcs = spectral_cube.coords.spectral + else: + # Can't split out spectral from GWCS + wcs = spectral_cube.coords + pass_spectral_axis = True # Filter out NaNs (False = good) mask = np.logical_or(mask, np.isnan(flux)) @@ -311,10 +320,10 @@ def collapse_to_spectrum(self, add_data=True, **kwargs): # by default we want to propagate uncertainties: kwargs.setdefault("propagate_uncertainties", True) - # Collapse an e.g. 3D spectral cube to 1D spectrum, assuming that last axis - # is always wavelength. This may need adjustment after the following - # specutils PR is merged: https://github.com/astropy/specutils/pull/1033 - spatial_axes = (0, 1) + # Collapse a 3D spectral cube to 1D spectrum. + spatial_axes = [0, 1, 2] + spatial_axes.remove(self.spectral_axis_index) + spatial_axes = tuple(spatial_axes) if selected_func == 'mean': # Use built-in sum function to collapse NDDataArray collapsed_sum_for_mean = nddata_reshaped.sum(axis=spatial_axes, **kwargs) @@ -334,22 +343,29 @@ def collapse_to_spectrum(self, add_data=True, **kwargs): axis=spatial_axes, **kwargs ) # returns an NDDataArray - # Convert to Spectrum1D, with the spectral axis in correct units: - if hasattr(spectral_cube.coords, 'spectral_wcs'): - target_wave_unit = spectral_cube.coords.spectral_wcs.world_axis_units[0] - else: - target_wave_unit = spectral_cube.coords.spectral.world_axis_units[0] + # Convert to Spectrum, with the spectral axis in correct units: + target_wave_unit = spectral_cube.coords.world_axis_units[2-self.spectral_axis_index] flux = collapsed_nddata.data << collapsed_nddata.unit mask = collapsed_nddata.mask uncertainty = collapsed_nddata.uncertainty + if pass_spectral_axis: + wcs_args = [0, 0, 0] + spec_indices = np.arange(spectral_cube.shape[self.spectral_axis_index]) + wcs_args[self.spectral_axis_index] = spec_indices + wcs_args.reverse() + spectral_and_spatial = wcs.pixel_to_world(*wcs_args) + spectral_axis = [x for x in spectral_and_spatial if isinstance(x, SpectralCoord)][0] # noqa + collapsed_spec = _return_spectrum_with_correct_units( flux, wcs, collapsed_nddata.meta, 'flux', target_wave_unit=target_wave_unit, uncertainty=uncertainty, - mask=mask + mask=mask, + spectral_axis=spectral_axis ) + # stuff for exporting to file self.extracted_spec = collapsed_spec self.extracted_spec_available = True @@ -373,7 +389,7 @@ def collapse_to_spectrum(self, add_data=True, **kwargs): def get_aperture(self): # Retrieve flux cube and create an array to represent the cone mask - flux_cube = self._app._jdaviz_helper._loaded_flux_cube.get_object(cls=Spectrum1D, + flux_cube = self._app._jdaviz_helper._loaded_flux_cube.get_object(cls=Spectrum, statistic=None) display_unit = astropy.units.Unit(self.app._get_display_unit(self.slice_display_unit_name)) @@ -383,7 +399,9 @@ def get_aperture(self): aperture = regions2aperture(self.aperture.selected_spatial_region) aperture.positions = center - im_shape = (flux_cube.shape[0], flux_cube.shape[1]) + im_shape = list(flux_cube.shape) + im_shape.remove(im_shape[self.spectral_axis_index]) + im_shape = tuple(im_shape) aper_method = self.aperture_method_selected.lower() if self.wavelength_dependent: # Cone aperture @@ -422,12 +440,17 @@ def get_aperture(self): slice_mask = aperture.to_mask(method=aper_method).to_image(im_shape) # Add slice mask to fractional pixel array - mask_weights[:, :, index] = slice_mask + if self.spectral_axis_index == 0: + mask_weights[index, :, :] = slice_mask + else: + mask_weights[:, :, index] = slice_mask else: # Cylindrical aperture slice_mask = aperture.to_mask(method=aper_method).to_image(im_shape) # Turn 2D slice_mask into 3D array that is the same shape as the flux cube - mask_weights = np.stack([slice_mask] * len(flux_cube.spectral_axis), axis=2) + mask_weights = np.stack([slice_mask] * len(flux_cube.spectral_axis), + axis=self.spectral_axis_index) + return mask_weights def vue_spectral_extraction(self, *args, **kwargs): diff --git a/jdaviz/configs/cubeviz/plugins/spectral_extraction/tests/test_spectral_extraction.py b/jdaviz/configs/cubeviz/plugins/spectral_extraction/tests/test_spectral_extraction.py index 1c19dd8fc0..1da8217249 100644 --- a/jdaviz/configs/cubeviz/plugins/spectral_extraction/tests/test_spectral_extraction.py +++ b/jdaviz/configs/cubeviz/plugins/spectral_extraction/tests/test_spectral_extraction.py @@ -11,7 +11,7 @@ from numpy.testing import assert_allclose, assert_array_equal from regions import (CirclePixelRegion, CircleAnnulusPixelRegion, EllipsePixelRegion, RectanglePixelRegion, PixCoord) -from specutils import Spectrum1D +from specutils import Spectrum from astropy.wcs import WCS @@ -31,11 +31,11 @@ def test_version_after_nddata_update(cubeviz_helper, spectrum1d_cube_with_uncert collapsed_cube_nddata = spectral_cube.sum(axis=(0, 1)) # return NDDataArray # Collapse the spectral cube using the methods in jdaviz: - collapsed_cube_s1d = plg.collapse_to_spectrum(add_data=False) # returns Spectrum1D + collapsed_cube_s1d = plg.collapse_to_spectrum(add_data=False) # returns Spectrum assert plg._obj.disabled_msg == '' assert isinstance(spectral_cube, NDDataArray) - assert isinstance(collapsed_cube_s1d, Spectrum1D) + assert isinstance(collapsed_cube_s1d, Spectrum) assert_allclose( collapsed_cube_nddata.data, @@ -161,7 +161,7 @@ def test_save_collapsed_to_fits(cubeviz_helper, spectrum1d_cube_with_uncerts, tm assert fname_path.is_file() # read file back in, make sure it matches - dat = Spectrum1D.read(fname_path) + dat = Spectrum.read(fname_path) assert_array_equal(dat.data, extract_plugin._obj.extracted_spec.data) assert dat.unit == extract_plugin._obj.extracted_spec.unit @@ -347,7 +347,7 @@ def test_cone_and_cylinder_errors(cubeviz_helper, spectrum1d_cube_largest): def test_cone_aperture_with_frequency_units(cubeviz_helper, spectral_cube_wcs): - data = Spectrum1D(flux=np.ones((128, 129, 256)) * u.nJy, wcs=spectral_cube_wcs) + data = Spectrum(flux=np.ones((128, 129, 256)) * u.nJy, wcs=spectral_cube_wcs) cubeviz_helper.load_data(data, data_label="Test Flux") cubeviz_helper.load_regions([CirclePixelRegion(PixCoord(14, 15), radius=2.5)]) @@ -384,7 +384,7 @@ def test_unit_translation(cubeviz_helper): w = WCS(wcs_dict) flux = np.zeros((30, 20, 3001), dtype=np.float32) flux[5:15, 1:11, :] = 1 - cube = Spectrum1D(flux=flux * u.MJy, wcs=w, meta=wcs_dict) + cube = Spectrum(flux=flux * u.MJy, wcs=w, meta=wcs_dict) cubeviz_helper.load_data(cube, data_label="test") center = PixCoord(5, 10) diff --git a/jdaviz/configs/cubeviz/plugins/tests/test_cubeviz_helper.py b/jdaviz/configs/cubeviz/plugins/tests/test_cubeviz_helper.py index 37a359801f..ad2ff1a723 100644 --- a/jdaviz/configs/cubeviz/plugins/tests/test_cubeviz_helper.py +++ b/jdaviz/configs/cubeviz/plugins/tests/test_cubeviz_helper.py @@ -2,7 +2,7 @@ from astropy import units as u from astropy.tests.helper import assert_quantity_allclose -from specutils import Spectrum1D +from specutils import Spectrum from glue.core.roi import XRangeROI @@ -68,7 +68,7 @@ def test_valid_function(cubeviz_helper, spectrum1d_cube): spatial_subset='Subset 1', function="minimum") results_max = cubeviz_helper.get_data(data_label="test[FLUX]", spatial_subset='Subset 1', function="maximum") - assert isinstance(results_min, Spectrum1D) + assert isinstance(results_min, Spectrum) assert_quantity_allclose(results_min.flux, [6., 14.] * u.Jy, atol=1e-5 * u.Jy) assert_quantity_allclose(results_max.flux, diff --git a/jdaviz/configs/cubeviz/plugins/tests/test_parsers.py b/jdaviz/configs/cubeviz/plugins/tests/test_parsers.py index 8a42cc422a..b5227eba2c 100644 --- a/jdaviz/configs/cubeviz/plugins/tests/test_parsers.py +++ b/jdaviz/configs/cubeviz/plugins/tests/test_parsers.py @@ -4,7 +4,7 @@ from astropy import units as u from astropy.utils.introspection import minversion from astropy.wcs import WCS -from specutils import Spectrum1D +from specutils import Spectrum from glue.core.roi import XRangeROI from glue_astronomy.translators.spectrum1d import PaddedSpectrumWCS from numpy.testing import assert_allclose, assert_array_equal @@ -34,7 +34,7 @@ def test_fits_image_hdu_with_microns(image_cube_hdu_obj_microns, cubeviz_helper) assert len(cubeviz_helper.app.data_collection) == 3 assert cubeviz_helper.app.data_collection[0].label == 'has_microns[FLUX]' - flux_cube = cubeviz_helper.app.data_collection[0].get_object(Spectrum1D, statistic=None) + flux_cube = cubeviz_helper.app.data_collection[0].get_object(Spectrum, statistic=None) assert flux_cube.spectral_axis.unit == u.um # This tests the same data as test_fits_image_hdu_parse above. @@ -125,7 +125,7 @@ def test_fits_image_hdu_parse_from_file(tmpdir, image_cube_hdu_obj, cubeviz_help def test_spectrum3d_parse(image_cube_hdu_obj, cubeviz_helper): flux = image_cube_hdu_obj[1].data << u.Unit(image_cube_hdu_obj[1].header['BUNIT']) wcs = WCS(image_cube_hdu_obj[1].header, image_cube_hdu_obj) - sc = Spectrum1D(flux=flux, wcs=wcs) + sc = Spectrum(flux=flux, wcs=wcs) cubeviz_helper.load_data(sc) data = cubeviz_helper.app.data_collection[0] @@ -155,7 +155,7 @@ def test_spectrum3d_parse(image_cube_hdu_obj, cubeviz_helper): def test_spectrum3d_no_wcs_parse(cubeviz_helper): - sc = Spectrum1D(flux=np.ones(24).reshape((2, 3, 4)) * u.nJy) # x, y, z + sc = Spectrum(flux=np.ones(24).reshape((2, 3, 4)) * u.nJy) # x, y, z cubeviz_helper.load_data(sc) assert sc.spectral_axis.unit == u.pix @@ -172,7 +172,7 @@ def test_spectrum1d_parse(spectrum1d, cubeviz_helper): cubeviz_helper.load_data(spectrum1d) assert len(cubeviz_helper.app.data_collection) == 1 - assert cubeviz_helper.app.data_collection[0].label.endswith('Spectrum1D') + assert cubeviz_helper.app.data_collection[0].label.endswith('Spectrum') assert cubeviz_helper.app.data_collection[0].meta['uncertainty_type'] == 'std' # Coordinate display is only for spatial image, which is missing here. @@ -220,7 +220,7 @@ def test_invalid_data_types(cubeviz_helper): cubeviz_helper.load_data(WCS(naxis=3)) with pytest.raises(NotImplementedError, match='Unsupported data format'): - cubeviz_helper.load_data(Spectrum1D(flux=np.ones((2, 2)) * u.nJy)) + cubeviz_helper.load_data(Spectrum(flux=np.ones((2, 2)) * u.nJy)) with pytest.raises(NotImplementedError, match='Unsupported data format'): cubeviz_helper.load_data(np.ones((2, 2))) diff --git a/jdaviz/configs/cubeviz/plugins/tests/test_regions.py b/jdaviz/configs/cubeviz/plugins/tests/test_regions.py index 7949347d25..7918fd2fe3 100644 --- a/jdaviz/configs/cubeviz/plugins/tests/test_regions.py +++ b/jdaviz/configs/cubeviz/plugins/tests/test_regions.py @@ -8,7 +8,7 @@ from astropy.coordinates import SkyCoord from glue.core.roi import XRangeROI from regions import PixCoord, CirclePixelRegion, CircleSkyRegion, EllipsePixelRegion -from specutils import Spectrum1D +from specutils import Spectrum from jdaviz.configs.imviz.tests.test_regions import BaseRegionHandler @@ -73,4 +73,4 @@ def test_spatial_spectral_mix(self): 'has_microns[FLUX] (Subset 1)', 'has_microns[FLUX] (Subset 2)'], spectral_subsets # noqa for sp in spectral_subsets.values(): - assert isinstance(sp, Spectrum1D) + assert isinstance(sp, Spectrum) diff --git a/jdaviz/configs/cubeviz/plugins/tools.py b/jdaviz/configs/cubeviz/plugins/tools.py index 6c986b163e..e8d5d13a0a 100644 --- a/jdaviz/configs/cubeviz/plugins/tools.py +++ b/jdaviz/configs/cubeviz/plugins/tools.py @@ -6,7 +6,7 @@ from glue_jupyter.bqplot.profile import BqplotProfileView from glue.viewers.common.tool import CheckableTool import numpy as np -from specutils import Spectrum1D +from specutils import Spectrum from jdaviz.configs.imviz.plugins.tools import _MatchedZoomMixin from jdaviz.core.events import SliceToolStateMessage, SliceSelectSliceMessage @@ -153,15 +153,15 @@ def on_mouse_move(self, data): return cube_data = cube_data[0] - if isinstance(cube_data, Spectrum1D): + if isinstance(cube_data, Spectrum): spectrum = cube_data else: spectrum = cube_data.get_object(statistic=None) - # Note: change this when Spectrum1D.with_spectral_axis is fixed. + # Note: change this when Spectrum.with_spectral_axis is fixed. x_unit = self._spectrum_viewer.state.x_display_unit if spectrum.spectral_axis.unit != x_unit: new_spectral_axis = spectrum.spectral_axis.to(x_unit) - spectrum = Spectrum1D(spectrum.flux, new_spectral_axis) + spectrum = Spectrum(spectrum.flux, new_spectral_axis) if x >= spectrum.flux.shape[0] or x < 0 or y >= spectrum.flux.shape[1] or y < 0: self._reset_spectrum_viewer_bounds() diff --git a/jdaviz/configs/cubeviz/plugins/viewers.py b/jdaviz/configs/cubeviz/plugins/viewers.py index 20fa227e6d..39449faf19 100644 --- a/jdaviz/configs/cubeviz/plugins/viewers.py +++ b/jdaviz/configs/cubeviz/plugins/viewers.py @@ -76,10 +76,19 @@ def _set_slice_indicator_value(self, value): class WithSliceSelection: - @property + @cached_property def slice_index(self): # index in state.slices corresponding to the slice axis - return 2 + for layer in self.layers: + try: + data_obj = layer.layer.data + return data_obj.meta['spectral_axis_index'] + except (AttributeError, KeyError): + raise + else: + break + else: + return 2 @property def slice_component_label(self): @@ -235,9 +244,6 @@ def _initial_x_axis(self, *args): x_att = att_name self.state.x_att_world = ref_data.id[x_att] break - else: - x_att = "Pixel Axis 0 [z]" - self.state.x_att = ref_data.id[x_att] def set_plot_axes(self): self.figure.axes[1].tick_format = None diff --git a/jdaviz/configs/default/plugins/collapse/tests/test_collapse.py b/jdaviz/configs/default/plugins/collapse/tests/test_collapse.py index a35a30e9b0..63820fce11 100644 --- a/jdaviz/configs/default/plugins/collapse/tests/test_collapse.py +++ b/jdaviz/configs/default/plugins/collapse/tests/test_collapse.py @@ -2,12 +2,12 @@ import pytest from astropy.nddata import CCDData from astropy import units as u -from specutils import Spectrum1D +from specutils import Spectrum @pytest.mark.filterwarnings('ignore') def test_linking_after_collapse(cubeviz_helper, spectral_cube_wcs): - cubeviz_helper.load_data(Spectrum1D(flux=np.ones((3, 4, 5)) * u.nJy, wcs=spectral_cube_wcs)) + cubeviz_helper.load_data(Spectrum(flux=np.ones((3, 4, 5)) * u.nJy, wcs=spectral_cube_wcs)) dc = cubeviz_helper.app.data_collection # TODO: this now fails when instantiating Collapse after initialization @@ -40,7 +40,7 @@ def test_linking_after_collapse(cubeviz_helper, spectral_cube_wcs): def test_save_collapsed_to_fits(cubeviz_helper, spectral_cube_wcs, tmp_path): - cubeviz_helper.load_data(Spectrum1D(flux=np.ones((3, 4, 5)) * u.nJy, wcs=spectral_cube_wcs)) + cubeviz_helper.load_data(Spectrum(flux=np.ones((3, 4, 5)) * u.nJy, wcs=spectral_cube_wcs)) collapse_plugin = cubeviz_helper.plugins['Collapse'] diff --git a/jdaviz/configs/default/plugins/export/export.py b/jdaviz/configs/default/plugins/export/export.py index 094a70ea0b..fd41534a7d 100644 --- a/jdaviz/configs/default/plugins/export/export.py +++ b/jdaviz/configs/default/plugins/export/export.py @@ -15,7 +15,7 @@ from jdaviz.core.events import AddDataMessage, SnackbarMessage from jdaviz.core.user_api import PluginUserApi -from specutils import Spectrum1D +from specutils import Spectrum from astropy import units as u from astropy.nddata import CCDData @@ -263,7 +263,7 @@ def _set_dataset_not_supported_msg(self, msg=None): # NOTE: should not be a valid choice due to dataset filters, but we'll include # another check here. self.data_invalid_msg = "Data export is only available for plugin generated data." - elif not isinstance(self.dataset.selected_obj, (Spectrum1D, CCDData)): + elif not isinstance(self.dataset.selected_obj, (Spectrum, CCDData)): self.data_invalid_msg = "Export is not yet implemented for this type of data" elif (data_unit := self.dataset.selected_obj.unit) == u.Unit('DN/s'): self.data_invalid_msg = f'Export Disabled: The unit {data_unit} could not be saved in native FITS format.' # noqa: E501 diff --git a/jdaviz/configs/default/plugins/export/tests/test_export.py b/jdaviz/configs/default/plugins/export/tests/test_export.py index a321befa7c..f5d77d85a9 100644 --- a/jdaviz/configs/default/plugins/export/tests/test_export.py +++ b/jdaviz/configs/default/plugins/export/tests/test_export.py @@ -9,7 +9,7 @@ from glue.core.edit_subset_mode import AndMode, NewMode from glue.core.roi import CircularROI, XRangeROI from regions import Regions, CircleSkyRegion -from specutils import Spectrum1D +from specutils import Spectrum @pytest.mark.usefixtures('_jail') @@ -74,8 +74,8 @@ def test_not_implemented(self, cubeviz_helper, spectral_cube_wcs): the correct warning message to display in UI). """ - data = Spectrum1D(flux=np.ones((500, 500, 2)) * u.nJy, - wcs=spectral_cube_wcs) + data = Spectrum(flux=np.ones((500, 500, 2)) * u.nJy, + wcs=spectral_cube_wcs) cubeviz_helper.load_data(data) cubeviz_helper.app.get_viewer('flux-viewer').apply_roi(CircularROI(xc=255, @@ -128,7 +128,7 @@ def test_export_subsets_wcs(self, imviz_helper, spectral_cube_wcs): def test_basic_export_subsets_cubeviz(self, cubeviz_helper, spectral_cube_wcs): - data = Spectrum1D(flux=np.ones((128, 128, 256)) * u.nJy, wcs=spectral_cube_wcs) + data = Spectrum(flux=np.ones((128, 128, 256)) * u.nJy, wcs=spectral_cube_wcs) cubeviz_helper.load_data(data) @@ -229,7 +229,7 @@ def test_disable_export_for_unsupported_units(specviz2d_helper): dn_per_s = u.DN / u.s data = np.zeros((5, 10)) data[3] = np.arange(10) - data = Spectrum1D(flux=data*dn_per_s, spectral_axis=data[3]*u.um) + data = Spectrum(flux=data*dn_per_s, spectral_axis=data[3]*u.um) specviz2d_helper.load_data(data) gs = specviz2d_helper.plugins["Gaussian Smooth"] diff --git a/jdaviz/configs/default/plugins/gaussian_smooth/gaussian_smooth.py b/jdaviz/configs/default/plugins/gaussian_smooth/gaussian_smooth.py index 9e83cc2abb..d10fe7d077 100644 --- a/jdaviz/configs/default/plugins/gaussian_smooth/gaussian_smooth.py +++ b/jdaviz/configs/default/plugins/gaussian_smooth/gaussian_smooth.py @@ -2,7 +2,7 @@ from astropy import units as u from astropy.convolution import convolve, Gaussian2DKernel -from specutils import Spectrum1D +from specutils import Spectrum from specutils.manipulation import gaussian_smooth from traitlets import List, Unicode, Bool, observe @@ -148,7 +148,7 @@ def smooth(self, add_data=True): Returns ------- - spec : `~specutils.Spectrum1D` + spec : `~specutils.Spectrum` The smoothed spectrum or data cube """ if self.mode_selected == 'Spatial': @@ -187,18 +187,18 @@ def spectral_smooth(self): Returns ------- - spec : `~specutils.Spectrum1D` + spec : `~specutils.Spectrum` The smoothed spectrum """ # Testing inputs to make sure putting smoothed spectrum into # datacollection works # input_flux = Quantity(np.array([0.2, 0.3, 2.2, 0.3]), u.Jy) # input_spaxis = Quantity(np.array([1, 2, 3, 4]), u.micron) - # spec1 = Spectrum1D(input_flux, spectral_axis=input_spaxis) + # spec1 = Spectrum(input_flux, spectral_axis=input_spaxis) # Takes the user input from the dialog (stddev) and uses it to # define a standard deviation for gaussian smoothing - cube = self.dataset.get_object(cls=Spectrum1D, statistic=None) + cube = self.dataset.get_object(cls=Spectrum, statistic=None) spec_smoothed = gaussian_smooth(cube, stddev=self.stddev) return spec_smoothed @@ -212,7 +212,7 @@ def spatial_smooth(self): Returns ------- - cube : `~specutils.Spectrum1D` + cube : `~specutils.Spectrum` The smoothed cube """ cube = self.dataset.selected_obj @@ -234,6 +234,6 @@ def spatial_smooth(self): # Create a new cube with the old metadata. Note that astropy # convolution generates values for masked (NaN) data. - newcube = Spectrum1D(flux=convolved_data * flux_unit, wcs=w) + newcube = Spectrum(flux=convolved_data * flux_unit, wcs=w) return newcube diff --git a/jdaviz/configs/default/plugins/gaussian_smooth/tests/test_gaussian_smooth.py b/jdaviz/configs/default/plugins/gaussian_smooth/tests/test_gaussian_smooth.py index 20e703c857..677f3cfb6f 100644 --- a/jdaviz/configs/default/plugins/gaussian_smooth/tests/test_gaussian_smooth.py +++ b/jdaviz/configs/default/plugins/gaussian_smooth/tests/test_gaussian_smooth.py @@ -1,7 +1,7 @@ import numpy as np import pytest from astropy.utils.exceptions import AstropyUserWarning -from specutils import Spectrum1D +from specutils import Spectrum def test_linking_after_spectral_smooth(cubeviz_helper, spectrum1d_cube): @@ -115,7 +115,7 @@ def test_spatial_convolution(cubeviz_helper, spectrum1d_cube): assert len(dc) == 2 assert dc[1].label == f'{data_label}[FLUX] spatial-smooth stddev-3.0' assert dc[1].shape == (2, 4, 2) # specutils moved spectral axis to last - assert (dc[f'{data_label}[FLUX] spatial-smooth stddev-3.0'].get_object(cls=Spectrum1D, + assert (dc[f'{data_label}[FLUX] spatial-smooth stddev-3.0'].get_object(cls=Spectrum, statistic=None).shape == (2, 4, 2)) diff --git a/jdaviz/configs/default/plugins/line_lists/line_lists.py b/jdaviz/configs/default/plugins/line_lists/line_lists.py index fcb4ecb9d7..5de6fc7b2c 100644 --- a/jdaviz/configs/default/plugins/line_lists/line_lists.py +++ b/jdaviz/configs/default/plugins/line_lists/line_lists.py @@ -205,7 +205,7 @@ def _on_viewer_data_changed(self, msg=None): self._bounds["min"] = viewer_data.spectral_axis[0] self._bounds["max"] = viewer_data.spectral_axis[-1] - # set redshift slider to redshift stored in Spectrum1D object + # set redshift slider to redshift stored in Spectrum object if viewer_data.meta.get('plugin', None) is not None: self.rs_redshift = (viewer_data.redshift.value if hasattr(viewer_data.redshift, 'value') diff --git a/jdaviz/configs/default/plugins/line_lists/tests/test_line_lists.py b/jdaviz/configs/default/plugins/line_lists/tests/test_line_lists.py index 37062dde72..24499f1f8f 100644 --- a/jdaviz/configs/default/plugins/line_lists/tests/test_line_lists.py +++ b/jdaviz/configs/default/plugins/line_lists/tests/test_line_lists.py @@ -4,15 +4,15 @@ import astropy.units as u from astropy.table import QTable -from specutils import Spectrum1D +from specutils import Spectrum from jdaviz.core.marks import SpectralLine from jdaviz.core.linelists import get_available_linelists def test_line_lists(specviz_helper): - spec = Spectrum1D(flux=np.random.rand(100)*u.Jy, - spectral_axis=np.arange(6000, 7000, 10)*u.AA) + spec = Spectrum(flux=np.random.rand(100)*u.Jy, + spectral_axis=np.arange(6000, 7000, 10)*u.AA) specviz_helper.load_data(spec) lt = QTable() diff --git a/jdaviz/configs/default/plugins/model_fitting/fitting_backend.py b/jdaviz/configs/default/plugins/model_fitting/fitting_backend.py index 9c2bb75a78..4afec6a648 100644 --- a/jdaviz/configs/default/plugins/model_fitting/fitting_backend.py +++ b/jdaviz/configs/default/plugins/model_fitting/fitting_backend.py @@ -7,7 +7,7 @@ import astropy.units as u -from specutils import Spectrum1D +from specutils import Spectrum from specutils.fitting import fit_lines __all__ = ['fit_model_to_spectrum'] @@ -16,7 +16,7 @@ def fit_model_to_spectrum(spectrum, component_list, expression, run_fitter=False, window=None, n_cpu=None): """Fits a `~astropy.modeling.CompoundModel` to a - `~specutils.Spectrum1D` instance. + `~specutils.Spectrum` instance. If the input spectrum represents a spectral cube, then fits the model to every spaxel in the cube, using @@ -25,7 +25,7 @@ def fit_model_to_spectrum(spectrum, component_list, expression, Parameters ---------- - spectrum : `~specutils.Spectrum1D` + spectrum : `~specutils.Spectrum` The spectrum to be fitted. component_list : list @@ -62,7 +62,7 @@ def fit_model_to_spectrum(spectrum, component_list, expression, spaxel, a list with 2D arrays, each one storing fitted parameter values for all spaxels, is returned. - output_spectrum : `~specutils.Spectrum1D` + output_spectrum : `~specutils.Spectrum` The realization of the fitted model as a spectrum. The spectrum will be 1D or 3D depending on the shape of input spectrum. """ @@ -77,13 +77,13 @@ def fit_model_to_spectrum(spectrum, component_list, expression, def _fit_1D(initial_model, spectrum, run_fitter, filter_non_finite=True, window=None): """ - Fits an astropy CompoundModel to a Spectrum1D instance. + Fits an astropy CompoundModel to a Spectrum instance. Parameters ---------- initial_model : :class: `astropy.modeling.CompoundModel` Initial guess for the model to be fitted. - spectrum : :class:`specutils.Spectrum1D` + spectrum : :class:`specutils.Spectrum` The spectrum to be fitted. run_fitter : bool When False (the default), the function composes the compound @@ -95,7 +95,7 @@ def _fit_1D(initial_model, spectrum, run_fitter, filter_non_finite=True, window= ------- output_model : :class: `astropy.modeling.CompoundModel` The model resulting from the fit. - output_spectrum : :class:`specutils.Spectrum1D` + output_spectrum : :class:`specutils.Spectrum` The realization of the fitted model as a spectrum. """ @@ -113,9 +113,9 @@ def _fit_1D(initial_model, spectrum, run_fitter, filter_non_finite=True, window= output_values = initial_model(spectrum.spectral_axis) # Build return spectrum - output_spectrum = Spectrum1D(spectral_axis=spectrum.spectral_axis, - flux=output_values, - mask=spectrum.mask) + output_spectrum = Spectrum(spectral_axis=spectrum.spectral_axis, + flux=output_values, + mask=spectrum.mask) return output_model, output_spectrum @@ -130,7 +130,7 @@ def _fit_3D(initial_model, spectrum, window=None, n_cpu=None): ---------- initial_model : :class: `astropy.modeling.CompoundModel` Initial guess for the model to be fitted. - spectrum : :class:`specutils.Spectrum1D` + spectrum : :class:`specutils.Spectrum` The spectrum that stores the cube in its 'flux' attribute. window : `None` or :class:`specutils.spectra.SpectralRegion` See :func:`specutils.fitting.fitmodels.fit_lines`. @@ -145,7 +145,7 @@ def _fit_3D(initial_model, spectrum, window=None, n_cpu=None): output_model : :list: a list that stores 2D arrays. Each array contains one parameter from `astropy.modeling.CompoundModel` instances fitted to every spaxel in the input cube. - output_spectrum : :class:`specutils.Spectrum1D` + output_spectrum : :class:`specutils.Spectrum` The spectrum that stores the fitted model values in its 'flux' attribute. """ @@ -215,9 +215,9 @@ def collect_result(results): # Build output 3D spectrum funit = spectrum.flux.unit - output_spectrum = Spectrum1D(wcs=spectrum.wcs, - flux=output_flux_cube * funit, - mask=spectrum.mask) + output_spectrum = Spectrum(wcs=spectrum.wcs, + flux=output_flux_cube * funit, + mask=spectrum.mask) return fitted_models, output_spectrum @@ -251,7 +251,7 @@ def __call__(self): x = parameters[0] y = parameters[1] - # Calling the Spectrum1D constructor for every spaxel + # Calling the Spectrum constructor for every spaxel # turned out to be less expensive than expected. Experiments # show that the cost amounts to a couple percent additional # running time in comparison with a version that uses a 3D @@ -266,7 +266,7 @@ def __call__(self): # If no mask is provided: mask = np.zeros_like(flux.value).astype(bool) - sp = Spectrum1D(spectral_axis=self.wave, flux=flux, mask=mask) + sp = Spectrum(spectral_axis=self.wave, flux=flux, mask=mask) if sp.uncertainty and not np.all(sp.uncertainty.array == 0): weights = 'unc' @@ -366,7 +366,7 @@ def _generate_spaxel_list(spectrum): Parameters ---------- - spectrum : :class:`specutils.Spectrum1D` + spectrum : :class:`specutils.Spectrum` The spectrum that stores the cube in its ``'flux'`` attribute. Returns diff --git a/jdaviz/configs/default/plugins/model_fitting/model_fitting.py b/jdaviz/configs/default/plugins/model_fitting/model_fitting.py index 9c1a5c403a..99de2fc9c1 100644 --- a/jdaviz/configs/default/plugins/model_fitting/model_fitting.py +++ b/jdaviz/configs/default/plugins/model_fitting/model_fitting.py @@ -3,7 +3,7 @@ from copy import deepcopy import astropy.units as u -from specutils import Spectrum1D +from specutils import Spectrum from specutils.utils import QuantityModel from traitlets import Bool, List, Unicode, observe @@ -341,7 +341,7 @@ def _dataset_selected_changed(self, event=None): if selected_spec is None: return - # Replace NaNs from collapsed Spectrum1D in Cubeviz + # Replace NaNs from collapsed Spectrum in Cubeviz # (won't affect calculations because these locations are masked) selected_spec.flux[np.isnan(selected_spec.flux)] = 0.0 # TODO: can we simplify this logic? @@ -908,7 +908,7 @@ def _fit_model_to_cube(self, add_data): if "_orig_spec" in data.meta: spec = data.meta["_orig_spec"] else: - spec = data.get_object(cls=Spectrum1D, statistic=None) + spec = data.get_object(cls=Spectrum, statistic=None) snackbar_message = SnackbarMessage( "Fitting model to cube...", @@ -944,7 +944,7 @@ def _fit_model_to_cube(self, add_data): temp_label = "{} ({}, {})".format(self.results_label, m["x"], m["y"]) self.app.fitted_models[temp_label] = m["model"] - output_cube = Spectrum1D(flux=fitted_spectrum.flux, wcs=fitted_spectrum.wcs) + output_cube = Spectrum(flux=fitted_spectrum.flux, wcs=fitted_spectrum.wcs) # Create new data entry for glue if add_data: 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 ce63f9924d..66a6e61d7c 100644 --- a/jdaviz/configs/default/plugins/model_fitting/tests/test_fitting.py +++ b/jdaviz/configs/default/plugins/model_fitting/tests/test_fitting.py @@ -10,7 +10,7 @@ from astropy.tests.helper import assert_quantity_allclose from astropy.wcs import WCS from numpy.testing import assert_allclose, assert_array_equal -from specutils.spectra import Spectrum1D +from specutils.spectra import Spectrum from jdaviz.configs.default.plugins.model_fitting import fitting_backend as fb from jdaviz.configs.default.plugins.model_fitting import initializers @@ -56,7 +56,7 @@ def test_model_params(): def test_model_ids(cubeviz_helper, spectral_cube_wcs): - cubeviz_helper.load_data(Spectrum1D(flux=np.ones((3, 4, 5)) * u.nJy, wcs=spectral_cube_wcs), + cubeviz_helper.load_data(Spectrum(flux=np.ones((3, 4, 5)) * u.nJy, wcs=spectral_cube_wcs), data_label='test') plugin = cubeviz_helper.plugins["Model Fitting"]._obj plugin.dataset_selected = 'test[FLUX]' @@ -79,7 +79,7 @@ def test_model_ids(cubeviz_helper, spectral_cube_wcs): def test_parameter_retrieval(cubeviz_helper, spectral_cube_wcs): flux = np.ones((3, 4, 5)) flux[2, 2, :] = [1, 2, 3, 4, 5] - cubeviz_helper.load_data(Spectrum1D(flux=flux * u.nJy, wcs=spectral_cube_wcs), + cubeviz_helper.load_data(Spectrum(flux=flux * u.nJy, wcs=spectral_cube_wcs), data_label='test') plugin = cubeviz_helper.plugins["Model Fitting"] plugin.create_model_component("Linear1D", "L") @@ -112,7 +112,7 @@ def test_fitting_backend(unc): uncertainties = StdDevUncertainty(np.zeros(y.shape)*u.Jy) elif unc is None: uncertainties = None - spectrum = Spectrum1D(flux=y*u.Jy, spectral_axis=x*u.um, uncertainty=uncertainties) + spectrum = Spectrum(flux=y*u.Jy, spectral_axis=x*u.um, uncertainty=uncertainties) g1f = models.Gaussian1D(0.7*u.Jy, 4.65*u.um, 0.3*u.um, name='g1') g2f = models.Gaussian1D(2.0*u.Jy, 5.55*u.um, 0.3*u.um, name='g2') @@ -149,7 +149,7 @@ def test_cube_fitting_backend(cubeviz_helper, unc, tmp_path): IMAGE_SIZE_X = 15 IMAGE_SIZE_Y = 14 - # Flux cube oriented as in JWST data. To build a Spectrum1D + # Flux cube oriented as in JWST data. To build a Spectrum # instance with this, one need to transpose it so the spectral # axis direction corresponds to the last index. flux_cube = np.zeros((SPECTRUM_SIZE, IMAGE_SIZE_X, IMAGE_SIZE_Y)) @@ -164,7 +164,7 @@ def test_cube_fitting_backend(cubeviz_helper, unc, tmp_path): for spx in spaxels: flux_cube[:, spx[0], spx[1]] = build_spectrum(sigma=SIGMA)[1] - # Transpose so it can be packed in a Spectrum1D instance. + # Transpose so it can be packed in a Spectrum instance. flux_cube = flux_cube.transpose(1, 2, 0) # (15, 14, 200) cube_wcs = WCS({ 'WCSAXES': 3, 'RADESYS': 'ICRS', 'EQUINOX': 2000.0, @@ -184,8 +184,8 @@ def test_cube_fitting_backend(cubeviz_helper, unc, tmp_path): elif unc is None: uncertainties = None - spectrum = Spectrum1D(flux=flux_cube*u.Jy, wcs=cube_wcs, - uncertainty=uncertainties, mask=mask) + spectrum = Spectrum(flux=flux_cube*u.Jy, wcs=cube_wcs, + uncertainty=uncertainties, mask=mask) # Initial model for fit. g1f = models.Gaussian1D(0.7*u.Jy, 4.65*u.um, 0.3*u.um, name='g1') @@ -221,7 +221,7 @@ def test_cube_fitting_backend(cubeviz_helper, unc, tmp_path): assert fitted_model[0].mean.unit == u.um # Check that spectrum result is formatted as expected. - assert isinstance(fitted_spectrum, Spectrum1D) + assert isinstance(fitted_spectrum, Spectrum) assert len(fitted_spectrum.shape) == 3 assert fitted_spectrum.shape == (IMAGE_SIZE_X, IMAGE_SIZE_Y, SPECTRUM_SIZE) assert fitted_spectrum.flux.unit == u.Jy @@ -271,7 +271,7 @@ def test_cube_fitting_backend(cubeviz_helper, unc, tmp_path): # 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") + Spectrum.read(out_fn, format="jdaviz-cube") # Check Cubeviz roundtrip. cubeviz_helper.load_data(out_fn) diff --git a/jdaviz/configs/default/plugins/model_fitting/tests/test_plugin.py b/jdaviz/configs/default/plugins/model_fitting/tests/test_plugin.py index 8bda0c735f..05d679461e 100644 --- a/jdaviz/configs/default/plugins/model_fitting/tests/test_plugin.py +++ b/jdaviz/configs/default/plugins/model_fitting/tests/test_plugin.py @@ -15,7 +15,7 @@ import astropy.units as u from glue.core.roi import CircularROI, XRangeROI -from specutils import Spectrum1D +from specutils import Spectrum from jdaviz.configs.cubeviz.plugins.tests.test_parsers import ASTROPY_LT_5_3 from jdaviz.configs.default.plugins.model_fitting.initializers import MODELS @@ -162,7 +162,7 @@ def test_register_cube_model(cubeviz_helper, spectrum1d_cube): def test_fit_cube_no_wcs(cubeviz_helper): # This is like when user do something to a cube outside of Jdaviz # and then load it back into a new instance of Cubeviz for further analysis. - sp = Spectrum1D(flux=np.ones((7, 8, 9)) * u.nJy) # ny, nx, nz + sp = Spectrum(flux=np.ones((7, 8, 9)) * u.nJy) # ny, nx, nz cubeviz_helper.load_data(sp, data_label="test_cube") mf = cubeviz_helper.plugins['Model Fitting'] mf.create_model_component('Linear1D') @@ -309,7 +309,7 @@ def test_subset_masks(cubeviz_helper, spectrum1d_cube_larger): p = cubeviz_helper.app.get_tray_item_from_name('g-model-fitting') # Get the data object without collapsing the spectrum: - data = cubeviz_helper.app.data_collection[0].get_object(cls=Spectrum1D, statistic=None) + data = cubeviz_helper.app.data_collection[0].get_object(cls=Spectrum, statistic=None) masked_data = p._apply_subset_masks(data, p.spatial_subset) assert data.mask is None @@ -321,10 +321,10 @@ def test_subset_masks(cubeviz_helper, spectrum1d_cube_larger): # Get the data object again (ensures mask == None) data = cubeviz_helper.app.data_collection[0].get_object( - cls=Spectrum1D, statistic=None + cls=Spectrum, statistic=None ) subset = cubeviz_helper.app.data_collection[0].get_subset_object( - p.spatial_subset_selected, cls=Spectrum1D, statistic=None + p.spatial_subset_selected, cls=Spectrum, statistic=None ) masked_data = p._apply_subset_masks(data, p.spatial_subset) expected_spatial_mask = np.ones(data.flux.shape).astype(bool) @@ -351,10 +351,10 @@ def test_subset_masks(cubeviz_helper, spectrum1d_cube_larger): # Get the data object again (ensures mask == None) data = cubeviz_helper.app.data_collection[0].get_object( - cls=Spectrum1D, statistic=None + cls=Spectrum, statistic=None ) subset = cubeviz_helper.app.data_collection[0].get_subset_object( - p.spectral_subset_selected, cls=Spectrum1D, statistic=None + p.spectral_subset_selected, cls=Spectrum, statistic=None ) masked_data = p._apply_subset_masks(data, p.spectral_subset) @@ -366,7 +366,7 @@ def test_subset_masks(cubeviz_helper, spectrum1d_cube_larger): # Get the data object again (ensures mask == None) data = cubeviz_helper.app.data_collection[0].get_object( - cls=Spectrum1D, statistic=None + cls=Spectrum, statistic=None ) # apply both spectral+spatial masks: @@ -383,8 +383,8 @@ def test_invalid_subset(specviz_helper, spectrum1d): specviz_helper.load_data(spectrum1d, data_label="right_spectrum") # 5000-7000 - sp2 = Spectrum1D(spectral_axis=spectrum1d.spectral_axis - 1000*spectrum1d.spectral_axis.unit, - flux=spectrum1d.flux * 1.25) + sp2 = Spectrum(spectral_axis=spectrum1d.spectral_axis - 1000*spectrum1d.spectral_axis.unit, + flux=spectrum1d.flux * 1.25) specviz_helper.load_data(sp2, data_label="left_spectrum") # apply subset that overlaps on left_spectrum, but not right_spectrum @@ -417,7 +417,7 @@ def test_all_nan_uncert(specviz_helper): # being filtered in the fitter, as would normally happen with nans) uncertainty = StdDevUncertainty([np.nan, np.nan, np.nan, np.nan, np.nan, np.nan] * u.Jy) - spec = Spectrum1D(flux=[1, 2, 3, 4, 5, 6]*u.Jy, uncertainty=uncertainty) + spec = Spectrum(flux=[1, 2, 3, 4, 5, 6]*u.Jy, uncertainty=uncertainty) specviz_helper.load_data(spec) plugin = specviz_helper.plugins['Model Fitting'] @@ -444,7 +444,7 @@ def test_all_nan_uncert_subset(specviz_helper): # message uncertainty = StdDevUncertainty([1, 1, np.nan, np.nan, np.nan, np.nan] * u.Jy) - spec = Spectrum1D(flux=[2, 4, 3, 4, 5, 6]*u.Jy, uncertainty=uncertainty) + spec = Spectrum(flux=[2, 4, 3, 4, 5, 6]*u.Jy, uncertainty=uncertainty) specviz_helper.load_data(spec) plugin = specviz_helper.plugins['Model Fitting'] diff --git a/jdaviz/configs/imviz/helper.py b/jdaviz/configs/imviz/helper.py index 11e04c6161..2df64dab9d 100644 --- a/jdaviz/configs/imviz/helper.py +++ b/jdaviz/configs/imviz/helper.py @@ -330,7 +330,7 @@ def get_data(self, data_label=None, spatial_subset=None, cls=None): Provide a label to retrieve a specific data set from data_collection. spatial_subset : str, optional Spatial subset applied to data. - cls : `~specutils.Spectrum1D`, `~astropy.nddata.CCDData`, optional + cls : `~specutils.Spectrum`, `~astropy.nddata.CCDData`, optional The type that data will be returned as. Returns diff --git a/jdaviz/configs/imviz/plugins/aper_phot_simple/aper_phot_simple.py b/jdaviz/configs/imviz/plugins/aper_phot_simple/aper_phot_simple.py index 54490b6d4e..d874f96e66 100644 --- a/jdaviz/configs/imviz/plugins/aper_phot_simple/aper_phot_simple.py +++ b/jdaviz/configs/imviz/plugins/aper_phot_simple/aper_phot_simple.py @@ -316,9 +316,17 @@ def _calc_background_median(self, reg, data=None): data = self.dataset.selected_dc_item comp = data.get_component(data.main_components[0]) + if self.config == "cubeviz" and data.ndim > 2: + if "spectral_axis_index" in getattr(data, "meta", {}): + spectral_axis_index = data.meta["spectral_axis_index"] + else: + spectral_axis_index = 0 if self.config == "cubeviz" and data.ndim > 2: - comp_data = comp.data[:, :, self._cubeviz_slice_ind].T # nx, ny --> ny, nx + if spectral_axis_index == 0: + comp_data = comp.data[self._cubeviz_slice_ind, :, :] + else: + comp_data = comp.data[:, :, self._cubeviz_slice_ind].T # nx, ny --> ny, nx # Similar to coords_info logic. if '_orig_spec' in getattr(data, 'meta', {}): w = data.meta['_orig_spec'].wcs.celestial @@ -400,6 +408,12 @@ def calculate_photometry(self, dataset=None, aperture=None, background=None, # we can use the pre-cached value data = self.dataset.selected_dc_item + if self.config == "cubeviz" and data.ndim > 2: + if "spectral_axis_index" in getattr(data, "meta", {}): + spectral_axis_index = data.meta["spectral_axis_index"] + else: + spectral_axis_index = 0 + if aperture is not None: if aperture not in self.aperture.choices: raise ValueError(f"aperture must be one of {self.aperture.choices}") @@ -447,7 +461,10 @@ def calculate_photometry(self, dataset=None, aperture=None, background=None, raise ValueError('Missing or invalid background value') if self.config == "cubeviz" and data.ndim > 2: - comp_data = comp.data[:, :, self._cubeviz_slice_ind].T # nx, ny --> ny, nx + if spectral_axis_index == 0: + comp_data = comp.data[self._cubeviz_slice_ind, :, :] + else: + comp_data = comp.data[:, :, self._cubeviz_slice_ind].T # nx, ny --> ny, nx # Similar to coords_info logic. if '_orig_spec' in getattr(data, 'meta', {}): w = data.meta['_orig_spec'].wcs @@ -468,7 +485,11 @@ def calculate_photometry(self, dataset=None, aperture=None, background=None, ycenter = reg.center.y if data.coords is not None: if self.config == "cubeviz" and data.ndim > 2: - sky_center = w.pixel_to_world(self._cubeviz_slice_ind, ycenter, xcenter)[1] + if spectral_axis_index == 0: + sky = w.pixel_to_world(xcenter, ycenter, self._cubeviz_slice_ind) + else: + sky = w.pixel_to_world(self._cubeviz_slice_ind, ycenter, xcenter) + sky_center = [coord for coord in sky if hasattr(coord, "icrs")][0] else: # "imviz" sky_center = w.pixel_to_world(xcenter, ycenter) else: diff --git a/jdaviz/configs/imviz/plugins/coords_info/coords_info.py b/jdaviz/configs/imviz/plugins/coords_info/coords_info.py index 1392d052b2..62a023b4a0 100644 --- a/jdaviz/configs/imviz/plugins/coords_info/coords_info.py +++ b/jdaviz/configs/imviz/plugins/coords_info/coords_info.py @@ -56,6 +56,7 @@ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._marks = {} self._dict = {} # dictionary representation of current mouseover info + self._spectral_axis_index = 2 # Needed for cube data self._x, self._y = None, None # latest known cursor positions # subscribe/unsubscribe to mouse events across all existing viewers @@ -231,7 +232,10 @@ def _image_shape_inds(self, image): # return the indices in image.shape for the x and y dimension, respectively if image.ndim == 3: # cubeviz case - return (0, 1) # (ix_shape, iy_shape) + if self._spectral_axis_index == 0: + return (2, 1) + else: + return (0, 1) # (ix_shape, iy_shape) elif image.ndim == 2: return (1, 0) # (ix_shape, iy_shape) else: # pragma: no cover @@ -240,7 +244,10 @@ def _image_shape_inds(self, image): def _get_cube_value(self, image, arr, x, y, viewer): if image.ndim == 3: # cubeviz case: - return arr[int(round(x)), int(round(y)), viewer.state.slices[-1]] + if self._spectral_axis_index == 0: + return arr[viewer.state.slices[-1], int(round(y)), int(round(x))] + else: + return arr[int(round(x)), int(round(y)), viewer.state.slices[-1]] elif image.ndim == 2: return arr[int(round(y)), int(round(x))] else: # pragma: no cover @@ -334,10 +341,17 @@ def _image_viewer_update(self, viewer, x, y): else: data_wcs = None + if "spectral_axis_index" in getattr(coo_data, "meta", {}): + self._spectral_axis_index = coo_data.meta["spectral_axis_index"] + if data_wcs: try: if wcs_ndim == 3: - sky = data_wcs.pixel_to_world(viewer.slice, y, x)[1].icrs + if self._spectral_axis_index == 0: + sky = data_wcs.pixel_to_world(x, y, viewer.slice) + else: + sky = data_wcs.pixel_to_world(viewer.slice, y, x) + sky = [coord for coord in sky if hasattr(coord, "icrs")][0].icrs else: # wcs_ndim == 2 sky = data_wcs.pixel_to_world(x, y).icrs except Exception: diff --git a/jdaviz/configs/mosviz/helper.py b/jdaviz/configs/mosviz/helper.py index 669a3442ac..9e75a67016 100644 --- a/jdaviz/configs/mosviz/helper.py +++ b/jdaviz/configs/mosviz/helper.py @@ -257,7 +257,7 @@ def _get_sp_attribute(table_data, row, attr, fill=None): if sp1_val is not None and sp1_val != sp2_val: # then there was a conflict - msg = f"Warning: value for {attr} in row {row} in disagreement between Spectrum1D and Spectrum2D" # noqa + msg = f"Warning: value for {attr} in row {row} in disagreement between Spectrum and Spectrum2D" # noqa msg = SnackbarMessage(msg, color='warning', sender=self) self.app.hub.broadcast(msg) @@ -282,12 +282,12 @@ def load_data(self, spectra_1d=None, spectra_2d=None, images=None, ---------- spectra_1d : list or str A list of spectra as translatable container objects (e.g. - ``Spectrum1D``) that can be read by glue-jupyter. Alternatively, + ``Spectrum``) that can be read by glue-jupyter. Alternatively, can be a string file path. spectra_2d : list or str A list of spectra as translatable container objects (e.g. - ``Spectrum1D``) that can be read by glue-jupyter. Alternatively, + ``Spectrum``) that can be read by glue-jupyter. Alternatively, can be a string file path. images : list of obj, str, or `None` @@ -459,12 +459,12 @@ def load_spectra(self, spectra_1d, spectra_2d): ---------- spectra_1d : list or str A list of spectra as translatable container objects (e.g. - ``Spectrum1D``) that can be read by glue-jupyter. Alternatively, + ``Spectrum``) that can be read by glue-jupyter. Alternatively, can be a string file path. spectra_2d : list or str A list of spectra as translatable container objects (e.g. - ``Spectrum1D``) that can be read by glue-jupyter. Alternatively, + ``Spectrum``) that can be read by glue-jupyter. Alternatively, can be a string file path. """ @@ -498,7 +498,7 @@ def load_1d_spectra(self, data_obj, data_labels=None, add_redshift_column=False) ---------- data_obj : list or str A list of spectra as translatable container objects (e.g. - ``Spectrum1D``) that can be read by glue-jupyter. Alternatively, + ``Spectrum``) that can be read by glue-jupyter. Alternatively, can be a string file path. data_labels : str or list String representing the label for the data item loaded via @@ -526,7 +526,7 @@ def load_2d_spectra(self, data_obj, data_labels=None, add_redshift_column=False) ---------- data_obj : list or str A list of 2D spectra as translatable container objects (e.g. - ``Spectrum1D``) that can be read by glue-jupyter. Alternatively, + ``Spectrum``) that can be read by glue-jupyter. Alternatively, can be a string file path. data_labels : str or list String representing the label for the data item loaded via @@ -920,7 +920,7 @@ def get_spectrum_1d(self, row=None, apply_slider_redshift="Warn"): Returns ------- - `~specutils.Spectrum1D` + `~specutils.Spectrum` """ return self._get_spectrum('1D Spectra', row, apply_slider_redshift) @@ -940,7 +940,7 @@ def get_spectrum_2d(self, row=None, apply_slider_redshift="Warn"): Returns ------- - `~specutils.Spectrum1D` + `~specutils.Spectrum` """ return self._get_spectrum('2D Spectra', row, apply_slider_redshift) @@ -955,7 +955,7 @@ def get_data(self, data_label=None, spectral_subset=None, cls=None): Provide a label to retrieve a specific data set from data_collection. spectral_subset : str, optional Spectral subset applied to data. - cls : `~specutils.Spectrum1D`, `~astropy.nddata.CCDData`, optional + cls : `~specutils.Spectrum`, `~astropy.nddata.CCDData`, optional The type that data will be returned as. Returns diff --git a/jdaviz/configs/mosviz/plugins/parsers.py b/jdaviz/configs/mosviz/plugins/parsers.py index 6566de033f..43b92e5e4f 100644 --- a/jdaviz/configs/mosviz/plugins/parsers.py +++ b/jdaviz/configs/mosviz/plugins/parsers.py @@ -10,7 +10,7 @@ from astropy.wcs import WCS from glue.core.data import Data from glue.core.link_helpers import LinkSameWithUnits -from specutils import Spectrum1D, SpectrumList, SpectrumCollection +from specutils import Spectrum, SpectrumList, SpectrumCollection from specutils.io.default_loaders.jwst_reader import identify_jwst_s2d_multi_fits from jdaviz.configs.imviz.plugins.parsers import get_image_data_iterator @@ -226,10 +226,10 @@ def mos_spec1d_parser(app, data_obj, data_labels=None, if not isinstance(data_obj, (list, tuple, SpectrumCollection)): data_obj = [data_obj] - # If the file has multiple objects in it, the Spectrum1D read machinery + # If the file has multiple objects in it, the Spectrum read machinery # will fail to find a reader for it, and we fall back on SpectrumList try: - data_obj = [Spectrum1D.read(x) if _check_is_file(x) else x for x in data_obj] + data_obj = [Spectrum.read(x) if _check_is_file(x) else x for x in data_obj] except IORegistryError: if len(data_obj) == 1: if _check_is_file(data_obj[0]): @@ -318,7 +318,7 @@ def _parse_as_spectrum1d(hdulist, ext, transpose): else: kw = {'wcs': wcs} - return Spectrum1D(flux=data * data_unit, meta=metadata, **kw) + return Spectrum(flux=data * data_unit, meta=metadata, **kw) # Coerce into list-like object if (not isinstance(data_obj, (list, tuple, SpectrumCollection)) or @@ -344,7 +344,7 @@ def _parse_as_spectrum1d(hdulist, ext, transpose): with app.data_collection.delay_link_manager_update(): for index, data in enumerate(data_obj): - # If we got a filepath, first try and parse using the Spectrum1D and + # If we got a filepath, first try and parse using the Spectrum and # SpectrumList parsers, and then fall back to parsing it as a generic # FITS file. if _check_is_file(data): @@ -353,7 +353,7 @@ def _parse_as_spectrum1d(hdulist, ext, transpose): with fits.open(data) as hdulist: data = _parse_as_spectrum1d(hdulist, ext, transpose) else: - data = Spectrum1D.read(data) + data = Spectrum.read(data) except IORegistryError: with fits.open(data) as hdulist: data = _parse_as_spectrum1d(hdulist, ext, transpose) @@ -887,7 +887,7 @@ def mos_niriss_parser(app, data_dir, instrument=None, meta[PRIHDR_KEY] = standardize_metadata(temp[0].header) # The wavelength is stored in a WAVELENGTH HDU. This is - # a 2D array, but in order to be able to use Spectrum1D + # a 2D array, but in order to be able to use Spectrum # we use the average wavelength for all image rows if data.shape[0] > data.shape[1]: @@ -898,7 +898,7 @@ def mos_niriss_parser(app, data_dir, instrument=None, else: wav = temp[wav_hdus[sci]].data.mean(axis=0) * u.micron - spec2d = Spectrum1D(data * u.one, spectral_axis=wav, meta=meta) + spec2d = Spectrum(data * u.one, spectral_axis=wav, meta=meta) spec2d.meta['INSTRUME'] = instrument.upper() spec2d.meta['mosviz_row'] = len(spec_labels_2d) diff --git a/jdaviz/configs/mosviz/plugins/viewers.py b/jdaviz/configs/mosviz/plugins/viewers.py index 91fee2ee5b..bcff4c1280 100644 --- a/jdaviz/configs/mosviz/plugins/viewers.py +++ b/jdaviz/configs/mosviz/plugins/viewers.py @@ -7,7 +7,7 @@ from glue_jupyter.bqplot.image import BqplotImageView from glue_jupyter.table import TableViewer from scipy.interpolate import interp1d -from specutils import Spectrum1D +from specutils import Spectrum from jdaviz.core.events import (AddDataToViewerMessage, RemoveDataFromViewerMessage, @@ -68,7 +68,7 @@ def _mark_targets(self): class MosvizProfile2DView(JdavizViewerMixin, BqplotImageView): # Due to limitations in CCDData and 2D data that has spectral and spatial # axes, the default conversion class must handle cubes - default_class = Spectrum1D + default_class = Spectrum # categories: zoom resets, zoom, pan, subset, select tools, shortcuts tools_nested = [ @@ -215,7 +215,7 @@ def set_plot_axes(self): self.figure.axes[1].tick_format = None self.figure.axes[1].label_location = "middle" - # Sync with Spectrum1D viewer (that is also used by other viz). + # Sync with Spectrum viewer (that is also used by other viz). # Make it so y axis label is not covering tick numbers. self.figure.fig_margin["left"] = 95 self.figure.fig_margin["bottom"] = 60 diff --git a/jdaviz/configs/mosviz/tests/test_data_loading.py b/jdaviz/configs/mosviz/tests/test_data_loading.py index 21b0865bc9..cc4fce29c6 100644 --- a/jdaviz/configs/mosviz/tests/test_data_loading.py +++ b/jdaviz/configs/mosviz/tests/test_data_loading.py @@ -5,7 +5,7 @@ import numpy as np import pytest from astropy.nddata import CCDData -from specutils import Spectrum1D +from specutils import Spectrum from jdaviz.utils import PRIHDR_KEY @@ -27,7 +27,7 @@ def test_load_spectrum1d(mosviz_helper, spectrum1d): ).data() assert len(data) == 1 - assert isinstance(data[0], Spectrum1D) + assert isinstance(data[0], Spectrum) with pytest.raises(AttributeError): mosviz_helper.load_1d_spectra([1, 2, 3]) @@ -74,7 +74,7 @@ def test_load_spectrum_collection(mosviz_helper, spectrum_collection): ).data() assert len(data) == 1 - assert isinstance(data[0], Spectrum1D) + assert isinstance(data[0], Spectrum) def test_load_list_of_spectrum1d(mosviz_helper, spectrum1d): @@ -96,7 +96,7 @@ def test_load_list_of_spectrum1d(mosviz_helper, spectrum1d): ).data() assert len(data) == 1 - assert isinstance(data[0], Spectrum1D) + assert isinstance(data[0], Spectrum) def test_load_mos_spectrum2d(mosviz_helper, mos_spectrum2d): diff --git a/jdaviz/configs/specviz/helper.py b/jdaviz/configs/specviz/helper.py index f99dcbffc4..5821a6ad25 100644 --- a/jdaviz/configs/specviz/helper.py +++ b/jdaviz/configs/specviz/helper.py @@ -3,7 +3,7 @@ from astropy import units as u from regions.core.core import Region from glue.core.subset_group import GroupedSubset -from specutils import SpectralRegion, Spectrum1D +from specutils import SpectralRegion, Spectrum from jdaviz.core.helpers import ConfigHelper from jdaviz.core.events import RedshiftMessage @@ -16,13 +16,13 @@ def _apply_redshift_to_spectra(spectra, redshift): flux = spectra.flux # This is a hack around inability to input separate redshift with - # a SpectralAxis instance in Spectrum1D + # a SpectralAxis instance in Spectrum spaxis = spectra.spectral_axis.value * spectra.spectral_axis.unit mask = spectra.mask uncertainty = spectra.uncertainty - output_spectra = Spectrum1D(flux, spectral_axis=spaxis, - redshift=redshift, mask=mask, - uncertainty=uncertainty) + output_spectra = Spectrum(flux, spectral_axis=spaxis, + redshift=redshift, mask=mask, + uncertainty=uncertainty) return output_spectra @@ -47,13 +47,13 @@ def load_data(self, data, data_label=None, format=None, show_in_viewer=True, Parameters ---------- - data : str, `~specutils.Spectrum1D`, or `~specutils.SpectrumList` - Spectrum1D, SpectrumList, or path to compatible data file. + data : str, `~specutils.Spectrum`, or `~specutils.SpectrumList` + Spectrum, SpectrumList, or path to compatible data file. data_label : str The Glue data label found in the ``DataCollection``. format : str Loader format specification used to indicate data format in - `~specutils.Spectrum1D.read` io method. + `~specutils.Spectrum.read` io method. show_in_viewer : bool Show data in viewer(s). concat_by_file : bool @@ -82,7 +82,7 @@ def get_spectra(self, data_label=None, spectral_subset=None, apply_slider_redshi if data_label is not None: spectrum = get_data_method(data_label=data_label, spectral_subset=spectral_subset, - cls=Spectrum1D) + cls=Spectrum) spectra[data_label] = spectrum else: for layer_state in viewer.state.layers: @@ -91,7 +91,7 @@ def get_spectra(self, data_label=None, spectral_subset=None, apply_slider_redshi if lyr.label == spectral_subset: spectrum = get_data_method(data_label=lyr.data.label, spectral_subset=spectral_subset, - cls=Spectrum1D, + cls=Spectrum, **function_kwargs) spectra[lyr.data.label] = spectrum else: @@ -101,19 +101,19 @@ def get_spectra(self, data_label=None, spectral_subset=None, apply_slider_redshi isinstance(all_subsets[lyr.label][0], Region)): spectrum = get_data_method(data_label=lyr.data.label, spatial_subset=lyr.label, - cls=Spectrum1D, + cls=Spectrum, **function_kwargs) spectra[f'{lyr.data.label} ({lyr.label})'] = spectrum elif (isinstance(lyr, GroupedSubset) and lyr.label in all_subsets.keys() and isinstance(all_subsets[lyr.label], SpectralRegion)): spectrum = get_data_method(data_label=lyr.data.label, spectral_subset=lyr.label, - cls=Spectrum1D, + cls=Spectrum, **function_kwargs) spectra[f'{lyr.data.label} ({lyr.label})'] = spectrum else: spectrum = get_data_method(data_label=lyr.label, - cls=Spectrum1D, + cls=Spectrum, **function_kwargs) spectra[lyr.label] = spectrum @@ -123,7 +123,7 @@ def get_spectra(self, data_label=None, spectral_subset=None, apply_slider_redshi return spectra else: output_spectra = {} - # We need to create new Spectrum1D outputs with the redshifts set + # We need to create new Spectrum outputs with the redshifts set for key in spectra.keys(): output_spectra[key] = _apply_redshift_to_spectra(spectra[key], self._redshift) @@ -299,7 +299,7 @@ def get_data(self, data_label=None, spectral_subset=None, cls=None, Provide a label to retrieve a specific data set from data_collection. spectral_subset : str, optional Spectral subset applied to data. - cls : `~specutils.Spectrum1D`, optional + cls : `~specutils.Spectrum`, optional The type that data will be returned as. use_display_units: bool, optional Whether to convert to the display units defined in the plugin. @@ -323,7 +323,7 @@ def get_data(self, data_label=None, spectral_subset=None, cls=None, function = getattr(default_sp_viewer.state, 'function', None) if cls is None: - cls = Spectrum1D + cls = Spectrum elif spatial_subset or function: raise ValueError('kwargs spatial subset and function are not valid in specviz') else: diff --git a/jdaviz/configs/specviz/plugins/line_analysis/line_analysis.py b/jdaviz/configs/specviz/plugins/line_analysis/line_analysis.py index aa1dd144be..e14ba59510 100644 --- a/jdaviz/configs/specviz/plugins/line_analysis/line_analysis.py +++ b/jdaviz/configs/specviz/plugins/line_analysis/line_analysis.py @@ -7,7 +7,7 @@ from glue_jupyter.common.toolbar_vuetify import read_icon from traitlets import Bool, List, Float, Unicode, observe from astropy import units as u -from specutils import analysis, Spectrum1D +from specutils import analysis, Spectrum from jdaviz.core.events import (AddDataMessage, RemoveDataMessage, @@ -321,7 +321,7 @@ def _uncertainty(result): if (flux_unit.is_equivalent(u.Jy) or flux_unit.is_equivalent(u.Jy/u.sr)): # Perform integration in frequency space - freq_spec = Spectrum1D( + freq_spec = Spectrum( spectral_axis=spec_subtracted.spectral_axis.to(u.Hz, equivalencies=u.spectral()), flux=spec_subtracted.flux, @@ -354,7 +354,7 @@ def _uncertainty(result): elif (flux_unit.is_equivalent(u.Unit('W/(m2 m)')) or flux_unit.is_equivalent(u.Unit('W/(m2 m sr)'))): # Perform integration in wavelength space using MKS unit (meters) - wave_spec = Spectrum1D( + wave_spec = Spectrum( spectral_axis=spec_subtracted.spectral_axis.to(u.m, equivalencies=u.spectral()), flux=spec_subtracted.flux, diff --git a/jdaviz/configs/specviz/plugins/line_analysis/tests/test_line_analysis.py b/jdaviz/configs/specviz/plugins/line_analysis/tests/test_line_analysis.py index f178754ab9..49e7744b12 100644 --- a/jdaviz/configs/specviz/plugins/line_analysis/tests/test_line_analysis.py +++ b/jdaviz/configs/specviz/plugins/line_analysis/tests/test_line_analysis.py @@ -7,7 +7,7 @@ from glue.core.edit_subset_mode import NewMode from numpy.testing import assert_allclose from regions import RectanglePixelRegion, PixCoord -from specutils import Spectrum1D +from specutils import Spectrum from jdaviz.configs.specviz.plugins.line_analysis.line_analysis import _coerce_unit from jdaviz.core.events import LineIdentifyMessage @@ -416,8 +416,8 @@ def test_invalid_subset(specviz_helper, spectrum1d): specviz_helper.load_data(spectrum1d, data_label="right_spectrum") # 5000-7000 - sp2 = Spectrum1D(spectral_axis=spectrum1d.spectral_axis - 1000*spectrum1d.spectral_axis.unit, - flux=spectrum1d.flux * 1.25) + sp2 = Spectrum(spectral_axis=spectrum1d.spectral_axis - 1000*spectrum1d.spectral_axis.unit, + flux=spectrum1d.flux * 1.25) specviz_helper.load_data(sp2, data_label="left_spectrum") # apply subset that overlaps on left_spectrum, but not right_spectrum diff --git a/jdaviz/configs/specviz/plugins/line_analysis/tests/test_lineflux.py b/jdaviz/configs/specviz/plugins/line_analysis/tests/test_lineflux.py index 9277e26d88..4dcaf4b1cb 100644 --- a/jdaviz/configs/specviz/plugins/line_analysis/tests/test_lineflux.py +++ b/jdaviz/configs/specviz/plugins/line_analysis/tests/test_lineflux.py @@ -3,7 +3,7 @@ from glue.viewers.profile.state import FUNCTIONS as COLLAPSE_FUNCTIONS import numpy as np import pytest -from specutils import Spectrum1D +from specutils import Spectrum from jdaviz import Cubeviz @@ -40,17 +40,17 @@ def _gauss_with_unity_area(x, mean, sigma): # unit-flux gaussian in frequency space freq = np.arange(1, 2, 0.001)*u.Hz flux_freq = _gauss_with_unity_area(freq.value, mn, sig)*1.0E26*u.Jy -fnu_freq = Spectrum1D(spectral_axis=freq, flux=flux_freq) +fnu_freq = Spectrum(spectral_axis=freq, flux=flux_freq) unit_flux_gaussian_test_cases.append(fnu_freq) -fnu_wave = Spectrum1D(spectral_axis=fnu_freq.wavelength, flux=flux_freq) +fnu_wave = Spectrum(spectral_axis=fnu_freq.wavelength, flux=flux_freq) unit_flux_gaussian_test_cases.append(fnu_wave) # unit-flux gaussian in wavelength space lam = np.arange(1, 2, 0.001)*u.m flux_wave = _gauss_with_unity_area(lam.value, mn, sig)*1.0*u.W/u.m**2/u.m -flam_wave = Spectrum1D(spectral_axis=lam, flux=flux_wave) +flam_wave = Spectrum(spectral_axis=lam, flux=flux_wave) unit_flux_gaussian_test_cases.append(flam_wave) -flam_freq = Spectrum1D(spectral_axis=flam_wave.frequency, flux=flux_wave) +flam_freq = Spectrum(spectral_axis=flam_wave.frequency, flux=flux_wave) unit_flux_gaussian_test_cases.append(flam_freq) @@ -116,7 +116,7 @@ def test_unit_gaussian_mixed_units_per_steradian(specviz_helper): # unit-flux gaussian in wavelength space, mixed units, per steradian lam_a = np.arange(1, 2, 0.001)*u.Angstrom flx_wave = _gauss_with_unity_area(lam_a.value, mn, sig)*1E3*u.erg/u.s/u.cm**2/u.Angstrom/u.sr - fl_wave = Spectrum1D(spectral_axis=lam_a, flux=flx_wave) + fl_wave = Spectrum(spectral_axis=lam_a, flux=flx_wave) specviz_helper.load_data(fl_wave) lineflux_result = _calculate_line_flux(specviz_helper) diff --git a/jdaviz/configs/specviz/plugins/parsers.py b/jdaviz/configs/specviz/plugins/parsers.py index 23a794dd52..6e700865c3 100644 --- a/jdaviz/configs/specviz/plugins/parsers.py +++ b/jdaviz/configs/specviz/plugins/parsers.py @@ -5,7 +5,7 @@ from astropy.io.registry import IORegistryError from astropy.nddata import StdDevUncertainty from astropy.io import fits -from specutils import Spectrum1D, SpectrumList, SpectrumCollection +from specutils import Spectrum, SpectrumList, SpectrumCollection from jdaviz.core.events import SnackbarMessage from jdaviz.core.registries import data_parser_registry @@ -19,17 +19,17 @@ def specviz_spectrum1d_parser(app, data, data_label=None, format=None, show_in_viewer=True, concat_by_file=False): """ - Loads a data file or `~specutils.Spectrum1D` object into Specviz. + Loads a data file or `~specutils.Spectrum` object into Specviz. Parameters ---------- - data : str, `~specutils.Spectrum1D`, or `~specutils.SpectrumList` - Spectrum1D, SpectrumList, or path to compatible data file. + data : str, `~specutils.Spectrum`, or `~specutils.SpectrumList` + Spectrum, SpectrumList, or path to compatible data file. data_label : str The Glue data label found in the ``DataCollection``. format : str Loader format specification used to indicate data format in - `~specutils.Spectrum1D.read` io method. + `~specutils.Spectrum.read` io method. concat_by_file : bool If True and there is more than one available extension, concatenate the extensions within each spectrum file passed to the parser and @@ -42,8 +42,8 @@ def specviz_spectrum1d_parser(app, data, data_label=None, format=None, show_in_v data_label = app.return_data_label(data, alt_name="specviz_data") if isinstance(data, SpectrumCollection): raise TypeError("SpectrumCollection detected." - " Please provide a Spectrum1D or SpectrumList") - elif isinstance(data, Spectrum1D): + " Please provide a Spectrum or SpectrumList") + elif isinstance(data, Spectrum): data_label = [app.return_data_label(data_label, alt_name="specviz_data")] data = [data] # No special processing is needed in this case, but we include it for completeness @@ -52,7 +52,7 @@ def specviz_spectrum1d_parser(app, data, data_label=None, format=None, show_in_v elif isinstance(data, list): # special processing for HDUList if isinstance(data, fits.HDUList): - data = [Spectrum1D.read(data)] + data = [Spectrum.read(data)] data_label = [app.return_data_label(data_label, alt_name="specviz_data")] else: # list treated as SpectrumList if not an HDUList @@ -62,7 +62,7 @@ def specviz_spectrum1d_parser(app, data, data_label=None, format=None, show_in_v if path.is_file(): try: - data = [Spectrum1D.read(str(path), format=format)] + data = [Spectrum.read(str(path), format=format)] data_label = [app.return_data_label(data_label, alt_name="specviz_data")] except IORegistryError: @@ -103,7 +103,7 @@ def specviz_spectrum1d_parser(app, data, data_label=None, format=None, show_in_v # others may not, if uncert is None, set to list of NaN. later, # if the concatenated list of uncertanties is all nan (meaning # they were all nan to begin with, or all None), it will be set - # to None on the final Spectrum1D + # to None on the final Spectrum if spec.uncertainty[wlind] is not None: dfnuallorig.append(spec.uncertainty[wlind].array) else: @@ -195,7 +195,7 @@ def group_spectra_by_filename(datasets): def combine_lists_to_1d_spectrum(wl, fnu, dfnu, wave_units, flux_units): """ - Combine lists of 1D spectra into a composite `~specutils.Spectrum1D` object. + Combine lists of 1D spectra into a composite `~specutils.Spectrum` object. Parameters ---------- @@ -208,7 +208,7 @@ def combine_lists_to_1d_spectrum(wl, fnu, dfnu, wave_units, flux_units): Returns ------- - spec : `~specutils.Spectrum1D` + spec : `~specutils.Spectrum` Composite 1D spectrum. """ wlallarr = np.array(wl) @@ -226,6 +226,6 @@ def combine_lists_to_1d_spectrum(wl, fnu, dfnu, wave_units, flux_units): else: unc = None - spec = Spectrum1D(flux=fnuall * flux_units, spectral_axis=wlall * wave_units, - uncertainty=unc) + spec = Spectrum(flux=fnuall * flux_units, spectral_axis=wlall * wave_units, + uncertainty=unc) return spec 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 b7ff19ab43..b67d2d04b0 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 @@ -3,7 +3,7 @@ import astropy from astropy import units as u from astropy.nddata import InverseVariance -from specutils import Spectrum1D +from specutils import Spectrum from astropy.utils.introspection import minversion ASTROPY_LT_5_3 = not minversion(astropy, "5.3") @@ -105,7 +105,7 @@ def test_non_stddev_uncertainty(specviz_helper): var = stddev ** 2 inv_var = np.ones(len(flux)) / var wavelength = np.linspace(1, 5, len(flux)) * u.um - spec = Spectrum1D( + spec = Spectrum( flux, uncertainty=InverseVariance(inv_var), spectral_axis=wavelength diff --git a/jdaviz/configs/specviz/plugins/viewers.py b/jdaviz/configs/specviz/plugins/viewers.py index e92f4abfa4..0f48da1649 100644 --- a/jdaviz/configs/specviz/plugins/viewers.py +++ b/jdaviz/configs/specviz/plugins/viewers.py @@ -14,7 +14,7 @@ from glue_astronomy.spectral_coordinates import SpectralCoordinates from glue_jupyter.bqplot.profile import BqplotProfileView from matplotlib.colors import cnames -from specutils import Spectrum1D +from specutils import Spectrum from jdaviz.core.events import SpectralMarksChangedMessage, LineIdentifyMessage, SnackbarMessage from jdaviz.core.registries import viewer_registry @@ -47,7 +47,7 @@ class SpecvizProfileView(JdavizViewerMixin, BqplotProfileView): ['jdaviz:sidebar_plot', 'jdaviz:sidebar_export'] ] - default_class = Spectrum1D + default_class = Spectrum spectral_lines = None _state_cls = FreezableProfileViewerState @@ -91,7 +91,7 @@ def data(self, cls=None): layer_data = self.jdaviz_app._get_object_cache[cache_key] else: # If spectrum, collapse via the defined statistic - if _class == Spectrum1D: + if _class == Spectrum: layer_data = lyr.get_object(cls=_class, statistic=statistic) else: layer_data = lyr.get_object(cls=_class) @@ -496,7 +496,7 @@ def _plot_uncertainties(self): # This may need adjustment after the following # specutils PR is merged: https://github.com/astropy/specutils/pull/1033 spectral_axis = -1 - data_obj = lyr.data.get_object(cls=Spectrum1D, statistic=None) + data_obj = lyr.data.get_object(cls=Spectrum, statistic=None) if isinstance(lyr.data.coords, SpectralCoordinates): spectral_wcs = lyr.data.coords diff --git a/jdaviz/configs/specviz/tests/test_helper.py b/jdaviz/configs/specviz/tests/test_helper.py index f75d5f9b4d..b83bedff76 100644 --- a/jdaviz/configs/specviz/tests/test_helper.py +++ b/jdaviz/configs/specviz/tests/test_helper.py @@ -7,7 +7,7 @@ from astropy.tests.helper import assert_quantity_allclose from glue.core.roi import XRangeROI from glue.core.edit_subset_mode import OrMode, AndMode, AndNotMode -from specutils import Spectrum1D, SpectrumList, SpectrumCollection +from specutils import Spectrum, SpectrumList, SpectrumCollection from astropy.utils.data import download_file from jdaviz.app import Application @@ -35,7 +35,7 @@ def test_load_spectrum1d(self): data = self.spec_app.get_data() - assert isinstance(data, Spectrum1D) + assert isinstance(data, Spectrum) def test_load_hdulist(self): # Create a fake fits file with a 1D spectrum for testing. @@ -54,8 +54,8 @@ def test_load_hdulist(self): self.label = "Test 1D Spectrum" self.spec_app.load_data(fake_hdulist) data = self.spec_app.get_data(data_label=self.label) - # HDUList should load as Spectrum1D - assert isinstance(data, Spectrum1D) + # HDUList should load as Spectrum + assert isinstance(data, Spectrum) def test_load_spectrum_list_no_labels(self): # now load three more spectra from a SpectrumList, without labels @@ -448,11 +448,11 @@ def test_spectra_partial_overlap(specviz_helper): wave_1 = np.linspace(6000, 7000, 10) * u.AA flux_1 = ([1200] * wave_1.size) * u.nJy - sp_1 = Spectrum1D(flux=flux_1, spectral_axis=wave_1) + sp_1 = Spectrum(flux=flux_1, spectral_axis=wave_1) wave_2 = wave_1 + (800 * u.AA) flux_2 = ([60] * wave_2.size) * u.nJy - sp_2 = Spectrum1D(flux=flux_2, spectral_axis=wave_2) + sp_2 = Spectrum(flux=flux_2, spectral_axis=wave_2) specviz_helper.load_data(sp_1, data_label='left') specviz_helper.load_data(sp_2, data_label='right') @@ -471,10 +471,10 @@ def test_spectra_partial_overlap(specviz_helper): def test_spectra_incompatible_flux(specviz_helper): """https://github.com/spacetelescope/jdaviz/issues/2459""" wav = [1.1, 1.2, 1.3] * u.um - sp1 = Spectrum1D(flux=[1, 1.1, 1] * (u.MJy / u.sr), spectral_axis=wav) - sp2 = Spectrum1D(flux=[1, 1, 1.1] * (u.MJy), spectral_axis=wav) + sp1 = Spectrum(flux=[1, 1.1, 1] * (u.MJy / u.sr), spectral_axis=wav) + sp2 = Spectrum(flux=[1, 1, 1.1] * (u.MJy), spectral_axis=wav) flux3 = ([1, 1.1, 1] * u.MJy).to(u.erg / u.s / u.cm / u.cm / u.AA, u.spectral_density(wav)) - sp3 = Spectrum1D(flux=flux3, spectral_axis=wav) + sp3 = Spectrum(flux=flux3, spectral_axis=wav) specviz_helper.load_data(sp2, data_label="2") # OK specviz_helper.load_data(sp1, data_label="1") # Not OK diff --git a/jdaviz/configs/specviz/tests/test_viewers.py b/jdaviz/configs/specviz/tests/test_viewers.py index 80928d4ad9..ff19d6bb10 100644 --- a/jdaviz/configs/specviz/tests/test_viewers.py +++ b/jdaviz/configs/specviz/tests/test_viewers.py @@ -1,7 +1,7 @@ import astropy.units as u import numpy as np import pytest -from specutils import Spectrum1D +from specutils import Spectrum @pytest.mark.parametrize( @@ -17,7 +17,7 @@ def test_spectrum_viewer_axis_labels(specviz_helper, input_unit, y_axis_label): flux = np.arange(1, 10) * input_unit spectral_axis = np.arange(1, 10) * u.um - spec = Spectrum1D(flux, spectral_axis) + spec = Spectrum(flux, spectral_axis) specviz_helper.load_data(spec) diff --git a/jdaviz/configs/specviz2d/helper.py b/jdaviz/configs/specviz2d/helper.py index 74bf898251..d2e042689a 100644 --- a/jdaviz/configs/specviz2d/helper.py +++ b/jdaviz/configs/specviz2d/helper.py @@ -38,12 +38,12 @@ def load_data(self, spectrum_2d=None, spectrum_1d=None, spectrum_1d_label=None, ---------- spectrum_2d: str A spectrum as translatable container objects (e.g., - ``Spectrum1D``) that can be read by glue-jupyter. Alternatively, + ``Spectrum``) that can be read by glue-jupyter. Alternatively, can be a string file path. - spectrum_1d: str or Spectrum1D + spectrum_1d: str or Spectrum A spectrum as translatable container objects (e.g., - ``Spectrum1D``) that can be read by glue-jupyter. Alternatively, + ``Spectrum``) that can be read by glue-jupyter. Alternatively, can be a string file path. spectrum_1d_label : str @@ -164,7 +164,7 @@ def get_data(self, data_label=None, spectral_subset=None, cls=None): Provide a label to retrieve a specific data set from data_collection. spectral_subset : str, optional Spectral subset applied to data. - cls : `~specutils.Spectrum1D`, `~astropy.nddata.CCDData`, optional + cls : `~specutils.Spectrum`, `~astropy.nddata.CCDData`, optional The type that data will be returned as. Returns diff --git a/jdaviz/configs/specviz2d/plugins/parsers.py b/jdaviz/configs/specviz2d/plugins/parsers.py index 199e0fd622..662671d4eb 100644 --- a/jdaviz/configs/specviz2d/plugins/parsers.py +++ b/jdaviz/configs/specviz2d/plugins/parsers.py @@ -1,6 +1,6 @@ from pathlib import Path -from specutils import Spectrum1D +from specutils import Spectrum from astropy.io import fits import astropy.units as u import numpy as np @@ -62,7 +62,7 @@ def spec2d_1d_parser(app, data_obj, data_label=None, show_in_viewer=True): metadata = standardize_metadata(header) metadata[PRIHDR_KEY] = standardize_metadata(prihdr) - data_obj = Spectrum1D(flux, spectral_axis=spectral_axis, meta=metadata) + data_obj = Spectrum(flux, spectral_axis=spectral_axis, meta=metadata) data_label = app.return_data_label(data_label, alt_name="specviz2d_data") app.data_collection[data_label] = data_obj diff --git a/jdaviz/configs/specviz2d/plugins/spectral_extraction/tests/test_spectral_extraction.py b/jdaviz/configs/specviz2d/plugins/spectral_extraction/tests/test_spectral_extraction.py index 694319bc4d..d9d1d010be 100644 --- a/jdaviz/configs/specviz2d/plugins/spectral_extraction/tests/test_spectral_extraction.py +++ b/jdaviz/configs/specviz2d/plugins/spectral_extraction/tests/test_spectral_extraction.py @@ -3,7 +3,7 @@ from astropy.utils.data import download_file from packaging.version import Version from specreduce import tracing, background, extract -from specutils import Spectrum1D +from specutils import Spectrum GWCS_LT_0_18_1 = Version(gwcs.__version__) < Version('0.18.1') @@ -104,11 +104,11 @@ def test_plugin(specviz2d_helper): pext.import_bg(bg) assert pext.bg_width == 4 bg_img = pext.export_bg_img() - assert isinstance(bg_img, Spectrum1D) + assert isinstance(bg_img, Spectrum) bg_spec = pext.export_bg_spectrum() - assert isinstance(bg_spec, Spectrum1D) + assert isinstance(bg_spec, Spectrum) bg_sub = pext.export_bg_sub() - assert isinstance(bg_sub, Spectrum1D) + assert isinstance(bg_sub, Spectrum) # interact with extraction section, check marks pext.ext_width = 1 @@ -126,11 +126,11 @@ def test_plugin(specviz2d_helper): pext.import_extract(ext) assert pext.ext_width == 2 sp_ext = pext.export_extract_spectrum() - assert isinstance(sp_ext, Spectrum1D) + assert isinstance(sp_ext, Spectrum) pext.ext_type_selected = 'Horne' sp_ext = pext.export_extract_spectrum() - assert isinstance(sp_ext, Spectrum1D) + assert isinstance(sp_ext, Spectrum) # test API calls for step in ['trace', 'bg', 'ext']: diff --git a/jdaviz/configs/specviz2d/tests/test_helper.py b/jdaviz/configs/specviz2d/tests/test_helper.py index a6eb3a203b..d03ff48cf3 100644 --- a/jdaviz/configs/specviz2d/tests/test_helper.py +++ b/jdaviz/configs/specviz2d/tests/test_helper.py @@ -1,4 +1,4 @@ -from specutils import Spectrum1D +from specutils import Spectrum from jdaviz import Specviz @@ -10,7 +10,7 @@ def test_helper(specviz2d_helper, mos_spectrum2d): returned_data = specviz2d_helper.get_data("Spectrum 2D") assert len(returned_data.shape) == 1 - assert isinstance(returned_data, Spectrum1D) + assert isinstance(returned_data, Spectrum) def test_plugin_user_apis(specviz2d_helper): diff --git a/jdaviz/conftest.py b/jdaviz/conftest.py index d4be86ca84..8277e7d737 100644 --- a/jdaviz/conftest.py +++ b/jdaviz/conftest.py @@ -12,7 +12,7 @@ from astropy.io import fits from astropy.nddata import CCDData, StdDevUncertainty from astropy.wcs import WCS -from specutils import Spectrum1D, SpectrumCollection, SpectrumList +from specutils import Spectrum, SpectrumCollection, SpectrumList from jdaviz import __version__, Cubeviz, Imviz, Mosviz, Specviz, Specviz2d from jdaviz.configs.imviz.tests.utils import create_wfi_image_model @@ -159,7 +159,7 @@ def _create_spectrum1d_with_spectral_unit(spectralunit=u.AA): meta = dict(header=dict(FILENAME="jdaviz-test-file.fits")) - return Spectrum1D(spectral_axis=spec_axis, flux=flux, uncertainty=uncertainty, meta=meta) + return Spectrum(spectral_axis=spec_axis, flux=flux, uncertainty=uncertainty, meta=meta) @pytest.fixture @@ -195,8 +195,8 @@ def multi_order_spectrum_list(spectrum1d, spectral_orders=10): spec_axis.value / 500) * u.Jy uncertainty = StdDevUncertainty(np.abs(np.random.randn(len(spec_axis.value))) * u.Jy) meta = dict(header=dict(FILENAME="jdaviz-test-multi-order-file.fits")) - spectrum1d = Spectrum1D(spectral_axis=spec_axis, flux=flux, - uncertainty=uncertainty, meta=meta) + spectrum1d = Spectrum(spectral_axis=spec_axis, flux=flux, + uncertainty=uncertainty, meta=meta) sc.append(spectrum1d) @@ -216,12 +216,12 @@ def _create_spectrum1d_cube_with_fluxunit(fluxunit=u.Jy, shape=(2, 2, 4), with_u if with_uncerts: uncert = StdDevUncertainty(np.abs(np.random.normal(flux) * u.Jy)) - return Spectrum1D(flux=flux, - uncertainty=uncert, - wcs=w, - meta=wcs_dict) + return Spectrum(flux=flux, + uncertainty=uncert, + wcs=w, + meta=wcs_dict) else: - return Spectrum1D(flux=flux, wcs=w, meta=wcs_dict) + return Spectrum(flux=flux, wcs=w, meta=wcs_dict) @pytest.fixture @@ -248,7 +248,7 @@ def spectrum1d_cube_largest(): w = WCS(wcs_dict) flux = np.zeros((30, 20, 3001), dtype=np.float32) # nx=20 ny=30 nz=3001 flux[5:15, 1:11, :] = 1 # Bright corner - return Spectrum1D(flux=flux * u.Jy, wcs=w, meta=wcs_dict) + return Spectrum(flux=flux * u.Jy, wcs=w, meta=wcs_dict) @pytest.fixture @@ -273,28 +273,28 @@ def mos_spectrum1d(mos_spectrum2d): 10*np.exp(-0.001*(spec_axis.value-6563)**2) + spec_axis.value/500) * u.Jy - return Spectrum1D(spectral_axis=spec_axis, flux=flux) + return Spectrum(spectral_axis=spec_axis, flux=flux) @pytest.fixture def spectrum2d(): ''' - A simple 2D Spectrum1D with a center "trace" array rising from 0 to 10 + A simple 2D Spectrum with a center "trace" array rising from 0 to 10 with two "zero array" buffers above and below ''' data = np.zeros((5, 10)) data[3] = np.arange(10) - return Spectrum1D(flux=data*u.MJy, spectral_axis=data[3]*u.um) + return Spectrum(flux=data*u.MJy, spectral_axis=data[3]*u.um) @pytest.fixture def mos_spectrum2d(): ''' - A specially defined 2D (spatial) Spectrum1D whose wavelength range matches the + A specially defined 2D (spatial) Spectrum whose wavelength range matches the mos-specific 1D spectrum. - TODO: This should be reformed to match the global Spectrum1D defined above so that we may + TODO: This should be reformed to match the global Spectrum defined above so that we may deprecate the mos-specific spectrum1d. ''' header = { @@ -308,7 +308,7 @@ def mos_spectrum2d(): wcs = WCS(header) np.random.seed(42) data = np.random.sample((1024, 15)) * u.one - return Spectrum1D(data, wcs=wcs, meta=header) + return Spectrum(data, wcs=wcs, meta=header) @pytest.fixture diff --git a/jdaviz/core/data_formats.py b/jdaviz/core/data_formats.py index 32f464f704..7da07906a6 100644 --- a/jdaviz/core/data_formats.py +++ b/jdaviz/core/data_formats.py @@ -7,7 +7,7 @@ from astropy.wcs import WCS from specutils.io.registers import identify_spectrum_format -from specutils import Spectrum1D, SpectrumList, SpectrumCollection +from specutils import Spectrum, SpectrumList, SpectrumCollection from stdatamodels import asdf_in_fits from jdaviz.core.config import list_configurations @@ -27,7 +27,7 @@ # get formats table for specutils objects formats_table = astropy.io.registry.get_formats(readwrite='Read') formats_table.add_index('Data class') -formats_table = formats_table.loc[['Spectrum1D', 'SpectrumList']] +formats_table = formats_table.loc[['Spectrum', 'SpectrumList']] formats_table.sort(['Data class', 'Format']) file_to_config_mapping = {i: default_mapping.get( @@ -161,7 +161,7 @@ def identify_helper(filename, ext=1): The HDUList of the file opened to identify the helper """ supported_dtypes = [ - Spectrum1D, + Spectrum, SpectrumList, SpectrumCollection, CCDData @@ -238,7 +238,7 @@ def identify_helper(filename, ext=1): return (['specviz'], hdul) # If the data could be spectral: - for cls in [Spectrum1D, SpectrumList]: + for cls in [Spectrum, SpectrumList]: if cls in possible_formats.keys(): recognized_spectrum_format = possible_formats[cls][0].lower() diff --git a/jdaviz/core/helpers.py b/jdaviz/core/helpers.py index fe89c94468..cb60a45017 100644 --- a/jdaviz/core/helpers.py +++ b/jdaviz/core/helpers.py @@ -21,7 +21,7 @@ from glue.core.subset import Subset, MaskSubsetState from glue.config import data_translator from ipywidgets.widgets import widget_serialization -from specutils import Spectrum1D, SpectralRegion +from specutils import Spectrum, SpectralRegion from jdaviz.app import Application @@ -460,7 +460,7 @@ def _get_data(self, data_label=None, spatial_subset=None, spectral_subset=None, mask_subset=None, function=None, cls=None, use_display_units=False): def _handle_display_units(data, use_display_units): if use_display_units: - if isinstance(data, Spectrum1D): + if isinstance(data, Spectrum): spectral_unit = self.app._get_display_unit('spectral') if not spectral_unit: return data @@ -490,12 +490,12 @@ def _handle_display_units(data, use_display_units): else: new_uncert = None - data = Spectrum1D(spectral_axis=data.spectral_axis.to(spectral_unit, - u.spectral()), - flux=data.flux.to(flux_unit, - u.spectral_density(data.spectral_axis)), - uncertainty=new_uncert, - mask=data.mask) + data = Spectrum(spectral_axis=data.spectral_axis.to(spectral_unit, + u.spectral()), + flux=data.flux.to(flux_unit, + u.spectral_density(data.spectral_axis)), + uncertainty=new_uncert, + mask=data.mask) else: # pragma: nocover raise NotImplementedError(f"converting {data.__class__.__name__} to display units is not supported") # noqa return data @@ -539,14 +539,14 @@ def _handle_display_units(data, use_display_units): if 'Trace' in data.meta: cls = None elif data.ndim == 2 and self.app.config == "specviz2d": - cls = Spectrum1D + cls = Spectrum elif data.ndim == 2: cls = CCDData elif data.ndim in [1, 3]: - cls = Spectrum1D + cls = Spectrum object_kwargs = {} - if cls == Spectrum1D: + if cls == Spectrum: object_kwargs['statistic'] = function if not spatial_subset and not mask_subset: @@ -609,7 +609,7 @@ def _handle_display_units(data, use_display_units): f" subset {mask_subset} applied of type {cls}." f" Exception: {e}") if spatial_subset or function: - # Return collapsed Spectrum1D object with spectral subset mask applied + # Return collapsed Spectrum object with spectral subset mask applied data.mask = spec_subset.mask else: data = spec_subset @@ -624,7 +624,7 @@ def get_data(self, data_label=None, cls=None, use_display_units=False, **kwargs) ---------- data_label : str, optional Provide a label to retrieve a specific data set from data_collection. - cls : `~specutils.Spectrum1D`, `~astropy.nddata.CCDData`, optional + cls : `~specutils.Spectrum`, `~astropy.nddata.CCDData`, optional The type that data will be returned as. use_display_units : bool, optional Whether to convert to the display units defined in the plugin. diff --git a/jdaviz/core/launcher.py b/jdaviz/core/launcher.py index 251611368b..734a8e5ca4 100644 --- a/jdaviz/core/launcher.py +++ b/jdaviz/core/launcher.py @@ -63,7 +63,7 @@ def _launch_config_with_data(config, data=None, show=True, filepath=None, **kwar config : str (path-like) Name for a local data file. data : str or any Jdaviz-compatible data - A filepath or Jdaviz-compatible data object (such as Spectrum1D or CCDData) + A filepath or Jdaviz-compatible data object (such as Spectrum or CCDData) show : bool Determines whether to immediately show the application filepath : str diff --git a/jdaviz/core/marks.py b/jdaviz/core/marks.py index e5df8bf736..95a7fd1be7 100644 --- a/jdaviz/core/marks.py +++ b/jdaviz/core/marks.py @@ -5,7 +5,7 @@ from bqplot.marks import Lines, Label, Scatter from copy import deepcopy from glue.core import HubListener -from specutils import Spectrum1D +from specutils import Spectrum from jdaviz.core.events import GlobalDisplayUnitChanged from jdaviz.core.events import (SliceToolStateMessage, LineIdentifyMessage, @@ -110,8 +110,8 @@ def set_y_unit(self, unit=None): unit = u.Unit(unit) if self.yunit is not None and not np.all([s == 0 for s in self.y.shape]): - if self.viewer.default_class is Spectrum1D: - spec = self.viewer.state.reference_data.get_object(cls=Spectrum1D) + if self.viewer.default_class is Spectrum: + spec = self.viewer.state.reference_data.get_object(cls=Spectrum) eqv = u.spectral_density(spec.spectral_axis) y = (self.y * self.yunit).to_value(unit, equivalencies=eqv) else: @@ -158,7 +158,7 @@ def __init__(self, viewer, x, **kwargs): def _update_reference_data(self, reference_data): if reference_data is None: return - self._update_unit(reference_data.get_object(cls=Spectrum1D).spectral_axis.unit) + self._update_unit(reference_data.get_object(cls=Spectrum).spectral_axis.unit) def _update_unit(self, new_unit): # the x-units may have changed. We want to convert the internal self.x diff --git a/jdaviz/core/template_mixin.py b/jdaviz/core/template_mixin.py index eeb936db49..5a4f1fe70c 100644 --- a/jdaviz/core/template_mixin.py +++ b/jdaviz/core/template_mixin.py @@ -30,7 +30,7 @@ from glue_jupyter.registries import viewer_registry from glue_jupyter.widgets.linked_dropdown import get_choices as _get_glue_choices from regions import PixelRegion -from specutils import Spectrum1D +from specutils import Spectrum from specutils.manipulation import extract_region from traitlets import Any, Bool, Dict, Float, HasTraits, List, Unicode, observe @@ -2003,8 +2003,8 @@ def selected_min_max(self, dataset): """ if self.is_multiselect: # pragma: no cover raise TypeError("This action cannot be done when multiselect is active") - if not isinstance(dataset, Spectrum1D): # pragma: no cover - raise TypeError("dataset must be a Spectrum1D object") + if not isinstance(dataset, Spectrum): # pragma: no cover + raise TypeError("dataset must be a Spectrum object") if self.selected_obj is None: return np.nanmin(dataset.spectral_axis), np.nanmax(dataset.spectral_axis) @@ -3292,7 +3292,7 @@ def default_data_cls(self): return NDData if 'is_trace' in self.filters: return None - return Spectrum1D + return Spectrum def _get_dc_item(self, selected): if selected not in self.labels: diff --git a/jdaviz/core/tests/test_template_mixin.py b/jdaviz/core/tests/test_template_mixin.py index c6d01bb8a9..37d2f6dc28 100644 --- a/jdaviz/core/tests/test_template_mixin.py +++ b/jdaviz/core/tests/test_template_mixin.py @@ -3,7 +3,7 @@ import astropy.units as u from glue.core.roi import XRangeROI, CircularROI -from specutils import Spectrum1D +from specutils import Spectrum def test_spectralsubsetselect(specviz_helper, spectrum1d): @@ -94,7 +94,7 @@ def test_spectral_subsetselect_collapsed(cubeviz_helper, spectrum1d_cube): # and when dimensions of mask match a collapsed spectrum: data = cubeviz_helper.app.data_collection[0] - collapsed_spectrum = data.get_object(cls=Spectrum1D) + collapsed_spectrum = data.get_object(cls=Spectrum) collapsed_spectrum.mask = np.zeros_like(collapsed_spectrum.spectral_axis.value).astype(bool) p._apply_subset_masks(collapsed_spectrum, p.spectral_subset) diff --git a/jdaviz/tests/test_subsets.py b/jdaviz/tests/test_subsets.py index 63cccdf374..e94035ce3d 100644 --- a/jdaviz/tests/test_subsets.py +++ b/jdaviz/tests/test_subsets.py @@ -10,7 +10,7 @@ from regions import (PixCoord, CirclePixelRegion, CircleSkyRegion, RectanglePixelRegion, EllipsePixelRegion, CircleAnnulusPixelRegion) from numpy.testing import assert_allclose -from specutils import SpectralRegion, Spectrum1D +from specutils import SpectralRegion, Spectrum from astropy.nddata import NDData from jdaviz.core.marks import ShadowSpatialSpectral @@ -154,7 +154,7 @@ def test_region_from_subset_3d(cubeviz_helper): def test_region_from_subset_profile(cubeviz_helper, spectral_cube_wcs): - data = Spectrum1D(flux=np.ones((128, 128, 256)) * u.nJy, wcs=spectral_cube_wcs) + data = Spectrum(flux=np.ones((128, 128, 256)) * u.nJy, wcs=spectral_cube_wcs) subset_plugin = cubeviz_helper.app.get_tray_item_from_name('g-subset-plugin') cubeviz_helper.load_data(data, data_label='Test 1D Flux') @@ -201,7 +201,7 @@ def test_region_from_subset_profile(cubeviz_helper, spectral_cube_wcs): def test_region_spectral_spatial(cubeviz_helper, spectral_cube_wcs): - data = Spectrum1D(flux=np.ones((128, 128, 256)) * u.nJy, wcs=spectral_cube_wcs) + data = Spectrum(flux=np.ones((128, 128, 256)) * u.nJy, wcs=spectral_cube_wcs) cubeviz_helper.load_data(data, data_label="Test Flux") # use gaussian smooth plugin as a regression test for @@ -301,7 +301,7 @@ def test_region_spectral_spatial(cubeviz_helper, spectral_cube_wcs): def test_disjoint_spatial_subset(cubeviz_helper, spectral_cube_wcs): - data = Spectrum1D(flux=np.ones((128, 128, 256)) * u.nJy, wcs=spectral_cube_wcs) + data = Spectrum(flux=np.ones((128, 128, 256)) * u.nJy, wcs=spectral_cube_wcs) cubeviz_helper.load_data(data, data_label="Test Flux") flux_viewer = cubeviz_helper.app.get_viewer("flux-viewer") @@ -322,7 +322,7 @@ def test_disjoint_spatial_subset(cubeviz_helper, spectral_cube_wcs): def test_disjoint_spectral_subset(cubeviz_helper, spectral_cube_wcs): subset_plugin = cubeviz_helper.app.get_tray_item_from_name('g-subset-plugin') - data = Spectrum1D(flux=np.ones((128, 128, 256)) * u.nJy, wcs=spectral_cube_wcs) + data = Spectrum(flux=np.ones((128, 128, 256)) * u.nJy, wcs=spectral_cube_wcs) cubeviz_helper.load_data(data, data_label="Test Flux") spec_viewer = cubeviz_helper.app.get_viewer("spectrum-viewer") @@ -843,7 +843,7 @@ def test_delete_subsets(cubeviz_helper, spectral_cube_wcs): """ Test that the toolbar selections get reset when the subset being actively edited gets deleted. """ - data = Spectrum1D(flux=np.ones((128, 128, 256)) * u.nJy, wcs=spectral_cube_wcs) + data = Spectrum(flux=np.ones((128, 128, 256)) * u.nJy, wcs=spectral_cube_wcs) cubeviz_helper.load_data(data, data_label="Test Flux") dc = cubeviz_helper.app.data_collection @@ -872,7 +872,7 @@ def test_get_regions_from_subsets_cubeviz(self, cubeviz_helper, spectral_cube_wc """ Basic tests for retrieving Sky Regions from spatial subsets in Cubeviz. """ - data = Spectrum1D(flux=np.ones((128, 128, 256)) * u.nJy, wcs=spectral_cube_wcs) + data = Spectrum(flux=np.ones((128, 128, 256)) * u.nJy, wcs=spectral_cube_wcs) cubeviz_helper.load_data(data) # basic test, a single circular region diff --git a/notebooks/MosvizExample.ipynb b/notebooks/MosvizExample.ipynb index 2b667033e8..a033fdb97b 100644 --- a/notebooks/MosvizExample.ipynb +++ b/notebooks/MosvizExample.ipynb @@ -53,7 +53,7 @@ "source": [ "But before we can use it, we need some data.\n", "\n", - "The Mosviz parsers accept lists of `Spectrum1D` and `CCDData` for 1D, 2D, and image data, respectively. Alternatively, users can also provide lists of file paths and Mosviz will internally attempt to parse them as their respective data types." + "The Mosviz parsers accept lists of `Spectrum` and `CCDData` for 1D, 2D, and image data, respectively. Alternatively, users can also provide lists of file paths and Mosviz will internally attempt to parse them as their respective data types." ] }, { @@ -96,7 +96,7 @@ "fn = download_file(example_data, cache=True)\n", "with ZipFile(fn, 'r') as sample_data_zip:\n", " sample_data_zip.extractall(data_dir)\n", - " \n", + "\n", "data_dir = (pathlib.Path(data_dir) / 'mosviz_nirspec_data_0.3' / 'level3')" ] }, diff --git a/pyproject.toml b/pyproject.toml index 5c10ad09d7..e451853ff0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,7 +23,7 @@ dependencies = [ "ipywidgets>=8.0.6", "voila>=0.4,<0.5", "pyyaml>=5.4.1", - "specutils>=1.9", + "specutils>=2.0", "specreduce>=1.3.0,<1.4.0", "photutils>=1.4", "glue-astronomy>=0.10",