diff --git a/CHANGES.rst b/CHANGES.rst index 732515e20b..e67d19118e 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -15,6 +15,7 @@ Mosviz Specviz ^^^^^^^ +- Specviz parser will now split a spectrum with a 2D flux array into multiple spectra on load. [#3229] Specviz2d ^^^^^^^^^ diff --git a/jdaviz/configs/specviz/helper.py b/jdaviz/configs/specviz/helper.py index 7eefe9e212..c13ac67175 100644 --- a/jdaviz/configs/specviz/helper.py +++ b/jdaviz/configs/specviz/helper.py @@ -41,7 +41,8 @@ def __init__(self, *args, **kwargs): handler=self._redshift_listener) def load_data(self, data, data_label=None, format=None, show_in_viewer=True, - concat_by_file=False, cache=None, local_path=None, timeout=None): + concat_by_file=False, cache=None, local_path=None, timeout=None, + load_as_list=False): """ Load data into Specviz. @@ -80,7 +81,8 @@ def load_data(self, data, data_label=None, format=None, show_in_viewer=True, concat_by_file=concat_by_file, cache=cache, local_path=local_path, - timeout=timeout) + timeout=timeout, + load_as_list=load_as_list) def get_spectra(self, data_label=None, spectral_subset=None, apply_slider_redshift="Warn"): """Returns the current data loaded into the main viewer diff --git a/jdaviz/configs/specviz/plugins/parsers.py b/jdaviz/configs/specviz/plugins/parsers.py index 51fbfc1ee6..10c9b2015b 100644 --- a/jdaviz/configs/specviz/plugins/parsers.py +++ b/jdaviz/configs/specviz/plugins/parsers.py @@ -18,7 +18,8 @@ @data_parser_registry("specviz-spectrum1d-parser") def specviz_spectrum1d_parser(app, data, data_label=None, format=None, show_in_viewer=True, - concat_by_file=False, cache=None, local_path=os.curdir, timeout=None): + concat_by_file=False, cache=None, local_path=os.curdir, timeout=None, + load_as_list=False): """ Loads a data file or `~specutils.Spectrum1D` object into Specviz. @@ -46,6 +47,9 @@ def specviz_spectrum1d_parser(app, data, data_label=None, format=None, show_in_v remote requests in seconds (passed to `~astropy.utils.data.download_file` or `~astroquery.mast.Conf.timeout`). + load_as_list : bool, optional + Force the parser to load the input file with the `~specutils.SpectrumList` read function + instead of `~specutils.Spectrum1D`. """ spectrum_viewer_reference_name = app._jdaviz_helper._default_spectrum_viewer_reference_name @@ -56,8 +60,12 @@ def specviz_spectrum1d_parser(app, data, data_label=None, format=None, show_in_v raise TypeError("SpectrumCollection detected." " Please provide a Spectrum1D or SpectrumList") elif isinstance(data, Spectrum1D): - data_label = [app.return_data_label(data_label, alt_name="specviz_data")] - data = [data] + # Handle the possibility of 2D spectra by splitting into separate spectra + if data.flux.ndim == 1: + data_label = [app.return_data_label(data_label, alt_name="specviz_data")] + data = [data] + elif data.flux.ndim == 2: + data, data_label = split_spectrum_with_2D_flux_array(data, data_label, app) # No special processing is needed in this case, but we include it for completeness elif isinstance(data, SpectrumList): pass @@ -77,19 +85,23 @@ def specviz_spectrum1d_parser(app, data, data_label=None, format=None, show_in_v path = pathlib.Path(data) - if path.is_file(): + if path.is_dir() or load_as_list: + data = SpectrumList.read(str(path), format=format) + if data == []: + raise ValueError(f"`specutils.SpectrumList.read('{str(path)}')` " + "returned an empty list") + elif path.is_file(): try: - data = [Spectrum1D.read(str(path), format=format)] - data_label = [app.return_data_label(data_label, alt_name="specviz_data")] + data = Spectrum1D.read(str(path), format=format) + if data.flux.ndim == 2: + data, data_label = split_spectrum_with_2D_flux_array(data, data_label, app) + else: + data = [data] + data_label = [app.return_data_label(data_label, alt_name="specviz_data")] except IORegistryError: # Multi-extension files may throw a registry error data = SpectrumList.read(str(path), format=format) - elif path.is_dir(): - data = SpectrumList.read(str(path), format=format) - if data == []: - raise ValueError(f"`specutils.SpectrumList.read('{str(path)}')` " - "returned an empty list") else: raise FileNotFoundError("No such file: " + str(path)) @@ -246,3 +258,20 @@ def combine_lists_to_1d_spectrum(wl, fnu, dfnu, wave_units, flux_units): spec = Spectrum1D(flux=fnuall * flux_units, spectral_axis=wlall * wave_units, uncertainty=unc) return spec + + +def split_spectrum_with_2D_flux_array(data, data_label, app): + temp_data = [] + temp_data_label = [] + for i in range(data.flux.shape[0]): + unc = None + mask = None + if data.uncertainty is not None: + unc = data.uncertainty[i, :] + if mask is not None: + mask = data.mask[i, :] + temp_data.append(Spectrum1D(flux=data.flux[i, :], spectral_axis=data.spectral_axis, + uncertainty=unc)) + temp_data_label.append(f'{app.return_data_label(data_label, alt_name="specviz_data")}[{i}]') # noqa + + return temp_data, temp_data_label diff --git a/jdaviz/configs/specviz/tests/test_helper.py b/jdaviz/configs/specviz/tests/test_helper.py index 6ca8c67064..9552fe1315 100644 --- a/jdaviz/configs/specviz/tests/test_helper.py +++ b/jdaviz/configs/specviz/tests/test_helper.py @@ -405,6 +405,15 @@ def test_load_spectrum_list_directory_concat(tmpdir, specviz_helper): assert len(specviz_helper.app.data_collection) == 41 +def test_load_spectrum1d_2d_flux(specviz_helper): + spec = Spectrum1D(spectral_axis=np.linspace(4000, 6000, 100)*u.Angstrom, + flux=np.ones((4, 100))*u.Unit("1e-17 erg / (Angstrom cm2 s)")) + specviz_helper.load_data(spec, data_label="test") + + assert len(specviz_helper.app.data_collection) == 4 + assert specviz_helper.app.data_collection[0].label == "test[0]" + + def test_plot_uncertainties(specviz_helper, spectrum1d): specviz_helper.load_data(spectrum1d)