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

Generalize specviz/2d load_data #3399

Draft
wants to merge 11 commits into
base: main
Choose a base branch
from
3 changes: 0 additions & 3 deletions docs/reference/api_parsers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,5 @@ Parsers API
.. automodapi:: jdaviz.configs.specviz.plugins.parsers
:no-inheritance-diagram:

.. automodapi:: jdaviz.configs.specviz2d.plugins.parsers
:no-inheritance-diagram:

.. automodapi:: jdaviz.configs.rampviz.plugins.parsers
:no-inheritance-diagram:
38 changes: 33 additions & 5 deletions jdaviz/configs/mosviz/plugins/parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from jdaviz.core.events import SnackbarMessage
from jdaviz.utils import standardize_metadata, PRIHDR_KEY, download_uri_to_path

__all__ = ['mos_spec1d_parser', 'mos_spec2d_parser', 'mos_image_parser']
__all__ = ['mos_spec1d_parser', 'mos_spec2d_parser', 'mos_image_parser', 'specreduce_trace_parser']

FALLBACK_NAME = "Unspecified"
EXPECTED_FILES = {"niriss": ['1D Spectra C', '1D Spectra R',
Expand Down Expand Up @@ -301,10 +301,10 @@ def mos_spec2d_parser(app, data_obj, data_labels=None, add_to_table=True,

"""
spectrum_2d_viewer_reference_name = (
app._jdaviz_helper._default_spectrum_2d_viewer_reference_name
getattr(app._jdaviz_helper, "_default_spectrum_2d_viewer_reference_name", None)
)
table_viewer_reference_name = (
app._jdaviz_helper._default_table_viewer_reference_name
getattr(app._jdaviz_helper, "_default_table_viewer_reference_name", None)
)

# Note: This is also used by Specviz2D
Expand Down Expand Up @@ -388,13 +388,13 @@ def _parse_as_spectrum1d(hdulist, ext, transpose):
label = data_labels[index]
app.data_collection[label] = data

if add_to_table:
if add_to_table and table_viewer_reference_name is not None:
_add_to_table(
app, data_labels, '2D Spectra',
table_viewer_reference_name=table_viewer_reference_name
)

if show_in_viewer:
if show_in_viewer and spectrum_2d_viewer_reference_name is not None:
if len(data_labels) > 1:
raise ValueError("More than one data label provided, unclear " +
"which to show in viewer")
Expand All @@ -403,6 +403,34 @@ def _parse_as_spectrum1d(hdulist, ext, transpose):
return len(data_obj)


@data_parser_registry("specreduce-trace")
def specreduce_trace_parser(app, data_obj, data_label=None, show_in_viewer=False):
"""
Loads a specreduce trace object.

Parameters
----------
app : `~jdaviz.app.Application`
The application-level object used to reference the viewers.
data_obj : str or list or spectrum-like
File path, list, or spectrum-like object to be read as a new row in
the mosviz table.
data_label : str, optional
The label applied to the glue data component.
show_in_viewer : bool
Show data in viewer(s).
"""
spectrum_2d_viewer_reference_name = (
getattr(app._jdaviz_helper, "_default_spectrum_2d_viewer_reference_name", None)
)

app.add_data(data_obj, data_label=data_label)
if show_in_viewer and spectrum_2d_viewer_reference_name:
app.add_data_to_viewer(
spectrum_2d_viewer_reference_name, data_label
)


def _load_fits_image_from_filename(filename, app):
with fits.open(filename) as hdulist:
# We do not use the generated labels
Expand Down
53 changes: 44 additions & 9 deletions jdaviz/configs/specviz/helper.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import pathlib
import warnings

from astropy import units as u
Expand All @@ -6,9 +7,11 @@
from glue.core.subset_group import GroupedSubset
from specutils import SpectralRegion, Spectrum1D

from jdaviz.core import data_formats
from jdaviz.core.helpers import ConfigHelper
from jdaviz.core.events import RedshiftMessage
from jdaviz.configs.default.plugins.line_lists.line_list_mixin import LineListMixin
from jdaviz.utils import download_uri_to_path

__all__ = ['Specviz']

Expand All @@ -33,6 +36,7 @@ class Specviz(ConfigHelper, LineListMixin):

_default_configuration = "specviz"
_default_spectrum_viewer_reference_name = "spectrum-viewer"
_dev_deconfig = False

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
Expand Down Expand Up @@ -74,16 +78,47 @@ def load_data(self, data, data_label=None, format=None, show_in_viewer=True,
`~astropy.utils.data.download_file` or
`~astroquery.mast.Conf.timeout`).
"""
parser = data_formats.get_parser(data, load_as_list=load_as_list)
if not self._dev_deconfig and parser != 'specviz-spectrum1d-parser':
raise NotImplementedError("Only Spectrum1D data is supported in Specviz.")

default_labels = {'mosviz-spec2d-parser': '2D Spectrum',
'specreduce-trace': 'Trace',
'specviz-spectrum1d-parser': 'Spectrum'}
if data_label is None:
data_label = default_labels.get(parser, 'Unknown')
data_label = self.app.return_unique_name(data_label)

if isinstance(data, str):
path = pathlib.Path(data)
if not path.is_file() and not path.is_dir():
data = download_uri_to_path(data, cache=cache,
local_path=local_path, timeout=timeout)

parser_kwargs = {'mosviz-spec2d-parser': {'show_in_viewer': False,
'data_labels': data_label},
'specreduce-trace': {'show_in_viewer': False,
'data_label': data_label},
'specviz-spectrum1d-parser': {'format': format,
'show_in_viewer': False,
'concat_by_file': concat_by_file,
'load_as_list': load_as_list,
'data_label': data_label}}
kwargs = parser_kwargs.get(parser, {})
super().load_data(data,
parser_reference='specviz-spectrum1d-parser',
data_label=data_label,
format=format,
show_in_viewer=show_in_viewer,
concat_by_file=concat_by_file,
cache=cache,
local_path=local_path,
timeout=timeout,
load_as_list=load_as_list)
parser_reference=parser,
**kwargs)

if show_in_viewer:
# loop through existing viewers and show in any that support this data type
added = 0
for viewer in self.viewers.values():
if data_label in viewer.data_menu.data_labels_unloaded:
added += 1
viewer.data_menu.add_data(data_label)
if added == 0:
# TODO: in the future open a new viewer with some default type based on the data
print(f"*** No viewer found to display \'{data_label}\'")

def get_spectra(self, data_label=None, spectral_subset=None, apply_slider_redshift="Warn"):
"""Returns the current data loaded into the main viewer
Expand Down
4 changes: 2 additions & 2 deletions jdaviz/configs/specviz/tests/test_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def test_load_spectrum_list_no_labels(self):
self.spec_app.load_data(self.spec_list)
assert len(self.spec_app.app.data_collection) == 4
for i in (1, 2, 3):
assert "specviz_data" in self.spec_app.app.data_collection[i].label
assert "Spectrum" in self.spec_app.app.data_collection[i].label

def test_load_spectrum_list_with_labels(self):
# now load three more spectra from a SpectrumList, with labels:
Expand Down Expand Up @@ -412,7 +412,7 @@ def test_load_2d_flux(specviz_helper):
# 1D Spectrum1D objects to load in Specviz.
spec = Spectrum1D(spectral_axis=np.linspace(4000, 6000, 10)*u.Angstrom,
flux=np.ones((4, 10))*u.Unit("1e-17 erg / (Angstrom cm2 s)"))
specviz_helper.load_data(spec, data_label="test")
specviz_helper.load_data(spec, data_label="test", load_as_list=True)

assert len(specviz_helper.app.data_collection) == 4
assert specviz_helper.app.data_collection[0].label == "test [0]"
Expand Down
1 change: 0 additions & 1 deletion jdaviz/configs/specviz2d/plugins/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
from .parsers import * # noqa
from .spectral_extraction.spectral_extraction import * # noqa
76 changes: 0 additions & 76 deletions jdaviz/configs/specviz2d/plugins/parsers.py
Copy link
Member Author

Choose a reason for hiding this comment

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

as far as I can tell, this parser hasn't been used since we began using the spectral extraction plugin in specviz2d

This file was deleted.

44 changes: 43 additions & 1 deletion jdaviz/core/data_formats.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from specutils.io.registers import identify_spectrum_format
from specutils import Spectrum1D, SpectrumList, SpectrumCollection
from specreduce.tracing import Trace
from stdatamodels import asdf_in_fits

from jdaviz.core.config import list_configurations
Expand Down Expand Up @@ -75,7 +76,6 @@ def get_valid_format(filename):
config : str
The recommended application configuration
"""

valid_file_format = identify_spectrum_format(filename, SpectrumList)
ndim = guess_dimensionality(filename)

Expand All @@ -87,6 +87,48 @@ def get_valid_format(filename):
return valid_file_format, recommended_config


def get_parser(obj, load_as_list=False):
"""
Identify the data parser from a filename or data object

Parameters
----------
obj : str or `pathlib.Path` or file-like object
The filename of the loaded data

Returns
-------
parser : str
The parser for the data object
"""
if isinstance(obj, (SpectrumList, SpectrumCollection)):
return 'specviz-spectrum1d-parser'
if isinstance(obj, Trace):
return 'specreduce-trace'
if isinstance(obj, Spectrum1D):
if obj.flux.ndim == 1:
return 'specviz-spectrum1d-parser'
else:
if load_as_list:
return 'specviz-spectrum1d-parser'
return 'mosviz-spec2d-parser'
if isinstance(obj, fits.HDUList):
columns = [c.name.lower() for hduitem in obj for c in getattr(hduitem, 'columns', [])]
if 'wavelength' in columns and 'flux' in columns:
return 'specviz-spectrum1d-parser'
else:
raise ValueError("cannot find valid parser for HDUList")
if isinstance(obj, list):
parsers = [get_parser(o, load_as_list=load_as_list) for o in obj]
if len(set(parsers)) > 1:
raise ValueError("cannot find single parser for list of objects")
return parsers[0]

_, config = get_valid_format(obj)
parsers = {'specviz': 'specviz-spectrum1d-parser', 'specviz2d': 'mosviz-spec2d-parser'}
return parsers.get(config)


def identify_data(filename, current=None):
"""Identify the data format and application configuration from a filename.

Expand Down
Loading