Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor cubeviz parser and plugins for specutils 2.0 compatibility #2762

Draft
wants to merge 22 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
ae654e2
Remove jwst s3d parser now that it can be handled by Spectrum1D
rosteen Mar 11, 2024
ed4a3a4
Starting to debug slice
rosteen Mar 12, 2024
c5266d1
Fix coords mouseover when SkyCoord is before SpectralCoord
rosteen Mar 12, 2024
ee0cb79
More debugging
rosteen Mar 13, 2024
1586e8d
Fix slice with different spectral_axis_index, add specutils_format kw…
rosteen Mar 19, 2024
fe37147
Remove unused import
rosteen Mar 19, 2024
4506524
Remove ESA parser from commissioning [skip ci]
rosteen Mar 19, 2024
0eb9cb6
Generalizing coords_info to handle spectral axis first or last [ci skip]
rosteen Mar 19, 2024
6565e9d
Working on debugging aperture photometry
rosteen Mar 20, 2024
1304cca
Need to pull meta from data not comp
rosteen Mar 20, 2024
b7c27d6
Fix aperture photometry and wrong coord order in coords_info
rosteen Mar 25, 2024
379f98c
Fix codestyle, delete defunct case in parser
rosteen Mar 25, 2024
007ae6e
Change Spectrum1D to Spectrum
rosteen Mar 27, 2024
eb35397
Debugging
rosteen Mar 29, 2024
a70e082
Change class name in recent code additions
rosteen Apr 9, 2024
85c86df
Get spectral extraction working again for cylinder case
rosteen Apr 9, 2024
217a5bd
Debugging wavelength dependent case
rosteen Apr 10, 2024
d832c5c
Make sure spectral extraction result is linked when added to data col…
rosteen Apr 10, 2024
49e94b3
Moved fix to correct place
rosteen Apr 10, 2024
c65f091
Fix indents
rosteen Apr 18, 2024
06819df
Revert this change from rebase to match main
rosteen Apr 18, 2024
489b3f1
Remove stray code from rebase
rosteen Apr 18, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions docs/create_products.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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`.

Expand All @@ -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
Expand All @@ -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`
Expand Down
6 changes: 3 additions & 3 deletions docs/cubeviz/export_data.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 <https://specutils.readthedocs.io/en/latest/spectrum1d.html#including-masks>`_:
`Spectrum masks <https://specutils.readthedocs.io/en/latest/spectrum1d.html#including-masks>`_:

.. code-block:: python

Expand Down
36 changes: 18 additions & 18 deletions docs/cubeviz/import_data.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 <https://specutils.readthedocs.io/en/stable/spectrum1d.html#defining-wcs>`_.
keywords. For more information on how :class:`~specutils.Spectrum`
uses WCS, please go to the `Spectrum defining WCS section <https://specutils.readthedocs.io/en/stable/spectrum1d.html#defining-wcs>`_.
To check if your FITS file contains valid WCS keywords, please use
`Astropy WCS validate <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:

Expand Down Expand Up @@ -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
Expand All @@ -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
----------
Expand All @@ -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
Expand All @@ -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()
Expand All @@ -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,
Expand All @@ -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()
Expand Down
2 changes: 1 addition & 1 deletion docs/cubeviz/plugins.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 <specviz-plugins>`.
In many cases, these capabilities can be further applied on a per spaxel basis
Expand Down
4 changes: 2 additions & 2 deletions docs/mosviz/plugins.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
8 changes: 4 additions & 4 deletions docs/specviz/export_data.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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`.

Expand All @@ -35,15 +35,15 @@ 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:

.. 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)

Expand Down
26 changes: 13 additions & 13 deletions docs/specviz/import_data.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 <https://specutils.readthedocs.io/en/stable/spectrum1d.html#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:

Expand All @@ -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
Expand All @@ -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
----------
Expand All @@ -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
Expand All @@ -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()
Expand All @@ -101,15 +101,15 @@ 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
a = mydatamodel.spec[0]
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()
Expand All @@ -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:

Expand Down
4 changes: 2 additions & 2 deletions docs/specviz/plugins.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion docs/specviz2d/export_data.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 5 additions & 5 deletions docs/specviz2d/import_data.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 <https://specutils.readthedocs.io/en/stable/spectrum1d.html#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
Expand Down Expand Up @@ -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.
Expand All @@ -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
Expand Down
Loading
Loading