diff --git a/CHANGES.rst b/CHANGES.rst index e05078dfb..0d2d2fe87 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -7,7 +7,7 @@ New Features - Spectral axis can now be any axis, rather than being forced to be last. See docs for more details. [#1033] -- Spectrum1D now properly handles GWCS input for wcs attribute. [#1074] +- Spectrum now properly handles GWCS input for wcs attribute. [#1074] - JWST reader no longer transposes the input data cube for 3D data and retains full GWCS information (including spatial). [#1074] @@ -15,6 +15,8 @@ New Features Other Changes and Additions ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- Spectrum1D renamed to Spectrum. [#1126] + 1.13.0 (2024-02-19) ------------------- diff --git a/docs/analysis.rst b/docs/analysis.rst index 53fb42b00..b2a30ab1a 100644 --- a/docs/analysis.rst +++ b/docs/analysis.rst @@ -8,7 +8,7 @@ The specutils package comes with a set of tools for doing common analysis tasks on astronomical spectra. Some examples of applying these tools are described below. The basic spectrum shown here is used in the examples in the sub-sections below - a gaussian-profile line with flux of 5 GHz Jy. See -:doc:`spectrum1d` for more on creating spectra: +:doc:`spectrum` for more on creating spectra: .. plot:: :include-source: true @@ -18,14 +18,14 @@ sub-sections below - a gaussian-profile line with flux of 5 GHz Jy. See >>> from astropy import units as u >>> from astropy.nddata import StdDevUncertainty >>> from astropy.modeling import models - >>> from specutils import Spectrum1D, SpectralRegion + >>> from specutils import Spectrum, SpectralRegion >>> np.random.seed(42) >>> spectral_axis = np.linspace(11., 1., 200) * u.GHz >>> spectral_model = models.Gaussian1D(amplitude=5*(2*np.pi*0.8**2)**-0.5*u.Jy, mean=5*u.GHz, stddev=0.8*u.GHz) >>> flux = spectral_model(spectral_axis) >>> flux += np.random.normal(0., 0.05, spectral_axis.shape) * u.Jy >>> uncertainty = StdDevUncertainty(0.2*np.ones(flux.shape)*u.Jy) - >>> noisy_gaussian = Spectrum1D(spectral_axis=spectral_axis, flux=flux, uncertainty=uncertainty) + >>> noisy_gaussian = Spectrum(spectral_axis=spectral_axis, flux=flux, uncertainty=uncertainty) >>> import matplotlib.pyplot as plt #doctest:+SKIP >>> plt.step(noisy_gaussian.spectral_axis, noisy_gaussian.flux) #doctest:+SKIP @@ -48,7 +48,7 @@ spectrum: A second method to calculate SNR does not require the uncertainty defined -on the `~specutils.Spectrum1D` object. This computes the signal to noise +on the `~specutils.Spectrum` object. This computes the signal to noise ratio DER_SNR following the definition set forth by the Spectral Container Working Group of ST-ECF, MAST and CADC. This algorithm is described at https://esahubble.org/static/archives/stecfnewsletters/pdf/hst_stecf_0042.pdf @@ -257,15 +257,15 @@ An example of how to do template matching with an unknown redshift is: >>> resample_method = "flux_conserving" >>> rs_values = np.arange(min_redshift, max_redshift+delta_redshift, delta_redshift) - >>> observed_spectrum = Spectrum1D(spectral_axis=spec_axis*(1+observed_redshift), flux=np.random.randn(50) * u.Jy, uncertainty=StdDevUncertainty(np.random.sample(50), unit='Jy')) - >>> spectral_template = Spectrum1D(spectral_axis=spec_axis, flux=np.random.randn(50) * u.Jy, uncertainty=StdDevUncertainty(np.random.sample(50), unit='Jy')) + >>> observed_spectrum = Spectrum(spectral_axis=spec_axis*(1+observed_redshift), flux=np.random.randn(50) * u.Jy, uncertainty=StdDevUncertainty(np.random.sample(50), unit='Jy')) + >>> spectral_template = Spectrum(spectral_axis=spec_axis, flux=np.random.randn(50) * u.Jy, uncertainty=StdDevUncertainty(np.random.sample(50), unit='Jy')) >>> tm_result = template_comparison.template_match(observed_spectrum=observed_spectrum, spectral_templates=spectral_template, resample_method=resample_method, redshift=rs_values) # doctest:+FLOAT_CMP Dust extinction --------------- -Dust extinction can be applied to Spectrum1D instances via their internal arrays, using +Dust extinction can be applied to Spectrum instances via their internal arrays, using the ``dust_extinction`` package (http://dust-extinction.readthedocs.io/en/latest) Below is an example of how to apply extinction. @@ -277,14 +277,14 @@ Below is an example of how to apply extinction. wave = np.logspace(np.log10(1000), np.log10(3e4), num=10) * u.AA flux = blackbody_lambda(wave, 10000 * u.K) - spec = Spectrum1D(spectral_axis=wave, flux=flux) + spec = Spectrum(spectral_axis=wave, flux=flux) # define the model ext = F99(Rv=3.1) # extinguish (redden) the spectrum flux_ext = spec.flux * ext.extinguish(spec.spectral_axis, Ebv=0.5) - spec_ext = Spectrum1D(spectral_axis=wave, flux=flux_ext) + spec_ext = Spectrum(spectral_axis=wave, flux=flux_ext) Template Cross-correlation @@ -311,8 +311,8 @@ value set. >>> flux1 = f1 + g1(spec_axis) >>> flux2 = f2 + g2(spec_axis) >>> uncertainty = StdDevUncertainty(0.2*np.ones(size)*u.Jy) - >>> ospec = Spectrum1D(spectral_axis=spec_axis, flux=flux1, uncertainty=uncertainty, velocity_convention='optical', rest_value=rest_value) - >>> tspec = Spectrum1D(spectral_axis=spec_axis, flux=flux2, uncertainty=uncertainty) + >>> ospec = Spectrum(spectral_axis=spec_axis, flux=flux1, uncertainty=uncertainty, velocity_convention='optical', rest_value=rest_value) + >>> tspec = Spectrum(spectral_axis=spec_axis, flux=flux2, uncertainty=uncertainty) >>> corr, lag = correlation.template_correlate(ospec, tspec) The lag values are reported in km/s units. The correlation values are computed after the template spectrum is diff --git a/docs/arithmetic.rst b/docs/arithmetic.rst index aa8b1fbf3..59ce6d4c4 100644 --- a/docs/arithmetic.rst +++ b/docs/arithmetic.rst @@ -20,16 +20,16 @@ Arithmetic support includes addition, subtract, multiplication, and division. .. code-block:: python - >>> from specutils import Spectrum1D + >>> from specutils import Spectrum >>> import astropy.units as u >>> import numpy as np >>> rng = np.random.default_rng(12345) - >>> spec1 = Spectrum1D(spectral_axis=np.arange(1, 50) * u.nm, flux=rng.random(49)*u.Jy) - >>> spec2 = Spectrum1D(spectral_axis=np.arange(1, 50) * u.nm, flux=rng.random(49)*u.Jy) + >>> spec1 = Spectrum(spectral_axis=np.arange(1, 50) * u.nm, flux=rng.random(49)*u.Jy) + >>> spec2 = Spectrum(spectral_axis=np.arange(1, 50) * u.nm, flux=rng.random(49)*u.Jy) >>> spec3 = spec1 + spec2 >>> spec3 # doctest: +FLOAT_CMP - >> rng = np.random.default_rng(12345) >>> wave = np.arange(10) * u.nm - >>> spec1 = Spectrum1D(spectral_axis=wave, + >>> spec1 = Spectrum(spectral_axis=wave, ... flux=rng.random(10)*u.Jy, ... uncertainty=StdDevUncertainty(rng.random(10) * 0.1)) - >>> spec2 = Spectrum1D(spectral_axis=wave, + >>> spec2 = Spectrum(spectral_axis=wave, ... flux=rng.random(10)*u.Jy, ... uncertainty=StdDevUncertainty(rng.random(10) * 0.1)) >>> spec1.uncertainty diff --git a/docs/custom_loading.rst b/docs/custom_loading.rst index 089248f13..ea706aaab 100644 --- a/docs/custom_loading.rst +++ b/docs/custom_loading.rst @@ -12,21 +12,21 @@ a separate python file and place the file in their ``~/.specutils`` directory. Loading from a FITS File ------------------------ A spectra with a *Linear Wavelength Solution* can be read using the ``read`` -method of the :class:`~specutils.Spectrum1D` class to parse the file name and +method of the :class:`~specutils.Spectrum` class to parse the file name and format .. code-block:: python import os - from specutils import Spectrum1D + from specutils import Spectrum file_path = os.path.join('path/to/folder', 'file_with_1d_wcs.fits') - spec = Spectrum1D.read(file_path, format='wcs1d-fits') + spec = Spectrum.read(file_path, format='wcs1d-fits') -This will create a :class:`~specutils.Spectrum1D` object that you can manipulate later. +This will create a :class:`~specutils.Spectrum` object that you can manipulate later. For instance, you could plot the spectrum. @@ -51,7 +51,7 @@ Defining a custom loader consists of importing the `~specutils.io.registers.data_loader` decorator from specutils and attaching it to a function that knows how to parse the user's data. The return object of this function must be an instance of one of the spectral classes -(:class:`~specutils.Spectrum1D`, :class:`~specutils.SpectrumCollection`, +(:class:`~specutils.Spectrum`, :class:`~specutils.SpectrumCollection`, :class:`~specutils.SpectrumList`). Optionally, the user may define an identifier function. This function acts to @@ -69,11 +69,11 @@ ensure that the data file being loaded is compatible with the loader function. from astropy.wcs import WCS from specutils.io.registers import data_loader - from specutils import Spectrum1D + from specutils import Spectrum # Define an optional identifier. If made specific enough, this circumvents the - # need to add ``format="my-format"`` in the ``Spectrum1D.read`` call. + # need to add ``format="my-format"`` in the ``Spectrum.read`` call. def identify_generic_fits(origin, *args, **kwargs): return (isinstance(args[0], str) and os.path.splitext(args[0].lower())[1] == '.fits') @@ -92,7 +92,7 @@ ensure that the data file being loaded is compatible with the loader function. uncertainty = StdDevUncertainty(tab["err"]) data = tab["flux"] * Unit("Jy") - return Spectrum1D(flux=data, wcs=wcs, uncertainty=uncertainty, meta=meta) + return Spectrum(flux=data, wcs=wcs, uncertainty=uncertainty, meta=meta) An ``extensions`` keyword can be provided. This allows for basic filename @@ -109,17 +109,17 @@ with a particular extension. loaders = get_loaders_by_extension('fits') The returned list contains the format labels that can be fed into the ``format`` -keyword argument of the ``Spectrum1D.read`` method. +keyword argument of the ``Spectrum.read`` method. After placing this python file in the user's ``~/.specutils`` directory, it can be utilized by referencing its name in the ``read`` method of the -:class:`~specutils.Spectrum1D` class +:class:`~specutils.Spectrum` class .. code-block:: python - from specutils import Spectrum1D + from specutils import Spectrum - spec = Spectrum1D.read("path/to/data", format="my-format") + spec = Spectrum.read("path/to/data", format="my-format") .. _multiple_spectra: @@ -134,11 +134,11 @@ custom JWST data loader as an example: .. literalinclude:: ../specutils/io/default_loaders/jwst_reader.py :language: python -Note that by default, any loader that uses ``dtype=Spectrum1D`` will also +Note that by default, any loader that uses ``dtype=Spectrum`` will also automatically add a reader for `~specutils.SpectrumList`. This enables user code to call `specutils.SpectrumList.read ` in all cases if it can't make assumptions about whether a loader returns one or -many `~specutils.Spectrum1D` objects. This method is available since +many `~specutils.Spectrum` objects. This method is available since `~specutils.SpectrumList` makes use of the Astropy IO registry (see `astropy.io.registry.read`). @@ -171,11 +171,11 @@ This again will be done in a separate python file and placed in the user's The custom writer can be used by passing the name of the custom writer to the ``format`` argument of the ``write`` method on the -:class:`~specutils.Spectrum1D`. +:class:`~specutils.Spectrum`. .. code-block:: python - spec = Spectrum1D(flux=np.random.sample(100) * u.Jy, + spec = Spectrum(flux=np.random.sample(100) * u.Jy, spectral_axis=np.arange(100) * u.AA) spec.write("my_output.fits", format="fits-writer") diff --git a/docs/fitting.rst b/docs/fitting.rst index b4a378655..1e698e97e 100644 --- a/docs/fitting.rst +++ b/docs/fitting.rst @@ -8,7 +8,7 @@ approach applies to continuum fitting or even full-spectrum fitting. ``specutils`` provides conveniences that aim to leverage the general fitting framework of `astropy.modeling` to spectral-specific tasks. -At a high level, this fitting takes the `~specutils.Spectrum1D` object and a +At a high level, this fitting takes the `~specutils.Spectrum` object and a list of `~astropy.modeling.Model` objects that have initial guesses for each of the parameters. these are used to create a compound model created from the model initial guesses. This model is then actually fit to the spectrum's ``flux``, @@ -19,7 +19,7 @@ Line Finding ------------ There are two techniques implemented in order to find emission and/or absorption -lines in a `~specutils.Spectrum1D` spectrum. +lines in a `~specutils.Spectrum` spectrum. The first technique is `~specutils.fitting.find_lines_threshold` that will find lines by thresholding the flux based on a factor applied to the @@ -38,7 +38,7 @@ We start with a synthetic spectrum: >>> import numpy as np >>> from astropy.modeling import models >>> import astropy.units as u - >>> from specutils import Spectrum1D, SpectralRegion + >>> from specutils import Spectrum, SpectralRegion >>> np.random.seed(42) >>> g1 = models.Gaussian1D(1, 4.6, 0.2) @@ -46,7 +46,7 @@ We start with a synthetic spectrum: >>> g3 = models.Gaussian1D(-1.7, 8.2, 0.1) >>> x = np.linspace(0, 10, 200) >>> y = g1(x) + g2(x) + g3(x) + np.random.normal(0., 0.2, x.shape) - >>> spectrum = Spectrum1D(flux=y*u.Jy, spectral_axis=x*u.um) + >>> spectrum = Spectrum(flux=y*u.Jy, spectral_axis=x*u.um) >>> from matplotlib import pyplot as plt >>> plt.plot(spectrum.spectral_axis, spectrum.flux) # doctest: +IGNORE_OUTPUT @@ -234,7 +234,7 @@ initial guess. from astropy.modeling import models from astropy import units as u - from specutils.spectra import Spectrum1D + from specutils.spectra import Spectrum from specutils.fitting import fit_lines # Create a simple spectrum with a Gaussian. @@ -242,7 +242,7 @@ initial guess. x = np.linspace(0., 10., 200) y = 3 * np.exp(-0.5 * (x- 6.3)**2 / 0.8**2) y += np.random.normal(0., 0.2, x.shape) - spectrum = Spectrum1D(flux=y*u.Jy, spectral_axis=x*u.um) + spectrum = Spectrum(flux=y*u.Jy, spectral_axis=x*u.um) # Fit the spectrum and calculate the fitted flux values (``y_fit``) g_init = models.Gaussian1D(amplitude=3.*u.Jy, mean=6.1*u.um, stddev=1.*u.um) @@ -274,7 +274,7 @@ output the fitted model in the spectrum units. from astropy.modeling import models from astropy import units as u - from specutils.spectra import Spectrum1D + from specutils.spectra import Spectrum from specutils.fitting import fit_lines # Create a simple spectrum with a Gaussian. @@ -284,7 +284,7 @@ output the fitted model in the spectrum units. y += np.random.normal(0., 0.2, x.shape) # Create the spectrum - spectrum = Spectrum1D(flux=y*u.Jy, spectral_axis=x*u.um) + spectrum = Spectrum(flux=y*u.Jy, spectral_axis=x*u.um) # Fit the spectrum g_init = models.Gaussian1D(amplitude=3.*u.Jy, mean=61000*u.AA, stddev=10000.*u.AA) @@ -313,7 +313,7 @@ mean of the model initial guess (so ``2*u.um`` around ``5.5*u.um``). from astropy.modeling import models from astropy import units as u - from specutils.spectra import Spectrum1D + from specutils.spectra import Spectrum from specutils.fitting import fit_lines # Create a simple spectrum with a Gaussian. @@ -323,7 +323,7 @@ mean of the model initial guess (so ``2*u.um`` around ``5.5*u.um``). y += np.random.normal(0., 0.2, x.shape) # Create the spectrum - spectrum = Spectrum1D(flux=y*u.Jy, spectral_axis=x*u.um) + spectrum = Spectrum(flux=y*u.Jy, spectral_axis=x*u.um) # Fit the spectrum g_init = models.Gaussian1D(amplitude=3.*u.Jy, mean=5.5*u.um, stddev=1.*u.um) @@ -352,7 +352,7 @@ Single peak fit using spectral data *only* within the window from astropy.modeling import models from astropy import units as u - from specutils.spectra import Spectrum1D + from specutils.spectra import Spectrum from specutils.fitting import fit_lines # Create a simple spectrum with a Gaussian. @@ -362,7 +362,7 @@ Single peak fit using spectral data *only* within the window y += np.random.normal(0., 0.2, x.shape) # Create the spectrum - spectrum = Spectrum1D(flux=y*u.Jy, spectral_axis=x*u.um) + spectrum = Spectrum(flux=y*u.Jy, spectral_axis=x*u.um) # Fit the spectrum g_init = models.Gaussian1D(amplitude=3.*u.Jy, mean=5.5*u.um, stddev=1.*u.um) @@ -391,7 +391,7 @@ model out. from astropy.modeling import models from astropy import units as u - from specutils.spectra import Spectrum1D + from specutils.spectra import Spectrum from specutils.fitting import fit_lines # Create a simple spectrum with a Gaussian. @@ -403,7 +403,7 @@ model out. y = g1(x) + g2(x) + np.random.normal(0., 0.2, x.shape) # Create the spectrum to fit - spectrum = Spectrum1D(flux=y*u.Jy, spectral_axis=x*u.um) + spectrum = Spectrum(flux=y*u.Jy, spectral_axis=x*u.um) # Fit the spectrum g1_init = models.Gaussian1D(amplitude=2.3*u.Jy, mean=5.6*u.um, stddev=0.1*u.um) @@ -432,7 +432,7 @@ Double peak fit using data in the spectrum from ``4.3*u.um`` to ``5.3*u.um``, on from astropy.modeling import models from astropy import units as u - from specutils.spectra import Spectrum1D + from specutils.spectra import Spectrum from specutils.fitting import fit_lines # Create a simple spectrum with a Gaussian. @@ -444,7 +444,7 @@ Double peak fit using data in the spectrum from ``4.3*u.um`` to ``5.3*u.um``, on y = g1(x) + g2(x) + np.random.normal(0., 0.2, x.shape) # Create the spectrum to fit - spectrum = Spectrum1D(flux=y*u.Jy, spectral_axis=x*u.um) + spectrum = Spectrum(flux=y*u.Jy, spectral_axis=x*u.um) # Fit the spectrum g2_init = models.Gaussian1D(amplitude=1.*u.Jy, mean=4.7*u.um, stddev=0.2*u.um) @@ -472,7 +472,7 @@ Double peak fit using data in the spectrum centered on ``4.7*u.um`` +/- ``0.3*u. from astropy.modeling import models from astropy import units as u - from specutils.spectra import Spectrum1D + from specutils.spectra import Spectrum from specutils.fitting import fit_lines # Create a simple spectrum with a Gaussian. @@ -484,7 +484,7 @@ Double peak fit using data in the spectrum centered on ``4.7*u.um`` +/- ``0.3*u. y = g1(x) + g2(x) + np.random.normal(0., 0.2, x.shape) # Create the spectrum to fit - spectrum = Spectrum1D(flux=y*u.Jy, spectral_axis=x*u.um) + spectrum = Spectrum(flux=y*u.Jy, spectral_axis=x*u.um) # Fit the spectrum g2_init = models.Gaussian1D(amplitude=1.*u.Jy, mean=4.7*u.um, stddev=0.2*u.um) @@ -513,7 +513,7 @@ each within ``0.2*u.um`` of the model's mean. from astropy.modeling import models from astropy import units as u - from specutils.spectra import Spectrum1D + from specutils.spectra import Spectrum from specutils.fitting import fit_lines # Create a simple spectrum with a Gaussian. @@ -525,7 +525,7 @@ each within ``0.2*u.um`` of the model's mean. y = g1(x) + g2(x) + np.random.normal(0., 0.2, x.shape) # Create the spectrum to fit - spectrum = Spectrum1D(flux=y*u.Jy, spectral_axis=x*u.um) + spectrum = Spectrum(flux=y*u.Jy, spectral_axis=x*u.um) # Fit each peak gl_init = models.Gaussian1D(amplitude=1.*u.Jy, mean=4.8*u.um, stddev=0.2*u.um) @@ -555,7 +555,7 @@ the corresponding window. >>> import matplotlib.pyplot as plt >>> from astropy.modeling import models >>> from astropy import units as u - >>> from specutils.spectra import Spectrum1D + >>> from specutils.spectra import Spectrum >>> from specutils.fitting import fit_lines >>> # Create a simple spectrum with a Gaussian. @@ -567,7 +567,7 @@ the corresponding window. >>> y = g1(x) + g2(x) + np.random.normal(0., 0.2, x.shape) >>> # Create the spectrum to fit - >>> spectrum = Spectrum1D(flux=y*u.Jy, spectral_axis=x*u.um) + >>> spectrum = Spectrum(flux=y*u.Jy, spectral_axis=x*u.um) >>> # Fit each peak >>> gl_init = models.Gaussian1D(amplitude=1.*u.Jy, mean=4.8*u.um, stddev=0.2*u.um) @@ -598,7 +598,7 @@ all the data *except* between ``5.2*u.um`` and ``5.8*u.um``. >>> import matplotlib.pyplot as plt >>> from astropy.modeling import models >>> from astropy import units as u - >>> from specutils.spectra import Spectrum1D, SpectralRegion + >>> from specutils.spectra import Spectrum, SpectralRegion >>> from specutils.fitting import fit_lines >>> # Create a simple spectrum with a Gaussian. @@ -609,7 +609,7 @@ all the data *except* between ``5.2*u.um`` and ``5.8*u.um``. >>> y = g1(x) + g2(x) + np.random.normal(0., 0.2, x.shape) >>> # Create the spectrum to fit - >>> spectrum = Spectrum1D(flux=y*u.Jy, spectral_axis=x*u.um) + >>> spectrum = Spectrum(flux=y*u.Jy, spectral_axis=x*u.um) >>> # Fit each peak >>> gl_init = models.Gaussian1D(amplitude=1.*u.Jy, mean=4.8*u.um, stddev=0.2*u.um) @@ -642,7 +642,7 @@ convenience functions to perform exactly this task. An example is shown below. >>> import matplotlib.pyplot as plt >>> from astropy.modeling import models >>> from astropy import units as u - >>> from specutils.spectra import Spectrum1D, SpectralRegion + >>> from specutils.spectra import Spectrum, SpectralRegion >>> from specutils.fitting import fit_generic_continuum >>> np.random.seed(0) @@ -653,7 +653,7 @@ convenience functions to perform exactly this task. An example is shown below. >>> y_continuum = 3.2 * np.exp(-0.5 * (x - 5.6)**2 / 4.8**2) >>> y += y_continuum - >>> spectrum = Spectrum1D(flux=y*u.Jy, spectral_axis=x*u.um) + >>> spectrum = Spectrum(flux=y*u.Jy, spectral_axis=x*u.um) >>> with warnings.catch_warnings(): # Ignore warnings ... warnings.simplefilter('ignore') @@ -698,7 +698,7 @@ is specified by a sequence: >>> import matplotlib.pyplot as plt >>> import astropy.units as u - >>> from specutils.spectra.spectrum1d import Spectrum1D + >>> from specutils.spectra.spectrum import Spectrum >>> from specutils.fitting.continuum import fit_continuum >>> np.random.seed(0) @@ -707,7 +707,7 @@ is specified by a sequence: >>> y += np.random.normal(0., 0.2, x.shape) >>> y += 3.2 * np.exp(-0.5 * (x - 5.6) ** 2 / 4.8 ** 2) - >>> spectrum = Spectrum1D(flux=y * u.Jy, spectral_axis=x * u.um) + >>> spectrum = Spectrum(flux=y * u.Jy, spectral_axis=x * u.um) >>> region = [(1 * u.um, 5 * u.um), (7 * u.um, 10 * u.um)] >>> with warnings.catch_warnings(): # Ignore warnings ... warnings.simplefilter('ignore') diff --git a/docs/identify.rst b/docs/identify.rst index 2a4249d24..d6ae04915 100644 --- a/docs/identify.rst +++ b/docs/identify.rst @@ -1,14 +1,14 @@ ============================== -Identifying Spectrum1D Formats +Identifying Spectrum Formats ============================== ``specutils`` provides a convenience function, `~specutils.io.registers.identify_spectrum_format`, which attempts to guess the -`~specutils.Spectrum1D` file format from the list of registered formats, and +`~specutils.Spectrum` file format from the list of registered formats, and essentially acts as a wrapper on `~astropy.io.registry.identify_format`. This function is useful for identifying a spectrum file format without reading the -whole file with the `~specutils.Spectrum1D.read` method. It uses the +whole file with the `~specutils.Spectrum.read` method. It uses the same identification method as ``read`` however, so it provides a convenience of access outside of calling ``read`` without any change in underlying functionality. It returns the best guess as to a valid format from the list of ``Formats`` @@ -21,7 +21,7 @@ For eample, to identify a SDSS MaNGA data cube file: >>> from astropy.utils.data import download_file >>> from specutils.io.registers import identify_spectrum_format >>> - >>> url = 'https://dr15.sdss.org/sas/dr15/manga/spectro/redux/v2_4_3/8485/stack/manga-8485-1901-LOGCUBE.fits.gz' + >>> url = 'https://dr17.sdss.org/sas/dr17/manga/spectro/redux/v3_1_1/8485/stack/manga-8485-1901-LOGCUBE.fits.gz' >>> dd = download_file(url) # doctest: +REMOTE_DATA >>> identify_spectrum_format(dd) # doctest: +REMOTE_DATA 'MaNGA cube' diff --git a/docs/index.rst b/docs/index.rst index 12f9f3cba..69ee4cfc0 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -27,14 +27,14 @@ guiding document for spectroscopic development in the Astropy Project. Changes in version 2 ==================== -Specutils version 2 implemented a major change in that `~specutils.Spectrum1D` +Specutils version 2 implemented a major change in that `~specutils.Spectrum` no longer forces the spectral axis to be last for multi-dimensional data. This was motivated by the desire for greater flexibility to allow for interoperability with other packages that may wish to use ``specutils`` classes as the basis for their own, and by the desire for consistency with the axis order that results from a simple ``astropy.io.fits.read`` of a file. The legacy behavior can be replicated by setting ``move_spectral_axis='last'`` when creating a new -`~specutils.Spectrum1D` object. +`~specutils.Spectrum` object. For a summary of other changes in version 2, please see the `release notes `_. @@ -69,12 +69,12 @@ may have downloaded from some archive, or reduced from your own observations. ... specdata = f[1].data # doctest: +REMOTE_DATA Then we re-format this dataset into astropy quantities, and create a - `~specutils.Spectrum1D` object: + `~specutils.Spectrum` object: - >>> from specutils import Spectrum1D + >>> from specutils import Spectrum >>> lamb = 10**specdata['loglam'] * u.AA # doctest: +REMOTE_DATA >>> flux = specdata['flux'] * 10**-17 * u.Unit('erg cm-2 s-1 AA-1') # doctest: +REMOTE_DATA - >>> spec = Spectrum1D(spectral_axis=lamb, flux=flux) # doctest: +REMOTE_DATA + >>> spec = Spectrum(spectral_axis=lamb, flux=flux) # doctest: +REMOTE_DATA And we plot it: @@ -126,7 +126,7 @@ For more details on usage of specutils, see the sections listed below. installation types_of_spectra - spectrum1d + spectrum spectrum_collection spectral_cube spectral_regions diff --git a/docs/manipulation.rst b/docs/manipulation.rst index f82bac80a..22332e798 100644 --- a/docs/manipulation.rst +++ b/docs/manipulation.rst @@ -24,7 +24,7 @@ Smoothing Specutils provides smoothing for spectra in two forms: 1) convolution based using smoothing `astropy.convolution` and 2) median filtering using the :func:`scipy.signal.medfilt`. Each of these act on the flux -of the :class:`~specutils.Spectrum1D` object. +of the :class:`~specutils.Spectrum` object. .. note:: Specutils smoothing kernel widths and standard deviations are in units of pixels and not ``Quantity``. @@ -48,18 +48,18 @@ along the spectral dimension. .. code-block:: python - >>> from specutils import Spectrum1D + >>> from specutils import Spectrum >>> import astropy.units as u >>> import numpy as np >>> from specutils.manipulation import box_smooth, gaussian_smooth, trapezoid_smooth - >>> spec1 = Spectrum1D(spectral_axis=np.arange(1, 50) * u.nm, + >>> spec1 = Spectrum(spectral_axis=np.arange(1, 50) * u.nm, ... flux=np.random.default_rng(12345).random(49)*u.Jy) >>> spec1_bsmooth = box_smooth(spec1, width=3) >>> spec1_gsmooth = gaussian_smooth(spec1, stddev=3) >>> spec1_tsmooth = trapezoid_smooth(spec1, width=3) >>> gaussian_smooth(spec1, stddev=3) # doctest: +FLOAT_CMP - (length=49))> + (length=49))> Each of the specific smoothing methods create the appropriate `astropy.convolution.convolve` kernel and then call a helper function :func:`~specutils.manipulation.convolution_smooth` @@ -72,10 +72,10 @@ that takes the spectrum and an astropy 1D kernel. So, one could also do: >>> box1d_kernel = Box1DKernel(width=3) - >>> spec1 = Spectrum1D(spectral_axis=np.arange(1, 50) * u.nm, + >>> spec1 = Spectrum(spectral_axis=np.arange(1, 50) * u.nm, ... flux=np.random.default_rng(12345).random(49) * u.Jy) >>> convolution_smooth(spec1, box1d_kernel) # doctest: +FLOAT_CMP - (length=49))> + (length=49))> In this case, the ``spec1_bsmooth2`` result should be equivalent to the ``spec1_bsmooth`` in the section above (assuming the flux data of the input ``spec`` is the same). Note that, @@ -104,29 +104,29 @@ method applys the median filter across the flux. >>> from specutils.manipulation import median_smooth - >>> spec1 = Spectrum1D(spectral_axis=np.arange(1, 50) * u.nm, + >>> spec1 = Spectrum(spectral_axis=np.arange(1, 50) * u.nm, ... flux=np.random.default_rng(12345).random(49) * u.Jy) >>> median_smooth(spec1, width=3) # doctest: +FLOAT_CMP - (length=49))> + (length=49))> Resampling ---------- :ref:`specutils ` contains several classes for resampling the flux -in a :class:`~specutils.Spectrum1D` object. Currently supported methods of +in a :class:`~specutils.Spectrum` object. Currently supported methods of resampling are integrated flux conserving with :class:`~specutils.manipulation.FluxConservingResampler`, linear interpolation with :class:`~specutils.manipulation.LinearInterpolatedResampler`, and cubic spline with :class:`~specutils.manipulation.SplineInterpolatedResampler`. -Each of these classes takes in a :class:`~specutils.Spectrum1D` and a user -defined output dispersion grid, and returns a new :class:`~specutils.Spectrum1D` +Each of these classes takes in a :class:`~specutils.Spectrum` and a user +defined output dispersion grid, and returns a new :class:`~specutils.Spectrum` with the resampled flux. Currently the resampling classes expect the new dispersion grid unit to be the same as the input spectrum's dispersion grid unit. Additionally, all resamplers take an optional ``extrapolation_treatment`` keyword which can be ``nan_fill``, ``zero_fill``, or ``truncate``, to determine what to do with output wavelength bins that have no overlap with the original spectrum. -If the input :class:`~specutils.Spectrum1D` contains an uncertainty, +If the input :class:`~specutils.Spectrum` contains an uncertainty, :class:`~specutils.manipulation.FluxConservingResampler` will propogate the -uncertainty to the final output :class:`~specutils.Spectrum1D`. However, the +uncertainty to the final output :class:`~specutils.Spectrum`. However, the other two implemented resampling classes (:class:`~specutils.manipulation.LinearInterpolatedResampler` and :class:`~specutils.manipulation.SplineInterpolatedResampler`) will ignore any input uncertainty. @@ -153,12 +153,12 @@ Here's a set of simple examples showing each of the three types of resampling: ... specdata = f[1].data[1020:1250] # doctest: +REMOTE_DATA Then we re-format this dataset into astropy quantities, and create a - `~specutils.Spectrum1D` object: + `~specutils.Spectrum` object: - >>> from specutils import Spectrum1D + >>> from specutils import Spectrum >>> lamb = 10**specdata['loglam'] * u.AA # doctest: +REMOTE_DATA >>> flux = specdata['flux'] * 10**-17 * u.Unit('erg cm-2 s-1 AA-1') # doctest: +REMOTE_DATA - >>> input_spec = Spectrum1D(spectral_axis=lamb, flux=flux) # doctest: +REMOTE_DATA + >>> input_spec = Spectrum(spectral_axis=lamb, flux=flux) # doctest: +REMOTE_DATA >>> f, ax = plt.subplots() # doctest: +IGNORE_OUTPUT +REMOTE_DATA >>> ax.step(input_spec.spectral_axis, input_spec.flux) # doctest: +IGNORE_OUTPUT +REMOTE_DATA @@ -216,8 +216,8 @@ single spectrum. This can be achieved as follows: :align: center :context: close-figs - >>> spec1 = Spectrum1D(spectral_axis=np.arange(1, 50) * u.micron, flux=np.random.randn(49)*u.Jy) - >>> spec2 = Spectrum1D(spectral_axis=np.arange(51, 100) * u.micron, flux=(np.random.randn(49)+1)*u.Jy) + >>> spec1 = Spectrum(spectral_axis=np.arange(1, 50) * u.micron, flux=np.random.randn(49)*u.Jy) + >>> spec2 = Spectrum(spectral_axis=np.arange(51, 100) * u.micron, flux=(np.random.randn(49)+1)*u.Jy) >>> new_spectral_axis = np.concatenate([spec1.spectral_axis.value, spec2.spectral_axis.to_value(spec1.spectral_axis.unit)]) * spec1.spectral_axis.unit @@ -257,7 +257,7 @@ known uncertainty: >>> spectral_model = models.Gaussian1D(amplitude=3*u.Jy, mean=5*u.GHz, stddev=0.8*u.GHz) >>> flux = spectral_model(spectral_axis) >>> flux += np.random.default_rng(42).normal(0., 0.2, spectral_axis.shape) * u.Jy - >>> noisy_gaussian = Spectrum1D(spectral_axis=spectral_axis, flux=flux) + >>> noisy_gaussian = Spectrum(spectral_axis=spectral_axis, flux=flux) Now we estimate the uncertainty from the region that does *not* contain the line: @@ -289,7 +289,7 @@ S/N Threshold Mask It is useful to be able to find all the spaxels in an ND spectrum in which the signal to noise ratio is greater than some threshold. -This method implements this functionality so that a `~specutils.Spectrum1D` +This method implements this functionality so that a `~specutils.Spectrum` object, `~specutils.SpectrumCollection` or an :class:`~astropy.nddata.NDData` derived object may be passed in as the first parameter. The second parameter is a floating point threshold. @@ -302,13 +302,13 @@ then call the ``snr_threshold`` method: >>> import numpy as np >>> from astropy.nddata import StdDevUncertainty >>> import astropy.units as u - >>> from specutils import Spectrum1D + >>> from specutils import Spectrum >>> from specutils.manipulation import snr_threshold >>> wavelengths = np.arange(0, 10)*u.um >>> rng = np.random.default_rng(42) >>> flux = 100*np.abs(rng.standard_normal(10))*u.Jy >>> uncertainty = StdDevUncertainty(np.abs(rng.standard_normal(10))*u.Jy) - >>> spectrum = Spectrum1D(spectral_axis=wavelengths, flux=flux, uncertainty=uncertainty) + >>> spectrum = Spectrum(spectral_axis=wavelengths, flux=flux, uncertainty=uncertainty) >>> spectrum_masked = snr_threshold(spectrum, 50) >>> # To create a masked flux array >>> flux_masked = spectrum_masked.flux @@ -331,19 +331,19 @@ the ``spectral_axis``. Therefore one can use a construct like this: .. code-block:: python - >>> from specutils import Spectrum1D + >>> from specutils import Spectrum >>> wavelengths = np.arange(0, 10) * u.um >>> flux = 100 * np.abs(np.random.default_rng(42).standard_normal(10)) * u.Jy - >>> spectrum = Spectrum1D(spectral_axis=wavelengths, flux=flux) + >>> spectrum = Spectrum(spectral_axis=wavelengths, flux=flux) >>> spectrum # doctest: +FLOAT_CMP - (shape=(10,), mean=76.02860 Jy); spectral_axis= (length=10))> >>> shift = 12300 * u.AA - >>> new_spec = Spectrum1D(spectral_axis=spectrum.spectral_axis + shift, flux=spectrum.flux) + >>> new_spec = Spectrum(spectral_axis=spectrum.spectral_axis + shift, flux=spectrum.flux) >>> new_spec # doctest: +FLOAT_CMP - (shape=(10,), mean=76.02860 Jy); spectral_axis= (length=10))> @@ -363,11 +363,11 @@ with the spline knots: >>> from specutils.manipulation.model_replace import model_replace >>> wave_val = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) >>> flux_val = np.array([2, 4, 6, 8, 10, 12, 14, 16, 18, 20]) - >>> input_spectrum = Spectrum1D(spectral_axis=wave_val * u.AA, flux=flux_val * u.mJy) + >>> input_spectrum = Spectrum(spectral_axis=wave_val * u.AA, flux=flux_val * u.mJy) >>> spline_knots = [3.5, 4.7, 6.8, 7.1] * u.AA >>> result = model_replace(input_spectrum, None, model=spline_knots) >>> result - (shape=(10,), mean=11.00000 mJy); spectral_axis= (length=10))> + (shape=(10,), mean=11.00000 mJy); spectral_axis= (length=10))> The default behavior is to keep the data outside the replaced region unchanged. Alternatively, the spectrum outside the replaced region can be filled with zeros: @@ -377,7 +377,7 @@ Alternatively, the spectrum outside the replaced region can be filled with zeros >>> spline_knots = [3.5, 4.7, 6.8, 7.1] * u.AA >>> result = model_replace(input_spectrum, None, model=spline_knots, extrapolation_treatment='zero_fill') >>> result - (shape=(10,), mean=4.40000 mJy); spectral_axis= (length=10))> + (shape=(10,), mean=4.40000 mJy); spectral_axis= (length=10))> One can define the spline knots by providing an instance of `~specutils.SpectralRegion`, and the number of knots to be evenly spread along the region: @@ -388,7 +388,7 @@ and the number of knots to be evenly spread along the region: >>> region = SpectralRegion(3.5*u.AA, 7.1*u.AA) >>> result = model_replace(input_spectrum, region, model=4) >>> result - (shape=(10,), mean=11.00000 mJy); spectral_axis= (length=10))> + (shape=(10,), mean=11.00000 mJy); spectral_axis= (length=10))> A model fitted over the region can also be used to replace the spectrum flux values: @@ -397,13 +397,13 @@ A model fitted over the region can also be used to replace the spectrum flux val >>> from astropy.modeling import models >>> from specutils.fitting import fit_lines >>> flux_val = np.array([1, 1.1, 0.9, 4., 10., 5., 2., 1., 1.2, 1.1]) - >>> input_spectrum = Spectrum1D(spectral_axis=wave_val * u.AA, flux=flux_val * u.mJy) + >>> input_spectrum = Spectrum(spectral_axis=wave_val * u.AA, flux=flux_val * u.mJy) >>> model = models.Gaussian1D(10, 5.6, 1.2) >>> fitted_model = fit_lines(input_spectrum, model) >>> region = SpectralRegion(3.5*u.AA, 7.1*u.AA) >>> result = model_replace(input_spectrum, region, model=fitted_model) >>> result # doctest: +FLOAT_CMP - (shape=(10,), mean=2.67887 mJy); spectral_axis= (length=10))> Reference/API diff --git a/docs/nitpick-exceptions b/docs/nitpick-exceptions index c99b5811a..88f13a00a 100644 --- a/docs/nitpick-exceptions +++ b/docs/nitpick-exceptions @@ -14,7 +14,7 @@ py:obj SpectralCoord py:obj SpectralQuantity py:obj SkyCoord -# Super class for Spectrum1D for which we don't control the API links. +# Super class for Spectrum for which we don't control the API links. py:class ndcube.mixins.ndslicing.NDCubeSlicingMixin py:class ndcube.ndcube.NDCube py:class ndcube.ndcube.NDCubeABC diff --git a/docs/spectral_cube.rst b/docs/spectral_cube.rst index 6b548bb01..ddb17d086 100644 --- a/docs/spectral_cube.rst +++ b/docs/spectral_cube.rst @@ -2,13 +2,13 @@ Working with Spectral Cubes ########################### -Spectral cubes can be read directly with :class:`~specutils.Spectrum1D`. +Spectral cubes can be read directly with :class:`~specutils.Spectrum`. A specific example of this is demonstrated here. In addition to the functions demonstrated below, as a subclass of `NDCube `_, -:class:`~specutils.Spectrum1D` also inherits useful methods for e.g. cropping +:class:`~specutils.Spectrum` also inherits useful methods for e.g. cropping based on combinations of world and spectral coordinates. Most of the functionality inherited from `~ndcube.NDCube` requires initializing the -``Spectrum1D`` object with a WCS describing the coordinates for all axes of +``Spectrum`` object with a WCS describing the coordinates for all axes of the data. Note that the workflow described here is for spectral cubes that are rectified @@ -25,15 +25,15 @@ Loading a cube ============== We'll use a ``MaNGA cube`` for our example, and load the data from the -repository directly into a new ``Spectrum1D`` object: +repository directly into a new ``Spectrum`` object: .. code-block:: python >>> from astropy.utils.data import download_file - >>> from specutils.spectra import Spectrum1D + >>> from specutils.spectra import Spectrum >>> filename = "https://stsci.box.com/shared/static/28a88k1qfipo4yxc4p4d40v4axtlal8y.fits" >>> file = download_file(filename, cache=True) # doctest: +REMOTE_DATA - >>> sc = Spectrum1D.read(file, format='MaNGA cube') # doctest: +REMOTE_DATA + >>> sc = Spectrum.read(file, format='MaNGA cube') # doctest: +REMOTE_DATA The cube has 74x74 spaxels with 4563 spectral axis points in each one: @@ -48,8 +48,8 @@ Print the contents of 3 spectral axis points in a 3x3 spaxel array: .. code-block:: python - >>> sc[30:33,30:33,2000:2003] # doctest: +REMOTE_DATA - >> sc[2000:2003, 30:33, 30:33] # doctest: +REMOTE_DATA + >> from specutils.manipulation import spectral_slab >>> ss = spectral_slab(sc, 5000.*u.AA, 5003.*u.AA) # doctest: +REMOTE_DATA >>> ss.shape # doctest: +REMOTE_DATA - (74, 74, 3) - >>> ss[30:33,30:33,::] # doctest: +REMOTE_DATA - >> ss[::, 30:33,30:33] # doctest: +REMOTE_DATA + >> from astropy import units as u >>> import numpy as np - >>> from specutils import Spectrum1D, SpectralRegion + >>> from specutils import Spectrum, SpectralRegion >>> from specutils.manipulation import extract_region >>> region = SpectralRegion(8*u.nm, 22*u.nm) - >>> spectrum = Spectrum1D(spectral_axis=np.arange(1, 50) * u.nm, flux=np.random.sample(49)*u.Jy) + >>> spectrum = Spectrum(spectral_axis=np.arange(1, 50) * u.nm, flux=np.random.sample(49)*u.Jy) >>> sub_spectrum = extract_region(spectrum, region) >>> sub_spectrum.spectral_axis >> from astropy import units as u >>> import numpy as np - >>> from specutils import Spectrum1D, SpectralRegion + >>> from specutils import Spectrum, SpectralRegion >>> from specutils.manipulation import extract_region - >>> spectrum = Spectrum1D(spectral_axis=np.arange(1, 50) * u.nm, flux=np.random.sample(49)*u.Jy) + >>> spectrum = Spectrum(spectral_axis=np.arange(1, 50) * u.nm, flux=np.random.sample(49)*u.Jy) >>> region_angstroms = SpectralRegion(80*u.AA, 220*u.AA) >>> sub_spectrum = extract_region(spectrum, region_angstroms) >>> sub_spectrum.spectral_axis @@ -199,11 +199,11 @@ An example of a multiple sub-region `~specutils.SpectralRegion`: >>> from astropy import units as u >>> import numpy as np - >>> from specutils import Spectrum1D, SpectralRegion + >>> from specutils import Spectrum, SpectralRegion >>> from specutils.manipulation import extract_region >>> region = SpectralRegion([(8*u.nm, 22*u.nm), (34*u.nm, 40*u.nm)]) - >>> spectrum = Spectrum1D(spectral_axis=np.arange(1, 50) * u.nm, flux=np.random.sample(49)*u.Jy) + >>> spectrum = Spectrum(spectral_axis=np.arange(1, 50) * u.nm, flux=np.random.sample(49)*u.Jy) >>> sub_spectra = extract_region(spectrum, region) >>> sub_spectra[0].spectral_axis >> from astropy import units as u >>> import numpy as np - >>> from specutils import Spectrum1D, SpectralRegion + >>> from specutils import Spectrum, SpectralRegion >>> from specutils.manipulation import extract_bounding_spectral_region - >>> spectrum = Spectrum1D(spectral_axis=np.arange(1, 50) * u.nm, + >>> spectrum = Spectrum(spectral_axis=np.arange(1, 50) * u.nm, ... flux=np.random.default_rng(12345).random(49)*u.Jy) >>> region = SpectralRegion([(8*u.nm, 12*u.nm), (24*u.nm, 30*u.nm)]) >>> sub_spectrum = extract_bounding_spectral_region(spectrum, region) @@ -250,10 +250,10 @@ into ``specutils``: >>> from astropy import units as u >>> import numpy as np - >>> from specutils import Spectrum1D, SpectralRegion + >>> from specutils import Spectrum, SpectralRegion >>> from specutils.manipulation import spectral_slab - >>> spectrum = Spectrum1D(spectral_axis=np.arange(1, 50) * u.nm, + >>> spectrum = Spectrum(spectral_axis=np.arange(1, 50) * u.nm, ... flux=np.random.default_rng(12345).random(49)*u.Jy) >>> sub_spectrum = spectral_slab(spectrum, 8*u.nm, 20*u.nm) >>> sub_spectrum.spectral_axis @@ -270,7 +270,7 @@ finding functions: >>> from astropy import units as u >>> import numpy as np - >>> from specutils import Spectrum1D, SpectralRegion + >>> from specutils import Spectrum, SpectralRegion >>> from astropy.modeling.models import Gaussian1D >>> from specutils.fitting import find_lines_derivative @@ -280,7 +280,7 @@ finding functions: >>> x = np.linspace(0, 10, 200) >>> y = g1(x) + g2(x) + g3(x) - >>> spectrum = Spectrum1D(flux=y * u.Jy, spectral_axis=x * u.um) + >>> spectrum = Spectrum(flux=y * u.Jy, spectral_axis=x * u.um) >>> lines = find_lines_derivative(spectrum, flux_threshold=0.01) >>> spec_reg = SpectralRegion.from_line_list(lines) @@ -315,6 +315,6 @@ Reference/API :no-inheritance-diagram: :skip: test - :skip: Spectrum1D + :skip: Spectrum :skip: SpectrumCollection :skip: SpectralAxis diff --git a/docs/spectrum1d.rst b/docs/spectrum.rst similarity index 75% rename from docs/spectrum1d.rst rename to docs/spectrum.rst index c3bb8dcc2..167362dae 100644 --- a/docs/spectrum1d.rst +++ b/docs/spectrum.rst @@ -1,16 +1,16 @@ -======================== -Working with Spectrum1Ds -======================== +============================= +Working with Spectrum objects +============================= As described in more detail in :doc:`types_of_spectra`, the core data class in -specutils for a single spectrum is `~specutils.Spectrum1D`. This object +specutils for a single spectrum is `~specutils.Spectrum`. This object can represent either one or many spectra, all with the same ``spectral_axis``. This section describes some of the basic features of this class. Basic Spectrum Creation ----------------------- -The simplest way to create a `~specutils.Spectrum1D` is to +The simplest way to create a `~specutils.Spectrum` is to create it explicitly from arrays or `~astropy.units.Quantity` objects: .. plot:: @@ -20,10 +20,10 @@ create it explicitly from arrays or `~astropy.units.Quantity` objects: >>> import numpy as np >>> import astropy.units as u >>> import matplotlib.pyplot as plt - >>> from specutils import Spectrum1D + >>> from specutils import Spectrum >>> 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) >>> ax = plt.subplots()[1] # doctest: +SKIP >>> ax.plot(spec1d.spectral_axis, spec1d.flux) # doctest: +SKIP >>> ax.set_xlabel("Dispersion") # doctest: +SKIP @@ -48,8 +48,8 @@ encouraged to :doc:`create their own loader `. .. code-block:: python - >>> from specutils import Spectrum1D - >>> spec1d = Spectrum1D.read("/path/to/file.fits") # doctest: +SKIP + >>> from specutils import Spectrum + >>> spec1d = Spectrum.read("/path/to/file.fits") # doctest: +SKIP Most of the built-in specutils default loaders can also read an existing `astropy.io.fits.HDUList` object or an open file object (as resulting @@ -60,11 +60,11 @@ a loader. .. code-block:: python - >>> from specutils import Spectrum1D + >>> from specutils import Spectrum >>> import urllib >>> specs = urllib.request.urlopen('https://data.sdss.org/sas/dr14/sdss/spectro/redux/26/spectra/0751/spec-0751-52251-0160.fits') # doctest: +REMOTE_DATA - >>> Spectrum1D.read(specs, format="SDSS-III/IV spec") # doctest: +REMOTE_DATA - (length=3841); uncertainty=InverseVariance)> + >>> Spectrum.read(specs, format="SDSS-III/IV spec") # doctest: +REMOTE_DATA + (length=3841); uncertainty=InverseVariance)> Note that the same spectrum could be more conveniently downloaded via astroquery, if the user has that package installed: @@ -73,14 +73,14 @@ astroquery, if the user has that package installed: >>> from astroquery.sdss import SDSS # doctest: +REMOTE_DATA >>> specs = SDSS.get_spectra(plate=751, mjd=52251, fiberID=160, data_release=14) # doctest: +REMOTE_DATA - >>> Spectrum1D.read(specs[0], format="SDSS-III/IV spec") # doctest: +REMOTE_DATA - (length=3841); uncertainty=InverseVariance)> + >>> Spectrum.read(specs[0], format="SDSS-III/IV spec") # doctest: +REMOTE_DATA + (length=3841); uncertainty=InverseVariance)> List of Loaders ~~~~~~~~~~~~~~~ -The `~specutils.Spectrum1D` class has built-in support for various input and output formats. +The `~specutils.Spectrum` class has built-in support for various input and output formats. A full list of the supported formats is shown in the table below. Note that the JWST readers require the ``stdatamodels`` package to be installed, which is an optional dependency for ``specutils``. @@ -92,8 +92,8 @@ require the ``stdatamodels`` package to be installed, which is an optional depen Writing to a File ----------------- -Similarly, a `~specutils.Spectrum1D` object can be saved to any of the supported formats using the -:meth:`specutils.Spectrum1D.write` method. +Similarly, a `~specutils.Spectrum` object can be saved to any of the supported formats using the +:meth:`specutils.Spectrum.write` method. .. code-block:: python @@ -104,8 +104,8 @@ Similarly, a `~specutils.Spectrum1D` object can be saved to any of the supported Including Uncertainties ----------------------- -The :class:`~specutils.Spectrum1D` class supports uncertainties, and -arithmetic operations performed with :class:`~specutils.Spectrum1D` +The :class:`~specutils.Spectrum` class supports uncertainties, and +arithmetic operations performed with :class:`~specutils.Spectrum` objects will propagate uncertainties. Uncertainties are a special subclass of :class:`~astropy.nddata.NDData`, and their @@ -114,10 +114,10 @@ specify the uncertainty type at creation time. .. code-block:: python - >>> from specutils import Spectrum1D + >>> from specutils import Spectrum >>> from astropy.nddata import StdDevUncertainty - >>> spec = Spectrum1D(spectral_axis=np.arange(5000, 5010)*u.AA, flux=np.random.sample(10)*u.Jy, uncertainty=StdDevUncertainty(np.random.sample(10) * 0.1)) + >>> spec = Spectrum(spectral_axis=np.arange(5000, 5010)*u.AA, flux=np.random.sample(10)*u.Jy, uncertainty=StdDevUncertainty(np.random.sample(10) * 0.1)) .. warning:: Not defining an uncertainty class will result in an :class:`~astropy.nddata.UnknownUncertainty` object which will not @@ -127,7 +127,7 @@ specify the uncertainty type at creation time. Including Masks --------------- -Masks are also available for :class:`~specutils.Spectrum1D`, following the +Masks are also available for :class:`~specutils.Spectrum`, following the same mechanisms as :class:`~astropy.nddata.NDData`. That is, the mask should have the property that it is ``False``/``0`` wherever the data is *good*, and ``True``/anything else where it should be masked. This allows "data quality" @@ -139,7 +139,7 @@ values are frequently "infectious", in that arithmetic operations sometimes propagate to yield results as just ``NaN`` where the intent is instead to skip that particular pixel. It also makes it impossible to store data that in the spectrum that may have meaning but should *sometimes* be masked. The separate -``mask`` attribute in :class:`~specutils.Spectrum1D` addresses that in that the +``mask`` attribute in :class:`~specutils.Spectrum` addresses that in that the spectrum may still have a value underneath the mask, but it is not used in most calculations. To allow for compatibility with ``NaN``-masking representations, however, specutils will recognize ``flux`` values input as ``NaN`` and set the @@ -149,24 +149,24 @@ mask to ``True`` for those values unless explicitly overridden. Including Redshift or Radial Velocity ------------------------------------- -The :class:`~specutils.Spectrum1D` class supports setting a redshift or radial +The :class:`~specutils.Spectrum` class supports setting a redshift or radial velocity upon initialization of the object, as well as updating these values. The default value for redshift and radial velocity is zero - to create a -:class:`~specutils.Spectrum1D` with a non-zero value, simply set the appropriate +:class:`~specutils.Spectrum` with a non-zero value, simply set the appropriate attribute on object creation: .. code-block:: python - >>> spec1 = Spectrum1D(spectral_axis=np.arange(5000, 5010)*u.AA, flux=np.random.sample(10)*u.Jy, redshift = 0.15) - >>> spec2 = Spectrum1D(spectral_axis=np.arange(5000, 5010)*u.AA, flux=np.random.sample(10)*u.Jy, radial_velocity = 1000*u.Unit("km/s")) + >>> spec1 = Spectrum(spectral_axis=np.arange(5000, 5010)*u.AA, flux=np.random.sample(10)*u.Jy, redshift = 0.15) + >>> spec2 = Spectrum(spectral_axis=np.arange(5000, 5010)*u.AA, flux=np.random.sample(10)*u.Jy, radial_velocity = 1000*u.Unit("km/s")) By default, updating either the ``redshift`` or ``radial_velocity`` attributes -of an existing :class:`~specutils.Spectrum1D` directly uses the -:meth:`specutils.Spectrum1D.shift_spectrum_to` method, which also updates the +of an existing :class:`~specutils.Spectrum` directly uses the +:meth:`specutils.Spectrum.shift_spectrum_to` method, which also updates the values of the ``spectral_axis`` to match the new frame. To leave the ``spectral_axis`` values unchanged while updating the ``redshift`` or -``radial_velocity`` value, use the :meth:`specutils.Spectrum1D.set_redshift_to` -or :meth:`specutils.Spectrum1D.set_radial_velocity_to` method as appropriate. +``radial_velocity`` value, use the :meth:`specutils.Spectrum.set_redshift_to` +or :meth:`specutils.Spectrum.set_radial_velocity_to` method as appropriate. An example of the different treatments of the ``spectral_axis`` is shown below. .. code-block:: python @@ -188,7 +188,7 @@ An example of the different treatments of the ``spectral_axis`` is shown below. redshift=0.016819635148755285) [5000., 5001., 5002., 5003., 5004., 5005., 5006., 5007., 5008., 5009.] Angstrom> -.. _spectrum1d-defining-wcs: +.. _spectrum-defining-wcs: Defining WCS ------------ @@ -196,7 +196,7 @@ Defining WCS Specutils always maintains a WCS object whether it is passed explicitly by the user, or is created dynamically by specutils itself. In the latter case, the user need not be aware that the WCS object is being used, and can interact -with the :class:`~specutils.Spectrum1D` object as if it were only a simple +with the :class:`~specutils.Spectrum` object as if it were only a simple data container. Currently, specutils understands two WCS formats: FITS WCS and GWCS. When a user @@ -212,14 +212,14 @@ Providing a FITS-style WCS .. code-block:: python - >>> from specutils.spectra import Spectrum1D + >>> from specutils.spectra import Spectrum >>> import astropy.wcs as fitswcs >>> import astropy.units as u >>> import numpy as np >>> my_wcs = fitswcs.WCS(header={ ... 'CDELT1': 1, 'CRVAL1': 6562.8, 'CUNIT1': 'Angstrom', 'CTYPE1': 'WAVE', ... 'RESTFRQ': 1400000000, 'CRPIX1': 25}) - >>> spec = Spectrum1D(flux=[5,6,7] * u.Jy, wcs=my_wcs) + >>> spec = Spectrum(flux=[5,6,7] * u.Jy, wcs=my_wcs) >>> spec.spectral_axis # doctest: +FLOAT_CMP >> spec.wcs.pixel_to_world(np.arange(3)) # doctest: +FLOAT_CMP -When creating a `~specutils.Spectrum1D` using a WCS, you can also use the +When creating a `~specutils.Spectrum` using a WCS, you can also use the ``move_spectral_axis`` argument to force the spectral axis to a certain dimension of a multi-dimenasional flux array. Prior to ``specutils`` version 2.0, the flux array was always reordered such that the spectral axis corresponded to the last @@ -244,7 +244,7 @@ the spatial axes (most often RA and Dec) in any particular order. Multi-dimensional Data Sets --------------------------- -`~specutils.Spectrum1D` also supports the multidimensional case where you +`~specutils.Spectrum` also supports the multidimensional case where you have, for example, an ``(n_spectra, n_pix)`` shaped data set where each ``n_spectra`` element provides a different flux data array. ``flux`` and ``uncertainty`` may be multidimensional as @@ -256,7 +256,7 @@ common spectral axis. In cases where the flux axis corresponding to the spectral axis cannot be determined automatically (for example, if multiple flux axes have the same length as the spectral axis), the spectral axis must be specified with the ``spectral_axis_index`` argument when initializing the -`~specutils.Spectrum1D`. +`~specutils.Spectrum`. .. note:: The case where each flux data array is related to a *different* spectral axis is encapsulated in the :class:`~specutils.SpectrumCollection` @@ -264,9 +264,9 @@ with the ``spectral_axis_index`` argument when initializing the .. code-block:: python - >>> from specutils import Spectrum1D + >>> from specutils import Spectrum - >>> spec = Spectrum1D(spectral_axis=np.arange(5000, 5010)*u.AA, + >>> spec = Spectrum(spectral_axis=np.arange(5000, 5010)*u.AA, ... flux=np.random.default_rng(12345).random((5, 10))*u.Jy) >>> spec_slice = spec[0] >>> spec_slice.spectral_axis @@ -276,21 +276,21 @@ with the ``spectral_axis_index`` argument when initializing the 0.33281393, 0.59830875, 0.18673419, 0.67275604, 0.94180287] Jy> While the above example only shows two dimensions, this concept generalizes to -any number of dimensions for `~specutils.Spectrum1D`. +any number of dimensions for `~specutils.Spectrum`. Slicing ------- -As seen above, `~specutils.Spectrum1D` supports slicing in the same way as any -other array-like object. Additionally, a `~specutils.Spectrum1D` can be sliced +As seen above, `~specutils.Spectrum` supports slicing in the same way as any +other array-like object. Additionally, a `~specutils.Spectrum` can be sliced along the spectral axis using world coordinates. .. code-block:: python - >>> from specutils import Spectrum1D + >>> from specutils import Spectrum - >>> spec = Spectrum1D(spectral_axis=np.arange(5000, 5010)*u.AA, + >>> spec = Spectrum(spectral_axis=np.arange(5000, 5010)*u.AA, ... flux=np.random.default_rng(12345).random((5, 10))*u.Jy) >>> spec_slice = spec[5002*u.AA:5006*u.AA] >>> spec_slice.spectral_axis @@ -301,17 +301,17 @@ same time as slicing the spectral axis based on spectral values. .. code-block:: python - >>> from specutils import Spectrum1D + >>> from specutils import Spectrum - >>> spec = Spectrum1D(spectral_axis=np.arange(5000, 5010)*u.AA, + >>> spec = Spectrum(spectral_axis=np.arange(5000, 5010)*u.AA, ... flux=np.random.default_rng(12345).random((5, 10))*u.Jy) >>> spec_slice = spec[2:4, 5002*u.AA:5006*u.AA] >>> spec_slice.shape (2, 4) -If the `specutils.Spectrum1D` was created with a WCS that included spatial +If the `specutils.Spectrum` was created with a WCS that included spatial information, for example in case of a spectral cube with two spatial dimensions, -the `specutils.Spectrum1D.crop` method can be used to subset the data based on +the `specutils.Spectrum.crop` method can be used to subset the data based on the world coordinates. The inputs required are two sets up `astropy.coordinates` objects defining the upper and lower corner of the region desired. Note that if one of the coordinates is decreasing along an axis, the higher world coordinate @@ -334,11 +334,11 @@ value will apply to the lower bound input. ... 'DISPAXIS': 2, 'VELOSYS': -2538.02, ... 'SPECSYS': 'BARYCENT', 'RADESYS': 'ICRS', 'EQUINOX': 2000.0, ... 'LONPOLE': 180.0, 'LATPOLE': 27.004754}) - >>> spec = Spectrum1D(flux=np.random.default_rng(12345).random((20, 5, 10)) * u.Jy, wcs=w) # doctest: +IGNORE_WARNINGS + >>> spec = Spectrum(flux=np.random.default_rng(12345).random((20, 5, 10)) * u.Jy, wcs=w) # doctest: +IGNORE_WARNINGS >>> lower = [SkyCoord(ra=205, dec=26, unit=u.deg), SpectralCoord(4.9, unit=u.um)] >>> upper = [SkyCoord(ra=205.5, dec=27.5, unit=u.deg), SpectralCoord(4.9, unit=u.um)] >>> spec.crop(lower, upper) # doctest: +IGNORE_WARNINGS +FLOAT_CMP - >> spec = Spectrum1D(spectral_axis=np.arange(5000, 5010)*u.AA, + >>> spec = Spectrum(spectral_axis=np.arange(5000, 5010)*u.AA, ... flux=np.random.default_rng(12345).random((5, 10))*u.Jy) >>> spec.mean() # doctest: +FLOAT_CMP @@ -368,7 +368,7 @@ spectral axis, or 'spatial', which will collapse along all non-spectral axes. .. code-block:: python >>> spec.mean(axis='spatial') # doctest: +FLOAT_CMP - (shape=(10,), mean=0.49803 Jy); spectral_axis= (length=10))> Note that in this case, the result of the collapse operation is a -`~specutils.Spectrum1D` rather than an `astropy.units.Quantity`, because the +`~specutils.Spectrum` rather than an `astropy.units.Quantity`, because the collapse operation left the spectral axis intact. It is also possible to supply your own function for the collapse operation by -calling `~specutils.Spectrum1D.collapse()` and providing a callable function +calling `~specutils.Spectrum.collapse()` and providing a callable function to the ``method`` argument. .. code-block:: python diff --git a/docs/spectrum_collection.rst b/docs/spectrum_collection.rst index 52a736a8d..0b2b49899 100644 --- a/docs/spectrum_collection.rst +++ b/docs/spectrum_collection.rst @@ -45,20 +45,20 @@ Collections from 1D spectra --------------------------- It is also possible to create a :class:`~specutils.SpectrumCollection` from -a list of :class:`~specutils.Spectrum1D`: +a list of :class:`~specutils.Spectrum`: .. code:: python >>> import warnings >>> import numpy as np >>> from astropy import units as u - >>> from specutils import Spectrum1D, SpectrumCollection - >>> spec = Spectrum1D(spectral_axis=np.linspace(0, 50, 50) * u.AA, + >>> from specutils import Spectrum, SpectrumCollection + >>> spec = Spectrum(spectral_axis=np.linspace(0, 50, 50) * u.AA, ... flux=np.random.randn(50) * u.Jy, ... uncertainty=StdDevUncertainty(np.random.sample(50), unit='Jy')) >>> with warnings.catch_warnings(): # Ignore warnings ... warnings.simplefilter('ignore') - ... spec1 = Spectrum1D(spectral_axis=np.linspace(20, 60, 50) * u.AA, + ... spec1 = Spectrum(spectral_axis=np.linspace(20, 60, 50) * u.AA, ... flux=np.random.randn(50) * u.Jy, ... uncertainty=StdDevUncertainty(np.random.sample(50), unit='Jy')) ... spec_coll = SpectrumCollection.from_spectra([spec, spec1]) @@ -73,9 +73,9 @@ a list of :class:`~specutils.Spectrum1D`: Unit("Angstrom") :class:`~specutils.SpectrumCollection` objects can be treated just like -:class:`~specutils.Spectrum1D` objects; calling a particular attribute on the +:class:`~specutils.Spectrum` objects; calling a particular attribute on the object will return an array whose type depends on the type of the attribute in -the :class:`~specutils.Spectrum1D` object. +the :class:`~specutils.Spectrum` object. .. code:: python @@ -106,6 +106,6 @@ Reference/API :no-inheritance-diagram: :skip: test - :skip: Spectrum1D + :skip: Spectrum :skip: SpectralRegion :skip: SpectralAxis diff --git a/docs/types_of_spectra.rst b/docs/types_of_spectra.rst index ffa401bfd..cd32db282 100644 --- a/docs/types_of_spectra.rst +++ b/docs/types_of_spectra.rst @@ -25,20 +25,20 @@ with their corresponding ``specutils`` representations: tabulated as an array, or encoded in a WCS). This is what typically is in mind when one speaks of "a single spectrum", and therefore the analysis tools are general couched as applying to this case. In ``specutils`` this is - represented by the `~specutils.Spectrum1D` object with a 1-dimensional + represented by the `~specutils.Spectrum` object with a 1-dimensional ``flux``. 2. A set of fluxes that can be represented in an array-like form of shape ``n x m (x ...)``, with a spectral axis strictly of length ``n`` (and a matched WCS). In ``specutils`` this is represented by the - `~specutils.Spectrum1D` object where ``len(flux.shape) > 1`` . In this sense + `~specutils.Spectrum` object where ``len(flux.shape) > 1`` . In this sense the "1D" refers to the spectral axis, *not* the flux. Note that - `~specutils.Spectrum1D` subclasses `NDCube `_, + `~specutils.Spectrum` subclasses `NDCube `_, which provideds utilities useful for these sorts of multidimensional fluxes. 3. A set of fluxes of shape ``n x m (x ...)``, and a set of spectral axes that are the same shape. This is distinguished from the above cases because there are as many spectral axes as there are spectra. In this sense it is a collection of spectra, so can be thought of as a collection of - `~specutils.Spectrum1D` objects. But because it is often more performant to + `~specutils.Spectrum` objects. But because it is often more performant to store the collection together as just one set of flux and spectral axis arrays, this case is represented by a separate object in ``specutils``: `~specutils.SpectrumCollection`. @@ -48,14 +48,14 @@ with their corresponding ``specutils`` representations: performance benefit to be gained from using arrays (because the flux array is not rectangular), this case does not have a specific representation in ``specutils``. Instead, this case should be dealt with by making lists (or - numpy object-arrays) of `~specutils.Spectrum1D` objects, and iterating over + numpy object-arrays) of `~specutils.Spectrum` objects, and iterating over them. Specutils does provide a `SpectrumList` class which is a simple subclass of `list` that is integrated with the Astropy IO registry. It enables data loaders to read and return multiple heterogenous spectra (see :ref:`multiple_spectra`). Users should not need to use `SpectrumList` - directly since a `list` of `Spectrum1D` objects is sufficient for all other + directly since a `list` of `Spectrum` objects is sufficient for all other purposes. In all of these cases, the objects have additional attributes (e.g. @@ -64,7 +64,7 @@ under the assumption that the additional attributes have matched shape to either flux or spectral axis (or some combination of the two). As detailed above, these cases are represented in specutils via two classes: -`~specutils.Spectrum1D` (Cases 1 and 2, and indirecly 4) and +`~specutils.Spectrum` (Cases 1 and 2, and indirecly 4) and `~specutils.SpectrumCollection` (Case 3). A diagram of these data structures is proved below. diff --git a/specutils/analysis/correlation.py b/specutils/analysis/correlation.py index cc1e068c7..47ad60526 100644 --- a/specutils/analysis/correlation.py +++ b/specutils/analysis/correlation.py @@ -7,7 +7,7 @@ from scipy.signal import correlate from ..manipulation import LinearInterpolatedResampler -from .. import Spectrum1D +from .. import Spectrum __all__ = ['template_correlate', 'template_logwl_resample'] @@ -28,9 +28,9 @@ def template_correlate(observed_spectrum, template_spectrum, lag_units=_KMS, Parameters ---------- - observed_spectrum : :class:`~specutils.Spectrum1D` + observed_spectrum : :class:`~specutils.Spectrum` The observed spectrum. - template_spectrum : :class:`~specutils.Spectrum1D` + template_spectrum : :class:`~specutils.Spectrum` The template spectrum, which will be correlated with the observed spectrum. lag_units: `~astropy.units.Unit` @@ -149,9 +149,9 @@ def template_logwl_resample(spectrum, template, wblue=None, wred=None, Parameters ---------- - observed_spectrum : :class:`~specutils.Spectrum1D` + observed_spectrum : :class:`~specutils.Spectrum` The observed spectrum. - template_spectrum : :class:`~specutils.Spectrum1D` + template_spectrum : :class:`~specutils.Spectrum` The template spectrum. wblue, wred: float Wavelength limits to include in the correlation. @@ -164,9 +164,9 @@ def template_logwl_resample(spectrum, template, wblue=None, wred=None, Returns ------- - resampled_observed : :class:`~specutils.Spectrum1D` + resampled_observed : :class:`~specutils.Spectrum` The observed spectrum resampled to a common spectral_axis. - resampled_template: :class:`~specutils.Spectrum1D` + resampled_template: :class:`~specutils.Spectrum` The template spectrum resampled to a common spectral_axis. """ @@ -220,12 +220,12 @@ def template_logwl_resample(spectrum, template, wblue=None, wred=None, clean_spectrum_flux = np.nan_to_num(resampled_spectrum.flux.value) * resampled_spectrum.flux.unit clean_template_flux = np.nan_to_num(resampled_template.flux.value) * resampled_template.flux.unit - clean_spectrum = Spectrum1D(spectral_axis=resampled_spectrum.spectral_axis, + clean_spectrum = Spectrum(spectral_axis=resampled_spectrum.spectral_axis, flux=clean_spectrum_flux, uncertainty=resampled_spectrum.uncertainty, velocity_convention='optical', rest_value=spectrum.rest_value) - clean_template = Spectrum1D(spectral_axis=resampled_template.spectral_axis, + clean_template = Spectrum(spectral_axis=resampled_template.spectral_axis, flux=clean_template_flux, uncertainty=resampled_template.uncertainty, velocity_convention='optical', @@ -241,9 +241,9 @@ def _normalize(observed_spectrum, template_spectrum): Parameters ---------- - observed_spectrum : :class:`~specutils.Spectrum1D` + observed_spectrum : :class:`~specutils.Spectrum` The observed spectrum. - template_spectrum : :class:`~specutils.Spectrum1D` + template_spectrum : :class:`~specutils.Spectrum` The template spectrum, which needs to be normalized in order to be compared with the observed spectrum. diff --git a/specutils/analysis/flux.py b/specutils/analysis/flux.py index 1066bb906..6cb4cc5d0 100644 --- a/specutils/analysis/flux.py +++ b/specutils/analysis/flux.py @@ -9,7 +9,7 @@ from astropy.nddata import VarianceUncertainty from .. import conf -from ..spectra import Spectrum1D +from ..spectra import Spectrum from ..manipulation import extract_region, LinearInterpolatedResampler from .utils import computation_wrapper import astropy.units as u @@ -31,7 +31,7 @@ def line_flux(spectrum, regions=None, Parameters ---------- - spectrum : Spectrum1D + spectrum : Spectrum The spectrum object over which the summed flux will be calculated. regions : `~specutils.SpectralRegion` or list of `~specutils.SpectralRegion` @@ -69,7 +69,7 @@ def equivalent_width(spectrum, continuum=1, regions=None, Parameters ---------- - spectrum : Spectrum1D + spectrum : Spectrum The spectrum object overwhich the equivalent width will be calculated. regions: `~specutils.SpectralRegion` or list of `~specutils.SpectralRegion` @@ -119,7 +119,7 @@ def _compute_line_flux(spectrum, regions=None, # Account for the existence of a mask. if hasattr(calc_spectrum, 'mask') and calc_spectrum.mask is not None: mask = calc_spectrum.mask - new_spec = Spectrum1D(flux=calc_spectrum.flux[~mask], + new_spec = Spectrum(flux=calc_spectrum.flux[~mask], spectral_axis=calc_spectrum.spectral_axis[~mask]) if mask_interpolation is None: @@ -166,7 +166,7 @@ def _compute_equivalent_width(spectrum, continuum=1, regions=None, # Account for the existence of a mask. if hasattr(spectrum, 'mask') and spectrum.mask is not None: mask = spectrum.mask - spectrum = Spectrum1D( + spectrum = Spectrum( flux=spectrum.flux[~mask], spectral_axis=spectrum.spectral_axis[~mask]) @@ -179,7 +179,7 @@ def _compute_equivalent_width(spectrum, continuum=1, regions=None, if continuum.size == 1: continuum = continuum * np.ones(spectrum.flux.size) - cont_spec = Spectrum1D(flux=continuum, + cont_spec = Spectrum(flux=continuum, spectral_axis=spectrum.spectral_axis) cont_flux = _compute_line_flux(cont_spec, mask_interpolation=mask_interpolation) @@ -222,7 +222,7 @@ def is_continuum_below_threshold(spectrum, threshold=0.01): Parameters ---------- - spectrum : `~specutils.spectra.spectrum1d.Spectrum1D` + spectrum : `~specutils.spectra.spectrum.Spectrum` The spectrum object over which the width will be calculated. threshold: float or `~astropy.units.Quantity` diff --git a/specutils/analysis/location.py b/specutils/analysis/location.py index 4e2be7185..17c43f8f6 100644 --- a/specutils/analysis/location.py +++ b/specutils/analysis/location.py @@ -22,7 +22,7 @@ def centroid(spectrum, regions=None, region=None, analytic=True): Parameters ---------- - spectrum : `~specutils.spectra.spectrum1d.Spectrum1D` + spectrum : `~specutils.spectra.spectrum.Spectrum` The spectrum object over which the centroid will be calculated. If the uncertainty is populated, the returned quantity will include an uncertainty attribute with the propagated uncertainty (as Standard Deviation-style uncertainties). This uncertainty @@ -78,7 +78,7 @@ def _centroid_single_region(spectrum, region=None, analytic=True): Parameters ---------- - spectrum : `~specutils.spectra.spectrum1d.Spectrum1D` + spectrum : `~specutils.spectra.spectrum.Spectrum` The spectrum object overwhich the centroid will be calculated. region : `~specutils.SpectralRegion` diff --git a/specutils/analysis/moment.py b/specutils/analysis/moment.py index 2889af553..7baad4ba1 100644 --- a/specutils/analysis/moment.py +++ b/specutils/analysis/moment.py @@ -19,7 +19,7 @@ def moment(spectrum, regions=None, order=0, axis='spectral'): Parameters ---------- - spectrum : `~specutils.spectra.spectrum1d.Spectrum1D` + spectrum : `~specutils.spectra.spectrum.Spectrum` The spectrum object over which the width will be calculated. regions: `~specutils.SpectralRegion` or list of `~specutils.SpectralRegion` diff --git a/specutils/analysis/template_comparison.py b/specutils/analysis/template_comparison.py index 7eca3a5b6..adfeda9bc 100644 --- a/specutils/analysis/template_comparison.py +++ b/specutils/analysis/template_comparison.py @@ -6,7 +6,7 @@ from ..manipulation import (FluxConservingResampler, LinearInterpolatedResampler, SplineInterpolatedResampler) -from ..spectra.spectrum1d import Spectrum1D +from ..spectra.spectrum import Spectrum __all__ = ['template_match', 'template_redshift'] @@ -18,9 +18,9 @@ def _normalize_for_template_matching(observed_spectrum, template_spectrum, stdde Parameters ---------- - observed_spectrum : :class:`~specutils.Spectrum1D` + observed_spectrum : :class:`~specutils.Spectrum` The observed spectrum. - template_spectrum : :class:`~specutils.Spectrum1D` + template_spectrum : :class:`~specutils.Spectrum` The template spectrum, which needs to be normalized in order to be compared with the observed spectrum. @@ -77,15 +77,15 @@ def _chi_square_for_templates(observed_spectrum, template_spectrum, resample_met Parameters ---------- - observed_spectrum : :class:`~specutils.Spectrum1D` + observed_spectrum : :class:`~specutils.Spectrum` The observed spectrum. - template_spectrum : :class:`~specutils.Spectrum1D` + template_spectrum : :class:`~specutils.Spectrum` The template spectrum, which will be resampled to match the wavelength of the observed spectrum. Returns ------- - normalized_template_spectrum : :class:`~specutils.Spectrum1D` + normalized_template_spectrum : :class:`~specutils.Spectrum` The normalized spectrum template. chi2 : `float` The chi2 of the flux of the observed spectrum and the flux of the @@ -129,7 +129,7 @@ def _chi_square_for_templates(observed_spectrum, template_spectrum, resample_met # Create normalized template spectrum, which will be returned with # corresponding chi2 - normalized_template_spectrum = Spectrum1D( + normalized_template_spectrum = Spectrum( spectral_axis=template_spectrum.spectral_axis, flux=template_spectrum.flux*normalization) @@ -145,10 +145,10 @@ def template_match(observed_spectrum, spectral_templates, redshift=None, Parameters ---------- - observed_spectrum : :class:`~specutils.Spectrum1D` + observed_spectrum : :class:`~specutils.Spectrum` The observed spectrum. - spectral_templates : :class:`~specutils.Spectrum1D` or :class:`~specutils.SpectrumCollection` or `list` - That will give a single :class:`~specutils.Spectrum1D` when iterated + spectral_templates : :class:`~specutils.Spectrum` or :class:`~specutils.SpectrumCollection` or `list` + That will give a single :class:`~specutils.Spectrum` when iterated over. The template spectra, which will be resampled, normalized, and compared to the observed spectrum, where the smallest chi2 and normalized template spectrum will be returned. @@ -169,7 +169,7 @@ def template_match(observed_spectrum, spectral_templates, redshift=None, Returns ------- - normalized_template_spectrum : :class:`~specutils.Spectrum1D` + normalized_template_spectrum : :class:`~specutils.Spectrum` The template spectrum that has been normalized and resampled to the observed spectrum's spectral axis. redshift : `None` or `float` @@ -201,7 +201,7 @@ def template_match(observed_spectrum, spectral_templates, redshift=None, return normalized_spectral_template, final_redshift, 0, chi2, chi2_list # At this point, the template spectrum is either a ``SpectrumCollection`` - # or a multi-dimensional``Spectrum1D``. Loop through the object and return + # or a multi-dimensional``Spectrum``. Loop through the object and return # the template spectrum with the lowest chi square and its corresponding # chi square. chi2_min = None @@ -241,9 +241,9 @@ def template_redshift(observed_spectrum, template_spectrum, redshift, Parameters ---------- - observed_spectrum : :class:`~specutils.Spectrum1D` + observed_spectrum : :class:`~specutils.Spectrum` The observed spectrum. - template_spectrum : :class:`~specutils.Spectrum1D` + template_spectrum : :class:`~specutils.Spectrum` The template spectrum, which will have it's redshift calculated. redshift : `float`, `int`, `list`, `tuple`, 'numpy.array` A scalar or iterable with the redshift values to test. @@ -259,13 +259,13 @@ def template_redshift(observed_spectrum, template_spectrum, redshift, Returns ------- - redshifted_spectrum: :class:`~specutils.Spectrum1D` - A new Spectrum1D object which incorporates the template_spectrum with a spectral_axis + redshifted_spectrum: :class:`~specutils.Spectrum` + A new Spectrum object which incorporates the template_spectrum with a spectral_axis that has been redshifted using the final_redshift, and resampled to that of the observed spectrum. final_redshift : `float` The best-fit redshift for template_spectrum to match the observed_spectrum. - normalized_template_spectrum : :class:`~specutils.Spectrum1D` + normalized_template_spectrum : :class:`~specutils.Spectrum` The normalized spectrum template. chi2_min: `float` The smallest chi2 value that was found. diff --git a/specutils/analysis/uncertainty.py b/specutils/analysis/uncertainty.py index 2ee6b110c..f8e169f02 100644 --- a/specutils/analysis/uncertainty.py +++ b/specutils/analysis/uncertainty.py @@ -19,7 +19,7 @@ def snr(spectrum, region=None): Parameters ---------- - spectrum : `~specutils.spectra.spectrum1d.Spectrum1D` + spectrum : `~specutils.spectra.spectrum.Spectrum` The spectrum object overwhich the equivalent width will be calculated. region: `~specutils.SpectralRegion` or list of `~specutils.SpectralRegion` @@ -41,7 +41,7 @@ def snr(spectrum, region=None): """ if not hasattr(spectrum, 'uncertainty') or spectrum.uncertainty is None: - raise Exception("Spectrum1D currently requires the uncertainty be defined.") + raise Exception("Spectrum currently requires the uncertainty be defined.") # No region, therefore whole spectrum. if region is None: @@ -64,7 +64,7 @@ def _snr_single_region(spectrum, region=None): Parameters ---------- - spectrum : `~specutils.spectra.spectrum1d.Spectrum1D` + spectrum : `~specutils.spectra.spectrum.Spectrum` The spectrum object overwhich the equivalent width will be calculated. region: `~specutils.SpectralRegion` @@ -106,7 +106,7 @@ def snr_derived(spectrum, region=None): Parameters ---------- - spectrum : `~specutils.spectra.spectrum1d.Spectrum1D` + spectrum : `~specutils.spectra.spectrum.Spectrum` The spectrum object overwhich the equivalent width will be calculated. region: `~specutils.SpectralRegion` @@ -152,7 +152,7 @@ def _snr_derived(spectrum, region=None): Parameters ---------- - spectrum : `~specutils.spectra.spectrum1d.Spectrum1D` + spectrum : `~specutils.spectra.spectrum.Spectrum` The spectrum object overwhich the equivalent width will be calculated. region: `~specutils.SpectralRegion` diff --git a/specutils/analysis/width.py b/specutils/analysis/width.py index 1205636ce..fa96f34fd 100644 --- a/specutils/analysis/width.py +++ b/specutils/analysis/width.py @@ -27,7 +27,7 @@ def gaussian_sigma_width(spectrum, regions=None, analytic=True): Parameters ---------- - spectrum : `~specutils.spectra.spectrum1d.Spectrum1D` + spectrum : `~specutils.spectra.spectrum.Spectrum` The spectrum object over which the width will be calculated. regions: `~specutils.SpectralRegion` or list of `~specutils.SpectralRegion` @@ -62,7 +62,7 @@ def gaussian_fwhm(spectrum, regions=None, analytic=True): Parameters ---------- - spectrum : `~specutils.spectra.spectrum1d.Spectrum1D` + spectrum : `~specutils.spectra.spectrum.Spectrum` The spectrum object overwhich the width will be calculated. regions : `~specutils.SpectralRegion` or list of `~specutils.SpectralRegion` @@ -99,7 +99,7 @@ def fwhm(spectrum, regions=None): Parameters ---------- - spectrum : `~specutils.spectra.spectrum1d.Spectrum1D` + spectrum : `~specutils.spectra.spectrum.Spectrum` The spectrum object over which the width will be calculated. regions: `~specutils.SpectralRegion` or list of `~specutils.SpectralRegion` @@ -130,7 +130,7 @@ def fwzi(spectrum, regions=None): Parameters ---------- - spectrum : `~specutils.spectra.spectrum1d.Spectrum1D` + spectrum : `~specutils.spectra.spectrum.Spectrum` The spectrum object over which the width will be calculated. regions: `~specutils.SpectralRegion` or list of `~specutils.SpectralRegion` diff --git a/specutils/conftest.py b/specutils/conftest.py index 66e3b4530..7e897baaa 100644 --- a/specutils/conftest.py +++ b/specutils/conftest.py @@ -10,7 +10,7 @@ from astropy import units as u from astropy.modeling import models -from specutils.spectra import Spectrum1D +from specutils.spectra import Spectrum try: from pytest_astropy_header.display import PYTEST_HEADER_MODULES, TESTED_VERSIONS @@ -46,11 +46,11 @@ class SpectraExamples: several examples of simple spectra that are to be used in the tests (e.g., arithmetic tests, smoothing tests etc). - The purpose of this being a test class instead of using a `Spectrum1D` - directly is that it contains both the `Spectrum1D` object and the flux + The purpose of this being a test class instead of using a `Spectrum` + directly is that it contains both the `Spectrum` object and the flux that was used to *create* the Spectrum. That's for tests that ensure the simpler operations just on the flux arrays are carried through to - the `Spectrum1D` operations. + the `Spectrum` operations. Each of the spectra are created from a base noise-less spectrum constructed from 4 Gaussians and a ramp. Then three example spectra @@ -104,11 +104,11 @@ def __init__(self): # self._flux_e1 = self.base_flux + 400 * np.random.random(self.base_flux.shape) - self._s1_um_mJy_e1 = Spectrum1D(spectral_axis=self.wavelengths_um * u.um, + self._s1_um_mJy_e1 = Spectrum(spectral_axis=self.wavelengths_um * u.um, flux=self._flux_e1 * u.mJy) self._flux_e2 = self.base_flux + 400 * np.random.random(self.base_flux.shape) - self._s1_um_mJy_e2 = Spectrum1D(spectral_axis=self.wavelengths_um * u.um, + self._s1_um_mJy_e2 = Spectrum(spectral_axis=self.wavelengths_um * u.um, flux=self._flux_e2 * u.mJy) # @@ -116,7 +116,7 @@ def __init__(self): # self.wavelengths_AA = self.wavelengths_um * 10000 - self._s1_AA_mJy_e3 = Spectrum1D(spectral_axis=self.wavelengths_AA * u.AA, + self._s1_AA_mJy_e3 = Spectrum(spectral_axis=self.wavelengths_AA * u.AA, flux=self._flux_e1 * u.mJy) # @@ -124,7 +124,7 @@ def __init__(self): # self._flux_e4 = (self.base_flux + 400 * np.random.random(self.base_flux.shape)) * 1000000 - self._s1_AA_nJy_e4 = Spectrum1D(spectral_axis=self.wavelengths_AA * u.AA, + self._s1_AA_nJy_e4 = Spectrum(spectral_axis=self.wavelengths_AA * u.AA, flux=self._flux_e4 * u.nJy) # @@ -134,7 +134,7 @@ def __init__(self): self._s1_um_mJy_e1_masked.mask = (np.random.randn(*self.base_flux.shape) + 1) > 0 # Create a spectrum like 1, but with descending spectral axis - self._s1_um_mJy_e1_desc = Spectrum1D(spectral_axis=self.wavelengths_um[::-1] * u.um, + self._s1_um_mJy_e1_desc = Spectrum(spectral_axis=self.wavelengths_um[::-1] * u.um, flux=self._flux_e1[::-1] * u.mJy) @property @@ -206,7 +206,7 @@ def test_add_spectra(spectral_examples): flux2 = define_spectra.s1_um_mJy_e2_flux flux3 = flux1 + flux2 - # Calculate using the spectrum1d/nddata code + # Calculate using the spectrum/nddata code spec3 = define_spectra.s1_um_mJy_e1 + define_spectra.s1_um_mJy_e2 assert np.allclose(spec3.flux.value, flux3) diff --git a/specutils/fitting/continuum.py b/specutils/fitting/continuum.py index fc0457e11..6bbfd9a79 100644 --- a/specutils/fitting/continuum.py +++ b/specutils/fitting/continuum.py @@ -19,7 +19,7 @@ def fit_generic_continuum(spectrum, median_window=3, model=Chebyshev1D(3), Parameters ---------- - spectrum : Spectrum1D + spectrum : Spectrum The spectrum object overwhich the equivalent width will be calculated. model : list of `~astropy.modeling.Model` The list of models that contain the initial guess. @@ -64,7 +64,7 @@ def fit_continuum(spectrum, model=Chebyshev1D(3), fitter=LevMarLSQFitter(), Parameters ---------- - spectrum : Spectrum1D + spectrum : Spectrum The spectrum object overwhich the equivalent width will be calculated. model: list of `~astropy.modeling.Model` The list of models that contain the initial guess. diff --git a/specutils/fitting/fitmodels.py b/specutils/fitting/fitmodels.py index 5f80853b6..630db3dd5 100644 --- a/specutils/fitting/fitmodels.py +++ b/specutils/fitting/fitmodels.py @@ -10,7 +10,7 @@ from scipy.signal import convolve from ..spectra.spectral_region import SpectralRegion -from ..spectra.spectrum1d import Spectrum1D +from ..spectra.spectrum import Spectrum from ..utils import QuantityModel from ..analysis import fwhm, gaussian_sigma_width, centroid, warn_continuum_below_threshold from ..manipulation import extract_region @@ -24,7 +24,7 @@ # the astropy models but it was determined that this is a decent start as most # fitting will probably use one of these. # -# Each method list must take a Spectrum1D object and should return a Quantity. +# Each method list must take a Spectrum object and should return a Quantity. _parameter_estimators = { 'Gaussian1D': { 'amplitude': lambda s: max(s.flux), @@ -66,7 +66,7 @@ def estimate_line_parameters(spectrum, model, region=None): Parameters ---------- - spectrum : `~specutils.Spectrum1D` + spectrum : `~specutils.Spectrum` The spectrum object from which we will estimate the model parameters. model : `~astropy.modeling.Model` @@ -114,7 +114,7 @@ def find_lines_threshold(spectrum, noise_factor=1): Parameters ---------- - spectrum : `~specutils.Spectrum1D` + spectrum : `~specutils.Spectrum` The spectrum object in which the lines will be found. noise_factor : float @@ -169,7 +169,7 @@ def find_lines_derivative(spectrum, flux_threshold=None): Parameters ---------- - spectrum : Spectrum1D + spectrum : Spectrum The spectrum object over which the equivalent width will be calculated. flux_threshold : float, `~astropy.units.Quantity` or None The threshold a pixel must be above to be considered part of a line. If @@ -267,7 +267,7 @@ def fit_lines(spectrum, model, fitter=fitting.LevMarLSQFitter(calc_uncertainties Parameters ---------- - spectrum : Spectrum1D + spectrum : Spectrum The spectrum object over which the equivalent width will be calculated. model: `~astropy.modeling.Model` or list of `~astropy.modeling.Model` The model or list of models that contain the initial guess. @@ -454,7 +454,7 @@ def _fit_lines(spectrum, model, fitter=fitting.LevMarLSQFitter(calc_uncertaintie # TODO: really the spectral region machinery should have the power # to create a mask, and we'd just use that... idxarr = np.arange(spectrum.flux.size).reshape(spectrum.flux.shape) - index_spectrum = Spectrum1D(spectral_axis=dispersion, + index_spectrum = Spectrum(spectral_axis=dispersion, flux=u.Quantity(idxarr, u.Jy, dtype=int)) extracted_regions = extract_region(index_spectrum, window) @@ -480,7 +480,7 @@ def _fit_lines(spectrum, model, fitter=fitting.LevMarLSQFitter(calc_uncertaintie input_spectrum = spectrum - spectrum = Spectrum1D( + spectrum = Spectrum( flux=flux.value * flux_unit, spectral_axis=dispersion, wcs=input_spectrum.wcs, @@ -585,7 +585,7 @@ def _strip_units_from_model(model_in, spectrum, convert=True): class instantiation. If convert is False, then we will *not* do the conversion of units - to the units of the Spectrum1D object. Otherwise we will convert. + to the units of the Spectrum object. Otherwise we will convert. """ # diff --git a/specutils/io/_list_of_loaders.py b/specutils/io/_list_of_loaders.py index a365cc8a2..a81c97650 100644 --- a/specutils/io/_list_of_loaders.py +++ b/specutils/io/_list_of_loaders.py @@ -1,9 +1,9 @@ import io -from specutils import Spectrum1D +from specutils import Spectrum import specutils.io.default_loaders # noqa """ The purpose of this file is to receive a list of loaders from -specutils.spectrum1d.read.list_formats(), format that list +specutils.spectrum.read.list_formats(), format that list into something that can be used by `automodapi`, and then set it as the __doc__. """ @@ -12,7 +12,7 @@ def _list_of_loaders(): # Receive list of loaders list_of_loaders = io.StringIO() - Spectrum1D.read.list_formats(list_of_loaders) + Spectrum.read.list_formats(list_of_loaders) # Use the second line (which uses "-" to split the # first row from the rest) to create the "=" signs diff --git a/specutils/io/asdf/converters.py b/specutils/io/asdf/converters.py index 146c1acc0..df0443886 100644 --- a/specutils/io/asdf/converters.py +++ b/specutils/io/asdf/converters.py @@ -4,9 +4,9 @@ from astropy.nddata import (StdDevUncertainty, VarianceUncertainty, InverseVariance, UnknownUncertainty) -from specutils.spectra import Spectrum1D, SpectrumList +from specutils.spectra import Spectrum, SpectrumList -__all__ = ['Spectrum1DConverter', 'SpectrumListConverter'] +__all__ = ['SpectrumConverter', 'SpectrumListConverter'] UNCERTAINTY_TYPE_MAPPING = { 'std': StdDevUncertainty, @@ -26,13 +26,15 @@ def from_yaml_tree(self, node, tag, ctx): return SpectralAxis(super().from_yaml_tree(node, tag, ctx)) -class Spectrum1DConverter(Converter): - """ASDF converter to serialize/deserialize Spectrum1D objects.""" - tags = ["tag:astropy.org:specutils/spectra/spectrum1d-*"] - types = ["specutils.spectra.spectrum1d.Spectrum1D"] +class SpectrumConverter(Converter): + """ASDF converter to serialize/deserialize Spectrum objects.""" + tags = ["tag:astropy.org:specutils/spectra/spectrum-*", + "tag:astropy.org:specutils/spectra/spectrum1d-*"] + types = ["specutils.spectra.spectrum.Spectrum", + "specutils.spectra.spectrum.Spectrum1D"] def to_yaml_tree(self, obj, tag, ctx): - """Converts Spectrum1D object into tree used for YAML representation.""" + """Converts Spectrum object into tree used for YAML representation.""" node = {} node['flux'] = obj.flux node['spectral_axis'] = obj.spectral_axis @@ -49,7 +51,7 @@ def to_yaml_tree(self, obj, tag, ctx): return node def from_yaml_tree(cls, node, tag, ctx): - """Converts tree representation back into Spectrum1D object.""" + """Converts tree representation back into Spectrum object.""" flux = node['flux'] spectral_axis = node['spectral_axis'] uncertainty = node.get('uncertainty', None) @@ -60,7 +62,7 @@ def from_yaml_tree(cls, node, tag, ctx): data = uncertainty['data'] uncertainty = class_(data) - return Spectrum1D(flux=flux, spectral_axis=spectral_axis, uncertainty=uncertainty, mask=mask) + return Spectrum(flux=flux, spectral_axis=spectral_axis, uncertainty=uncertainty, mask=mask) class SpectrumListConverter(Converter): diff --git a/specutils/io/asdf/extension.py b/specutils/io/asdf/extension.py index 51f2f6f12..18f9afef8 100644 --- a/specutils/io/asdf/extension.py +++ b/specutils/io/asdf/extension.py @@ -5,13 +5,14 @@ def get_extensions(): from asdf.extension import ManifestExtension - from specutils.io.asdf.converters import SpectralAxisConverter, Spectrum1DConverter, SpectrumListConverter + from specutils.io.asdf.converters import SpectralAxisConverter, SpectrumConverter, SpectrumListConverter - SPECUTILS_TRANSFORM_CONVERTERS = [SpectralAxisConverter(), Spectrum1DConverter(), SpectrumListConverter()] + SPECUTILS_TRANSFORM_CONVERTERS = [SpectralAxisConverter(), SpectrumConverter(), SpectrumListConverter()] # The order here is important; asdf will prefer to use extensions # that occur earlier in the list. TRANSFORM_MANIFEST_URIS = [ + "asdf://astropy.org/specutils/manifests/specutils-1.1.0", "asdf://astropy.org/specutils/manifests/specutils-1.0.0"] return [ diff --git a/specutils/io/asdf/manifests/specutils-1.0.0.yaml b/specutils/io/asdf/manifests/specutils-1.0.0.yaml index 76e1c038a..66db6cf88 100644 --- a/specutils/io/asdf/manifests/specutils-1.0.0.yaml +++ b/specutils/io/asdf/manifests/specutils-1.0.0.yaml @@ -11,7 +11,7 @@ tags: title: Represents a spectral axis description: |- This schema represents a SpectralAxis object -- tag_uri: tag:astropy.org:specutils/spectra/spectrum1d-1.0.0 +- tag_uri: tag:astropy.org:specutils/spectra/spectrum-1.0.0 schema_uri: http://astropy.org/schemas/specutils/spectra/spectrum1d-1.0.0 title: Represents a one-dimensional spectrum description: |- diff --git a/specutils/io/asdf/manifests/specutils-1.1.0.yaml b/specutils/io/asdf/manifests/specutils-1.1.0.yaml new file mode 100644 index 000000000..f2aa78456 --- /dev/null +++ b/specutils/io/asdf/manifests/specutils-1.1.0.yaml @@ -0,0 +1,23 @@ +id: asdf://astropy.org/specutils/manifests/specutils-1.0.0 +extension_uri: asdf://astropy.org/specutils/extensions/specutils-1.0.0 +title: Specutils extension 1.0.0 +description: |- + A set of tags for serializing specutils objects. +asdf_standard_requirement: + gte: 1.1.0 +tags: +- tag_uri: tag:astropy.org:specutils/spectra/spectral_axis-1.0.0 + schema_uri: http://astropy.org/schemas/astropy/coordinates/spectralcoord-1.0.0 + title: Represents a spectral axis + description: |- + This schema represents a SpectralAxis object +- tag_uri: tag:astropy.org:specutils/spectra/spectrum-1.0.0 + schema_uri: http://astropy.org/schemas/specutils/spectra/spectrum-1.0.0 + title: Represents a one-dimensional spectrum + description: |- + This schema represents a Spectrum object from specutils. +- tag_uri: tag:astropy.org:specutils/spectra/spectrum_list-1.0.0 + schema_uri: http://astropy.org/schemas/specutils/spectra/spectrum_list-1.0.0 + title: Represents a list of one-dimensional spectra + description: |- + This schema represents a SpectrumList object from specutils diff --git a/specutils/io/asdf/schemas/spectrum-1.0.0.yaml b/specutils/io/asdf/schemas/spectrum-1.0.0.yaml new file mode 100644 index 000000000..b1db01993 --- /dev/null +++ b/specutils/io/asdf/schemas/spectrum-1.0.0.yaml @@ -0,0 +1,43 @@ +%YAML 1.1 +--- +$schema: "http://stsci.edu/schemas/yaml-schema/draft-01" +id: "http://astropy.org/schemas/specutils/spectra/spectrum-1.0.0" + +title: > + Represents a one-dimensional spectrum +description: | + This schema represents a Spectrum object from specutils. + +type: object +properties: + flux: + description: | + Quantity that represents the flux component of the spectrum + $ref: "http://stsci.edu/schemas/asdf/unit/quantity-1.1.0" + spectral_axis: + description: | + SpectralCoord that represents the spectral axis of the spectrum + anyOf: + - tag: tag:astropy.org:specutils/spectra/spectral_axis-1.0.0 + - $ref: "http://stsci.edu/schemas/asdf/unit/quantity-1.1.0" + - $ref: "http://astropy.org/schemas/astropy/coordinates/spectralcoord-1.0.0" + uncertainty: + description: | + Uncertainty information about the spectrum + type: object + properties: + uncertainty_type: + description: | + String describing the type of uncertainty data + type: string + enum: ["std", "var", "ivar", "unknown"] + data: + description: | + Array representing the uncertainty data + $ref: "http://stsci.edu/schemas/asdf/core/ndarray-1.0.0" + mask: + description: | + Mask information about the spectrum + $ref: "http://stsci.edu/schemas/asdf/core/ndarray-1.0.0" +required: [flux, spectral_axis] +... diff --git a/specutils/io/asdf/schemas/spectrum_list-1.0.0.yaml b/specutils/io/asdf/schemas/spectrum_list-1.0.0.yaml index 322ec3d5c..7d577cca0 100644 --- a/specutils/io/asdf/schemas/spectrum_list-1.0.0.yaml +++ b/specutils/io/asdf/schemas/spectrum_list-1.0.0.yaml @@ -10,5 +10,5 @@ description: type: array items: - $ref: "spectrum1d-1.0.0" + $ref: "spectrum-1.0.0" ... diff --git a/specutils/io/asdf/tests/helpers.py b/specutils/io/asdf/tests/helpers.py index 4b47011ef..c16c8bca2 100644 --- a/specutils/io/asdf/tests/helpers.py +++ b/specutils/io/asdf/tests/helpers.py @@ -5,7 +5,7 @@ from astropy.tests.helper import assert_quantity_allclose from numpy.testing import assert_allclose, assert_array_equal -__all__ = ["assert_spectral_axis_equal", "assert_spectrum1d_equal", "assert_spectrumlist_equal"] +__all__ = ["assert_spectral_axis_equal", "assert_spectrum_equal", "assert_spectrumlist_equal"] def assert_spectral_axis_equal(a, b): @@ -15,8 +15,8 @@ def assert_spectral_axis_equal(a, b): assert_spectral_coord_equal(a, b) -def assert_spectrum1d_equal(a, b): - """Equality test for use in ASDF unit tests for Spectrum1D.""" +def assert_spectrum_equal(a, b): + """Equality test for use in ASDF unit tests for Spectrum.""" __tracebackhide__ = True assert_quantity_allclose(a.flux, b.flux) @@ -40,4 +40,4 @@ def assert_spectrumlist_equal(a, b): assert len(a) == len(b) for x, y in zip(a, b): - assert_spectrum1d_equal(x, y) + assert_spectrum_equal(x, y) diff --git a/specutils/io/asdf/tests/test_spectra.py b/specutils/io/asdf/tests/test_spectra.py index 0c6aff63b..cc4af90de 100644 --- a/specutils/io/asdf/tests/test_spectra.py +++ b/specutils/io/asdf/tests/test_spectra.py @@ -5,30 +5,30 @@ from astropy.coordinates import FK5 from astropy.nddata import StdDevUncertainty -from specutils import Spectrum1D, SpectrumList, SpectralAxis +from specutils import Spectrum, SpectrumList, SpectralAxis from specutils.io.asdf.tests.helpers import ( - assert_spectrum1d_equal, assert_spectrumlist_equal, assert_spectral_axis_equal) + assert_spectrum_equal, assert_spectrumlist_equal, assert_spectral_axis_equal) -def create_spectrum1d(xmin, xmax, uncertainty=False, mask=False): +def create_spectrum(xmin, xmax, uncertainty=False, mask=False): flux = np.ones(10) * u.Jy wavelength = np.linspace(xmin, xmax, 10) * u.nm unc = StdDevUncertainty(flux * 0.1) if uncertainty else None msk = np.array([0, 1, 1, 0, 1, 0, 1, 1, 0, 1], dtype=np.uint8) if mask else None - return Spectrum1D(spectral_axis=wavelength, flux=flux, uncertainty=unc, mask=msk) + return Spectrum(spectral_axis=wavelength, flux=flux, uncertainty=unc, mask=msk) @pytest.mark.parametrize('uncertainty', [False, True]) @pytest.mark.parametrize('mask', [False, True]) -def test_asdf_spectrum1d(tmp_path, uncertainty, mask): +def test_asdf_spectrum(tmp_path, uncertainty, mask): file_path = tmp_path / "test.asdf" - spectrum = create_spectrum1d(510, 530, uncertainty=uncertainty, mask=mask) + spectrum = create_spectrum(510, 530, uncertainty=uncertainty, mask=mask) with asdf.AsdfFile() as af: af["spectrum"] = spectrum af.write_to(file_path) with asdf.open(file_path) as af: - assert_spectrum1d_equal(af["spectrum"], spectrum) + assert_spectrum_equal(af["spectrum"], spectrum) def test_asdf_spectralaxis(tmp_path): @@ -47,10 +47,10 @@ def test_asdf_spectralaxis(tmp_path): def test_asdf_spectrumlist(tmp_path): file_path = tmp_path / "test.asdf" spectra = SpectrumList([ - create_spectrum1d(510, 530), - create_spectrum1d(500, 550), - create_spectrum1d(0, 10), - create_spectrum1d(0.1, 0.5) + create_spectrum(510, 530), + create_spectrum(500, 550), + create_spectrum(0, 10), + create_spectrum(0.1, 0.5) ]) with asdf.AsdfFile() as af: af["spectrum_list"] = spectra diff --git a/specutils/io/default_loaders/aaomega_2df.py b/specutils/io/default_loaders/aaomega_2df.py index 67e9f8294..b9f7601cd 100644 --- a/specutils/io/default_loaders/aaomega_2df.py +++ b/specutils/io/default_loaders/aaomega_2df.py @@ -5,7 +5,7 @@ from astropy.nddata import VarianceUncertainty from astropy.table import Table import astropy.units as u -from specutils import Spectrum1D, SpectrumList +from specutils import Spectrum, SpectrumList from specutils.io.registers import data_loader from .dc_common import ( @@ -62,7 +62,7 @@ def load_aaomega_file(filename, *args, **kwargs): # read in Fibre table data.... ftable = Table(fits_file[AAOMEGA_FIBRE_INDEX].data) - # A SpectrumList to hold all the Spectrum1D objects + # A SpectrumList to hold all the Spectrum objects sl = SpectrumList() # the row var contains the pixel data from the science frame @@ -173,7 +173,7 @@ def load_aaomega_file(filename, *args, **kwargs): meta["fibre_index"] = i # Our science spectrum - spectrum = Spectrum1D(wcs=wcs, flux=flux, meta=meta) + spectrum = Spectrum(wcs=wcs, flux=flux, meta=meta) # If the VARIANCE spectrum exists, add it as an additional spectrum # in the meta dict with key 'variance' if var_idx is not None: @@ -192,7 +192,7 @@ def load_aaomega_file(filename, *args, **kwargs): "header": fib_header, "purpose": "science_sky" } - spectrum.meta["science_sky"] = Spectrum1D( + spectrum.meta["science_sky"] = Spectrum( wcs=wcs, flux=rwss_flux, meta=rwss_meta ) diff --git a/specutils/io/default_loaders/apogee.py b/specutils/io/default_loaders/apogee.py index 8a6a77cd1..4af9e03ae 100644 --- a/specutils/io/default_loaders/apogee.py +++ b/specutils/io/default_loaders/apogee.py @@ -11,7 +11,7 @@ import numpy as np -from ...spectra import Spectrum1D +from ...spectra import Spectrum from ..registers import data_loader from ..parsing_utils import read_fileobj_or_hdulist @@ -77,7 +77,7 @@ def apVisit_loader(file_obj, **kwargs): Returns ------- - data: Spectrum1D + data: Spectrum The spectrum that is represented by the data in this table. """ @@ -103,7 +103,7 @@ def apVisit_loader(file_obj, **kwargs): hdulist[4].data[2, :]]) dispersion_unit = Unit('Angstrom') - return Spectrum1D(data=data * unit, + return Spectrum(data=data * unit, uncertainty=uncertainty, spectral_axis=dispersion * dispersion_unit, meta=meta) @@ -125,7 +125,7 @@ def apStar_loader(file_obj, **kwargs): Returns ------- - data: Spectrum1D + data: Spectrum The spectrum that is represented by the data in this table. """ @@ -145,7 +145,7 @@ def apStar_loader(file_obj, **kwargs): np.zeros((data.shape[0],)))).T, 0)[:, 0] dispersion_unit = Unit('Angstrom') - return Spectrum1D(data=data * unit, + return Spectrum(data=data * unit, uncertainty=uncertainty, spectral_axis=dispersion * dispersion_unit, meta=meta) @@ -166,7 +166,7 @@ def aspcapStar_loader(file_obj, **kwargs): Returns ------- - data: Spectrum1D + data: Spectrum The spectrum that is represented by the data in this table. """ @@ -184,7 +184,7 @@ def aspcapStar_loader(file_obj, **kwargs): dispersion = 10**wcs.all_pix2world(np.arange(data.shape[0]), 0)[0] dispersion_unit = Unit('Angstrom') - return Spectrum1D(data=data * unit, + return Spectrum(data=data * unit, uncertainty=uncertainty, spectral_axis=dispersion * dispersion_unit, meta=meta, diff --git a/specutils/io/default_loaders/ascii.py b/specutils/io/default_loaders/ascii.py index 03e0e43f2..2cbc19281 100644 --- a/specutils/io/default_loaders/ascii.py +++ b/specutils/io/default_loaders/ascii.py @@ -33,17 +33,17 @@ def ascii_loader(file_name, column_mapping=None, **kwargs): The path to the ASCII file. column_mapping : dict A dictionary describing the relation between the ASCII file columns - and the arguments of the `Spectrum1D` class, along with unit + and the arguments of the `Spectrum` class, along with unit information. The dictionary keys should be the ASCII file column names while the values should be a two-tuple where the first element is the - associated `Spectrum1D` keyword argument, and the second element is the + associated `Spectrum` keyword argument, and the second element is the unit for the ASCII file column:: column_mapping = {'FLUX': ('flux', 'Jy')} Returns ------- - data: Spectrum1D + data: Spectrum The spectrum that is represented by the data in this table. """ tab = Table.read(file_name, format='ascii') @@ -77,17 +77,17 @@ def ipac_loader(file_name, column_mapping=None, **kwargs): The path to the IPAC-style ASCII file. column_mapping : dict A dictionary describing the relation between the IPAC-style ASCII - file columns and the arguments of the `Spectrum1D` class, along with + file columns and the arguments of the `Spectrum` class, along with unit information. The dictionary keys should be the IPAC-style ASCII file column names while the values should be a two-tuple where the - first element is the associated `Spectrum1D` keyword argument, and the + first element is the associated `Spectrum` keyword argument, and the second element is the unit for the IPAC-style ASCII file column:: column_mapping = {'FLUX': ('flux', 'Jy')} Returns ------- - data: Spectrum1D + data: Spectrum The spectrum that is represented by the data in this table. """ tab = Table.read(file_name, format='ascii.ipac') diff --git a/specutils/io/default_loaders/dc_common.py b/specutils/io/default_loaders/dc_common.py index 4315ed4b2..5c2957d1b 100644 --- a/specutils/io/default_loaders/dc_common.py +++ b/specutils/io/default_loaders/dc_common.py @@ -13,7 +13,7 @@ from ..parsing_utils import read_fileobj_or_hdulist from ..registers import data_loader -from ... import Spectrum1D, SpectrumList +from ... import Spectrum, SpectrumList HEADER_PUPOSE_KEYWORDS = ["EXTNAME", "HDUNAME"] @@ -341,7 +341,7 @@ def add_single_spectra_to_map( meta = {"header": header, "purpose": PURPOSE_SPECTRA_MAP[purpose]} if purpose in CREATE_SPECTRA: - spectrum = Spectrum1D(wcs=wcs, flux=flux, meta=meta) + spectrum = Spectrum(wcs=wcs, flux=flux, meta=meta) spectra_map[PURPOSE_SPECTRA_MAP[purpose]].append(spectrum) elif purpose in ERROR_PURPOSES: try: diff --git a/specutils/io/default_loaders/desi.py b/specutils/io/default_loaders/desi.py index 4b48e492a..ae7952bfa 100644 --- a/specutils/io/default_loaders/desi.py +++ b/specutils/io/default_loaders/desi.py @@ -23,7 +23,7 @@ import numpy as np -from ...spectra import Spectrum1D, SpectrumList +from ...spectra import Spectrum, SpectrumList from ..registers import data_loader from ..parsing_utils import _fits_identify_by_name, read_fileobj_or_hdulist @@ -92,7 +92,7 @@ def spectra_loader(file_obj, **kwargs): Returns ------- SpectrumList - Each spectrograph arm, or 'band' is represented as a Spectrum1D + Each spectrograph arm, or 'band' is represented as a Spectrum object in the SpectrumList. """ return _read_desi(file_obj, **kwargs) @@ -119,7 +119,7 @@ def coadd_loader(file_obj, **kwargs): Returns ------- SpectrumList - Each spectrograph arm, or 'band' is represented as a Spectrum1D + Each spectrograph arm, or 'band' is represented as a Spectrum object in the SpectrumList. """ return _read_desi(file_obj, **kwargs) @@ -142,7 +142,7 @@ def _read_desi(file_obj, **kwargs): Returns ------- SpectrumList - Each spectrograph arm, or 'band' is represented as a Spectrum1D + Each spectrograph arm, or 'band' is represented as a Spectrum object in the SpectrumList. """ expected_hdus = ('PRIMARY', 'FIBERMAP', 'EXP_FIBERMAP', @@ -196,5 +196,5 @@ def _read_desi(file_obj, **kwargs): if i == 0: for key, value in meta_zero.items(): band_data[band]['meta'][key] = value - sl.append(Spectrum1D(**(band_data[band]))) + sl.append(Spectrum(**(band_data[band]))) return sl diff --git a/specutils/io/default_loaders/generic_cube.py b/specutils/io/default_loaders/generic_cube.py index 4059329bd..bd0217b53 100644 --- a/specutils/io/default_loaders/generic_cube.py +++ b/specutils/io/default_loaders/generic_cube.py @@ -9,12 +9,12 @@ from astropy.units import Unit from astropy.wcs import WCS -from ...spectra import Spectrum1D +from ...spectra import Spectrum from ..parsing_utils import read_fileobj_or_hdulist # Define an optional identifier. If made specific enough, this circumvents the -# need to add `format="my-format"` in the `Spectrum1D.read` call. +# need to add `format="my-format"` in the `Spectrum.read` call. def identify_generic_fits(origin, *args, **kwargs): with read_fileobj_or_hdulist(*args, **kwargs) as hdulist: return (hdulist[0].header['NAXIS'] == 3) @@ -73,5 +73,5 @@ def generic_fits(file_obj, **kwargs): # should wcs be transformed to a 1D case ? - return Spectrum1D(flux=data, wcs=wcs, meta=meta, spectral_axis=freqs) - # return Spectrum1D(flux=data, wcs=wcs, meta=meta) # this does not work yet + return Spectrum(flux=data, wcs=wcs, meta=meta, spectral_axis=freqs) + # return Spectrum(flux=data, wcs=wcs, meta=meta) # this does not work yet diff --git a/specutils/io/default_loaders/generic_ecsv_reader.py b/specutils/io/default_loaders/generic_ecsv_reader.py index ef485e26e..dc44ef33b 100644 --- a/specutils/io/default_loaders/generic_ecsv_reader.py +++ b/specutils/io/default_loaders/generic_ecsv_reader.py @@ -2,7 +2,7 @@ from astropy.table import Table -from ...spectra import Spectrum1D +from ...spectra import Spectrum from ..registers import data_loader from ..parsing_utils import (generic_spectrum_from_table, spectrum_from_column_mapping) @@ -14,7 +14,7 @@ def identify_ecsv(origin, *args, **kwargs): os.path.splitext(args[0].lower())[1] == '.ecsv') -@data_loader("ECSV", identifier=identify_ecsv, dtype=Spectrum1D, priority=-10) +@data_loader("ECSV", identifier=identify_ecsv, dtype=Spectrum, priority=-10) def generic_ecsv(file_name, column_mapping=None, **kwargs): """ Read a spectrum from an ECSV file, using generic_spectrum_from_table_loader() @@ -29,17 +29,17 @@ def generic_ecsv(file_name, column_mapping=None, **kwargs): The path to the ECSV file. column_mapping : dict A dictionary describing the relation between the ECSV file columns - and the arguments of the `Spectrum1D` class, along with unit + and the arguments of the `Spectrum` class, along with unit information. The dictionary keys should be the ECSV file column names while the values should be a two-tuple where the first element is the - associated `Spectrum1D` keyword argument, and the second element is the + associated `Spectrum` keyword argument, and the second element is the unit for the ECSV file column:: column_mapping = {'FLUX': ('flux', 'Jy')} Returns ------- - data: Spectrum1D + data: Spectrum The spectrum that is represented by the data in this table. """ table = Table.read(file_name, format='ascii.ecsv') diff --git a/specutils/io/default_loaders/hst_cos.py b/specutils/io/default_loaders/hst_cos.py index 7a54a00ef..5d245d37c 100644 --- a/specutils/io/default_loaders/hst_cos.py +++ b/specutils/io/default_loaders/hst_cos.py @@ -1,7 +1,7 @@ from astropy.units import Unit from astropy.nddata import StdDevUncertainty -from ...spectra import Spectrum1D +from ...spectra import Spectrum from ..registers import data_loader from ..parsing_utils import read_fileobj_or_hdulist @@ -30,7 +30,7 @@ def cos_spectrum_loader(file_obj, **kwargs): Returns ------- - data: Spectrum1D + data: Spectrum The spectrum that is represented by the data in this table. """ @@ -49,7 +49,7 @@ def cos_spectrum_loader(file_obj, **kwargs): data = data[sort_idx] uncertainty = uncertainty[sort_idx] - return Spectrum1D(flux=data, + return Spectrum(flux=data, spectral_axis=dispersion, uncertainty=uncertainty, meta=meta) diff --git a/specutils/io/default_loaders/hst_stis.py b/specutils/io/default_loaders/hst_stis.py index dcd36e484..5768ee194 100644 --- a/specutils/io/default_loaders/hst_stis.py +++ b/specutils/io/default_loaders/hst_stis.py @@ -1,7 +1,7 @@ from astropy.units import Unit from astropy.nddata import StdDevUncertainty -from ...spectra import Spectrum1D +from ...spectra import Spectrum from ..registers import data_loader from ..parsing_utils import read_fileobj_or_hdulist @@ -32,7 +32,7 @@ def stis_spectrum_loader(file_obj, **kwargs): Returns ------- - data: Spectrum1D + data: Spectrum The spectrum that is represented by the data in this table. """ @@ -51,7 +51,7 @@ def stis_spectrum_loader(file_obj, **kwargs): data = data[sort_idx] uncertainty = uncertainty[sort_idx] - return Spectrum1D(flux=data, + return Spectrum(flux=data, spectral_axis=dispersion, uncertainty=uncertainty, meta=meta) diff --git a/specutils/io/default_loaders/jwst_reader.py b/specutils/io/default_loaders/jwst_reader.py index 05e5b0e4a..ed6c18cdc 100644 --- a/specutils/io/default_loaders/jwst_reader.py +++ b/specutils/io/default_loaders/jwst_reader.py @@ -10,7 +10,7 @@ from astropy.nddata import StdDevUncertainty, VarianceUncertainty, InverseVariance from gwcs.wcstools import grid_from_bounding_box -from ...spectra import Spectrum1D, SpectrumList +from ...spectra import Spectrum, SpectrumList from ..registers import data_loader from ..parsing_utils import read_fileobj_or_hdulist @@ -127,7 +127,7 @@ def _identify_jwst_fits(*args): @data_loader( - "JWST c1d", identifier=identify_jwst_c1d_fits, dtype=Spectrum1D, + "JWST c1d", identifier=identify_jwst_c1d_fits, dtype=Spectrum, extensions=['fits'], priority=10, ) def jwst_c1d_single_loader(file_obj, **kwargs): @@ -141,7 +141,7 @@ def jwst_c1d_single_loader(file_obj, **kwargs): Returns ------- - Spectrum1D + Spectrum The spectrum contained in the file. """ spectrum_list = _jwst_spec1d_loader(file_obj, extname='COMBINE1D', **kwargs) @@ -175,7 +175,7 @@ def jwst_c1d_multi_loader(file_obj, **kwargs): @data_loader( - "JWST x1d", identifier=identify_jwst_x1d_fits, dtype=Spectrum1D, + "JWST x1d", identifier=identify_jwst_x1d_fits, dtype=Spectrum, extensions=['fits'], priority=10 ) def jwst_x1d_single_loader(file_obj, **kwargs): @@ -189,7 +189,7 @@ def jwst_x1d_single_loader(file_obj, **kwargs): Returns ------- - Spectrum1D + Spectrum The spectrum contained in the file. """ spectrum_list = _jwst_spec1d_loader(file_obj, extname='EXTRACT1D', **kwargs) @@ -367,7 +367,7 @@ def _jwst_spec1d_loader(file_obj, extname='EXTRACT1D', **kwargs): header.extend(slit_header, strip=True, update=True) meta = {'header': header} - spec = Spectrum1D(flux=flux, spectral_axis=wavelength, + spec = Spectrum(flux=flux, spectral_axis=wavelength, uncertainty=uncertainty, meta=meta) spectra.append(spec) @@ -375,7 +375,7 @@ def _jwst_spec1d_loader(file_obj, extname='EXTRACT1D', **kwargs): @data_loader( - "JWST s2d", identifier=identify_jwst_s2d_fits, dtype=Spectrum1D, + "JWST s2d", identifier=identify_jwst_s2d_fits, dtype=Spectrum, extensions=['fits'], priority=10, ) def jwst_s2d_single_loader(filename, **kwargs): @@ -389,7 +389,7 @@ def jwst_s2d_single_loader(filename, **kwargs): Returns ------- - Spectrum1D + Spectrum The spectrum contained in the file. """ spectrum_list = _jwst_s2d_loader(filename, **kwargs) @@ -489,17 +489,17 @@ def _jwst_s2d_loader(filename, **kwargs): # Make sure all rows are the same if not (lam == wavelength_array).all(): raise RuntimeError("This 2D or 3D spectrum is not rectified " - "and cannot be loaded into a Spectrum1D object.") + "and cannot be loaded into a Spectrum object.") elif dispaxis == 2: flux_array = hdu.data.T wavelength_array = lam[:, 0] # Make sure all columns are the same if not (lam.T == lam[None, :, 0]).all(): raise RuntimeError("This 2D or 3D spectrum is not rectified " - "and cannot be loaded into a Spectrum1D object.") + "and cannot be loaded into a Spectrum object.") else: raise RuntimeError("This 2D spectrum has an unknown dispaxis " - "and cannot be loaded into a Spectrum1D object.") + "and cannot be loaded into a Spectrum object.") flux = Quantity(flux_array, unit=flux_unit) wavelength = Quantity(wavelength_array, unit=lam_unit) @@ -510,14 +510,14 @@ def _jwst_s2d_loader(filename, **kwargs): header.extend(slit_header, strip=True, update=True) meta = {'header': header} - spec = Spectrum1D(flux=flux, spectral_axis=wavelength, meta=meta) + spec = Spectrum(flux=flux, spectral_axis=wavelength, meta=meta) spectra.append(spec) return SpectrumList(spectra) @data_loader( - "JWST s3d", identifier=identify_jwst_s3d_fits, dtype=Spectrum1D, + "JWST s3d", identifier=identify_jwst_s3d_fits, dtype=Spectrum, extensions=['fits'], priority=10, ) def jwst_s3d_single_loader(filename, **kwargs): @@ -531,7 +531,7 @@ def jwst_s3d_single_loader(filename, **kwargs): Returns ------- - Spectrum1D + Spectrum The spectrum contained in the file. """ spectrum_list = _jwst_s3d_loader(filename, **kwargs) @@ -610,7 +610,7 @@ def _jwst_s3d_loader(filename, **kwargs): mask_name = primary_header.get("MASKEXT", "DQ") mask = hdulist[mask_name].data - spec = Spectrum1D(flux=flux, wcs=wcs, meta=meta, uncertainty=err, mask=mask, spectral_axis_index=0) + spec = Spectrum(flux=flux, wcs=wcs, meta=meta, uncertainty=err, mask=mask, spectral_axis_index=0) spectra.append(spec) diff --git a/specutils/io/default_loaders/manga.py b/specutils/io/default_loaders/manga.py index 180529293..49debf674 100644 --- a/specutils/io/default_loaders/manga.py +++ b/specutils/io/default_loaders/manga.py @@ -2,7 +2,7 @@ from astropy.nddata import InverseVariance from astropy.wcs import WCS -from ...spectra import Spectrum1D +from ...spectra import Spectrum from ..registers import data_loader from ..parsing_utils import read_fileobj_or_hdulist @@ -33,7 +33,7 @@ def identify_manga_rss(origin, *args, **kwargs): @data_loader( - "MaNGA cube", identifier=identify_manga_cube, dtype=Spectrum1D, + "MaNGA cube", identifier=identify_manga_cube, dtype=Spectrum, extensions=['fits'], priority=10, ) def manga_cube_loader(file_obj, **kwargs): @@ -48,7 +48,7 @@ def manga_cube_loader(file_obj, **kwargs): Returns ------- - Spectrum1D + Spectrum The spectrum contained in the file. """ @@ -60,7 +60,7 @@ def manga_cube_loader(file_obj, **kwargs): @data_loader( - "MaNGA rss", identifier=identify_manga_rss, dtype=Spectrum1D, + "MaNGA rss", identifier=identify_manga_rss, dtype=Spectrum, extensions=['fits'], priority=10, ) def manga_rss_loader(file_obj, **kwargs): @@ -75,7 +75,7 @@ def manga_rss_loader(file_obj, **kwargs): Returns ------- - Spectrum1D + Spectrum The spectrum contained in the file. """ @@ -87,12 +87,12 @@ def manga_rss_loader(file_obj, **kwargs): def _load_manga_spectra(hdulist, per_unit=None): - """ Return a MaNGA Spectrum1D object + """ Return a MaNGA Spectrum object - Returns a Spectrum1D object for a MaNGA data files. Use the `per_unit` + Returns a Spectrum object for a MaNGA data files. Use the `per_unit` kwarg to indicate the "spaxel" or "fiber" unit for cubes and rss files, respectively. Note that the spectral axis will automatically be moved to - be last during Spectrum1D initialization. + be last during Spectrum initialization. Parameters ---------- @@ -103,7 +103,7 @@ def _load_manga_spectra(hdulist, per_unit=None): Returns ------- - Spectrum1D + Spectrum The spectrum contained in the file. """ unit = u.Unit('1e-17 erg / (Angstrom cm2 s)') @@ -118,5 +118,5 @@ def _load_manga_spectra(hdulist, per_unit=None): # SDSS masks are arrays of bit values storing multiple boolean conditions. mask = hdulist['MASK'].data != 0 - return Spectrum1D(flux=flux, meta={'header': hdr}, wcs=wcs, + return Spectrum(flux=flux, meta={'header': hdr}, wcs=wcs, uncertainty=ivar, mask=mask) diff --git a/specutils/io/default_loaders/muscles_sed.py b/specutils/io/default_loaders/muscles_sed.py index 535516e6b..583ab80df 100644 --- a/specutils/io/default_loaders/muscles_sed.py +++ b/specutils/io/default_loaders/muscles_sed.py @@ -3,7 +3,7 @@ from astropy.table import Table from astropy.units import Quantity -from ...spectra import Spectrum1D +from ...spectra import Spectrum from ..registers import data_loader from ..parsing_utils import read_fileobj_or_hdulist @@ -23,7 +23,7 @@ def identify_muscles_sed(origin, *args, **kwargs): @data_loader( - label="MUSCLES SED", identifier=identify_muscles_sed, dtype=Spectrum1D, + label="MUSCLES SED", identifier=identify_muscles_sed, dtype=Spectrum, extensions=['fits'], priority=10, ) def muscles_sed(file_obj, **kwargs): @@ -38,7 +38,7 @@ def muscles_sed(file_obj, **kwargs): Returns ------- - data: Spectrum1D + data: Spectrum The spectrum that is represented by the data in this table. """ # name is not used; what was it for? @@ -54,5 +54,5 @@ def muscles_sed(file_obj, **kwargs): data = Quantity(tab["FLUX"]) wavelength = Quantity(tab["WAVELENGTH"]) - return Spectrum1D(flux=data, spectral_axis=wavelength, + return Spectrum(flux=data, spectral_axis=wavelength, uncertainty=uncertainty, meta=meta) diff --git a/specutils/io/default_loaders/sdss.py b/specutils/io/default_loaders/sdss.py index 97ccd095a..324bb47c1 100644 --- a/specutils/io/default_loaders/sdss.py +++ b/specutils/io/default_loaders/sdss.py @@ -15,7 +15,7 @@ import numpy as np -from ...spectra import Spectrum1D +from ...spectra import Spectrum from ..registers import data_loader from ..parsing_utils import read_fileobj_or_hdulist @@ -123,7 +123,7 @@ def spec_loader(file_obj, **kwargs): Returns ------- - data: Spectrum1D + data: Spectrum The spectrum that is represented by the 'loglam' (wavelength) and 'flux' data columns in the BINTABLE extension of the FITS `file_obj`. """ @@ -146,7 +146,7 @@ def spec_loader(file_obj, **kwargs): mask = hdulist[1].data["and_mask"] != 0 - return Spectrum1D( + return Spectrum( flux=flux, spectral_axis=dispersion * dispersion_unit, uncertainty=uncertainty, @@ -178,7 +178,7 @@ def spSpec_loader(file_obj, **kwargs): Returns ------- - data: Spectrum1D + data: Spectrum The spectrum that is represented by the wavelength solution from the header WCS and data array of the primary HDU. """ @@ -206,7 +206,7 @@ def spSpec_loader(file_obj, **kwargs): mask = hdulist[0].data[3, :] != 0 - return Spectrum1D(flux=flux, + return Spectrum(flux=flux, wcs=fixed_wcs, uncertainty=uncertainty, meta=meta, @@ -231,7 +231,7 @@ def spPlate_loader(file_obj, limit=None, **kwargs): Returns ------- - Spectrum1D + Spectrum The spectra represented by the wavelength solution from the header WCS and the data array of the primary HDU (typically 640 along dimension 1). """ @@ -259,7 +259,7 @@ def spPlate_loader(file_obj, limit=None, **kwargs): mask = hdulist[2].data[0:limit, :] != 0 meta["plugmap"] = Table.read(hdulist[5])[0:limit] - return Spectrum1D(flux=flux, + return Spectrum(flux=flux, wcs=fixed_wcs, uncertainty=uncertainty, meta=meta, diff --git a/specutils/io/default_loaders/sdss_v.py b/specutils/io/default_loaders/sdss_v.py index 514432978..22c6d7d49 100644 --- a/specutils/io/default_loaders/sdss_v.py +++ b/specutils/io/default_loaders/sdss_v.py @@ -6,7 +6,7 @@ from astropy.nddata import StdDevUncertainty, InverseVariance from astropy.io.fits import HDUList, BinTableHDU, ImageHDU -from ...spectra import Spectrum1D, SpectrumList +from ...spectra import Spectrum, SpectrumList from ..registers import data_loader from ..parsing_utils import read_fileobj_or_hdulist @@ -122,13 +122,13 @@ def _fetch_flux_unit(hdu): @data_loader( "SDSS-V apStar", identifier=apStar_identify, - dtype=Spectrum1D, + dtype=Spectrum, priority=10, extensions=["fits"], ) def load_sdss_apStar_1D(file_obj, idx: int = 0, **kwargs): """ - Load an apStar file as a Spectrum1D. + Load an apStar file as a Spectrum. Parameters ---------- @@ -139,7 +139,7 @@ def load_sdss_apStar_1D(file_obj, idx: int = 0, **kwargs): Returns ------- - Spectrum1D + Spectrum The spectrum contained in the file """ @@ -173,7 +173,7 @@ def load_sdss_apStar_1D(file_obj, idx: int = 0, **kwargs): # NOTE: specutils considers 0/False as valid values, simlar to numpy convention mask = mask != 0 - return Spectrum1D( + return Spectrum( spectral_axis=spectral_axis, flux=flux, uncertainty=e_flux, @@ -207,7 +207,7 @@ def load_sdss_apStar_list(file_obj, **kwargs): nvisits = hdulist[0].header.get("NVISITS") if nvisits <= 1: raise ValueError( - "Only 1 visit in this file. Use Spectrum1D.read() instead.") + "Only 1 visit in this file. Use Spectrum.read() instead.") return SpectrumList([ load_sdss_apStar_1D(file_obj, idx=i, **kwargs) for i in range(nvisits) @@ -217,13 +217,13 @@ def load_sdss_apStar_list(file_obj, **kwargs): @data_loader( "SDSS-V apVisit", identifier=apVisit_identify, - dtype=Spectrum1D, + dtype=Spectrum, priority=10, extensions=["fits"], ) def load_sdss_apVisit_1D(file_obj, **kwargs): """ - Load an apVisit file as a Spectrum1D. + Load an apVisit file as a Spectrum. Parameters ---------- @@ -232,7 +232,7 @@ def load_sdss_apVisit_1D(file_obj, **kwargs): Returns ------- - Spectrum1D + Spectrum The spectrum contained in the file """ flux_unit = Unit("1e-17 erg / (Angstrom cm2 s)") @@ -251,7 +251,7 @@ def load_sdss_apVisit_1D(file_obj, **kwargs): # NOTE: specutils considers 0/False as valid values, simlar to numpy convention mask = mask != 0 - return Spectrum1D(spectral_axis=spectral_axis, + return Spectrum(spectral_axis=spectral_axis, flux=flux, mask=mask, uncertainty=e_flux, @@ -299,7 +299,7 @@ def load_sdss_apVisit_list(file_obj, **kwargs): mask = mask != 0 spectra.append( - Spectrum1D( + Spectrum( spectral_axis=spectral_axis, flux=flux, mask=mask, @@ -315,13 +315,13 @@ def load_sdss_apVisit_list(file_obj, **kwargs): @data_loader( "SDSS-V spec", identifier=spec_sdss5_identify, - dtype=Spectrum1D, + dtype=Spectrum, priority=5, extensions=["fits"], ) def load_sdss_spec_1D(file_obj, *args, hdu: Optional[int] = None, **kwargs): """ - Load a given BOSS spec file as a Spectrum1D object. + Load a given BOSS spec file as a Spectrum object. Parameters ---------- @@ -332,7 +332,7 @@ def load_sdss_spec_1D(file_obj, *args, hdu: Optional[int] = None, **kwargs): Returns ------- - Spectrum1D + Spectrum The spectrum contained in the file at the specified HDU. """ if hdu is None: @@ -389,7 +389,7 @@ def _load_BOSS_HDU(hdulist: HDUList, hdu: int, **kwargs): Returns ------- - Spectrum1D + Spectrum The spectrum contained in the file """ @@ -418,7 +418,7 @@ def _load_BOSS_HDU(hdulist: HDUList, hdu: int, **kwargs): meta["header"] = hdulist[0].header meta["name"] = hdulist[hdu].name - return Spectrum1D(spectral_axis=spectral_axis, + return Spectrum(spectral_axis=spectral_axis, flux=flux, uncertainty=ivar, mask=mask, @@ -429,13 +429,13 @@ def _load_BOSS_HDU(hdulist: HDUList, hdu: int, **kwargs): @data_loader( "SDSS-V mwm", identifier=mwm_identify, - dtype=Spectrum1D, + dtype=Spectrum, priority=20, extensions=["fits"], ) def load_sdss_mwm_1d(file_obj, hdu: Optional[int] = None, **kwargs): """ - Load an unspecified spec file as a Spectrum1D. + Load an unspecified spec file as a Spectrum. Parameters ---------- @@ -446,7 +446,7 @@ def load_sdss_mwm_1d(file_obj, hdu: Optional[int] = None, **kwargs): Returns ------- - Spectrum1D + Spectrum The spectrum contained in the file """ with read_fileobj_or_hdulist(file_obj, memmap=False, **kwargs) as hdulist: @@ -487,7 +487,7 @@ def load_sdss_mwm_list(file_obj, **kwargs): ------- SpectrumList The spectra contained in the file, where: - Spectrum1D + Spectrum A given spectra of nD flux None If there are no spectra for that spectrograph/observatory @@ -527,7 +527,7 @@ def _load_mwmVisit_or_mwmStar_hdu(hdulist: HDUList, hdu: int, **kwargs): Returns ------- - Spectrum1D + Spectrum The spectrum with nD flux contained in the HDU. """ @@ -596,7 +596,7 @@ def _load_mwmVisit_or_mwmStar_hdu(hdulist: HDUList, hdu: int, **kwargs): finally: meta["name"] = hdulist[hdu].name - return Spectrum1D( + return Spectrum( spectral_axis=spectral_axis, flux=flux, uncertainty=e_flux, diff --git a/specutils/io/default_loaders/sixdfgs_reader.py b/specutils/io/default_loaders/sixdfgs_reader.py index 9765bb284..2e6fd3f21 100644 --- a/specutils/io/default_loaders/sixdfgs_reader.py +++ b/specutils/io/default_loaders/sixdfgs_reader.py @@ -3,7 +3,7 @@ from astropy.units import Quantity, Unit from astropy.wcs import WCS -from ...spectra import Spectrum1D, SpectrumList +from ...spectra import Spectrum, SpectrumList from ..registers import data_loader from ..parsing_utils import read_fileobj_or_hdulist @@ -62,7 +62,7 @@ def identify_6dfgs_combined_fits(origin, *args, **kwargs): @data_loader( - "6dFGS-tabular", identifier=identify_6dfgs_tabular_fits, dtype=Spectrum1D, + "6dFGS-tabular", identifier=identify_6dfgs_tabular_fits, dtype=Spectrum, extensions=["fit", "fits"], priority=10, ) def sixdfgs_tabular_fits_loader(file_obj, **kwargs): @@ -86,7 +86,7 @@ def sixdfgs_tabular_fits_loader(file_obj, **kwargs): Returns ------- - data: Spectrum1D + data: Spectrum The 6dF spectrum that is represented by the data in this table. """ @@ -101,11 +101,11 @@ def sixdfgs_tabular_fits_loader(file_obj, **kwargs): flux._unit = Unit("count/s") meta = {"header": header} - return Spectrum1D(flux=flux, spectral_axis=wavelength, meta=meta) + return Spectrum(flux=flux, spectral_axis=wavelength, meta=meta) @data_loader( - "6dFGS-split", identifier=identify_6dfgs_split_fits, dtype=Spectrum1D, + "6dFGS-split", identifier=identify_6dfgs_split_fits, dtype=Spectrum, extensions=["fit", "fits"], priority=10, ) def sixdfgs_split_fits_loader(file_obj, **kwargs): @@ -128,7 +128,7 @@ def sixdfgs_split_fits_loader(file_obj, **kwargs): Returns ------- - data: Spectrum1D + data: Spectrum The 6dF spectrum that is represented by the data in this file. """ @@ -190,7 +190,7 @@ def _load_single_6dfgs_hdu(hdu): sky_flux = hdu.data[2] * Unit("count") / w.wcs.cunit[0] sky_meta = {"header": header} - sky_spec = Spectrum1D(flux=sky_flux, wcs=w, meta=sky_meta) + sky_spec = Spectrum(flux=sky_flux, wcs=w, meta=sky_meta) meta["sky"] = sky_spec - return Spectrum1D(flux=flux, wcs=w, meta=meta, uncertainty=uncertainty) + return Spectrum(flux=flux, wcs=w, meta=meta, uncertainty=uncertainty) diff --git a/specutils/io/default_loaders/subaru_pfs_spec.py b/specutils/io/default_loaders/subaru_pfs_spec.py index 8e142426d..9031bc91a 100644 --- a/specutils/io/default_loaders/subaru_pfs_spec.py +++ b/specutils/io/default_loaders/subaru_pfs_spec.py @@ -11,7 +11,7 @@ import numpy as np -from ...spectra import Spectrum1D +from ...spectra import Spectrum from ..registers import data_loader from ..parsing_utils import _fits_identify_by_name, read_fileobj_or_hdulist @@ -49,7 +49,7 @@ def pfs_spec_loader(file_obj, **kwargs): Returns ------- - data : Spectrum1D + data : Spectrum The spectrum that is represented by the data in this table. """ @@ -84,7 +84,7 @@ def pfs_spec_loader(file_obj, **kwargs): mask = hdulist[2].data['mask'] != 0 - return Spectrum1D(flux=data * unit, + return Spectrum(flux=data * unit, spectral_axis=wave * wave_unit, uncertainty=uncertainty, meta=meta, diff --git a/specutils/io/default_loaders/tabular_fits.py b/specutils/io/default_loaders/tabular_fits.py index ad3c6b8aa..5a2b0b5e1 100644 --- a/specutils/io/default_loaders/tabular_fits.py +++ b/specutils/io/default_loaders/tabular_fits.py @@ -6,7 +6,7 @@ import astropy.units as u from astropy.wcs import WCS -from ...spectra import Spectrum1D +from ...spectra import Spectrum from ..registers import data_loader, custom_writer from ..parsing_utils import (generic_spectrum_from_table, spectrum_from_column_mapping, @@ -40,7 +40,7 @@ def identify_tabular_fits(origin, *args, **kwargs): @data_loader("tabular-fits", identifier=identify_tabular_fits, - dtype=Spectrum1D, extensions=['fits', 'fit'], priority=6) + dtype=Spectrum, extensions=['fits', 'fit'], priority=6) def tabular_fits_loader(file_obj, column_mapping=None, hdu=1, **kwargs): """ Load spectrum from a FITS file. @@ -54,17 +54,17 @@ def tabular_fits_loader(file_obj, column_mapping=None, hdu=1, **kwargs): The HDU of the fits file (default: 1st extension) to read from column_mapping : dict A dictionary describing the relation between the FITS file columns - and the arguments of the `Spectrum1D` class, along with unit + and the arguments of the `Spectrum` class, along with unit information. The dictionary keys should be the FITS file column names while the values should be a two-tuple where the first element is the - associated `Spectrum1D` keyword argument, and the second element is the + associated `Spectrum` keyword argument, and the second element is the unit for the ASCII file column:: column_mapping = {'FLUX': ('flux', 'Jy')} Returns ------- - data: Spectrum1D + data: Spectrum The spectrum that is represented by the data in this table. """ # Parse the wcs information. The wcs will be passed to the column finding @@ -96,7 +96,7 @@ def tabular_fits_writer(spectrum, file_name, hdu=1, update_header=False, **kwarg Parameters ---------- - spectrum: Spectrum1D + spectrum: Spectrum file_name: str The path to the FITS file hdu: int diff --git a/specutils/io/default_loaders/tests/test_jwst_reader.py b/specutils/io/default_loaders/tests/test_jwst_reader.py index 50523b2f7..c44bcada3 100644 --- a/specutils/io/default_loaders/tests/test_jwst_reader.py +++ b/specutils/io/default_loaders/tests/test_jwst_reader.py @@ -10,7 +10,7 @@ from astropy.utils.exceptions import AstropyUserWarning from gwcs.wcs import WCS -from specutils import Spectrum1D, SpectrumList +from specutils import Spectrum, SpectrumList try: from stdatamodels import asdf_in_fits @@ -104,7 +104,7 @@ def test_jwst_1d_multi_reader(tmp_path, spec_multi, format): assert len(data) == 3 for item in data: - assert isinstance(item, Spectrum1D) + assert isinstance(item, Spectrum) assert data[0].shape == (100,) assert data[1].shape == (120,) @@ -115,12 +115,12 @@ def test_jwst_1d_multi_reader(tmp_path, spec_multi, format): [('EXTRACT1D', 'JWST x1d'), ('COMBINE1D', 'JWST c1d')], indirect=['spec_single']) def test_jwst_1d_single_reader(tmp_path, spec_single, format): - """Test Spectrum1D.read for JWST x1d data""" + """Test Spectrum.read for JWST x1d data""" tmpfile = str(tmp_path / 'jwst.fits') spec_single.writeto(tmpfile) - data = Spectrum1D.read(tmpfile, format=format) - assert type(data) is Spectrum1D + data = Spectrum.read(tmpfile, format=format) + assert type(data) is Spectrum assert data.shape == (100,) @@ -133,20 +133,20 @@ def test_jwst_srctpye_defaults(tmp_path, x1d_single, srctype): x1d_single['EXTRACT1D'].header['SRCTYPE'] == srctype x1d_single.writeto(tmpfile) - data = Spectrum1D.read(tmpfile, format='JWST x1d') - assert type(data) is Spectrum1D + data = Spectrum.read(tmpfile, format='JWST x1d') + assert type(data) is Spectrum assert data.shape == (100,) assert x1d_single['EXTRACT1D'].header['SRCTYPE'] == "POINT" @pytest.mark.parametrize('spec_single', ['EXTRACT1D', 'COMBINE1D'], indirect=['spec_single']) def test_jwst_1d_single_reader_no_format(tmp_path, spec_single): - """Test Spectrum1D.read for JWST c1d/x1d data without format arg""" + """Test Spectrum.read for JWST c1d/x1d data without format arg""" tmpfile = str(tmp_path / 'jwst.fits') spec_single.writeto(tmpfile) - data = Spectrum1D.read(tmpfile) - assert type(data) is Spectrum1D + data = Spectrum.read(tmpfile) + assert type(data) is Spectrum assert data.shape == (100,) assert data.unit == u.Jy assert data.spectral_axis.unit == u.um @@ -154,7 +154,7 @@ def test_jwst_1d_single_reader_no_format(tmp_path, spec_single): @pytest.mark.parametrize('spec_multi', ['EXTRACT1D', 'COMBINE1D'], indirect=['spec_multi']) def test_jwst_1d_multi_reader_no_format(tmp_path, spec_multi): - """Test Spectrum1D.read for JWST c1d/x1d data without format arg""" + """Test Spectrum.read for JWST c1d/x1d data without format arg""" tmpfile = str(tmp_path / 'jwst.fits') spec_multi.writeto(tmpfile) @@ -163,12 +163,12 @@ def test_jwst_1d_multi_reader_no_format(tmp_path, spec_multi): assert len(data) == 3 for item in data: - assert isinstance(item, Spectrum1D) + assert isinstance(item, Spectrum) @pytest.mark.parametrize('spec_multi', ['EXTRACT1D', 'COMBINE1D'], indirect=['spec_multi']) def test_jwst_1d_multi_reader_check_units(tmp_path, spec_multi): - """Test units for Spectrum1D.read for JWST c1d/x1d data""" + """Test units for Spectrum.read for JWST c1d/x1d data""" tmpfile = str(tmp_path / 'jwst.fits') spec_multi.writeto(tmpfile) @@ -184,19 +184,19 @@ def test_jwst_1d_reader_meta(tmp_path, spec_single): tmpfile = str(tmp_path / 'jwst.fits') spec_single.writeto(tmpfile) - data = Spectrum1D.read(tmpfile) + data = Spectrum.read(tmpfile) assert ('TELESCOP', 'JWST') in data.meta['header'].items() assert ('SRCTYPE', 'POINT') in data.meta['header'].items() @pytest.mark.parametrize('spec_multi', ['EXTRACT1D', 'COMBINE1D'], indirect=['spec_multi']) def test_jwst_1d_single_reader_fail_on_multi(tmp_path, spec_multi): - """Make sure Spectrum1D.read on JWST c1d/x1d with many spectra errors out""" + """Make sure Spectrum.read on JWST c1d/x1d with many spectra errors out""" tmpfile = str(tmp_path / 'jwst.fits') spec_multi.writeto(tmpfile) with pytest.raises(IORegistryError): - Spectrum1D.read(tmpfile) + Spectrum.read(tmpfile) @pytest.mark.parametrize("srctype", ["BADVAL"]) @@ -222,7 +222,7 @@ def test_jwst_reader_warning_stddev(tmp_path, x1d_single): hdulist.writeto(tmpfile) with pytest.warns(Warning) as record: - Spectrum1D.read(tmpfile) + Spectrum.read(tmpfile) for r in record: if r.message is AstropyUserWarning: assert "Standard Deviation has values of 0" in r.message @@ -313,7 +313,7 @@ def test_jwst_s2d_reader(tmp_path, s2d_single): model = s2d_single model.save(path) - spec = Spectrum1D.read(path) + spec = Spectrum.read(path) assert hasattr(spec, "spectral_axis") assert spec.unit == u.dimensionless_unscaled @@ -428,12 +428,12 @@ def cube(tmp_path, tmp_asdf): @pytest.mark.skipif(not HAS_STDATAMODELS, reason="requires stdatamodels") def test_jwst_s3d_single(tmp_path, cube): - """Test Spectrum1D.read for JWST x1d data""" + """Test Spectrum.read for JWST x1d data""" tmpfile = str(tmp_path / 'jwst_s3d.fits') cube.writeto(tmpfile) - data = Spectrum1D.read(tmpfile, format='JWST s3d') - assert type(data) is Spectrum1D + data = Spectrum.read(tmpfile, format='JWST s3d') + assert type(data) is Spectrum assert data.shape == (30, 10, 10) assert data.uncertainty is not None assert data.mask is not None diff --git a/specutils/io/default_loaders/tests/test_sdss_v.py b/specutils/io/default_loaders/tests/test_sdss_v.py index f70490482..2f2a0e901 100644 --- a/specutils/io/default_loaders/tests/test_sdss_v.py +++ b/specutils/io/default_loaders/tests/test_sdss_v.py @@ -4,7 +4,7 @@ from astropy.io import fits from astropy.units import Unit, Angstrom -from specutils import Spectrum1D, SpectrumList +from specutils import Spectrum, SpectrumList def generate_apogee_hdu(observatory="APO", with_wl=True, datasum="0"): @@ -462,15 +462,15 @@ def spec_HDUList(n_spectra): ], ) def test_mwm_1d(file_obj, hdu, with_wl, hduflags): - """Test mwm Spectrum1D loader""" + """Test mwm Spectrum loader""" tmpfile = str(file_obj) + ".fits" mwm_HDUList(hduflags, with_wl).writeto(tmpfile, overwrite=True) if hdu is None: - data = Spectrum1D.read(tmpfile) + data = Spectrum.read(tmpfile) else: - data = Spectrum1D.read(tmpfile, hdu=hdu) - assert isinstance(data, Spectrum1D) + data = Spectrum.read(tmpfile, hdu=hdu) + assert isinstance(data, Spectrum) assert isinstance(data.meta["header"], fits.Header) if data.meta["instrument"].lower() == "apogee": length = 8575 @@ -500,7 +500,7 @@ def test_mwm_list(file_obj, with_wl, hduflags): data = SpectrumList.read(tmpfile, format="SDSS-V mwm multi") assert isinstance(data, SpectrumList) for i in range(len(data)): - assert isinstance(data[i], Spectrum1D) + assert isinstance(data[i], Spectrum) assert isinstance(data[i].meta["header"], fits.Header) if data[i].meta["instrument"].lower() == "apogee": length = 8575 @@ -525,11 +525,11 @@ def test_mwm_list(file_obj, with_wl, hduflags): ], ) def test_mwm_1d_fail_spec(file_obj, hdu, hduflags): - """Test mwm Spectrum1D loader fail on bad spec""" + """Test mwm Spectrum loader fail on bad spec""" tmpfile = str(file_obj) + ".fits" mwm_HDUList(hduflags, True).writeto(tmpfile, overwrite=True) with pytest.raises(IndexError): - Spectrum1D.read(tmpfile, hdu=hdu) + Spectrum.read(tmpfile, hdu=hdu) @pytest.mark.parametrize( @@ -540,12 +540,12 @@ def test_mwm_1d_fail_spec(file_obj, hdu, hduflags): ], ) def test_mwm_1d_fail(file_obj, with_wl): - """Test mwm Spectrum1D loader fail on empty""" + """Test mwm Spectrum loader fail on empty""" tmpfile = str(file_obj) + ".fits" mwm_HDUList([0, 0, 0, 0], with_wl).writeto(tmpfile, overwrite=True) with pytest.raises(ValueError): - Spectrum1D.read(tmpfile) + Spectrum.read(tmpfile) @pytest.mark.parametrize( @@ -579,8 +579,8 @@ def test_spec_1d(file_obj, n_spectra): idxs = [1] + list(np.arange(5, 5 + n_spectra, 1)) for i in idxs: - data = Spectrum1D.read(tmpfile, hdu=i) - assert isinstance(data, Spectrum1D) + data = Spectrum.read(tmpfile, hdu=i) + assert isinstance(data, Spectrum) assert len(data.flux.value) == 10 assert data.flux.unit == Unit("1e-17 erg / (s cm2 Angstrom)") @@ -630,7 +630,7 @@ def test_spec_1d_fail_hdu(file_obj, hdu): spec_HDUList(5).writeto(tmpfile, overwrite=True) with pytest.raises(ValueError): - Spectrum1D.read(tmpfile, hdu=hdu) + Spectrum.read(tmpfile, hdu=hdu) @pytest.mark.parametrize( @@ -644,8 +644,8 @@ def test_apStar_1D(file_obj, idx): tmpfile = str(file_obj) + ".fits" apStar_HDUList(6).writeto(tmpfile, overwrite=True) - data = Spectrum1D.read(tmpfile, idx=idx) - assert isinstance(data, Spectrum1D) + data = Spectrum.read(tmpfile, idx=idx) + assert isinstance(data, Spectrum) assert len(data.flux.value) == 10 assert data.flux.unit == Unit("1e-17 erg / (s cm2 Angstrom)") @@ -670,7 +670,7 @@ def test_apStar_list(file_obj, n_spectra): assert isinstance(data, SpectrumList) assert len(data) == n_spectra for i in range(len(data)): - assert isinstance(data[i], Spectrum1D) + assert isinstance(data[i], Spectrum) assert len(data[i].flux.value) == 10 assert data[i].flux.unit == Unit("1e-17 erg / (s cm2 Angstrom)") assert len(data[i].spectral_axis.value) == 10 @@ -702,8 +702,8 @@ def test_apVisit_1D(file_obj): tmpfile = str(file_obj) + ".fits" apVisit_HDUList().writeto(tmpfile, overwrite=True) - data = Spectrum1D.read(tmpfile) - assert isinstance(data, Spectrum1D) + data = Spectrum.read(tmpfile) + assert isinstance(data, Spectrum) assert np.array_equal(data.spectral_axis.value, np.arange(1, 31, 1)) assert len(data.flux.value) == 30 assert data.meta["header"].get("foobar") == "barfoo" diff --git a/specutils/io/default_loaders/twodfgrs_reader.py b/specutils/io/default_loaders/twodfgrs_reader.py index 720676991..62adaff6f 100644 --- a/specutils/io/default_loaders/twodfgrs_reader.py +++ b/specutils/io/default_loaders/twodfgrs_reader.py @@ -2,7 +2,7 @@ from astropy.units import Unit from astropy.wcs import WCS -from ...spectra import Spectrum1D, SpectrumList +from ...spectra import Spectrum, SpectrumList from ..registers import data_loader from ..parsing_utils import read_fileobj_or_hdulist @@ -37,9 +37,9 @@ def load_spectrum_from_extension(hdu, primary_header): variance = VarianceUncertainty(hdu.data[1]) sky = hdu.data[2] * Unit("count/s") - meta["sky"] = Spectrum1D(flux=sky, wcs=wcs) + meta["sky"] = Spectrum(flux=sky, wcs=wcs) - return Spectrum1D(flux=spectrum, wcs=wcs, meta=meta, uncertainty=variance) + return Spectrum(flux=spectrum, wcs=wcs, meta=meta, uncertainty=variance) @data_loader( diff --git a/specutils/io/default_loaders/twoslaq_lrg.py b/specutils/io/default_loaders/twoslaq_lrg.py index 5c8398c9b..a38c27fa4 100644 --- a/specutils/io/default_loaders/twoslaq_lrg.py +++ b/specutils/io/default_loaders/twoslaq_lrg.py @@ -1,7 +1,7 @@ from astropy.units import Unit from astropy.wcs import WCS -from ...spectra import Spectrum1D, SpectrumList +from ...spectra import Spectrum, SpectrumList from ..registers import data_loader from ..parsing_utils import read_fileobj_or_hdulist @@ -37,7 +37,7 @@ def twoslaq_lrg_fits_loader(file_obj, **kwargs): The LRG and QSO data appear to be in different formats, this only loads the LRG version. As there is a science and sky spectrum, the `SpectrumList` - loader provides both, whereas the `Spectrum1D` loader only provides the + loader provides both, whereas the `Spectrum` loader only provides the science. Parameters @@ -66,12 +66,12 @@ def twoslaq_lrg_fits_loader(file_obj, **kwargs): meta = {"header": header} return SpectrumList([ - Spectrum1D(flux=spectrum, wcs=wcs, meta=meta), - Spectrum1D(flux=sky, wcs=wcs, meta=meta), + Spectrum(flux=spectrum, wcs=wcs, meta=meta), + Spectrum(flux=sky, wcs=wcs, meta=meta), ]) # Commented out until discussion about whether to provide science-only or not -# @data_loader("2SLAQ-LRG", identifier=identify_2slaq_lrg,dtype=Spectrum1D, +# @data_loader("2SLAQ-LRG", identifier=identify_2slaq_lrg,dtype=Spectrum, # extensions=["fit", "fits"]) # def twoslaq_lrg_fits_loader_only_science(filename, **kwargs): # """ @@ -86,7 +86,7 @@ def twoslaq_lrg_fits_loader(file_obj, **kwargs): # # The LRG and QSO data appear to be in different formats, this only loads the # LRG version. As there is a science and sky spectrum, the `SpectrumList` -# loader provides both, whereas the `Spectrum1D` loader only provides the +# loader provides both, whereas the `Spectrum` loader only provides the # science. # # Parameters @@ -95,7 +95,7 @@ def twoslaq_lrg_fits_loader(file_obj, **kwargs): # The path to the FITS file # Returns # ------- -# data: Spectrum1D +# data: Spectrum # The 2SLAQ-LRG spectrum that is represented by the data in this file. # """ # return SpectrumList.read(filename, format="2SLAQ-LRG")[0] diff --git a/specutils/io/default_loaders/wcs_fits.py b/specutils/io/default_loaders/wcs_fits.py index 3055d439b..0866a2863 100644 --- a/specutils/io/default_loaders/wcs_fits.py +++ b/specutils/io/default_loaders/wcs_fits.py @@ -11,7 +11,7 @@ import numpy as np import shlex -from ...spectra import Spectrum1D, SpectrumCollection +from ...spectra import Spectrum, SpectrumCollection from ..registers import data_loader, custom_writer from ..parsing_utils import read_fileobj_or_hdulist @@ -52,7 +52,7 @@ def identify_wcs1d_fits(origin, *args, **kwargs): @data_loader("wcs1d-fits", identifier=identify_wcs1d_fits, - dtype=Spectrum1D, extensions=['fits', 'fit'], priority=5) + dtype=Spectrum, extensions=['fits', 'fit'], priority=5) def wcs1d_fits_loader(file_obj, spectral_axis_unit=None, flux_unit=None, hdu=None, verbose=False, mask_hdu=True, uncertainty_hdu=True, uncertainty_type=None, **kwargs): @@ -96,7 +96,7 @@ def wcs1d_fits_loader(file_obj, spectral_axis_unit=None, flux_unit=None, Returns ------- - :class:`~specutils.Spectrum1D` + :class:`~specutils.Spectrum` Notes ----- @@ -214,7 +214,7 @@ def wcs1d_fits_loader(file_obj, spectral_axis_unit=None, flux_unit=None, if wcs.naxis > 4: raise ValueError('FITS file input to wcs1d_fits_loader is > 4D') - return Spectrum1D(flux=data, wcs=wcs, mask=mask, uncertainty=uncertainty, + return Spectrum(flux=data, wcs=wcs, mask=mask, uncertainty=uncertainty, meta=meta, spectral_axis_index=spectral_axis_index) @@ -227,7 +227,7 @@ def wcs1d_fits_writer(spectrum, file_name, hdu=0, update_header=False, Parameters ---------- - spectrum : :class:`~specutils.Spectrum1D` + spectrum : :class:`~specutils.Spectrum` file_name : str The path to the FITS file hdu : int, optional @@ -251,7 +251,7 @@ def wcs1d_fits_writer(spectrum, file_name, hdu=0, update_header=False, hdulist = wcs.to_fits() header = hdulist[0].header except AttributeError as err: - raise ValueError(f'Only Spectrum1D objects with valid WCS can be written as wcs1d: {err}') + raise ValueError(f'Only Spectrum objects with valid WCS can be written as wcs1d: {err}') # Verify spectral axis constructed from WCS disp = spectrum.spectral_axis @@ -302,7 +302,7 @@ def wcs1d_fits_writer(spectrum, file_name, hdu=0, update_header=False, hdu += 1 # Warn if saving was requested (per explicitly choosing extension name). elif uncertainty_name is not None and uncertainty_name != '': - warnings.warn("No uncertainty array found in this Spectrum1D, none saved.", + warnings.warn("No uncertainty array found in this Spectrum, none saved.", AstropyUserWarning) # Append mask array @@ -322,7 +322,7 @@ def wcs1d_fits_writer(spectrum, file_name, hdu=0, update_header=False, hdu += 1 # Warn if saving was requested (per explicitly choosing extension name). elif mask_name is not None and mask_name != '': - warnings.warn("No mask found in this Spectrum1D, none saved.", AstropyUserWarning) + warnings.warn("No mask found in this Spectrum, none saved.", AstropyUserWarning) if hasattr(funit, 'long_names') and len(funit.long_names) > 0: comment = f'[{funit.long_names[0]}] {funit.physical_type}' @@ -371,9 +371,9 @@ def identify_iraf_wcs(origin, *args, **kwargs): return is_wcs -@data_loader('iraf', identifier=identify_iraf_wcs, dtype=Spectrum1D, extensions=['fits']) +@data_loader('iraf', identifier=identify_iraf_wcs, dtype=Spectrum, extensions=['fits']) def non_linear_wcs1d_fits(file_obj, **kwargs): - """Load Spectrum1D with WCS spectral axis from FITS files written by IRAF + """Load Spectrum with WCS spectral axis from FITS files written by IRAF Parameters ---------- @@ -395,7 +395,7 @@ def non_linear_wcs1d_fits(file_obj, **kwargs): Returns ------- - :class:`~specutils.Spectrum1D` + :class:`~specutils.Spectrum` """ spectral_axis, flux, meta = _read_non_linear_iraf_fits(file_obj, **kwargs) @@ -417,7 +417,7 @@ def non_linear_wcs1d_fits(file_obj, **kwargs): raise ValueError('Spectral axis and flux dimensions do not match: ' f'{spectral_axis.shape} != {flux.shape}!') - return Spectrum1D(flux=flux, spectral_axis=spectral_axis, meta=meta) + return Spectrum(flux=flux, spectral_axis=spectral_axis, meta=meta) @data_loader('iraf', identifier=identify_iraf_wcs, dtype=SpectrumCollection, extensions=['fits']) @@ -453,7 +453,7 @@ def non_linear_multispec_fits(file_obj, **kwargs): if spectral_axis.ndim == 1: warnings.warn(f'Read 1D spectral axis of length {spectral_axis.shape[0]} - ' - 'consider loading into Spectrum1D.') + 'consider loading into Spectrum.') spectral_axis = spectral_axis.reshape((1, -1)) if flux.ndim == 1: flux = flux.reshape((1, -1)) @@ -498,7 +498,7 @@ def _read_non_linear_iraf_fits(file_obj, spectral_axis_unit=None, flux_unit=None Returns ------- Tuple of data to pass to :class:`~specutils.SpectrumCollection` or - `:class:`~specutils.Spectrum1D` on initialization: + `:class:`~specutils.Spectrum` on initialization: spectral_axis : :class:`~astropy.units.Quantity` The spectral axis or axes as constructed from WCS(hdulist[0].header). diff --git a/specutils/io/parsing_utils.py b/specutils/io/parsing_utils.py index 1485bb0d8..e465dcefc 100644 --- a/specutils/io/parsing_utils.py +++ b/specutils/io/parsing_utils.py @@ -11,7 +11,7 @@ import astropy.units as u import warnings -from specutils.spectra import Spectrum1D +from specutils.spectra import Spectrum @contextlib.contextmanager @@ -24,7 +24,7 @@ def read_fileobj_or_hdulist(*args, **kwargs): Provides a generator-iterator representing the open file object handle. """ # Access the fileobj or filename arg - # Do this so identify functions are useable outside of Spectrum1d.read context + # Do this so identify functions are useable outside of Spectrum.read context try: fileobj = args[2] except IndexError: @@ -55,7 +55,7 @@ def read_fileobj_or_hdulist(*args, **kwargs): def spectrum_from_column_mapping(table, column_mapping, wcs=None, verbose=False): """ Given a table and a mapping of the table column names to attributes - on the Spectrum1D object, parse the information into a Spectrum1D. + on the Spectrum object, parse the information into a Spectrum. Parameters ---------- @@ -64,30 +64,30 @@ def spectrum_from_column_mapping(table, column_mapping, wcs=None, verbose=False) column_mapping : dict A dictionary describing the relation between the table columns - and the arguments of the `Spectrum1D` class, along with unit + and the arguments of the `Spectrum` class, along with unit information. The dictionary keys should be the table column names while the values should be a two-tuple where the first element is the - associated `Spectrum1D` keyword argument, and the second element is the + associated `Spectrum` keyword argument, and the second element is the unit for the file column (or ``None`` to take unit from the table):: column_mapping = {'FLUX': ('flux', 'Jy'), 'WAVE': ('spectral_axis'spectral_axisu', 'um')} wcs : :class:`~astropy.wcs.WCS` or :class:`gwcs.WCS` - WCS object passed to the Spectrum1D initializer. + WCS object passed to the Spectrum initializer. verbose : bool Print extra info. Returns ------- - :class:`~specutils.Spectrum1D` + :class:`~specutils.Spectrum` The spectrum with 'spectral_axis', 'flux' and optionally 'uncertainty' as identified by `column_mapping`. """ spec_kwargs = {} - # Associate columns of the file with the appropriate spectrum1d arguments + # Associate columns of the file with the appropriate Spectrum arguments for col_name, (kwarg_name, cm_unit) in column_mapping.items(): # If the table object couldn't parse any unit information, # fallback to the column mapper defined unit @@ -135,12 +135,12 @@ def spectrum_from_column_mapping(table, column_mapping, wcs=None, verbose=False) spec_kwargs['uncertainty'] = StdDevUncertainty( spec_kwargs.get('uncertainty')) - return Spectrum1D(**spec_kwargs, wcs=wcs, meta={'header': table.meta}) + return Spectrum(**spec_kwargs, wcs=wcs, meta={'header': table.meta}) def generic_spectrum_from_table(table, wcs=None, **kwargs): """ - Load spectrum from an Astropy table into a Spectrum1D object. + Load spectrum from an Astropy table into a Spectrum object. Uses the following logic to figure out which column is which: * Spectral axis (dispersion) is the first column with units @@ -162,7 +162,7 @@ def generic_spectrum_from_table(table, wcs=None, **kwargs): Returns ------- - :class:`~specutils.Spectrum1D` + :class:`~specutils.Spectrum` The spectrum that is represented by the data from the columns as automatically identified above. @@ -290,10 +290,10 @@ def _find_spectral_column(table, columns_to_search, spectral_axis): else: mask = None - # Create the Spectrum1D object and return it + # Create the Spectrum object and return it if wcs is not None or spectral_axis_column is not None and flux_column is not None: # For > 1D spectral axis transpose to row-major format and return SpectrumCollection - spectrum = Spectrum1D(flux=flux, spectral_axis=spectral_axis, + spectrum = Spectrum(flux=flux, spectral_axis=spectral_axis, uncertainty=err, meta={'header': table.meta}, wcs=wcs, mask=mask) diff --git a/specutils/io/registers.py b/specutils/io/registers.py index b8faf3c13..cdee16f99 100644 --- a/specutils/io/registers.py +++ b/specutils/io/registers.py @@ -10,7 +10,7 @@ from astropy.io import registry as io_registry -from ..spectra import Spectrum1D, SpectrumList, SpectrumCollection +from ..spectra import Spectrum, SpectrumList, SpectrumCollection __all__ = ['data_loader', 'custom_writer', 'get_loaders_by_extension', 'identify_spectrum_format'] @@ -25,7 +25,7 @@ def _astropy_has_priorities(): return False -def data_loader(label, identifier=None, dtype=Spectrum1D, extensions=None, +def data_loader(label, identifier=None, dtype=Spectrum, extensions=None, priority=0, force=False, autogenerate_spectrumlist=True, verbose=False): """ Wraps a function that can be added to an `~astropy.io.registry` for custom @@ -53,7 +53,7 @@ def data_loader(label, identifier=None, dtype=Spectrum1D, extensions=None, Default is ``False``. Passed down to astropy registry. autogenerate_spectrumlist : bool, optional Whether to automatically register a SpectrumList reader for any - data_loader that reads Spectrum1D objects. Default is ``True``. + data_loader that reads Spectrum objects. Default is ``True``. verbose : bool Print extra info. @@ -109,8 +109,8 @@ def decorator(func): print(f"Successfully loaded reader \"{label}\".") # Optionally register a SpectrumList reader for any data_loader that - # reads Spectrum1D objects. - if dtype is Spectrum1D and autogenerate_spectrumlist: + # reads Spectrum objects. + if dtype is Spectrum and autogenerate_spectrumlist: def load_spectrum_list(*args, **kwargs): return SpectrumList([ func(*args, **kwargs) ]) @@ -140,7 +140,7 @@ def wrapper(*args, **kwargs): return decorator -def custom_writer(label, dtype=Spectrum1D, priority=0, force=False): +def custom_writer(label, dtype=Spectrum, priority=0, force=False): def decorator(func): if _astropy_has_priorities(): io_registry.register_writer( @@ -180,7 +180,7 @@ def _registered_readers(): for (fmt, cls), func in io_registry._readers.items()] return [fmt for (fmt, cls), func in _registered_readers() - if issubclass(cls, Spectrum1D) and + if issubclass(cls, Spectrum) and func.extensions is not None and extension in func.extensions] @@ -213,21 +213,21 @@ def _load_user_io(): pass -def identify_spectrum_format(filename, dtype=Spectrum1D): +def identify_spectrum_format(filename, dtype=Spectrum): """ Attempt to identify a spectrum file format Given a filename, attempts to identify a valid file format from the list of registered specutils loaders. Essentially a wrapper for `~astropy.io.registry.identify_format` setting **origin** to ``read`` and - **data_class_required** to `~specutils.Spectrum1D`. + **data_class_required** to `~specutils.Spectrum`. Parameters ---------- filename : str A path to a file to be identified dtype: object - class type of Spectrum1D, SpectrumList, or SpectrumCollection. Default is - Spectrum1D. + class type of Spectrum, SpectrumList, or SpectrumCollection. Default is + Spectrum. Returns ------- @@ -242,8 +242,8 @@ class type of Spectrum1D, SpectrumList, or SpectrumCollection. Default is # check for proper class type assert dtype in \ - [Spectrum1D, SpectrumList, SpectrumCollection], \ - 'dtype class must be either Spectrum1D, SpectrumList, or SpectrumCollection' + [Spectrum, SpectrumList, SpectrumCollection], \ + 'dtype class must be either Spectrum, SpectrumList, or SpectrumCollection' # identify the file format valid_format = io_registry.identify_format( diff --git a/specutils/manipulation/estimate_uncertainty.py b/specutils/manipulation/estimate_uncertainty.py index ec8d6396b..33c7859df 100644 --- a/specutils/manipulation/estimate_uncertainty.py +++ b/specutils/manipulation/estimate_uncertainty.py @@ -2,7 +2,7 @@ from astropy import units as u -from .. import Spectrum1D +from .. import Spectrum from astropy.nddata.nduncertainty import StdDevUncertainty, VarianceUncertainty, InverseVariance from .extract_spectral_region import extract_region @@ -18,7 +18,7 @@ def noise_region_uncertainty(spectrum, spectral_region, noise_func=np.std): Parameters ---------- - spectrum : `~specutils.Spectrum1D` + spectrum : `~specutils.Spectrum` The spectrum to which we want to set the uncertainty. spectral_region : `~specutils.SpectralRegion` @@ -30,7 +30,7 @@ def noise_region_uncertainty(spectrum, spectral_region, noise_func=np.std): Returns ------- - spectrum_uncertainty : `~specutils.Spectrum1D` + spectrum_uncertainty : `~specutils.Spectrum` The ``spectrum``, but with a constant uncertainty set by the result of the noise region calculation """ @@ -59,7 +59,7 @@ def noise_region_uncertainty(spectrum, spectral_region, noise_func=np.std): raise ValueError('Can not determine correct NDData Uncertainty based on units {} relative to the flux units {}'.format(noise.unit, spectrum.flux.unit)) # Return new specturm with uncertainty set. - return Spectrum1D(flux=spectrum.flux, spectral_axis=spectrum.spectral_axis, + return Spectrum(flux=spectrum.flux, spectral_axis=spectrum.spectral_axis, uncertainty=uncertainty, wcs=spectrum.wcs, velocity_convention=spectrum.velocity_convention, diff --git a/specutils/manipulation/extract_spectral_region.py b/specutils/manipulation/extract_spectral_region.py index 05793cec1..58b7509bb 100644 --- a/specutils/manipulation/extract_spectral_region.py +++ b/specutils/manipulation/extract_spectral_region.py @@ -3,7 +3,7 @@ import numpy as np from astropy import units as u -from ..spectra import Spectrum1D, SpectralRegion +from ..spectra import Spectrum, SpectralRegion __all__ = ['extract_region', 'extract_bounding_spectral_region', 'spectral_slab'] @@ -30,12 +30,12 @@ def _subregion_to_edge_pixels(subregion, spectrum): """ Calculate and return the left and right indices defined by the lower and upper bounds and based on the input - `~specutils.spectra.spectrum1d.Spectrum1D`. The left and right indices will + `~specutils.spectra.spectrum.Spectrum`. The left and right indices will be returned. Parameters ---------- - spectrum: `~specutils.spectra.spectrum1d.Spectrum1D` + spectrum: `~specutils.spectra.spectrum.Spectrum` The spectrum object from which the region will be extracted. Returns @@ -106,14 +106,14 @@ def _subregion_to_edge_pixels(subregion, spectrum): def extract_region(spectrum, region, return_single_spectrum=False): """ - Extract a region from the input `~specutils.Spectrum1D` + Extract a region from the input `~specutils.Spectrum` defined by the lower and upper bounds defined by the ``region`` instance. The extracted region will be returned as a new - `~specutils.Spectrum1D`. + `~specutils.Spectrum`. Parameters ---------- - spectrum: `~specutils.Spectrum1D` + spectrum: `~specutils.Spectrum` The spectrum object from which the region will be extracted. region: `~specutils.SpectralRegion` @@ -121,12 +121,12 @@ def extract_region(spectrum, region, return_single_spectrum=False): return_single_spectrum: `bool` If ``region`` has multiple sections, whether to return a single spectrum - instead of multiple `~specutils.Spectrum1D` objects. The returned spectrum + instead of multiple `~specutils.Spectrum` objects. The returned spectrum will be a unique, concatenated, spectrum of all sub-regions. Returns ------- - spectrum: `~specutils.Spectrum1D` or list of `~specutils.Spectrum1D` + spectrum: `~specutils.Spectrum` or list of `~specutils.Spectrum` Excised spectrum, or list of spectra if the input region contained multiple subregions and ``return_single_spectrum`` is `False`. @@ -146,7 +146,7 @@ def extract_region(spectrum, region, return_single_spectrum=False): And we calculate ``sub_spectrum = extract_region(spectrum, region)``, then the ``sub_spectrum`` spectral axis will be ``[0.2, 0.3, 0.4, 0.5] * u.um``. - If the ``region`` does not overlap with the ``spectrum`` then an empty Spectrum1D object + If the ``region`` does not overlap with the ``spectrum`` then an empty Spectrum object will be returned. """ @@ -156,7 +156,7 @@ def extract_region(spectrum, region, return_single_spectrum=False): # If both indices are out of bounds then return an empty spectrum if left_index == right_index: - empty_spectrum = Spectrum1D(spectral_axis=[]*spectrum.spectral_axis.unit, + empty_spectrum = Spectrum(spectral_axis=[]*spectrum.spectral_axis.unit, flux=[]*spectrum.flux.unit) extracted_spectrum.append(empty_spectrum) else: @@ -174,7 +174,7 @@ def extract_region(spectrum, region, return_single_spectrum=False): extracted_spectrum = extracted_spectrum[0] # Otherwise, if requested to return a single spectrum, we need to combine - # the spectrum1d objects in extracted_spectrum and return a single object. + # the Spectrum objects in extracted_spectrum and return a single object. elif return_single_spectrum: concat_keys = ['flux', 'uncertainty', 'mask'] # spectral_axis handled manually copy_keys = ['velocity_convention', 'rest_value', 'meta'] @@ -205,7 +205,7 @@ def _get_joined_value(sps, key, unique_inds=None): # so we'll concatenate that first and track the unique indices spectral_axis = _get_joined_value(extracted_spectrum, 'spectral_axis') spectral_axis_unique, unique_inds = np.unique(spectral_axis, return_index=True) - return Spectrum1D(spectral_axis=spectral_axis_unique, + return Spectrum(spectral_axis=spectral_axis_unique, **{key: _get_joined_value(extracted_spectrum, key, unique_inds) for key in concat_keys+copy_keys}) @@ -214,14 +214,14 @@ def _get_joined_value(sps, key, unique_inds=None): def spectral_slab(spectrum, lower, upper): """ - Extract a slab from the input `~specutils.Spectrum1D` + Extract a slab from the input `~specutils.Spectrum` defined by the lower and upper bounds defined by the ``region`` instance. The extracted region will be returned as a new - `~specutils.Spectrum1D`. + `~specutils.Spectrum`. Parameters ---------- - spectrum: `~specutils.Spectrum1D` + spectrum: `~specutils.Spectrum` The spectrum object from which the region will be extracted. lower, upper: `~astropy.units.Quantity` @@ -230,7 +230,7 @@ def spectral_slab(spectrum, lower, upper): Returns ------- - spectrum: `~specutils.Spectrum1D` or list of `~specutils.Spectrum1D` + spectrum: `~specutils.Spectrum` or list of `~specutils.Spectrum` Excised spectrum, or list of spectra if the input region contained multiple subregions. @@ -255,7 +255,7 @@ def extract_bounding_spectral_region(spectrum, region): Parameters ---------- - spectrum: `~specutils.Spectrum1D` + spectrum: `~specutils.Spectrum` The spectrum object from which the region will be extracted. region: `~specutils.SpectralRegion` @@ -264,7 +264,7 @@ def extract_bounding_spectral_region(spectrum, region): Returns ------- - spectrum: `~specutils.Spectrum1D` + spectrum: `~specutils.Spectrum` Excised spectrum from the bounding region defined by the set of sub-regions in the input ``region`` instance. diff --git a/specutils/manipulation/manipulation.py b/specutils/manipulation/manipulation.py index 7eb18fd0c..624804e60 100644 --- a/specutils/manipulation/manipulation.py +++ b/specutils/manipulation/manipulation.py @@ -19,7 +19,7 @@ def snr_threshold(spectrum, value, op=operator.gt): Parameters ---------- - spectrum : `~specutils.Spectrum1D`, `~specutils.SpectrumCollection` or `~astropy.nddata.NDData` + spectrum : `~specutils.Spectrum`, `~specutils.SpectrumCollection` or `~astropy.nddata.NDData` The spectrum object overwhich the S/N threshold will be calculated. value: ``float`` @@ -31,7 +31,7 @@ def snr_threshold(spectrum, value, op=operator.gt): Returns ------- - spectrum: `~specutils.Spectrum1D` + spectrum: `~specutils.Spectrum` Output object with ``spectrum.mask`` set based on threshold. Notes @@ -63,7 +63,7 @@ def snr_threshold(spectrum, value, op=operator.gt): if isinstance(op, str): op = operator_mapping[op] - # Spectrum1D + # Spectrum if hasattr(spectrum, 'flux'): data = spectrum.flux diff --git a/specutils/manipulation/model_replace.py b/specutils/manipulation/model_replace.py index 54f627ace..630c0b8d6 100644 --- a/specutils/manipulation/model_replace.py +++ b/specutils/manipulation/model_replace.py @@ -4,7 +4,7 @@ from astropy.units import Quantity from astropy.modeling import Fittable1DModel -from ..spectra import Spectrum1D +from ..spectra import Spectrum from ..utils import QuantityModel from . import extract_region @@ -17,7 +17,7 @@ def model_replace(spectrum, replace_region, model=10, extrapolation_treatment='d Parameters ---------- - spectrum : `~specutils.Spectrum1D` + spectrum : `~specutils.Spectrum` The spectrum to be modified. replace_region : `~specutils.SpectralRegion` @@ -48,7 +48,7 @@ def model_replace(spectrum, replace_region, model=10, extrapolation_treatment='d Returns ------- - spectrum : `~specutils.Spectrum1D` + spectrum : `~specutils.Spectrum` The spectrum with the region replaced by spline values, and data values or zeros outside the spline region. The spectral axis will have the same units as the spline knots. @@ -58,14 +58,14 @@ def model_replace(spectrum, replace_region, model=10, extrapolation_treatment='d >>> import numpy as np >>> import astropy.units as u - >>> from specutils.spectra.spectrum1d import Spectrum1D + >>> from specutils.spectra.spectrum import Spectrum >>> from specutils.manipulation.model_replace import model_replace >>> wave_val = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) >>> flux_val = np.array([2, 4, 6, 8, 10, 12, 14, 16, 18, 20]) - >>> input_spectrum = Spectrum1D(spectral_axis=wave_val * u.AA, flux=flux_val * u.mJy) + >>> input_spectrum = Spectrum(spectral_axis=wave_val * u.AA, flux=flux_val * u.mJy) >>> spline_knots = [3.5, 4.7, 6.8, 7.1] * u.AA >>> model_replace(input_spectrum, None, spline_knots) - (shape=(10,), mean=11.00000 mJy); spectral_axis= (length=10))> + (shape=(10,), mean=11.00000 mJy); spectral_axis= (length=10))> """ if extrapolation_treatment not in ('data_fill', 'zero_fill'): @@ -147,7 +147,7 @@ def model_replace(spectrum, replace_region, model=10, extrapolation_treatment='d new_unc = spectrum.uncertainty.__class__(array=out_uncert, unit=spectrum.uncertainty.unit) - return Spectrum1D(spectral_axis=new_spectral_axis, flux=out, uncertainty=new_unc) + return Spectrum(spectral_axis=new_spectral_axis, flux=out, uncertainty=new_unc) def _compute_spline_values(spectrum, spline_knots, new_spectral_axis, interpolate_uncertainty): diff --git a/specutils/manipulation/resample.py b/specutils/manipulation/resample.py index af6e642c3..59d456134 100644 --- a/specutils/manipulation/resample.py +++ b/specutils/manipulation/resample.py @@ -5,7 +5,7 @@ from astropy.units import Quantity from scipy.interpolate import CubicSpline -from ..spectra import Spectrum1D, SpectralAxis +from ..spectra import Spectrum, SpectralAxis __all__ = ['ResamplerBase', 'FluxConservingResampler', 'LinearInterpolatedResampler', 'SplineInterpolatedResampler'] @@ -31,14 +31,14 @@ def __init__(self, extrapolation_treatment='nan_fill'): def __call__(self, orig_spectrum, fin_spec_axis): """ - Return the resulting `~specutils.Spectrum1D` of the resampling. + Return the resulting `~specutils.Spectrum` of the resampling. """ return self.resample1d(orig_spectrum, fin_spec_axis) @abstractmethod def resample1d(self, orig_spectrum, fin_spec_axis): """ - Workhorse method that will return the resampled Spectrum1D + Workhorse method that will return the resampled Spectrum object. """ return NotImplemented @@ -68,15 +68,15 @@ class FluxConservingResampler(ResamplerBase): >>> import numpy as np >>> import astropy.units as u - >>> from specutils import Spectrum1D + >>> from specutils import Spectrum >>> from specutils.manipulation import FluxConservingResampler - >>> input_spectra = Spectrum1D( + >>> input_spectra = Spectrum( ... flux=np.array([1, 3, 7, 6, 20]) * u.mJy, ... spectral_axis=np.array([2, 4, 12, 16, 20]) * u.nm) >>> resample_grid = [1, 5, 9, 13, 14, 17, 21, 22, 23] *u.nm >>> fluxc_resample = FluxConservingResampler() >>> fluxc_resample(input_spectra, resample_grid) # doctest: +FLOAT_CMP - (shape=(9,), mean=7.60714 mJy); spectral_axis= (length=9))> + (shape=(9,), mean=7.60714 mJy); spectral_axis= (length=9))> """ @@ -227,15 +227,15 @@ def resample1d(self, orig_spectrum, fin_spec_axis): Parameters ---------- - orig_spectrum : `~specutils.Spectrum1D` + orig_spectrum : `~specutils.Spectrum` The original 1D spectrum. fin_spec_axis : Quantity The desired spectral axis array. Returns ------- - resampled_spectrum : `~specutils.Spectrum1D` - An output spectrum containing the resampled `~specutils.Spectrum1D` + resampled_spectrum : `~specutils.Spectrum` + An output spectrum containing the resampled `~specutils.Spectrum` """ if isinstance(fin_spec_axis, Quantity): @@ -298,7 +298,7 @@ def resample1d(self, orig_spectrum, fin_spec_axis): new_errs = new_errs[np.where(~np.isnan(output_fluxes))] output_fluxes = output_fluxes[np.where(~np.isnan(output_fluxes))] - resampled_spectrum = Spectrum1D(flux=output_fluxes, + resampled_spectrum = Spectrum(flux=output_fluxes, spectral_axis=fin_spec_axis, uncertainty=new_errs, spectral_axis_index = orig_spectrum.spectral_axis_index) @@ -326,15 +326,15 @@ class LinearInterpolatedResampler(ResamplerBase): >>> import numpy as np >>> import astropy.units as u - >>> from specutils import Spectrum1D + >>> from specutils import Spectrum >>> from specutils.manipulation import LinearInterpolatedResampler - >>> input_spectra = Spectrum1D( + >>> input_spectra = Spectrum( ... flux=np.array([1, 3, 7, 6, 20]) * u.mJy, ... spectral_axis=np.array([2, 4, 12, 16, 20]) * u.nm) >>> resample_grid = [1, 5, 9, 13, 14, 17, 21, 22, 23] * u.nm >>> fluxc_resample = LinearInterpolatedResampler() >>> fluxc_resample(input_spectra, resample_grid) # doctest: +FLOAT_CMP - (shape=(9,), mean=6.35000 mJy); spectral_axis= (length=9))> + (shape=(9,), mean=6.35000 mJy); spectral_axis= (length=9))> """ def __init__(self, extrapolation_treatment='nan_fill'): @@ -347,15 +347,15 @@ def resample1d(self, orig_spectrum, fin_spec_axis): Parameters ---------- - orig_spectrum : `~specutils.Spectrum1D` + orig_spectrum : `~specutils.Spectrum` The original 1D spectrum. fin_spec_axis : ndarray The desired spectral axis array. Returns ------- - resample_spectrum : `~specutils.Spectrum1D` - An output spectrum containing the resampled `~specutils.Spectrum1D` + resample_spectrum : `~specutils.Spectrum` + An output spectrum containing the resampled `~specutils.Spectrum` """ fill_val = np.nan # bin_edges=nan_fill case @@ -382,7 +382,7 @@ def resample1d(self, orig_spectrum, fin_spec_axis): new_unc = new_unc[np.where(~np.isnan(out_flux))] out_flux = out_flux[np.where(~np.isnan(out_flux))] - return Spectrum1D(spectral_axis=fin_spec_axis, + return Spectrum(spectral_axis=fin_spec_axis, flux=out_flux, uncertainty=new_unc, spectral_axis_index = orig_spectrum.spectral_axis_index) @@ -411,15 +411,15 @@ class SplineInterpolatedResampler(ResamplerBase): >>> import numpy as np >>> import astropy.units as u - >>> from specutils import Spectrum1D + >>> from specutils import Spectrum >>> from specutils.manipulation import SplineInterpolatedResampler - >>> input_spectra = Spectrum1D( + >>> input_spectra = Spectrum( ... flux=np.array([1, 3, 7, 6, 20]) * u.mJy, ... spectral_axis=np.array([2, 4, 12, 16, 20]) * u.nm) >>> resample_grid = [1, 5, 9, 13, 14, 17, 21, 22, 23] * u.nm >>> fluxc_resample = SplineInterpolatedResampler() >>> fluxc_resample(input_spectra, resample_grid) # doctest: +FLOAT_CMP - (shape=(9,), mean=6.11676 mJy); spectral_axis= (length=9))> """ @@ -433,15 +433,15 @@ def resample1d(self, orig_spectrum, fin_spec_axis): Parameters ---------- - orig_spectrum : `~specutils.Spectrum1D` + orig_spectrum : `~specutils.Spectrum` The original 1D spectrum. fin_spec_axis : Quantity The desired spectral axis array. Returns ------- - resample_spectrum : `~specutils.Spectrum1D` - An output spectrum containing the resampled `~specutils.Spectrum1D` + resample_spectrum : `~specutils.Spectrum` + An output spectrum containing the resampled `~specutils.Spectrum` """ orig_axis_in_new = orig_spectrum.spectral_axis.to(fin_spec_axis.unit) flux_spline = CubicSpline(orig_axis_in_new.value, orig_spectrum.flux.value, @@ -475,7 +475,7 @@ def resample1d(self, orig_spectrum, fin_spec_axis): new_unc = new_unc[np.where(~np.isnan(out_flux_val))] out_flux_val = out_flux_val[np.where(~np.isnan(out_flux_val))] - return Spectrum1D(spectral_axis=fin_spec_axis, + return Spectrum(spectral_axis=fin_spec_axis, flux=out_flux_val*orig_spectrum.flux.unit, uncertainty=new_unc, spectral_axis_index = orig_spectrum.spectral_axis_index) diff --git a/specutils/manipulation/smoothing.py b/specutils/manipulation/smoothing.py index 0cb41d868..45c5c6d33 100644 --- a/specutils/manipulation/smoothing.py +++ b/specutils/manipulation/smoothing.py @@ -8,7 +8,7 @@ from astropy.utils.exceptions import AstropyUserWarning from scipy.signal import medfilt -from ..spectra import Spectrum1D +from ..spectra import Spectrum __all__ = ['convolution_smooth', 'box_smooth', 'gaussian_smooth', 'trapezoid_smooth', 'median_smooth'] @@ -30,8 +30,8 @@ def convolution_smooth(spectrum, kernel): Parameters ---------- - spectrum : `~specutils.Spectrum1D` - The `~specutils.Spectrum1D` object to which the smoothing will be + spectrum : `~specutils.Spectrum` + The `~specutils.Spectrum` object to which the smoothing will be applied. kernel : `astropy.convolution.Kernel1D` subclass or array. The convolution based smoothing kernel - anything that @@ -39,8 +39,8 @@ def convolution_smooth(spectrum, kernel): Returns ------- - spectrum : `~specutils.Spectrum1D` - Output `~specutils.Spectrum1D` which is copy of the one passed in with + spectrum : `~specutils.Spectrum` + Output `~specutils.Spectrum` which is copy of the one passed in with the updated flux. Raises @@ -49,8 +49,8 @@ def convolution_smooth(spectrum, kernel): In the case that ``spectrum`` and ``kernel`` are not the correct types. """ # Parameter checks - if not isinstance(spectrum, Spectrum1D): - raise ValueError('The spectrum parameter must be a Spectrum1D object') + if not isinstance(spectrum, Spectrum): + raise ValueError('The spectrum parameter must be a Spectrum object') # Get the flux of the input spectrum flux = spectrum.flux @@ -120,12 +120,12 @@ def convolution_smooth(spectrum, kernel): def box_smooth(spectrum, width): """ - Smooth a `~specutils.Spectrum1D` instance along the spectral axis + Smooth a `~specutils.Spectrum` instance along the spectral axis based on a `astropy.convolution.Box1DKernel` kernel. Parameters ---------- - spectrum : `~specutils.Spectrum1D` + spectrum : `~specutils.Spectrum` The spectrum object to which the smoothing will be applied. width : number The width of the kernel, in pixels, as defined in @@ -133,8 +133,8 @@ def box_smooth(spectrum, width): Returns ------- - spectrum : `~specutils.Spectrum1D` - Output `~specutils.Spectrum1D` which a copy of the one passed in with + spectrum : `~specutils.Spectrum` + Output `~specutils.Spectrum` which a copy of the one passed in with the updated flux. Raises @@ -157,12 +157,12 @@ def box_smooth(spectrum, width): def gaussian_smooth(spectrum, stddev): """ - Smooth a `~specutils.Spectrum1D` instance along the spectral axis + Smooth a `~specutils.Spectrum` instance along the spectral axis based on a `astropy.convolution.Gaussian1DKernel`. Parameters ---------- - spectrum : `~specutils.Spectrum1D` + spectrum : `~specutils.Spectrum` The spectrum object to which the smoothing will be applied. stddev : number The stddev of the kernel, in pixels, as defined in @@ -170,8 +170,8 @@ def gaussian_smooth(spectrum, stddev): Returns ------- - spectrum : `~specutils.Spectrum1D` - Output `~specutils.Spectrum1D` which is copy of the one passed in with + spectrum : `~specutils.Spectrum` + Output `~specutils.Spectrum` which is copy of the one passed in with the updated flux. Raises @@ -194,13 +194,13 @@ def gaussian_smooth(spectrum, stddev): def trapezoid_smooth(spectrum, width): """ - Smooth a `~specutils.Spectrum1D` instance along the spectral axis + Smooth a `~specutils.Spectrum` instance along the spectral axis based on a `astropy.convolution.Trapezoid1DKernel` kernel. Parameters ---------- - spectrum : `~specutils.Spectrum1D` - The `~specutils.Spectrum1D` object to which the smoothing will be + spectrum : `~specutils.Spectrum` + The `~specutils.Spectrum` object to which the smoothing will be applied. width : number The width of the kernel, in pixels, as defined in @@ -208,8 +208,8 @@ def trapezoid_smooth(spectrum, width): Returns ------- - spectrum : `~specutils.Spectrum1D` - Output `~specutils.Spectrum1D` which is copy of the one passed in with + spectrum : `~specutils.Spectrum` + Output `~specutils.Spectrum` which is copy of the one passed in with the updated flux. Raises @@ -237,16 +237,16 @@ def median_smooth(spectrum, width): Parameters ---------- - spectrum : `~specutils.Spectrum1D` - The `~specutils.Spectrum1D` object to which the smoothing will be + spectrum : `~specutils.Spectrum` + The `~specutils.Spectrum` object to which the smoothing will be applied. width : number The width of the median filter in pixels. Returns ------- - spectrum : `~specutils.Spectrum1D` - Output `~specutils.Spectrum1D` which is copy of the one passed in with + spectrum : `~specutils.Spectrum` + Output `~specutils.Spectrum` which is copy of the one passed in with the updated flux. Raises @@ -257,8 +257,8 @@ def median_smooth(spectrum, width): """ # Parameter checks - if not isinstance(spectrum, Spectrum1D): - raise ValueError('The spectrum parameter must be a Spectrum1D object') + if not isinstance(spectrum, Spectrum): + raise ValueError('The spectrum parameter must be a Spectrum object') if not isinstance(width, (int, float)) or width <= 0: raise ValueError("The stddev parameter, {}, must be a number greater " diff --git a/specutils/manipulation/utils.py b/specutils/manipulation/utils.py index d8eab1b5d..f61de6a55 100644 --- a/specutils/manipulation/utils.py +++ b/specutils/manipulation/utils.py @@ -3,7 +3,7 @@ from astropy.utils.exceptions import AstropyUserWarning from astropy.coordinates import SpectralCoord -from ..spectra import Spectrum1D, SpectralRegion +from ..spectra import Spectrum, SpectralRegion __all__ = ['excise_regions', 'linear_exciser', 'spectrum_from_model'] @@ -12,7 +12,7 @@ def true_exciser(spectrum, region): """ Basic spectral excise method where the array elements in the spectral region defined by the parameter ``region`` (a `~specutils.SpectralRegion`) - will be deleted from all applicable elements of the Spectrum1D object: + will be deleted from all applicable elements of the Spectrum object: flux, spectral_axis, mask, and uncertainty. If multiple subregions are defined in ``region``, all the subregions will be excised. @@ -20,16 +20,16 @@ def true_exciser(spectrum, region): Parameters ---------- - spectrum : `~specutils.Spectrum1D` - The `~specutils.Spectrum1D` object to which the excision will be applied. + spectrum : `~specutils.Spectrum` + The `~specutils.Spectrum` object to which the excision will be applied. region : `~specutils.SpectralRegion` The region of the spectrum to remove. Returns ------- - spectrum : `~specutils.Spectrum1D` - Output `~specutils.Spectrum1D` with the region excised. + spectrum : `~specutils.Spectrum` + Output `~specutils.Spectrum` with the region excised. Raises ------ @@ -66,7 +66,7 @@ def true_exciser(spectrum, region): new_uncertainty = None # Return a new object with the regions excised. - return Spectrum1D(flux=new_flux, + return Spectrum(flux=new_flux, spectral_axis=new_spectral_axis, uncertainty=new_uncertainty, mask=new_mask, @@ -87,16 +87,16 @@ def linear_exciser(spectrum, region): Parameters ---------- - spectrum : `~specutils.Spectrum1D` - The `~specutils.Spectrum1D` object to which the excision will be applied. + spectrum : `~specutils.Spectrum` + The `~specutils.Spectrum` object to which the excision will be applied. region : `~specutils.SpectralRegion` The region of the spectrum to replace. Returns ------- - spectrum : `~specutils.Spectrum1D` - Output `~specutils.Spectrum1D` with the region excised. + spectrum : `~specutils.Spectrum` + Output `~specutils.Spectrum` with the region excised. Raises ------ @@ -140,7 +140,7 @@ def linear_exciser(spectrum, region): new_uncertainty[s:e] = np.sqrt(spectrum.uncertainty[s]**2 + spectrum.uncertainty[e]**2) # Return a new object with the regions excised. - return Spectrum1D(flux=modified_flux, + return Spectrum(flux=modified_flux, spectral_axis=spectral_axis, uncertainty=new_uncertainty, wcs=spectrum.wcs, @@ -157,8 +157,8 @@ def excise_regions(spectrum, regions, exciser=true_exciser): Parameters ---------- - spectrum : `~specutils.Spectrum1D` - The `~specutils.Spectrum1D` object to which the excision will be applied. + spectrum : `~specutils.Spectrum` + The `~specutils.Spectrum` object to which the excision will be applied. regions : list of `~specutils.SpectralRegion` Each element of the list is a `~specutils.SpectralRegion`. The flux @@ -175,8 +175,8 @@ def excise_regions(spectrum, regions, exciser=true_exciser): Returns ------- - spectrum : `~specutils.Spectrum1D` - Output `~specutils.Spectrum1D` which has the regions excised. + spectrum : `~specutils.Spectrum` + Output `~specutils.Spectrum` which has the regions excised. Raises ------ @@ -186,8 +186,8 @@ def excise_regions(spectrum, regions, exciser=true_exciser): """ # Parameter checks - if not isinstance(spectrum, Spectrum1D): - raise ValueError('The spectrum parameter must be Spectrum1D object.') + if not isinstance(spectrum, Spectrum): + raise ValueError('The spectrum parameter must be Spectrum object.') for region in regions: spectrum = excise_region(spectrum, region, exciser) @@ -202,8 +202,8 @@ def excise_region(spectrum, region, exciser=true_exciser): Parameters ---------- - spectrum : `~specutils.Spectrum1D` - The `~specutils.Spectrum1D` object to which the smoothing will be applied. + spectrum : `~specutils.Spectrum` + The `~specutils.Spectrum` object to which the smoothing will be applied. region : `~specutils.SpectralRegion` A `~specutils.SpectralRegion` object defining the region to excise. @@ -219,8 +219,8 @@ def excise_region(spectrum, region, exciser=true_exciser): Returns ------- - spectrum : `~specutils.Spectrum1D` - Output `~specutils.Spectrum1D` with the region excised. + spectrum : `~specutils.Spectrum` + Output `~specutils.Spectrum` with the region excised. Raises ------ @@ -230,8 +230,8 @@ def excise_region(spectrum, region, exciser=true_exciser): """ # Parameter checks - if not isinstance(spectrum, Spectrum1D): - raise ValueError('The spectrum parameter must be a Spectrum1D object.') + if not isinstance(spectrum, Spectrum): + raise ValueError('The spectrum parameter must be a Spectrum object.') if not isinstance(region, SpectralRegion): raise ValueError('The region parameter must be a SpectralRegion object.') @@ -245,23 +245,23 @@ def excise_region(spectrum, region, exciser=true_exciser): def spectrum_from_model(model_input, spectrum): """ - This method will create a `~specutils.Spectrum1D` object + This method will create a `~specutils.Spectrum` object with the flux defined by calling the input ``model``. All - other parameters for the output `~specutils.Spectrum1D` object - will be the same as the input `~specutils.Spectrum1D` object. + other parameters for the output `~specutils.Spectrum` object + will be the same as the input `~specutils.Spectrum` object. Parameters ---------- model : `~astropy.modeling.Model` The input model or compound model from which flux is calculated. - spectrum : `~specutils.Spectrum1D` - The `~specutils.Spectrum1D` object to use as the model template. + spectrum : `~specutils.Spectrum` + The `~specutils.Spectrum` object to use as the model template. Returns ------- - spectrum : `~specutils.Spectrum1D` - Output `~specutils.Spectrum1D` which is copy of the one passed in with the updated flux. + spectrum : `~specutils.Spectrum` + Output `~specutils.Spectrum` which is copy of the one passed in with the updated flux. The uncertainty will not be copied as it is not necessarily the same. """ @@ -275,7 +275,7 @@ def spectrum_from_model(model_input, spectrum): else: flux = model_input(spectrum.spectral_axis.value)*spectrum.flux.unit - return Spectrum1D(flux=flux, + return Spectrum(flux=flux, spectral_axis=spectrum.spectral_axis, wcs=spectrum.wcs, velocity_convention=spectrum.velocity_convention, diff --git a/specutils/spectra/__init__.py b/specutils/spectra/__init__.py index 3606d4350..3e3e17b05 100644 --- a/specutils/spectra/__init__.py +++ b/specutils/spectra/__init__.py @@ -2,7 +2,7 @@ The core specutils data objects package. This contains the `~astropy.nddata.NDData`-inherited classes used for storing the spectrum data. """ -from .spectrum1d import * # noqa +from .spectrum import * # noqa from .spectral_region import * # noqa from .spectrum_collection import * # noqa from .spectrum_list import * # noqa diff --git a/specutils/spectra/spectrum1d.py b/specutils/spectra/spectrum.py similarity index 96% rename from specutils/spectra/spectrum1d.py rename to specutils/spectra/spectrum.py index 3bf4d4b07..0c389d2fa 100644 --- a/specutils/spectra/spectrum1d.py +++ b/specutils/spectra/spectrum.py @@ -16,18 +16,17 @@ from ndcube import NDCube -__all__ = ['Spectrum1D'] +__all__ = ['Spectrum1D', 'Spectrum'] -class Spectrum1D(OneDSpectrumMixin, NDCube, NDIOMixin, NDArithmeticMixin): +class Spectrum(OneDSpectrumMixin, NDCube, NDIOMixin, NDArithmeticMixin): """ - Spectrum container for 1D spectral data. + Spectrum container for N-dimensional data with one spectral axis. - Note that "1D" in this case refers to the fact that there is only one - spectral axis. `Spectrum1D` can contain "vector 1D spectra" by having the - ``flux`` have a shape with dimension greater than 1. The requirement - is that the last dimension of ``flux`` match the length of the - ``spectral_axis``. + `Spectrum` can contain "vector spectra" by having the + ``flux`` have a shape with dimension greater than 1. One dimension of + ``flux`` must match the length of the ``spectral_axis`` if ``spectral_axis`` + is provided. For multidimensional spectra that are all the same shape but have different spectral axes, use a :class:`~specutils.SpectrumCollection`. For a @@ -39,7 +38,7 @@ class Spectrum1D(OneDSpectrumMixin, NDCube, NDIOMixin, NDArithmeticMixin): ---------- flux : `~astropy.units.Quantity` The flux data for this spectrum. This can be a simple `~astropy.units.Quantity`, - or an existing `~Spectrum1D` or `~ndcube.NDCube` object. + or an existing `~Spectrum` or `~ndcube.NDCube` object. spectral_axis : `~astropy.units.Quantity` or `~specutils.SpectralAxis` Dispersion information with the same shape as the last (or only) dimension of flux, or one greater than the last dimension of flux @@ -87,9 +86,9 @@ def __init__(self, flux=None, spectral_axis=None, spectral_axis_index=None, redshift=None, radial_velocity=None, bin_specification=None, move_spectral_axis=None, **kwargs): - # If the flux (data) argument is already a Spectrum1D (as it would + # If the flux (data) argument is already a Spectrum (as it would # be for internal arithmetic operations), avoid setup entirely. - if isinstance(flux, Spectrum1D): + if isinstance(flux, Spectrum): super().__init__(flux) return @@ -161,7 +160,7 @@ def __init__(self, flux=None, spectral_axis=None, spectral_axis_index=None, if (not isinstance(flux, u.Quantity) or isinstance(flux, float) or isinstance(flux, int)) and np.ndim(flux) == 0: - super(Spectrum1D, self).__init__(data=flux, wcs=wcs, **kwargs) + super(Spectrum, self).__init__(data=flux, wcs=wcs, **kwargs) return if rest_value is None: @@ -410,13 +409,13 @@ def __init__(self, flux=None, spectral_axis=None, spectral_axis_index=None, def __getitem__(self, item): """ Override the class indexer. We do this here because there are two cases - for slicing on a ``Spectrum1D``: + for slicing on a ``Spectrum``: 1.) When the flux is one dimensional, indexing represents a single flux value at a particular spectral axis bin, and returns a new - ``Spectrum1D`` where all attributes are sliced. + ``Spectrum`` where all attributes are sliced. 2.) When flux is multi-dimensional (i.e. several fluxes over the - same spectral axis), indexing returns a new ``Spectrum1D`` with + same spectral axis), indexing returns a new ``Spectrum`` with the sliced flux range and a deep copy of all other attributes. The first case is handled by the parent class, while the second is @@ -530,7 +529,7 @@ def __getitem__(self, item): # a regular slicing operation, the wcs is handed back to the # initializer and a new spectral axis is created. This would then also # be in length units, which may not be the units used initially. So, - # we create a new ``Spectrum1D`` that includes the sliced spectral + # we create a new ``Spectrum`` that includes the sliced spectral # axis. This means that a new wcs object will be created with the # appropriate unit translation handling. if "original_wcs" not in self.meta: @@ -544,7 +543,7 @@ def __getitem__(self, item): def _copy(self, **kwargs): """ - Perform deep copy operations on each attribute of the ``Spectrum1D`` + Perform deep copy operations on each attribute of the ``Spectrum`` object. """ alt_kwargs = dict( @@ -591,7 +590,7 @@ def collapse(self, method, axis=None): value (default), over a specified numerical axis or axes if specified, or over the spectral or non-spectral axes if ``physical_type`` is specified. - If the collapse leaves the spectral axis unchanged, a `~specutils.Spectrum1D` + If the collapse leaves the spectral axis unchanged, a `~specutils.Spectrum` will be returned. Otherwise an `~astropy.units.Quantity` array will be returned. @@ -613,7 +612,7 @@ def collapse(self, method, axis=None): Returns ------- - :class:`~specutils.Spectrum1D` or :class:`~astropy.units.Quantity` + :class:`~specutils.Spectrum` or :class:`~astropy.units.Quantity` """ collapse_funcs = {"mean": np.nanmean, "max": np.nanmax, "min": np.nanmin, @@ -641,13 +640,13 @@ def collapse(self, method, axis=None): else: collapsed_flux = collapse_funcs[method](flux_to_collapse, axis=axis) - # Return a Spectrum1D if we collapsed over the spectral axis, a Quantity if not + # Return a Spectrum if we collapsed over the spectral axis, a Quantity if not if axis in (self.spectral_axis_index, None): return collapsed_flux elif isinstance(axis, tuple) and self.spectral_axis_index in axis: return collapsed_flux else: - return Spectrum1D(collapsed_flux, wcs=self.wcs) + return Spectrum(collapsed_flux, wcs=self.wcs) def mean(self, **kwargs): return self.collapse("mean", **kwargs) @@ -802,9 +801,9 @@ def shift_spectrum_to(self, *, redshift=None, radial_velocity=None): def with_spectral_axis_last(self): """ - Convenience method to return a new copy of theSpectrum1D with the spectral axis last. + Convenience method to return a new copy of the Spectrum with the spectral axis last. """ - return Spectrum1D(flux=self.flux, wcs=self.wcs, + return Spectrum(flux=self.flux, wcs=self.wcs, mask=self.mask, uncertainty=self.uncertainty, redshift=self.redshift, move_spectral_axis="last") @@ -871,7 +870,7 @@ def _format_array_summary(self, label, array): return "{:17} [ ], mean= n/a".format(label+':') def __str__(self): - result = "Spectrum1D " + result = "Spectrum " result += "(length={})\n".format(len(self.spectral_axis)) # Add Flux information @@ -907,6 +906,13 @@ def __repr__(self): if self.uncertainty is not None: inner_str += f"; uncertainty={self.uncertainty.__class__.__name__}" - result = "".format(inner_str) + result = "".format(inner_str) return result + + +@deprecated(since="2.0", alternative="Spectrum") +class Spectrum1D(Spectrum): + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) diff --git a/specutils/spectra/spectrum_collection.py b/specutils/spectra/spectrum_collection.py index f3c4a59fc..2910c2d9d 100644 --- a/specutils/spectra/spectrum_collection.py +++ b/specutils/spectra/spectrum_collection.py @@ -5,7 +5,7 @@ from astropy.nddata import NDUncertainty, StdDevUncertainty from astropy.coordinates import SpectralCoord -from .spectrum1d import Spectrum1D +from .spectrum import Spectrum from astropy.nddata import NDIOMixin __all__ = ['SpectrumCollection'] @@ -17,18 +17,18 @@ class SpectrumCollection(NDIOMixin): but have different spectral axes. Spectra that meet this requirement can be stored as multidimensional arrays, and thus can have operations performed on them faster than if they are treated as individual - :class:`~specutils.Spectrum1D` objects. + :class:`~specutils.Spectrum` objects. For multidimensional spectra that all have the *same* spectral axis, use a - :class:`~specutils.Spectrum1D` with dimension greater than 1. For a + :class:`~specutils.Spectrum` with dimension greater than 1. For a collection of spectra that have different shapes, use :class:`~specutils.SpectrumList`. For more on this topic, see :ref:`specutils-representation-overview`. The attributes on this class uses the same names and conventions as - :class:`~specutils.Spectrum1D`, allowing some operations to work the same. + :class:`~specutils.Spectrum`, allowing some operations to work the same. Where this does not work, the user can use standard indexing notation to - access individual :class:`~specutils.Spectrum1D` objects. + access individual :class:`~specutils.Spectrum` objects. Parameters ---------- @@ -111,7 +111,7 @@ def __getitem__(self, key): except KeyError: meta = self.meta - return Spectrum1D(flux=flux, spectral_axis=spectral_axis, + return Spectrum(flux=flux, spectral_axis=spectral_axis, uncertainty=uncertainty, wcs=wcs, mask=mask, meta=meta) @@ -119,12 +119,12 @@ def __getitem__(self, key): def from_spectra(cls, spectra): """ Create a spectrum collection from a set of individual - :class:`specutils.Spectrum1D` objects. + :class:`specutils.Spectrum` objects. Parameters ---------- spectra : list, ndarray - A list of :class:`~specutils.Spectrum1D` objects to be held in the + A list of :class:`~specutils.Spectrum` objects to be held in the collection. Currently the spectral_axis parameters (e.g. observer, radial_velocity) must be the same for each spectrum. """ diff --git a/specutils/spectra/spectrum_list.py b/specutils/spectra/spectrum_list.py index 194c7aa56..486a83658 100644 --- a/specutils/spectra/spectrum_list.py +++ b/specutils/spectra/spectrum_list.py @@ -6,12 +6,12 @@ class SpectrumList(list, NDIOMixin): """ - A list that is used to hold a list of `~specutils.Spectrum1D` objects + A list that is used to hold a list of `~specutils.Spectrum` objects The primary purpose of this class is to allow loaders to return a list of spectra that have different shapes. For spectra that have the same shape but different spectral axes, see `~specutils.SpectrumCollection`. For a spectrum or spectra that all share the same spectral axis, use - `~specutils.Spectrum1D`. For more on this topic, see + `~specutils.Spectrum`. For more on this topic, see :ref:`specutils-representation-overview`. """ diff --git a/specutils/spectra/spectrum_mixin.py b/specutils/spectra/spectrum_mixin.py index 7c1b7c237..3813e1f6f 100644 --- a/specutils/spectra/spectrum_mixin.py +++ b/specutils/spectra/spectrum_mixin.py @@ -60,14 +60,6 @@ def spectral_axis(self): """ return self._spectral_axis - @property - @deprecated('v1.1', alternative="spectral_axis.unit") - def spectral_axis_unit(self): - """ - Returns the units of the spectral axis. - """ - return u.Unit(self.wcs.world_axis_units[0]) - @property def flux(self): """ @@ -104,7 +96,7 @@ def with_flux_unit(self, unit, equivalencies=None, suppress_conversion=False): Returns ------- - `~specutils.Spectrum1D` + `~specutils.Spectrum` A new spectrum with the converted flux array """ new_spec = deepcopy(self) diff --git a/specutils/tests/test_analysis.py b/specutils/tests/test_analysis.py index 170b58cd3..e29c21605 100644 --- a/specutils/tests/test_analysis.py +++ b/specutils/tests/test_analysis.py @@ -8,7 +8,7 @@ from astropy.tests.helper import quantity_allclose from astropy.utils.exceptions import AstropyUserWarning -from ..spectra import Spectrum1D, SpectralRegion +from ..spectra import Spectrum, SpectralRegion from ..spectra.spectrum_collection import SpectrumCollection from ..spectra.spectral_axis import SpectralAxis @@ -28,7 +28,7 @@ def test_line_flux(): noise = np.random.normal(0., 0.01, frequencies.shape) * u.Jy flux = g(frequencies) + noise - spectrum = Spectrum1D(spectral_axis=frequencies, flux=flux) + spectrum = Spectrum(spectral_axis=frequencies, flux=flux) result = line_flux(spectrum) @@ -44,7 +44,7 @@ def test_line_flux(): def test_line_flux_uncertainty(): np.random.seed(42) - spec = Spectrum1D(spectral_axis=np.arange(10) * u.AA, + spec = Spectrum(spectral_axis=np.arange(10) * u.AA, flux=np.random.sample(10) * u.Jy, uncertainty=StdDevUncertainty(np.random.sample(10) * 0.01)) @@ -68,7 +68,7 @@ def test_line_flux_masked(): noise = 400 * np.random.random(flux.shape) * u.mJy flux += noise - spectrum = Spectrum1D(spectral_axis=wavelengths, flux=flux) + spectrum = Spectrum(spectral_axis=wavelengths, flux=flux) spectrum.uncertainty = StdDevUncertainty(noise) spectrum_masked = snr_threshold(spectrum, 10.) @@ -96,7 +96,7 @@ def test_equivalent_width(): noise = np.random.normal(0., 0.01, frequencies.shape) * u.Jy flux = g(frequencies) + noise + 1*u.Jy - spectrum = Spectrum1D(spectral_axis=frequencies, flux=flux) + spectrum = Spectrum(spectral_axis=frequencies, flux=flux) result = equivalent_width(spectrum) @@ -123,7 +123,7 @@ def test_equivalent_width_masked(): noise = 400 * np.random.random(flux.shape) * u.mJy flux += noise - spectrum = Spectrum1D(spectral_axis=wavelengths, flux=flux) + spectrum = Spectrum(spectral_axis=wavelengths, flux=flux) spectrum.uncertainty = StdDevUncertainty(noise) spectrum_masked = snr_threshold(spectrum, 10.) @@ -152,7 +152,7 @@ def test_equivalent_width_regions(): noise = np.random.normal(0., 0.001, frequencies.shape) * u.Jy flux = g(frequencies) + noise + 1*u.Jy - spec = Spectrum1D(spectral_axis=frequencies, flux=flux) + spec = Spectrum(spectral_axis=frequencies, flux=flux) result = equivalent_width(spec, regions=SpectralRegion(60*u.GHz, 10*u.GHz)) expected = -(np.sqrt(2*np.pi) * u.GHz) @@ -170,7 +170,7 @@ def test_equivalent_width_continuum(continuum): noise = np.random.normal(0., 0.01, frequencies.shape) * u.Jy flux = g(frequencies) + noise + continuum - spectrum = Spectrum1D(spectral_axis=frequencies, flux=flux) + spectrum = Spectrum(spectral_axis=frequencies, flux=flux) result = equivalent_width(spectrum, continuum=continuum) @@ -194,7 +194,7 @@ def test_equivalent_width_absorption(): noise = np.random.normal(0., 0.01, frequencies.shape) * u.Jy flux = continuum - g(frequencies) + noise - spectrum = Spectrum1D(spectral_axis=frequencies, flux=flux) + spectrum = Spectrum(spectral_axis=frequencies, flux=flux) result = equivalent_width(spectrum) @@ -226,7 +226,7 @@ def test_equivalent_width_bin_edges(bin_specification): noise = np.random.normal(0., 0.01, spectral_axis.shape) * flunit flux = continuum - g(spectral_axis) + noise - spectrum = Spectrum1D(spectral_axis=spectral_axis, flux=flux) + spectrum = Spectrum(spectral_axis=spectral_axis, flux=flux) result = equivalent_width(spectrum) @@ -317,14 +317,14 @@ def test_snr_multiple_flux(simulated_spectra): # uncertainty = StdDevUncertainty(0.1*np.random.random((5, 10))*u.mJy) - spec = Spectrum1D(spectral_axis=np.arange(10) * u.AA, + spec = Spectrum(spectral_axis=np.arange(10) * u.AA, flux=np.random.sample((5, 10)) * u.Jy, uncertainty=uncertainty) snr_spec = snr(spec) assert np.allclose(np.array(snr_spec), [18.20863867, 31.89475309, 14.51598119, 22.24603204, 32.01461421]) uncertainty = StdDevUncertainty(0.1*np.random.random(10)*u.mJy) - spec = Spectrum1D(spectral_axis=np.arange(10) * u.AA, flux=np.random.sample(10) * u.Jy, uncertainty=uncertainty) + spec = Spectrum(spectral_axis=np.arange(10) * u.AA, flux=np.random.sample(10) * u.Jy, uncertainty=uncertainty) snr_spec = snr(spec) assert np.allclose(np.array(snr_spec), 31.325265361800415) @@ -438,7 +438,7 @@ def test_snr_derived(): x = np.arange(1, 101) * u.um y = np.random.random(len(x))*u.Jy - spectrum = Spectrum1D(spectral_axis=x, flux=y) + spectrum = Spectrum(spectral_axis=x, flux=y) assert np.allclose(snr_derived(spectrum), 1.604666860424951) @@ -455,7 +455,7 @@ def test_snr_derived_masked(): x = np.arange(1, 101) * u.um y = np.random.random(len(x))*u.Jy mask = (np.random.randn(x.shape[0])) > 0 - spectrum = Spectrum1D(spectral_axis=x, flux=y, mask=mask) + spectrum = Spectrum(spectral_axis=x, flux=y, mask=mask) assert np.allclose(snr_derived(spectrum), 2.08175408) @@ -549,7 +549,7 @@ def test_inverted_centroid(simulated_spectra, analytic): spec_centroid_expected = (np.sum(spectrum.flux * spectrum.spectral_axis) / np.sum(spectrum.flux)) - spectrum_inverted = Spectrum1D(spectral_axis=spectrum.spectral_axis, + spectrum_inverted = Spectrum(spectral_axis=spectrum.spectral_axis, flux=-spectrum.flux, uncertainty=uncertainty) spec_centroid_inverted = centroid(spectrum_inverted, analytic=analytic) assert np.allclose(spec_centroid_inverted.value, spec_centroid_expected.value) @@ -569,7 +569,7 @@ def test_inverted_centroid_masked(simulated_spectra, analytic): spectrum.spectral_axis[~spectrum.mask]) / np.sum(spectrum.flux[~spectrum.mask])) - spectrum_inverted = Spectrum1D(spectral_axis=spectrum.spectral_axis, + spectrum_inverted = Spectrum(spectral_axis=spectrum.spectral_axis, flux=-spectrum.flux, mask=spectrum.mask, uncertainty=uncertainty) @@ -590,7 +590,7 @@ def test_centroid_multiple_flux(simulated_spectra, analytic): np.random.seed(42) - spec = Spectrum1D(spectral_axis=np.arange(1, 11) * u.um, + spec = Spectrum(spectral_axis=np.arange(1, 11) * u.um, flux=np.random.sample((5, 10)) * u.Jy) uncertainty = StdDevUncertainty(0.1*np.random.random(spec.flux.shape)*u.mJy) spec.uncertainty = uncertainty @@ -619,7 +619,7 @@ def test_gaussian_sigma_width(analytic): frequencies = np.linspace(0, mean*2, 101)[1:] * u.GHz g1 = models.Gaussian1D(amplitude=5*u.Jy, mean=mean*u.GHz, stddev=0.8*u.GHz) - spectrum = Spectrum1D(spectral_axis=frequencies, flux=g1(frequencies)) + spectrum = Spectrum(spectral_axis=frequencies, flux=g1(frequencies)) uncertainty = StdDevUncertainty(0.1*np.random.random(len(spectrum.flux))*u.mJy) spectrum.uncertainty = uncertainty @@ -647,7 +647,7 @@ def test_gaussian_sigma_width_masked(analytic): mask = (np.random.randn(frequencies.shape[0]) + 1.) > 0 - spectrum = Spectrum1D(spectral_axis=frequencies, flux=g1(frequencies), + spectrum = Spectrum(spectral_axis=frequencies, flux=g1(frequencies), uncertainty=uncertainty, mask=mask) result = gaussian_sigma_width(spectrum, analytic=analytic) @@ -673,7 +673,7 @@ def test_gaussian_sigma_width_regions(analytic): uncertainty = StdDevUncertainty(0.1*np.random.random(len(frequencies))*u.Jy) compound = g1 + g2 + g3 - spectrum = Spectrum1D(spectral_axis=frequencies, flux=compound(frequencies), + spectrum = Spectrum(spectral_axis=frequencies, flux=compound(frequencies), uncertainty=uncertainty) region1 = SpectralRegion(15*u.GHz, 5*u.GHz) @@ -722,10 +722,10 @@ def test_gaussian_sigma_width_multi_spectrum(analytic): flux += 0.001*np.random.random(flux.shape)*u.Jy - 0.0005*u.Jy if analytic: - spectra = Spectrum1D(spectral_axis=frequencies, flux=flux) + spectra = Spectrum(spectral_axis=frequencies, flux=flux) else: uncertainty = StdDevUncertainty(0.1*np.random.random(flux.shape)*u.Jy) - spectra = Spectrum1D(spectral_axis=frequencies, flux=flux, uncertainty=uncertainty) + spectra = Spectrum(spectral_axis=frequencies, flux=flux, uncertainty=uncertainty) results = gaussian_sigma_width(spectra, analytic=analytic) @@ -744,7 +744,7 @@ def test_gaussian_fwhm(analytic): frequencies = np.linspace(0, mean*2, 101)[1:] * u.GHz g1 = models.Gaussian1D(amplitude=5*u.Jy, mean=mean*u.GHz, stddev=0.8*u.GHz) - spectrum = Spectrum1D(spectral_axis=frequencies, flux=g1(frequencies)) + spectrum = Spectrum(spectral_axis=frequencies, flux=g1(frequencies)) uncertainty = StdDevUncertainty(0.1*np.random.random(len(spectrum.flux))*u.mJy) spectrum.uncertainty = uncertainty @@ -773,7 +773,7 @@ def test_gaussian_fwhm_masked(analytic): mask = (np.random.randn(frequencies.shape[0]) + 1.) > 0 - spectrum = Spectrum1D(spectral_axis=frequencies, flux=g1(frequencies), + spectrum = Spectrum(spectral_axis=frequencies, flux=g1(frequencies), uncertainty=uncertainty, mask=mask) result = gaussian_fwhm(spectrum, analytic=analytic) @@ -798,7 +798,7 @@ def test_gaussian_fwhm_uncentered(mean): uncertainty=StdDevUncertainty(0.1*np.random.random(len(frequencies))*u.Jy) g1 = models.Gaussian1D(amplitude=5*u.Jy, mean=mean*u.GHz, stddev=0.8*u.GHz) - spectrum = Spectrum1D(spectral_axis=frequencies, flux=g1(frequencies), + spectrum = Spectrum(spectral_axis=frequencies, flux=g1(frequencies), uncertainty=uncertainty) result = gaussian_fwhm(spectrum) @@ -817,7 +817,7 @@ def test_fwhm_masked(): g1 = models.Gaussian1D(amplitude=5*u.Jy, mean=2*u.GHz, stddev=stddev) mask = (np.random.randn(frequencies.shape[0]) + 1.) > 0 - spectrum = Spectrum1D(spectral_axis=frequencies, flux=g1(frequencies), + spectrum = Spectrum(spectral_axis=frequencies, flux=g1(frequencies), mask=mask) result = fwhm(spectrum) @@ -829,7 +829,7 @@ def test_fwhm_masked(): wavelengths = np.linspace(1, 10, 100) * u.um flux = (1.0 / wavelengths.value) * u.Jy # highest point first. - spectrum = Spectrum1D(spectral_axis=wavelengths, flux=flux) + spectrum = Spectrum(spectral_axis=wavelengths, flux=flux) result = fwhm(spectrum) # Note that this makes a little more sense than the previous version; # since the maximum value occurs at wavelength=1, and the half-value of @@ -842,7 +842,7 @@ def test_fwhm_masked(): wavelengths = np.linspace(1, 10, 31) * u.um flux = (1.0 / wavelengths.value) * u.Jy # highest point first. - spectrum = Spectrum1D(spectral_axis=wavelengths, flux=flux) + spectrum = Spectrum(spectral_axis=wavelengths, flux=flux) result = fwhm(spectrum) assert quantity_allclose(result, 1.01 * u.um) @@ -851,7 +851,7 @@ def test_fwhm_masked(): wavelengths = np.linspace(1, 10, 100) * u.um flux = wavelengths.value * u.Jy # highest point last. - spectrum = Spectrum1D(spectral_axis=wavelengths, flux=flux) + spectrum = Spectrum(spectral_axis=wavelengths, flux=flux) result = fwhm(spectrum) assert result == 5 * u.um @@ -859,7 +859,7 @@ def test_fwhm_masked(): wavelengths = np.linspace(1, 10, 100) * u.um flux = np.ones(wavelengths.shape) * u.Jy # highest point last. - spectrum = Spectrum1D(spectral_axis=wavelengths, flux=flux) + spectrum = Spectrum(spectral_axis=wavelengths, flux=flux) result = fwhm(spectrum) assert result == 9 * u.um @@ -873,7 +873,7 @@ def test_fwhm(): stddev = 0.8*u.GHz g1 = models.Gaussian1D(amplitude=5*u.Jy, mean=2*u.GHz, stddev=stddev) - spectrum = Spectrum1D(spectral_axis=frequencies, flux=g1(frequencies)) + spectrum = Spectrum(spectral_axis=frequencies, flux=g1(frequencies)) result = fwhm(spectrum) @@ -884,7 +884,7 @@ def test_fwhm(): wavelengths = np.linspace(1, 10, 100) * u.um flux = (1.0 / wavelengths.value) * u.Jy # highest point first. - spectrum = Spectrum1D(spectral_axis=wavelengths, flux=flux) + spectrum = Spectrum(spectral_axis=wavelengths, flux=flux) result = fwhm(spectrum) # Note that this makes a little more sense than the previous version; # since the maximum value occurs at wavelength=1, and the half-value of @@ -897,7 +897,7 @@ def test_fwhm(): wavelengths = np.linspace(1, 10, 31) * u.um flux = (1.0 / wavelengths.value) * u.Jy # highest point first. - spectrum = Spectrum1D(spectral_axis=wavelengths, flux=flux) + spectrum = Spectrum(spectral_axis=wavelengths, flux=flux) result = fwhm(spectrum) assert quantity_allclose(result, 1.01 * u.um) @@ -905,7 +905,7 @@ def test_fwhm(): wavelengths = np.linspace(1, 10, 100) * u.um flux = wavelengths.value * u.Jy # highest point last. - spectrum = Spectrum1D(spectral_axis=wavelengths, flux=flux) + spectrum = Spectrum(spectral_axis=wavelengths, flux=flux) result = fwhm(spectrum) assert result == 5*u.um @@ -913,7 +913,7 @@ def test_fwhm(): wavelengths = np.linspace(1, 10, 100) * u.um flux = np.ones(wavelengths.shape) * u.Jy # highest point last. - spectrum = Spectrum1D(spectral_axis=wavelengths, flux=flux) + spectrum = Spectrum(spectral_axis=wavelengths, flux=flux) result = fwhm(spectrum) assert result == 9*u.um @@ -934,7 +934,7 @@ def test_fwhm_multi_spectrum(): flux[1] = g2(frequencies) flux[2] = g3(frequencies) - spectra = Spectrum1D(spectral_axis=frequencies, flux=flux) + spectra = Spectrum(spectral_axis=frequencies, flux=flux) results = fwhm(spectra) @@ -954,8 +954,8 @@ def test_fwzi(): flux = g(disp) flux_with_noise = g(disp) + ((np.random.sample(disp.size) - 0.5) * 0.1) * u.Jy - spec = Spectrum1D(spectral_axis=disp, flux=flux) - spec_with_noise = Spectrum1D(spectral_axis=disp, flux=flux_with_noise) + spec = Spectrum(spectral_axis=disp, flux=flux) + spec_with_noise = Spectrum(spectral_axis=disp, flux=flux_with_noise) assert quantity_allclose(fwzi(spec), 226.89732509 * u.AA) assert quantity_allclose(fwzi(spec_with_noise), 106.99998944 * u.AA) @@ -977,7 +977,7 @@ def test_fwzi_masked(): uncertainty = StdDevUncertainty(0.1*np.random.random(len(disp))*u.Jy) mask = (np.random.randn(disp.shape[0]) - 0.5) > 0 - spec = Spectrum1D(spectral_axis=disp, flux=flux, uncertainty=uncertainty, + spec = Spectrum(spectral_axis=disp, flux=flux, uncertainty=uncertainty, mask=mask) assert quantity_allclose(fwzi(spec), 35.9996284 * u.AA) @@ -998,7 +998,7 @@ def test_fwzi_multi_spectrum(): for i in range(3): flux[i] = models.Gaussian1D(*params[i])(disp) - spec = Spectrum1D(spectral_axis=disp, flux=flux * u.Jy) + spec = Spectrum(spectral_axis=disp, flux=flux * u.Jy) expected = [113.51706001 * u.AA, 567.21252727 * u.AA, 499.5024546 * u.AA] @@ -1010,21 +1010,21 @@ def test_is_continuum_below_threshold(): # No mask, no uncertainty wavelengths = [300, 500, 1000] * u.nm data = [0.001, -0.003, 0.003] * u.Jy - spectrum = Spectrum1D(spectral_axis=wavelengths, flux=data) + spectrum = Spectrum(spectral_axis=wavelengths, flux=data) assert is_continuum_below_threshold(spectrum, threshold=0.1*u.Jy) == True # noqa # # No mask, no uncertainty, threshold is float # wavelengths = [300, 500, 1000] * u.nm # data = [0.0081, 0.0043, 0.0072] * u.Jy -# spectrum = Spectrum1D(spectral_axis=wavelengths, flux=data) +# spectrum = Spectrum(spectral_axis=wavelengths, flux=data) # assert True == is_continuum_below_threshold(spectrum, threshold=0.1) # No mask, with uncertainty wavelengths = [300, 500, 1000] * u.nm data = [0.03, 0.029, 0.031] * u.Jy uncertainty = StdDevUncertainty([1.01, 1.03, 1.01] * u.Jy) - spectrum = Spectrum1D(spectral_axis=wavelengths, flux=data, + spectrum = Spectrum(spectral_axis=wavelengths, flux=data, uncertainty=uncertainty) assert is_continuum_below_threshold(spectrum, threshold=0.1*u.Jy) == True # noqa @@ -1034,7 +1034,7 @@ def test_is_continuum_below_threshold(): data = [0.01, 1.029, 0.013] * u.Jy mask = np.array([False, True, False]) uncertainty = StdDevUncertainty([1.01, 1.13, 1.1] * u.Jy) - spectrum = Spectrum1D(spectral_axis=wavelengths, flux=data, + spectrum = Spectrum(spectral_axis=wavelengths, flux=data, uncertainty=uncertainty, mask=mask) assert is_continuum_below_threshold(spectrum, threshold=0.1*u.Jy) == True # noqa @@ -1044,7 +1044,7 @@ def test_is_continuum_below_threshold(): data = [10.03, 10.029, 10.033] * u.Jy mask = np.array([False, False, False]) uncertainty = StdDevUncertainty([1.01, 1.13, 1.1] * u.Jy) - spectrum = Spectrum1D(spectral_axis=wavelengths, flux=data, + spectrum = Spectrum(spectral_axis=wavelengths, flux=data, uncertainty=uncertainty, mask=mask) with pytest.warns(AstropyUserWarning, @@ -1062,7 +1062,7 @@ def test_moment(): noise = np.random.normal(0., 0.01, frequencies.shape) * u.Jy flux = g(frequencies) + noise - spectrum = Spectrum1D(spectral_axis=frequencies, flux=flux) + spectrum = Spectrum(spectral_axis=frequencies, flux=flux) moment_0 = moment(spectrum, order=0) assert moment_0.unit.is_equivalent(u.Jy) @@ -1095,7 +1095,7 @@ def test_moment_cube(): flux_multid = np.broadcast_to(flux, [9, 10, flux.shape[0]]) * u.Jy - spectrum = Spectrum1D(spectral_axis=frequencies, flux=flux_multid) + spectrum = Spectrum(spectral_axis=frequencies, flux=flux_multid) moment_1 = moment(spectrum, order=1) @@ -1140,7 +1140,7 @@ def test_moment_cube_order_2(): flux_multid = np.broadcast_to(flux, [10, 10, flux.shape[0]]) * u.Jy - spectrum = Spectrum1D(spectral_axis=frequencies, flux=flux_multid) + spectrum = Spectrum(spectral_axis=frequencies, flux=flux_multid) # higher order moment_2 = moment(spectrum, order=2) @@ -1177,7 +1177,7 @@ def test_moment_cube_order_1_to_6(): flux_multid = np.broadcast_to(flux, [9, 10, flux.shape[0]]) * u.Jy - spectrum = Spectrum1D(spectral_axis=frequencies, flux=flux_multid) + spectrum = Spectrum(spectral_axis=frequencies, flux=flux_multid) moment_1 = moment(spectrum, order=1) @@ -1221,13 +1221,13 @@ def test_moment_collection(): g = models.Gaussian1D(amplitude=1*u.Jy, mean=10*u.GHz, stddev=1*u.GHz) noise = np.random.normal(0., 0.01, frequencies.shape) * u.Jy flux = g(frequencies) + noise - s1 = Spectrum1D(spectral_axis=frequencies, flux=flux) + s1 = Spectrum(spectral_axis=frequencies, flux=flux) frequencies = np.linspace(200, 2, 10000) * u.GHz g = models.Gaussian1D(amplitude=2*u.Jy, mean=20*u.GHz, stddev=2*u.GHz) noise = np.random.normal(0., 0.02, frequencies.shape) * u.Jy flux = g(frequencies) + noise - s2 = Spectrum1D(spectral_axis=frequencies, flux=flux) + s2 = Spectrum(spectral_axis=frequencies, flux=flux) collection = SpectrumCollection.from_spectra([s1, s2]) diff --git a/specutils/tests/test_arithmetic.py b/specutils/tests/test_arithmetic.py index b432609b7..dade46c25 100644 --- a/specutils/tests/test_arithmetic.py +++ b/specutils/tests/test_arithmetic.py @@ -2,7 +2,7 @@ from astropy.tests.helper import assert_quantity_allclose import numpy as np -from ..spectra.spectrum1d import Spectrum1D +from ..spectra.spectrum import Spectrum def test_spectral_axes(): @@ -11,9 +11,9 @@ def test_spectral_axes(): flux3 = flux1 + flux2 - spec1 = Spectrum1D(spectral_axis=np.arange(1, 50) * u.nm, + spec1 = Spectrum(spectral_axis=np.arange(1, 50) * u.nm, flux=flux1 * u.Jy) - spec2 = Spectrum1D(spectral_axis=np.arange(1, 50) * u.nm, + spec2 = Spectrum(spectral_axis=np.arange(1, 50) * u.nm, flux=flux2 * u.Jy) spec3 = spec1 + spec2 @@ -28,7 +28,7 @@ def test_add_basic_spectra(simulated_spectra): flux2 = simulated_spectra.s1_um_mJy_e2_flux flux3 = flux1 + flux2 - # Calculate using the spectrum1d/nddata code + # Calculate using the spectrum/nddata code spec3 = simulated_spectra.s1_um_mJy_e1 + simulated_spectra.s1_um_mJy_e2 assert np.allclose(spec3.flux.value, flux3) @@ -42,7 +42,7 @@ def test_add_diff_flux_prefix(simulated_spectra): flux2 = simulated_spectra.s1_AA_nJy_e4_flux flux3 = flux1 + (flux2 / 1000000) - # Calculate using the spectrum1d/nddata code + # Calculate using the spectrum/nddata code spec3 = simulated_spectra.s1_AA_mJy_e3 + simulated_spectra.s1_AA_nJy_e4 assert np.allclose(spec3.flux.value, flux3) @@ -55,7 +55,7 @@ def test_subtract_basic_spectra(simulated_spectra): flux2 = simulated_spectra.s1_um_mJy_e2_flux flux3 = flux2 - flux1 - # Calculate using the spectrum1d/nddata code + # Calculate using the spectrum/nddata code spec3 = simulated_spectra.s1_um_mJy_e2 - simulated_spectra.s1_um_mJy_e1 assert np.allclose(spec3.flux.value, flux3) @@ -68,7 +68,7 @@ def test_divide_basic_spectra(simulated_spectra): flux2 = simulated_spectra.s1_um_mJy_e2_flux flux3 = flux1 / flux2 - # Calculate using the spectrum1d/nddata code + # Calculate using the spectrum/nddata code spec3 = simulated_spectra.s1_um_mJy_e1 / simulated_spectra.s1_um_mJy_e2 assert np.allclose(spec3.flux.value, flux3) @@ -81,7 +81,7 @@ def test_multiplication_basic_spectra(simulated_spectra): flux2 = simulated_spectra.s1_um_mJy_e2_flux flux3 = flux1 * flux2 - # Calculate using the spectrum1d/nddata code + # Calculate using the spectrum/nddata code spec3 = simulated_spectra.s1_um_mJy_e1 * simulated_spectra.s1_um_mJy_e2 assert np.allclose(spec3.flux.value, flux3) @@ -89,7 +89,7 @@ def test_multiplication_basic_spectra(simulated_spectra): def test_add_diff_spectral_axis(simulated_spectra): - # Calculate using the spectrum1d/nddata code + # Calculate using the spectrum/nddata code spec3 = simulated_spectra.s1_um_mJy_e1 + simulated_spectra.s1_AA_mJy_e3 # noqa @@ -110,8 +110,8 @@ def test_mask_nans(): flux2 = np.random.random(10) nan_idx = [1, 3, 5] flux2[nan_idx] = np.nan - spec1 = Spectrum1D(spectral_axis=np.arange(10) * u.nm, flux=flux1 * u.Jy) - spec2 = Spectrum1D(spectral_axis=np.arange(10) * u.nm, flux=flux2 * u.Jy) + spec1 = Spectrum(spectral_axis=np.arange(10) * u.nm, flux=flux1 * u.Jy) + spec2 = Spectrum(spectral_axis=np.arange(10) * u.nm, flux=flux2 * u.Jy) spec3 = spec1 + spec2 diff --git a/specutils/tests/test_continuum.py b/specutils/tests/test_continuum.py index 7ffd5a2c2..cca79fd48 100644 --- a/specutils/tests/test_continuum.py +++ b/specutils/tests/test_continuum.py @@ -5,7 +5,7 @@ from astropy.modeling.polynomial import Chebyshev1D from astropy.utils.exceptions import AstropyUserWarning -from ..spectra.spectrum1d import Spectrum1D +from ..spectra.spectrum import Spectrum from ..spectra import SpectralRegion from ..fitting.continuum import fit_generic_continuum, fit_continuum from ..manipulation.smoothing import median_smooth @@ -33,7 +33,7 @@ def test_continuum_fit(): """ x_single_continuum, y_single_continuum = single_peak_continuum() - s_single_continuum = Spectrum1D(flux=y_single_continuum*u.Jy, spectral_axis=x_single_continuum*u.um) + s_single_continuum = Spectrum(flux=y_single_continuum*u.Jy, spectral_axis=x_single_continuum*u.um) with pytest.warns(AstropyUserWarning, match='Model is linear in parameters'): g1_fit = fit_generic_continuum(s_single_continuum) @@ -56,7 +56,7 @@ def test_continuum_calculation(): """ x_single_continuum, y_single_continuum = single_peak_continuum() - spectrum = Spectrum1D(flux=y_single_continuum*u.Jy, spectral_axis=x_single_continuum*u.um) + spectrum = Spectrum(flux=y_single_continuum*u.Jy, spectral_axis=x_single_continuum*u.um) with pytest.warns(AstropyUserWarning, match='Model is linear in parameters'): g1_fit = fit_generic_continuum(spectrum) @@ -79,7 +79,7 @@ def test_continuum_full_window(): """ x_single_continuum, y_single_continuum = single_peak_continuum() - spectrum = Spectrum1D(flux=y_single_continuum*u.Jy, spectral_axis=x_single_continuum*u.um) + spectrum = Spectrum(flux=y_single_continuum*u.Jy, spectral_axis=x_single_continuum*u.um) # Smooth in the same way fit_generic_continuum does. spectrum_smoothed = median_smooth(spectrum, 3) @@ -102,7 +102,7 @@ def test_continuum_spectral_region(): """ x_single_continuum, y_single_continuum = single_peak_continuum() - spectrum = Spectrum1D(flux=y_single_continuum*u.Jy, spectral_axis=x_single_continuum*u.um) + spectrum = Spectrum(flux=y_single_continuum*u.Jy, spectral_axis=x_single_continuum*u.um) # Smooth in the same way fit_generic_continuum does. spectrum_smoothed = median_smooth(spectrum, 3) @@ -131,7 +131,7 @@ def test_continuum_window_no_noise(): """ x_single_continuum, y_single_continuum = single_peak_continuum(noise=0.) - spectrum = Spectrum1D(flux=y_single_continuum*u.Jy, spectral_axis=x_single_continuum*u.um) + spectrum = Spectrum(flux=y_single_continuum*u.Jy, spectral_axis=x_single_continuum*u.um) # Smooth in the same way fit_generic_continuum does. spectrum_smoothed = median_smooth(spectrum, 3) @@ -165,7 +165,7 @@ def test_double_continuum_window(): Fit to no-noise spectrum comprised of a exponential continuum plus an emission Gaussian """ x_single_continuum, y_single_continuum = single_peak_continuum(noise=0.,constant_continuum=False) - spectrum = Spectrum1D(flux=y_single_continuum*u.Jy, spectral_axis=x_single_continuum*u.um) + spectrum = Spectrum(flux=y_single_continuum*u.Jy, spectral_axis=x_single_continuum*u.um) # Smooth in the same way fit_generic_continuum does. spectrum_smoothed = median_smooth(spectrum, 3) @@ -200,7 +200,7 @@ def test_double_continuum_window_alternate(): """ x_single_continuum, y_single_continuum = single_peak_continuum(noise=0.,constant_continuum=False) - spectrum = Spectrum1D(flux=y_single_continuum*u.Jy, spectral_axis=x_single_continuum*u.um) + spectrum = Spectrum(flux=y_single_continuum*u.Jy, spectral_axis=x_single_continuum*u.um) # Smooth in the same way fit_generic_continuum does. spectrum_smoothed = median_smooth(spectrum, 3) diff --git a/specutils/tests/test_correlation.py b/specutils/tests/test_correlation.py index 42c671ea9..a1c18eafd 100644 --- a/specutils/tests/test_correlation.py +++ b/specutils/tests/test_correlation.py @@ -5,7 +5,7 @@ from astropy.nddata import StdDevUncertainty from astropy.modeling import models -from ..spectra.spectrum1d import Spectrum1D +from ..spectra.spectrum import Spectrum from ..analysis import correlation @@ -25,13 +25,13 @@ def test_autocorrelation(): flux1 = f1 + g1(spec_axis) # Observed spectrum must have a rest wavelength value set in. - spec1 = Spectrum1D(spectral_axis=spec_axis, + spec1 = Spectrum(spectral_axis=spec_axis, flux=flux1, uncertainty=StdDevUncertainty(np.random.sample(size), unit='Jy'), velocity_convention='optical', rest_value=5020.*u.AA) - spec2 = Spectrum1D(spectral_axis=spec_axis, + spec2 = Spectrum(spectral_axis=spec_axis, flux=flux1, uncertainty=StdDevUncertainty(np.random.sample(size), unit='Jy')) @@ -51,7 +51,7 @@ def test_autocorrelation(): assert maximum == midpoint # Test that this works without uncertainty - spec1 = Spectrum1D(spectral_axis=spec_axis, + spec1 = Spectrum(spectral_axis=spec_axis, flux=flux1, velocity_convention='optical', rest_value=5020.*u.AA) @@ -93,13 +93,13 @@ def test_correlation(): flux2 = f2 + g2(spec_axis) # Observed spectrum must have a rest wavelength value set in. - spec1 = Spectrum1D(spectral_axis=spec_axis, + spec1 = Spectrum(spectral_axis=spec_axis, flux=flux1, uncertainty=StdDevUncertainty(np.random.sample(size), unit='Jy'), velocity_convention='optical', rest_value=rest_value) - spec2 = Spectrum1D(spectral_axis=spec_axis, + spec2 = Spectrum(spectral_axis=spec_axis, flux=flux2, uncertainty=StdDevUncertainty(np.random.sample(size), unit='Jy')) @@ -172,13 +172,13 @@ def test_correlation_zero_padding(): # Observed spectrum must have a rest wavelength value set in. # Uncertainty is arbitrary. - spec1 = Spectrum1D(spectral_axis=spec_axis_1, + spec1 = Spectrum(spectral_axis=spec_axis_1, flux=flux1, uncertainty=StdDevUncertainty(np.random.sample(size1), unit='Jy'), velocity_convention='optical', rest_value=rest_value) - spec2 = Spectrum1D(spectral_axis=spec_axis_2, + spec2 = Spectrum(spectral_axis=spec_axis_2, flux=flux2, uncertainty=StdDevUncertainty(np.random.sample(size2), unit='Jy')) @@ -236,13 +236,13 @@ def test_correlation_random_lines(): # Observed spectrum must have a rest wavelength value set in. # Uncertainty is arbitrary. - spec1 = Spectrum1D(spectral_axis=spec_axis_1, + spec1 = Spectrum(spectral_axis=spec_axis_1, flux=flux1, uncertainty=StdDevUncertainty(np.random.sample(size1), unit='Jy'), velocity_convention='optical', rest_value=rest_value) - spec2 = Spectrum1D(spectral_axis=spec_axis_2, + spec2 = Spectrum(spectral_axis=spec_axis_2, flux=flux2, uncertainty=StdDevUncertainty(np.random.sample(size2), unit='Jy')) diff --git a/specutils/tests/test_fitting.py b/specutils/tests/test_fitting.py index 329863297..bbd7088e2 100644 --- a/specutils/tests/test_fitting.py +++ b/specutils/tests/test_fitting.py @@ -11,7 +11,7 @@ find_lines_threshold, fit_lines) from ..manipulation import (extract_region, noise_region_uncertainty, spectrum_from_model) -from ..spectra import SpectralRegion, Spectrum1D +from ..spectra import SpectralRegion, Spectrum def single_peak(): @@ -63,7 +63,7 @@ def test_find_lines_derivative(): # Create the spectrum to fit x_double, y_double = double_peak_absorption_and_emission() - spectrum = Spectrum1D(flux=y_double*u.Jy, spectral_axis=x_double*u.um) + spectrum = Spectrum(flux=y_double*u.Jy, spectral_axis=x_double*u.um) # Derivative method with pytest.warns(AstropyUserWarning, @@ -81,7 +81,7 @@ def test_find_lines_threshold(): # Create the spectrum to fit x_double, y_double = double_peak_absorption_and_emission() - spectrum = Spectrum1D(flux=y_double*u.Jy, spectral_axis=x_double*u.um) + spectrum = Spectrum(flux=y_double*u.Jy, spectral_axis=x_double*u.um) # Derivative method noise_region = SpectralRegion(0*u.um, 3*u.um) @@ -104,7 +104,7 @@ def test_single_peak_estimate(): # Create the spectrum x_single, y_single = single_peak() - s_single = Spectrum1D(flux=y_single*u.Jy, spectral_axis=x_single*u.um) + s_single = Spectrum(flux=y_single*u.Jy, spectral_axis=x_single*u.um) # # Estimate parameter Gaussian1D @@ -181,7 +181,7 @@ def test_single_peak_fit(): # Create the spectrum x_single, y_single = single_peak() - s_single = Spectrum1D(flux=y_single*u.Jy, spectral_axis=x_single*u.um) + s_single = Spectrum(flux=y_single*u.Jy, spectral_axis=x_single*u.um) # Fit the spectrum g_init = models.Gaussian1D(amplitude=3.*u.Jy, mean=6.1*u.um, stddev=1.*u.um) @@ -222,10 +222,10 @@ def calculate_rms(x, init_mod, implicit_weights, valid_uncertainty): y = np.random.poisson(ymod) unc = np.sqrt(ymod) if valid_uncertainty: - spec = Spectrum1D(spectral_axis=x, flux=y * u.Jy, + spec = Spectrum(spectral_axis=x, flux=y * u.Jy, uncertainty=StdDevUncertainty(unc * u.Jy)) else: - spec = Spectrum1D(spectral_axis=x, flux=y * u.Jy, + spec = Spectrum(spectral_axis=x, flux=y * u.Jy, uncertainty=None) weights = 'unc' if implicit_weights else unc ** -1 @@ -254,7 +254,7 @@ def test_single_peak_fit_window(): # Create the sepctrum x_single, y_single = single_peak() - s_single = Spectrum1D(flux=y_single*u.Jy, spectral_axis=x_single*u.um) + s_single = Spectrum(flux=y_single*u.Jy, spectral_axis=x_single*u.um) # Fit the spectrum g_init = models.Gaussian1D(amplitude=3.*u.Jy, mean=5.5*u.um, stddev=1.*u.um) @@ -278,7 +278,7 @@ def test_single_peak_fit_tuple_window(): # Create the spectrum to fit x_single, y_single = single_peak() - s_single = Spectrum1D(flux=y_single*u.Jy, spectral_axis=x_single*u.um) + s_single = Spectrum(flux=y_single*u.Jy, spectral_axis=x_single*u.um) # Fit the spectrum g_init = models.Gaussian1D(amplitude=3.*u.Jy, mean=5.5*u.um, stddev=1.*u.um) @@ -302,7 +302,7 @@ def test_double_peak_fit(): # Create the spectrum to fit x_double, y_double = double_peak() - s_double = Spectrum1D(flux=y_double*u.Jy, spectral_axis=x_double*u.um) + s_double = Spectrum(flux=y_double*u.Jy, spectral_axis=x_double*u.um) # Fit the spectrum g1_init = models.Gaussian1D(amplitude=2.3*u.Jy, mean=5.6*u.um, stddev=0.1*u.um) @@ -327,7 +327,7 @@ def test_double_peak_fit_tuple_window(): # Create the spectrum to fit x_double, y_double = double_peak() - s_double = Spectrum1D(flux=y_double*u.Jy, spectral_axis=x_double*u.um, rest_value=0*u.um) + s_double = Spectrum(flux=y_double*u.Jy, spectral_axis=x_double*u.um, rest_value=0*u.um) # Fit the spectrum. g2_init = models.Gaussian1D(amplitude=1.*u.Jy, mean=4.7*u.um, stddev=0.2*u.um) @@ -351,7 +351,7 @@ def test_double_peak_fit_window(): # Create the specturm to fit x_double, y_double = double_peak() - s_double = Spectrum1D(flux=y_double*u.Jy, spectral_axis=x_double*u.um, rest_value=0*u.um) + s_double = Spectrum(flux=y_double*u.Jy, spectral_axis=x_double*u.um, rest_value=0*u.um) # Fit the spectrum g2_init = models.Gaussian1D(amplitude=1.*u.Jy, mean=4.7*u.um, stddev=0.2*u.um) @@ -375,7 +375,7 @@ def test_double_peak_fit_separate_window(): # Create the spectrum to fit x_double, y_double = double_peak() - s_double = Spectrum1D(flux=y_double*u.Jy, spectral_axis=x_double*u.um, rest_value=0*u.um) + s_double = Spectrum(flux=y_double*u.Jy, spectral_axis=x_double*u.um, rest_value=0*u.um) # Fit the spectrum gl_init = models.Gaussian1D(amplitude=1.*u.Jy, mean=4.8*u.um, stddev=0.2*u.um) @@ -409,7 +409,7 @@ def test_double_peak_fit_separate_window_tuple_window(): """ x_double, y_double = double_peak() - s_double = Spectrum1D(flux=y_double*u.Jy, spectral_axis=x_double*u.um, rest_value=0*u.um) + s_double = Spectrum(flux=y_double*u.Jy, spectral_axis=x_double*u.um, rest_value=0*u.um) g1_init = models.Gaussian1D(amplitude=2.*u.Jy, mean=5.3*u.um, stddev=0.2*u.um) g2_init = models.Gaussian1D(amplitude=1.*u.Jy, mean=4.9*u.um, stddev=0.1*u.um) @@ -442,7 +442,7 @@ def test_double_peak_fit_with_exclusion(): """ x_double, y_double = double_peak() - s_double = Spectrum1D(flux=y_double*u.Jy, spectral_axis=x_double*u.um, rest_value=0*u.um) + s_double = Spectrum(flux=y_double*u.Jy, spectral_axis=x_double*u.um, rest_value=0*u.um) g1_init = models.Gaussian1D(amplitude=1.*u.Jy, mean=4.9*u.um, stddev=0.2*u.um) g1_fit = fit_lines(s_double, g1_init, exclude_regions=[SpectralRegion(5.2*u.um, 5.8*u.um)]) @@ -472,7 +472,7 @@ def test_fixed_parameters(): x = np.linspace(0., 10., 200) y = 3 * np.exp(-0.5 * (x - 6.3)**2 / 0.8**2) y += np.random.normal(0., 0.2, x.shape) - spectrum = Spectrum1D(flux=y*u.Jy, spectral_axis=x*u.um) + spectrum = Spectrum(flux=y*u.Jy, spectral_axis=x*u.um) # Test passing fixed and bounds parameters g_init = models.Gaussian1D(amplitude=3.*u.Jy, mean=6.1*u.um, stddev=1.*u.um, @@ -503,7 +503,7 @@ def test_name_preservation_after_fitting(): x = np.linspace(0., 10., 200) y = 3 * np.exp(-0.5 * (x - 6.3)**2 / 0.8**2) y += np.random.normal(0., 0.2, x.shape) - spectrum = Spectrum1D(flux=y*u.Jy, spectral_axis=x*u.um) + spectrum = Spectrum(flux=y*u.Jy, spectral_axis=x*u.um) subcomponents = models.Gaussian1D(name="Model I") * models.Gaussian1D(name="Second Model") c_model = subcomponents + models.Gaussian1D(name="Model 3") @@ -525,7 +525,7 @@ def test_ignore_units(): # Create the spectrum x_single, y_single = single_peak() - s_single = Spectrum1D(flux=y_single*u.Jy, spectral_axis=x_single*u.um) + s_single = Spectrum(flux=y_single*u.Jy, spectral_axis=x_single*u.um) # Fit the spectrum g_init = models.Gaussian1D(amplitude=3, mean=6.1, stddev=1.) @@ -548,7 +548,7 @@ def test_ignore_units(): # Create the spectrum to fit x_double, y_double = double_peak() - s_double = Spectrum1D(flux=y_double*u.Jy, spectral_axis=x_double*u.um) + s_double = Spectrum(flux=y_double*u.Jy, spectral_axis=x_double*u.um) # Fit the spectrum g1_init = models.Gaussian1D(amplitude=2.3, mean=5.6, stddev=0.1) @@ -573,7 +573,7 @@ def test_fitter_parameters(): # Create the spectrum x_single, y_single = single_peak() - s_single = Spectrum1D(flux=y_single*u.Jy, spectral_axis=x_single*u.um) + s_single = Spectrum(flux=y_single*u.Jy, spectral_axis=x_single*u.um) # Fit the spectrum g_init = models.Gaussian1D(amplitude=3.*u.Jy, mean=6.1*u.um, stddev=1.*u.um) @@ -609,7 +609,7 @@ def test_spectrum_from_model(): y_continuum = 3.2 * np.exp(-0.5 * (x - 5.6)**2 / 4.8**2) y += y_continuum - spectrum = Spectrum1D(flux=y*u.Jy, spectral_axis=x*u.um) + spectrum = Spectrum(flux=y*u.Jy, spectral_axis=x*u.um) # Unitless test chebyshev = models.Chebyshev1D(3, c0=0.1, c1=4, c2=5) @@ -640,7 +640,7 @@ def test_masking(): Test fitting spectra with masks """ wl, flux = double_peak() - s = Spectrum1D(flux=flux*u.Jy, spectral_axis=wl*u.um) + s = Spectrum(flux=flux*u.Jy, spectral_axis=wl*u.um) # first we fit a single gaussian to the double_peak model, using the # known-good second peak (but a bit higher in amplitude). It should lock @@ -651,7 +651,7 @@ def test_masking(): # now create a spectrum where the region around the second peak is masked. # The fit should now go to the *first* peak - s_msk = Spectrum1D(flux=flux*u.Jy, spectral_axis=wl*u.um, mask=(5.1 < wl)&(wl < 6.1)) + s_msk = Spectrum(flux=flux*u.Jy, spectral_axis=wl*u.um, mask=(5.1 < wl)&(wl < 6.1)) g_fit2 = fit_lines(s_msk, g_init) assert u.allclose(g_fit2.mean.value, 4.6, atol=.1) @@ -670,13 +670,13 @@ def test_window_extras(): window_region = SpectralRegion(4*u.um, 8*u.um) mask = (5.1 < wl) & (wl < 6.1) - s_msk = Spectrum1D(flux=flux*u.Jy, spectral_axis=wl*u.um, mask=mask) + s_msk = Spectrum(flux=flux*u.Jy, spectral_axis=wl*u.um, mask=mask) g_fit1 = fit_lines(s_msk, g_init, window=window_region) assert u.allclose(g_fit1.mean.value, 4.6, atol=.1) # check that if we weight instead of masking, we get the same result - s = Spectrum1D(flux=flux*u.Jy, spectral_axis=wl*u.um) + s = Spectrum(flux=flux*u.Jy, spectral_axis=wl*u.um) weights = (~mask).astype(float) g_fit2 = fit_lines(s, g_init, weights=weights, window=window_region) assert u.allclose(g_fit2.mean.value, 4.6, atol=.1) @@ -689,7 +689,7 @@ def test_window_extras(): def test_fit_subspectrum(): # Create test spectrum - spectrum = Spectrum1D( + spectrum = Spectrum( flux=np.random.sample(10) * u.Jy, spectral_axis=(np.arange(10) + 6558) * u.AA, rest_value=6561.16*u.angstrom, diff --git a/specutils/tests/test_io.py b/specutils/tests/test_io.py index 01ee22a8c..62504c9e8 100644 --- a/specutils/tests/test_io.py +++ b/specutils/tests/test_io.py @@ -12,7 +12,7 @@ from astropy.table import Table from astropy.utils.exceptions import AstropyUserWarning -from specutils import Spectrum1D, SpectrumList +from specutils import Spectrum, SpectrumList from specutils.io import data_loader from specutils.io.parsing_utils import generic_spectrum_from_table # or something like that from specutils.io.registers import _astropy_has_priorities @@ -27,7 +27,7 @@ def test_generic_spectrum_from_table(recwarn): flux = np.ones(len(wave))*1.e-14*u.Jy table = Table([wave, flux], names=["wave", "flux"]) - # Test that the units and values of the Spectrum1D object match those in the table + # Test that the units and values of the Spectrum object match those in the table spectrum = generic_spectrum_from_table(table) assert spectrum.spectral_axis.unit == table['wave'].unit assert spectrum.flux.unit == table['flux'].unit @@ -74,7 +74,7 @@ def test_speclist_autoidentify(): assert (formats['Auto-identify'] == 'Yes').all() -@pytest.mark.filterwarnings(r'ignore:.*data loader provided for Spectrum1D without explicit identifier') +@pytest.mark.filterwarnings(r'ignore:.*data loader provided for Spectrum without explicit identifier') def test_default_identifier(tmp_path): fname = str(tmp_path / 'empty.txt') @@ -88,7 +88,7 @@ def reader(*args, **kwargs): """Doesn't actually get used.""" return - for datatype in [Spectrum1D, SpectrumList]: + for datatype in [Spectrum, SpectrumList]: fmts = registry.identify_format('read', datatype, fname, None, [], {}) assert format_name in fmts @@ -114,7 +114,7 @@ def reader(*args, **kwargs): """Doesn't actually get used.""" return - for datatype in [Spectrum1D, SpectrumList]: + for datatype in [Spectrum, SpectrumList]: fmts = registry.identify_format('read', datatype, good_fname, None, [], {}) assert format_name in fmts @@ -147,7 +147,7 @@ def reader(*args, **kwargs): """Doesn't actually get used.""" return - for datatype in [Spectrum1D, SpectrumList]: + for datatype in [Spectrum, SpectrumList]: fmts = registry.identify_format('read', datatype, good_fname, None, [], {}) assert format_name in fmts @@ -179,7 +179,7 @@ def identifier(origin, *args, **kwargs): def counting_loader1(*args, **kwargs): counter["test1"] += 1 wave = np.arange(1, 1.1, 0.01)*u.AA - return Spectrum1D( + return Spectrum( spectral_axis=wave, flux=np.ones(len(wave))*1.e-14*u.Jy, ) @@ -188,16 +188,16 @@ def counting_loader1(*args, **kwargs): def counting_loader2(*args, **kwargs): counter["test2"] += 1 wave = np.arange(1, 1.1, 0.01)*u.AA - return Spectrum1D( + return Spectrum( spectral_axis=wave, flux=np.ones(len(wave))*1.e-14*u.Jy, ) - Spectrum1D.read(fname) + Spectrum.read(fname) assert counter["test2"] == 1 assert counter["test1"] == 0 - for datatype in [Spectrum1D, SpectrumList]: + for datatype in [Spectrum, SpectrumList]: registry.unregister_reader("test_counting_loader1", datatype) registry.unregister_identifier("test_counting_loader1", datatype) registry.unregister_reader("test_counting_loader2", datatype) diff --git a/specutils/tests/test_loaders.py b/specutils/tests/test_loaders.py index 52d998e3a..d7a961705 100644 --- a/specutils/tests/test_loaders.py +++ b/specutils/tests/test_loaders.py @@ -20,7 +20,7 @@ from numpy.testing import assert_allclose from .conftest import remote_access -from .. import Spectrum1D, SpectrumCollection, SpectrumList +from .. import Spectrum, SpectrumCollection, SpectrumList from ..io import get_loaders_by_extension from ..io.default_loaders import subaru_pfs_spec from ..io.default_loaders.sdss import _sdss_wcs_to_log_wcs @@ -51,10 +51,10 @@ def test_get_loaders_by_extension(): @remote_access([{'id': '1481190', 'filename': 'L5g_0355+11_Cruz09.fits'}]) -def test_spectrum1d_GMOSfits(remote_data_path): +def test_spectrum_GMOSfits(remote_data_path): with warnings.catch_warnings(): warnings.simplefilter('ignore', (VerifyWarning, UnitsWarning)) - optical_spec_2 = Spectrum1D.read(remote_data_path, format='wcs1d-fits') + optical_spec_2 = Spectrum.read(remote_data_path, format='wcs1d-fits') assert len(optical_spec_2.data) == 3020 @@ -76,7 +76,7 @@ def test_spectrumlist_GMOSfits(remote_data_path): def test_specific_spec_axis_unit(remote_data_path): with warnings.catch_warnings(): warnings.simplefilter('ignore', (VerifyWarning, UnitsWarning)) - optical_spec = Spectrum1D.read(remote_data_path, + optical_spec = Spectrum.read(remote_data_path, spectral_axis_unit="Angstrom", format='wcs1d-fits') @@ -85,7 +85,7 @@ def test_specific_spec_axis_unit(remote_data_path): @remote_access([{'id': '2656720', 'filename': '_v1410ori_20181204_261_Forrest%20Sims.fit'}]) def test_ctypye_not_compliant(remote_data_path): - optical_spec = Spectrum1D.read(remote_data_path, # noqa + optical_spec = Spectrum.read(remote_data_path, # noqa spectral_axis_unit="Angstrom", format='wcs1d-fits') @@ -100,7 +100,7 @@ def test_generic_ecsv_reader(tmp_path): table.write(tmpfile, format='ascii.ecsv') # Read it in and check against the original - spectrum = Spectrum1D.read(tmpfile, format='ECSV') + spectrum = Spectrum.read(tmpfile, format='ECSV') assert spectrum.spectral_axis.unit == table['wave'].unit assert spectrum.flux.unit == table['flux'].unit assert spectrum.uncertainty.unit == table['uncertainty'].unit @@ -113,15 +113,15 @@ def test_generic_ecsv_reader(tmp_path): @remote_access([{'id': '1481119', 'filename': 'COS_FUV.fits'}, {'id': '1481181', 'filename': 'COS_NUV.fits'}]) def test_hst_cos(remote_data_path): - spec = Spectrum1D.read(remote_data_path) + spec = Spectrum.read(remote_data_path) - assert isinstance(spec, Spectrum1D) + assert isinstance(spec, Spectrum) assert spec.flux.size > 0 # HDUList case with fits.open(remote_data_path) as hdulist: - spec = Spectrum1D.read(hdulist, format="HST/COS") - assert isinstance(spec, Spectrum1D) + spec = Spectrum.read(hdulist, format="HST/COS") + assert isinstance(spec, Spectrum) assert spec.flux.size > 0 @@ -129,24 +129,24 @@ def test_hst_cos(remote_data_path): {'id': '1481185', 'filename': 'STIS_NUV.fits'}, {'id': '1481183', 'filename': 'STIS_CCD.fits'}]) def test_hst_stis(remote_data_path): - spec = Spectrum1D.read(remote_data_path) + spec = Spectrum.read(remote_data_path) - assert isinstance(spec, Spectrum1D) + assert isinstance(spec, Spectrum) assert spec.flux.size > 0 # HDUList case with fits.open(remote_data_path) as hdulist: - spec = Spectrum1D.read(hdulist, format="HST/STIS") - assert isinstance(spec, Spectrum1D) + spec = Spectrum.read(hdulist, format="HST/STIS") + assert isinstance(spec, Spectrum) assert spec.flux.size > 0 @pytest.mark.remote_data def test_manga_cube(): - url = 'https://dr15.sdss.org/sas/dr15/manga/spectro/redux/v2_4_3/8485/stack/manga-8485-1901-LOGCUBE.fits.gz' - spec = Spectrum1D.read(url, format='MaNGA cube') + url = 'https://dr17.sdss.org/sas/dr17/manga/spectro/redux/v3_1_1/8485/stack/manga-8485-1901-LOGCUBE.fits.gz' + spec = Spectrum.read(url, format='MaNGA cube') - assert isinstance(spec, Spectrum1D) + assert isinstance(spec, Spectrum) assert spec.flux.size > 0 assert spec.meta['header']['INSTRUME'] == 'MaNGA' assert spec.shape == (4563, 34, 34) @@ -154,10 +154,10 @@ def test_manga_cube(): @pytest.mark.remote_data def test_manga_rss(): - url = 'https://dr15.sdss.org/sas/dr15/manga/spectro/redux/v2_4_3/8485/stack/manga-8485-1901-LOGRSS.fits.gz' - spec = Spectrum1D.read(url, format='MaNGA rss') + url = 'https://dr17.sdss.org/sas/dr17/manga/spectro/redux/v3_1_1/8485/stack/manga-8485-1901-LOGRSS.fits.gz' + spec = Spectrum.read(url, format='MaNGA rss') - assert isinstance(spec, Spectrum1D) + assert isinstance(spec, Spectrum) assert spec.flux.size > 0 assert spec.meta['header']['INSTRUME'] == 'MaNGA' assert spec.shape == (171, 4563) @@ -168,8 +168,8 @@ def test_sdss_spec(tmp_path): sp_pattern = 'spec-4055-55359-0596.fits' with urllib.request.urlopen(EBOSS_SPECTRUM_URL) as response: # Read from open file object - spec = Spectrum1D.read(response, format="SDSS-III/IV spec") - assert isinstance(spec, Spectrum1D) + spec = Spectrum.read(response, format="SDSS-III/IV spec") + assert isinstance(spec, Spectrum) assert spec.flux.size > 0 # TODO: make this test pass @@ -182,20 +182,20 @@ def test_sdss_spec(tmp_path): shutil.copyfileobj(response, tmp_file) # Read from local disk via filename - spec = Spectrum1D.read(tmp_file.name) - assert isinstance(spec, Spectrum1D) + spec = Spectrum.read(tmp_file.name) + assert isinstance(spec, Spectrum) assert spec.flux.size > 0 # Read from HDUList object with fits.open(tmp_file.name) as hdulist: - spec = Spectrum1D.read(hdulist) - assert isinstance(spec, Spectrum1D) + spec = Spectrum.read(hdulist) + assert isinstance(spec, Spectrum) assert spec.flux.size > 0 # Read from file handle with open(tmp_file.name, mode='rb') as fileio: - spec = Spectrum1D.read(fileio) - assert isinstance(spec, Spectrum1D) + spec = Spectrum.read(fileio) + assert isinstance(spec, Spectrum) assert spec.flux.size > 0 @@ -205,8 +205,8 @@ def test_sdss_spspec(tmp_path): url = f'http://das.sdss.org/spectro/1d_26/0273/1d/{sp_pattern}' with urllib.request.urlopen(url) as response: # Read from open file object - spec = Spectrum1D.read(response, format="SDSS-I/II spSpec") - assert isinstance(spec, Spectrum1D) + spec = Spectrum.read(response, format="SDSS-I/II spSpec") + assert isinstance(spec, Spectrum) assert spec.flux.size > 0 assert (spec.wavelength[0] / u.AA).value == pytest.approx(3799.268615) @@ -217,25 +217,25 @@ def test_sdss_spspec(tmp_path): with warnings.catch_warnings(): warnings.simplefilter('ignore', FITSFixedWarning) - spec = Spectrum1D.read(tmp_file.name) + spec = Spectrum.read(tmp_file.name) - assert isinstance(spec, Spectrum1D) + assert isinstance(spec, Spectrum) assert spec.flux.size > 0 # Read from HDUList object with warnings.catch_warnings(): warnings.simplefilter('ignore', FITSFixedWarning) with fits.open(tmp_file.name) as hdulist: - spec = Spectrum1D.read(hdulist) - assert isinstance(spec, Spectrum1D) + spec = Spectrum.read(hdulist) + assert isinstance(spec, Spectrum) assert spec.flux.size > 0 # Read from file handle with warnings.catch_warnings(): warnings.simplefilter('ignore', FITSFixedWarning) with open(tmp_file.name, mode='rb') as fileio: - spec = Spectrum1D.read(fileio) - assert isinstance(spec, Spectrum1D) + spec = Spectrum.read(fileio) + assert isinstance(spec, Spectrum) assert spec.flux.size > 0 @@ -244,9 +244,9 @@ def test_sdss_spec_stream(): """Test direct read and recognition of SDSS-III/IV spec from remote URL, i.e. do not rely on filename pattern. """ - spec = Spectrum1D.read(EBOSS_SPECTRUM_URL) + spec = Spectrum.read(EBOSS_SPECTRUM_URL) - assert isinstance(spec, Spectrum1D) + assert isinstance(spec, Spectrum) assert spec.flux.size > 0 assert spec.uncertainty.array.min() >= 0.0 @@ -257,9 +257,9 @@ def test_sdss_spspec_stream(): i.e. do not rely on filename pattern. """ sdss_url = 'http://das.sdss.org/spectro/1d_26/0273/1d/spSpec-51957-0273-016.fit' - spec = Spectrum1D.read(sdss_url) + spec = Spectrum.read(sdss_url) - assert isinstance(spec, Spectrum1D) + assert isinstance(spec, Spectrum) assert spec.flux.size > 0 assert spec.uncertainty.array.min() >= 0.0 @@ -286,9 +286,9 @@ def test_sdss_compressed(compress, tmp_path): with warnings.catch_warnings(): warnings.simplefilter('ignore', FITSFixedWarning) os.system(f'{compress} {tmp_file.name}') - spec = Spectrum1D.read(tmp_file.name + ext[compress]) + spec = Spectrum.read(tmp_file.name + ext[compress]) - assert isinstance(spec, Spectrum1D) + assert isinstance(spec, Spectrum) assert spec.flux.size > 0 assert spec.uncertainty.array.min() >= 0.0 @@ -296,9 +296,9 @@ def test_sdss_compressed(compress, tmp_path): with warnings.catch_warnings(): warnings.simplefilter('ignore', FITSFixedWarning) os.system(f'mv {tmp_file.name}{ext[compress]} {tmp_file.name}') - spec = Spectrum1D.read(tmp_file.name) + spec = Spectrum.read(tmp_file.name) - assert isinstance(spec, Spectrum1D) + assert isinstance(spec, Spectrum) assert spec.flux.size > 0 assert spec.uncertainty.array.min() >= 0.0 @@ -311,8 +311,8 @@ def test_sdss_spplate(tmp_path): # Read reference spectrum from open file object with warnings.catch_warnings(): warnings.simplefilter('ignore', FITSFixedWarning) - spec = Spectrum1D.read(response, format="SDSS-I/II spSpec") - assert isinstance(spec, Spectrum1D) + spec = Spectrum.read(response, format="SDSS-I/II spSpec") + assert isinstance(spec, Spectrum) assert spec.flux.size > 0 specid = spec.meta['header']['FIBERID'] @@ -320,8 +320,8 @@ def test_sdss_spplate(tmp_path): # Read "plate" spectrum with 2D flux array from open file object with warnings.catch_warnings(): warnings.simplefilter('ignore', FITSFixedWarning) - plate = Spectrum1D.read(response, format="SDSS spPlate") - assert isinstance(plate, Spectrum1D) + plate = Spectrum.read(response, format="SDSS spPlate") + assert isinstance(plate, Spectrum) assert plate.flux.ndim == 2 assert plate.flux.shape[0] == 640 assert quantity_allclose(spec.spectral_axis, plate.spectral_axis) @@ -335,9 +335,9 @@ def test_sdss_spplate(tmp_path): # Read from local disk via file signature with warnings.catch_warnings(): warnings.simplefilter('ignore', FITSFixedWarning) - plate = Spectrum1D.read(tmp_file.name, limit=32) + plate = Spectrum.read(tmp_file.name, limit=32) - assert isinstance(plate, Spectrum1D) + assert isinstance(plate, Spectrum) assert plate.flux.ndim == 2 assert plate.flux.shape[0] == 32 assert quantity_allclose(spec.spectral_axis, plate.spectral_axis) @@ -347,7 +347,7 @@ def test_sdss_spplate(tmp_path): with warnings.catch_warnings(): warnings.simplefilter('ignore', FITSFixedWarning) with fits.open(tmp_file.name) as hdulist: - plate = Spectrum1D.read(hdulist, limit=32) + plate = Spectrum.read(hdulist, limit=32) assert plate.flux.shape[0] == 32 assert quantity_allclose(spec.spectral_axis, plate.spectral_axis) assert quantity_allclose(spec.flux, plate.flux[specid-1]) @@ -356,7 +356,7 @@ def test_sdss_spplate(tmp_path): with warnings.catch_warnings(): warnings.simplefilter('ignore', FITSFixedWarning) with open(tmp_file.name, mode='rb') as fileio: - plate = Spectrum1D.read(fileio, limit=32) + plate = Spectrum.read(fileio, limit=32) assert plate.flux.shape[0] == 32 assert quantity_allclose(spec.spectral_axis, plate.spectral_axis) assert quantity_allclose(spec.flux, plate.flux[specid-1]) @@ -376,7 +376,7 @@ def test_no_reader_matches(name, tmp_path): fp.write('asdfadasdadvzxcv') with pytest.raises(IORegistryError): - Spectrum1D.read(filename) + Spectrum.read(filename) @pytest.mark.filterwarnings('ignore:linear Solution') @@ -384,9 +384,9 @@ def test_no_reader_matches(name, tmp_path): @remote_access([{'id': '3359174', 'filename': 'linear_fits_solution.fits'}]) def test_iraf_linear(remote_data_path): - spectrum_1d = Spectrum1D.read(remote_data_path, format='iraf') + spectrum_1d = Spectrum.read(remote_data_path, format='iraf') - assert isinstance(spectrum_1d, Spectrum1D) + assert isinstance(spectrum_1d, Spectrum) assert quantity_allclose(spectrum_1d.wavelength[0], u.Quantity(3514.56625402, unit='Angstrom')) assert quantity_allclose(spectrum_1d.wavelength[100], @@ -400,7 +400,7 @@ def test_iraf_linear(remote_data_path): def test_iraf_log_linear(remote_data_path): with pytest.raises(NotImplementedError): - assert Spectrum1D.read(remote_data_path, format='iraf') + assert Spectrum.read(remote_data_path, format='iraf') @pytest.mark.filterwarnings('ignore:Flux unit was not provided') @@ -414,15 +414,15 @@ def test_iraf_non_linear_chebyshev(remote_data_path): wavelength_axis = chebyshev_model(range(1, 4097)) * u.angstrom - spectrum_1d = Spectrum1D.read(remote_data_path, format='iraf') + spectrum_1d = Spectrum.read(remote_data_path, format='iraf') - assert isinstance(spectrum_1d, Spectrum1D) + assert isinstance(spectrum_1d, Spectrum) assert_allclose(wavelength_axis, spectrum_1d.wavelength) # Read from HDUList with fits.open(remote_data_path) as hdulist: - spectrum_1d = Spectrum1D.read(hdulist, format='iraf') - assert isinstance(spectrum_1d, Spectrum1D) + spectrum_1d = Spectrum.read(hdulist, format='iraf') + assert isinstance(spectrum_1d, Spectrum) assert_allclose(wavelength_axis, spectrum_1d.wavelength) @@ -440,9 +440,9 @@ def test_iraf_non_linear_legendre(remote_data_path): wavelength_axis = legendre_model(range(1, 4143)) * u.angstrom - spectrum_1d = Spectrum1D.read(remote_data_path, format='iraf') + spectrum_1d = Spectrum.read(remote_data_path, format='iraf') - assert isinstance(spectrum_1d, Spectrum1D) + assert isinstance(spectrum_1d, Spectrum) assert_allclose(wavelength_axis, spectrum_1d.wavelength) @@ -451,7 +451,7 @@ def test_iraf_non_linear_legendre(remote_data_path): def test_iraf_non_linear_linear_spline(remote_data_path): with pytest.raises(NotImplementedError): - assert Spectrum1D.read(remote_data_path, format='iraf') + assert Spectrum.read(remote_data_path, format='iraf') @pytest.mark.filterwarnings('ignore:non-ASCII characters are present in the FITS file header') @@ -459,7 +459,7 @@ def test_iraf_non_linear_linear_spline(remote_data_path): def test_iraf_non_linear_cubic_spline(remote_data_path): with pytest.raises(NotImplementedError): - assert Spectrum1D.read(remote_data_path, format='iraf') + assert Spectrum.read(remote_data_path, format='iraf') @pytest.mark.filterwarnings('ignore:Flux unit was not provided') @@ -513,12 +513,12 @@ def test_tabular_fits_writer(tmp_path, spectral_axis): if spectral_axis not in ('wavelength', ): disp = np.flip(disp) - spectrum = Spectrum1D(flux=flux, spectral_axis=disp, uncertainty=unc) + spectrum = Spectrum(flux=flux, spectral_axis=disp, uncertainty=unc) tmpfile = str(tmp_path / '_tst.fits') spectrum.write(tmpfile, format='tabular-fits') # Read it in and check against the original - spec = Spectrum1D.read(tmpfile) + spec = Spectrum.read(tmpfile) assert spec.flux.unit == spectrum.flux.unit assert spec.spectral_axis.unit == spectrum.spectral_axis.unit assert quantity_allclose(spec.spectral_axis, spectrum.spectral_axis) @@ -529,7 +529,7 @@ def test_tabular_fits_writer(tmp_path, spectral_axis): # Test spectrum with different flux unit flux = np.random.normal(0., 1.e-9, disp.shape[0]) * u.W * u.m**-2 * u.AA**-1 unc = StdDevUncertainty(0.1 * np.sqrt(np.abs(flux.value)) * flux.unit) - spectrum = Spectrum1D(flux=flux, spectral_axis=disp, uncertainty=unc) + spectrum = Spectrum(flux=flux, spectral_axis=disp, uncertainty=unc) # Try to overwrite the file with pytest.raises(OSError, match=r'File .*exists'): @@ -542,7 +542,7 @@ def test_tabular_fits_writer(tmp_path, spectral_axis): 'uncertainty': ('uncertainty', None)} # Read it back again and check against the original - spec = Spectrum1D.read(tmpfile, format='tabular-fits', column_mapping=cmap) + spec = Spectrum.read(tmpfile, format='tabular-fits', column_mapping=cmap) assert spec.flux.unit == u.Unit('erg / (s cm**2 AA)') assert spec.spectral_axis.unit == u.um assert quantity_allclose(spec.spectral_axis, spectrum.spectral_axis) @@ -565,12 +565,12 @@ def test_tabular_fits_multid(tmp_path, ndim, spectral_axis): if spectral_axis not in ('wavelength', ): disp = np.flip(disp) - spectrum = Spectrum1D(flux=flux, spectral_axis=disp, uncertainty=unc) + spectrum = Spectrum(flux=flux, spectral_axis=disp, uncertainty=unc) tmpfile = str(tmp_path / '_tst.fits') spectrum.write(tmpfile, format='tabular-fits') # Read it in and check against the original - spec = Spectrum1D.read(tmpfile) + spec = Spectrum.read(tmpfile) assert spec.flux.unit == spectrum.flux.unit assert spec.spectral_axis.unit == spectrum.spectral_axis.unit assert spec.flux.shape == flux.shape @@ -585,7 +585,7 @@ def test_tabular_fits_multid(tmp_path, ndim, spectral_axis): 'flux': ('flux', 'erg / (s cm**2 AA)'), 'uncertainty': ('uncertainty', None)} - spec = Spectrum1D.read(tmpfile, format='tabular-fits', column_mapping=cmap) + spec = Spectrum.read(tmpfile, format='tabular-fits', column_mapping=cmap) assert spec.flux.unit == u.Unit('erg / (s cm**2 AA)') assert spec.spectral_axis.unit == u.THz assert quantity_allclose(spec.spectral_axis, spectrum.spectral_axis) @@ -605,13 +605,13 @@ def test_tabular_fits_mask(tmp_path, mask_type): mask = np.zeros(flux.shape, dtype=mask_type) mask[0] = 1 - sp1 = Spectrum1D(spectral_axis=wave, flux=flux, mask=mask) + sp1 = Spectrum(spectral_axis=wave, flux=flux, mask=mask) assert sp1.mask.dtype == mask.dtype tmpfile = str(tmp_path / '_mask_tst.fits') sp1.write(tmpfile, format='tabular-fits', overwrite=True) - sp2 = Spectrum1D.read(tmpfile) + sp2 = Spectrum.read(tmpfile) assert np.all(sp1.spectral_axis == sp2.spectral_axis) assert np.all(sp1.flux == sp2.flux) assert sp2.mask is not None @@ -634,12 +634,12 @@ def test_tabular_fits_mask(tmp_path, mask_type): mask = np.zeros(flux.shape, dtype=mask_type) mask[0,0] = 1 - sp1 = Spectrum1D(spectral_axis=wave, flux=flux, mask=mask) + sp1 = Spectrum(spectral_axis=wave, flux=flux, mask=mask) tmpfile = str(tmp_path / '_mask_tst.fits') sp1.write(tmpfile, format='tabular-fits', overwrite=True) - sp2 = Spectrum1D.read(tmpfile) + sp2 = Spectrum.read(tmpfile) assert np.all(sp1.spectral_axis == sp2.spectral_axis) assert np.all(sp1.flux == sp2.flux) assert sp2.mask is not None @@ -664,7 +664,7 @@ def test_tabular_fits_maskheader(tmp_path): hdr = fits.header.Header({'TELESCOP': 'Leviathan', 'APERTURE': 1.8, 'OBSERVER': 'Parsons', 'NAXIS': 1, 'NAXIS1': 8}) - spectrum = Spectrum1D(flux=flux, spectral_axis=disp, meta={'header': hdr}) + spectrum = Spectrum(flux=flux, spectral_axis=disp, meta={'header': hdr}) tmpfile = str(tmp_path / '_tst.fits') spectrum.write(tmpfile, format='tabular-fits') @@ -699,13 +699,13 @@ def test_tabular_fits_maskheader(tmp_path): @pytest.mark.filterwarnings("ignore:The unit 'Angstrom' has been deprecated") def test_tabular_fits_autowrite(tmp_path): - """Test writing of Spectrum1D with automatic selection of BINTABLE format.""" + """Test writing of Spectrum with automatic selection of BINTABLE format.""" disp = np.linspace(1, 1.2, 21) * u.AA flux = np.random.normal(0., 1.0e-14, disp.shape[0]) * u.W / (u.m**2 * u.AA) hdr = fits.header.Header({'TELESCOP': 'Leviathan', 'APERTURE': 1.8, 'OBSERVER': 'Parsons', 'NAXIS': 1, 'NAXIS1': 8}) - spectrum = Spectrum1D(flux=flux, spectral_axis=disp, meta={'header': hdr}) + spectrum = Spectrum(flux=flux, spectral_axis=disp, meta={'header': hdr}) tmpfile = str(tmp_path / '_tst.fits') spectrum.write(tmpfile) @@ -720,11 +720,11 @@ def test_tabular_fits_autowrite(tmp_path): spectrum.write(tmpfile, format='tabular-fits', overwrite=True, hdu=0) # Test automatic selection of wcs1d format, which will fail without suitable wcs - with pytest.raises(ValueError, match=r'Only Spectrum1D objects with valid WCS'): + with pytest.raises(ValueError, match=r'Only Spectrum objects with valid WCS'): spectrum.write(tmpfile, overwrite=True, hdu=0) tmpfile = str(tmp_path / '_wcs.fits') - with pytest.raises(ValueError, match=r'Only Spectrum1D objects with valid WCS'): + with pytest.raises(ValueError, match=r'Only Spectrum objects with valid WCS'): spectrum.write(tmpfile, overwrite=True) @@ -745,7 +745,7 @@ def test_tabular_fits_compressed(compress, tmp_path): flux = np.random.normal(0., 1.0e-14, disp.shape[0]) * u.Jy unc = StdDevUncertainty(0.01 * np.abs(flux)) - spectrum = Spectrum1D(flux=flux, spectral_axis=disp, uncertainty=unc) + spectrum = Spectrum(flux=flux, spectral_axis=disp, uncertainty=unc) tmpfile = str(tmp_path / '_tst.fits') spectrum.write(tmpfile, format='tabular-fits') @@ -753,9 +753,9 @@ def test_tabular_fits_compressed(compress, tmp_path): with warnings.catch_warnings(): warnings.simplefilter('ignore', FITSFixedWarning) os.system(f'{compress} {tmpfile}') - spec = Spectrum1D.read(tmpfile + ext[compress]) + spec = Spectrum.read(tmpfile + ext[compress]) - assert isinstance(spec, Spectrum1D) + assert isinstance(spec, Spectrum) assert spec.spectral_axis.shape[0] == len(disp) assert spec.flux.size == len(disp) assert spec.uncertainty.array.min() >= 0.0 @@ -765,9 +765,9 @@ def test_tabular_fits_compressed(compress, tmp_path): with warnings.catch_warnings(): warnings.simplefilter('ignore', FITSFixedWarning) os.system(f'mv {tmpfile}{ext[compress]} {tmpfile}') - spec = Spectrum1D.read(tmpfile) + spec = Spectrum.read(tmpfile) - assert isinstance(spec, Spectrum1D) + assert isinstance(spec, Spectrum) assert spec.spectral_axis.shape[0] == len(disp) assert spec.flux.size == len(disp) assert spec.uncertainty.array.min() >= 0.0 @@ -778,7 +778,7 @@ def test_tabular_fits_compressed(compress, tmp_path): @pytest.mark.parametrize("uncertainty", [None, StdDevUncertainty, VarianceUncertainty, InverseVariance]) def test_wcs1d_fits_writer(tmp_path, spectral_axis, uncertainty): - """Test write/read for Spectrum1D with WCS-constructed spectral_axis.""" + """Test write/read for Spectrum with WCS-constructed spectral_axis.""" wlunits = {'WAVE': 'Angstrom', 'FREQ': 'GHz', 'ENER': 'eV', 'WAVN': 'cm**-1'} # Header dictionary for constructing WCS hdr = {'CTYPE1': spectral_axis, 'CUNIT1': wlunits[spectral_axis], @@ -795,15 +795,15 @@ def test_wcs1d_fits_writer(tmp_path, spectral_axis, uncertainty): # ToDo: test with explicit (and different from flux) units. if uncertainty is None: - spectrum = Spectrum1D(flux=flux, wcs=WCS(hdr), mask=mask) + spectrum = Spectrum(flux=flux, wcs=WCS(hdr), mask=mask) assert spectrum.uncertainty is None else: unc = uncertainty(0.1 * np.sqrt(np.abs(flux.value))) - spectrum = Spectrum1D(flux=flux, wcs=WCS(hdr), mask=mask, uncertainty=unc) + spectrum = Spectrum(flux=flux, wcs=WCS(hdr), mask=mask, uncertainty=unc) spectrum.write(tmpfile, hdu=0) # Read it in and check against the original - spec = Spectrum1D.read(tmpfile) + spec = Spectrum.read(tmpfile) assert spec.flux.unit == spectrum.flux.unit assert spec.spectral_axis.unit == spectrum.spectral_axis.unit assert quantity_allclose(spec.spectral_axis, spectrum.spectral_axis) @@ -817,9 +817,9 @@ def test_wcs1d_fits_writer(tmp_path, spectral_axis, uncertainty): # Read from HDUList with fits.open(tmpfile) as hdulist: - spec = Spectrum1D.read(hdulist, format='wcs1d-fits') + spec = Spectrum.read(hdulist, format='wcs1d-fits') - assert isinstance(spec, Spectrum1D) + assert isinstance(spec, Spectrum) assert quantity_allclose(spec.spectral_axis, spectrum.spectral_axis) assert quantity_allclose(spec.flux, spectrum.flux) assert np.all(spec.mask == spectrum.mask) @@ -833,7 +833,7 @@ def test_wcs1d_fits_writer(tmp_path, spectral_axis, uncertainty): @pytest.mark.parametrize("mask_type", [None, bool, np.uint8, np.int8, np.uint16, np.int16, '>i2']) @pytest.mark.parametrize("uncertainty", [StdDevUncertainty, InverseVariance]) def test_wcs1d_fits_masks(tmp_path, spectral_axis, mask_type, uncertainty): - """Test write/read for Spectrum1D with WCS-constructed spectral_axis.""" + """Test write/read for Spectrum with WCS-constructed spectral_axis.""" wlunits = {'WAVE': 'nm', 'FREQ': 'GHz', 'ENER': 'eV', 'WAVN': 'cm**-1'} # Header dictionary for constructing WCS hdr = {'CTYPE1': spectral_axis, 'CUNIT1': wlunits[spectral_axis], @@ -849,17 +849,17 @@ def test_wcs1d_fits_masks(tmp_path, spectral_axis, mask_type, uncertainty): if mask_type is None: mask = None - spectrum = Spectrum1D(flux=flux, wcs=WCS(hdr), uncertainty=unc) + spectrum = Spectrum(flux=flux, wcs=WCS(hdr), uncertainty=unc) assert spectrum.mask is None else: mask = np.array([0, 0, 1, 0, 3, 0, 0, -99, -199, 0]).astype(mask_type) - spectrum = Spectrum1D(flux=flux, wcs=WCS(hdr), mask=mask, uncertainty=unc) + spectrum = Spectrum(flux=flux, wcs=WCS(hdr), mask=mask, uncertainty=unc) assert spectrum.mask.dtype == mask.dtype spectrum.write(tmpfile, hdu=0) # Read it in and check against the original - spec = Spectrum1D.read(tmpfile) + spec = Spectrum.read(tmpfile) assert quantity_allclose(spec.spectral_axis, spectrum.spectral_axis) assert quantity_allclose(spec.spectral_axis, disp) assert quantity_allclose(spec.flux, spectrum.flux) @@ -874,9 +874,9 @@ def test_wcs1d_fits_masks(tmp_path, spectral_axis, mask_type, uncertainty): # Read from HDUList with fits.open(tmpfile) as hdulist: - spec = Spectrum1D.read(hdulist, format='wcs1d-fits') + spec = Spectrum.read(hdulist, format='wcs1d-fits') - assert isinstance(spec, Spectrum1D) + assert isinstance(spec, Spectrum) assert quantity_allclose(spec.spectral_axis, spectrum.spectral_axis) assert quantity_allclose(spec.flux, spectrum.flux) assert quantity_allclose(spec.uncertainty.quantity, spectrum.uncertainty.quantity) @@ -894,7 +894,7 @@ def test_wcs1d_fits_masks(tmp_path, spectral_axis, mask_type, uncertainty): @pytest.mark.parametrize("uncertainty", [None, StdDevUncertainty, VarianceUncertainty, InverseVariance]) def test_wcs1d_fits_cube(tmp_path, spectral_axis, with_mask, uncertainty): - """Test write/read for Spectrum1D spectral cube with WCS spectral_axis.""" + """Test write/read for Spectrum spectral cube with WCS spectral_axis.""" wlunits = {'WAVE': 'Angstrom', 'FREQ': 'GHz', 'ENER': 'eV', 'WAVN': 'cm**-1'} # Header dictionary for constructing WCS hdr = {'CTYPE1': spectral_axis, 'CUNIT1': wlunits[spectral_axis], @@ -921,18 +921,18 @@ def test_wcs1d_fits_cube(tmp_path, spectral_axis, with_mask, uncertainty): mask = None if uncertainty is None: - spectrum = Spectrum1D(flux=flux, wcs=WCS(hdr), mask=mask) + spectrum = Spectrum(flux=flux, wcs=WCS(hdr), mask=mask) assert spectrum.uncertainty is None with pytest.warns(AstropyUserWarning, match='No uncertainty array found'): spectrum.write(tmpfile, hdu=0, uncertainty_name='STD') else: unc = uncertainty(0.1 * np.sqrt(np.abs(flux.value))) - spectrum = Spectrum1D(flux=flux, wcs=WCS(hdr), mask=mask, uncertainty=unc) + spectrum = Spectrum(flux=flux, wcs=WCS(hdr), mask=mask, uncertainty=unc) spectrum.write(tmpfile, hdu=0) # Broken reader! # Read it in and check against the original - spec = Spectrum1D.read(tmpfile, format='wcs1d-fits') + spec = Spectrum.read(tmpfile, format='wcs1d-fits') assert spec.flux.unit == spectrum.flux.unit assert spec.flux.shape == spectrum.flux.shape assert spec.spectral_axis.unit == spectrum.spectral_axis.unit @@ -948,11 +948,11 @@ def test_wcs1d_fits_cube(tmp_path, spectral_axis, with_mask, uncertainty): # Read from HDUList with fits.open(tmpfile) as hdulist: w = WCS(hdulist[0].header) - spec = Spectrum1D.read(hdulist, format='wcs1d-fits') + spec = Spectrum.read(hdulist, format='wcs1d-fits') assert w.naxis == 3 assert w.axis_type_names == [spectral_axis, 'RA', 'DEC'] - assert isinstance(spec, Spectrum1D) + assert isinstance(spec, Spectrum) assert spec.flux.shape == spectrum.flux.shape assert quantity_allclose(spec.spectral_axis, spectrum.spectral_axis) assert quantity_allclose(spec.flux, spectrum.flux) @@ -967,7 +967,7 @@ def test_wcs1d_fits_cube(tmp_path, spectral_axis, with_mask, uncertainty): @pytest.mark.parametrize("hdu", [None, 0, 1]) def test_wcs1d_fits_uncertainty(tmp_path, uncertainty_rsv, hdu): """ - Test Spectrum1D.write with custom `uncertainty` names, + Test Spectrum.write with custom `uncertainty` names, ensure it raises on illegal (reserved) names. """ # Header dictionary for constructing WCS @@ -987,7 +987,7 @@ def test_wcs1d_fits_uncertainty(tmp_path, uncertainty_rsv, hdu): # Set uncertainty to mismatched type uncertainty = [u for n, u in UNCERT_REF.items() if u != UNCERT_REF[uncertainty_rsv]][0] unc = uncertainty(0.1 * np.sqrt(np.abs(flux.value))) - spectrum = Spectrum1D(flux=flux, wcs=WCS(hdr), mask=mask, uncertainty=unc) + spectrum = Spectrum(flux=flux, wcs=WCS(hdr), mask=mask, uncertainty=unc) with pytest.raises(ValueError, match=f"Illegal label for uncertainty: '{uncertainty_rsv}' " f"is reserved for {UNCERT_REF[uncertainty_rsv]}, not {uncertainty}."): @@ -1014,27 +1014,27 @@ def test_wcs1d_fits_uncertainty(tmp_path, uncertainty_rsv, hdu): # Read it in and check against the original with pytest.raises(ValueError, match=f"Invalid uncertainty type: '{uncertainty_alt}'; should"): - spec = Spectrum1D.read(tmpfile, uncertainty_type=uncertainty_alt, **kwargs) + spec = Spectrum.read(tmpfile, uncertainty_type=uncertainty_alt, **kwargs) # Need to specify type if not default with pytest.warns(AstropyUserWarning, match="Could not determine uncertainty type for HDU " rf"'{hdu+1}' .'{uncertainty_alt.upper()}'., assuming 'StdDev'"): - spec = Spectrum1D.read(tmpfile, **kwargs) + spec = Spectrum.read(tmpfile, **kwargs) if uncertainty_type != 'std': assert spec.uncertainty.uncertainty_type != uncertainty_type - spec = Spectrum1D.read(tmpfile, uncertainty_type=uncertainty_type, **kwargs) + spec = Spectrum.read(tmpfile, uncertainty_type=uncertainty_type, **kwargs) assert spec.flux.unit == spectrum.flux.unit assert spec.spectral_axis.unit == spectrum.spectral_axis.unit assert quantity_allclose(spec.uncertainty.quantity, spectrum.uncertainty.quantity) kwargs['uncertainty_hdu'] = uncertainty_alt - spec = Spectrum1D.read(tmpfile, uncertainty_type=uncertainty_type, **kwargs) + spec = Spectrum.read(tmpfile, uncertainty_type=uncertainty_type, **kwargs) assert quantity_allclose(spec.uncertainty.quantity, spectrum.uncertainty.quantity) @pytest.mark.filterwarnings('ignore:Card is too long') @pytest.mark.parametrize("hdu", range(3)) def test_wcs1d_fits_hdus(tmp_path, hdu): - """Test writing of Spectrum1D in WCS1D format to different IMAGE_HDUs.""" + """Test writing of Spectrum in WCS1D format to different IMAGE_HDUs.""" # Header dictionary for constructing WCS hdr = {'CTYPE1': 'wavelength', 'CUNIT1': 'um', 'CRPIX1': 1, 'CRVAL1': 1, 'CDELT1': 0.01} @@ -1042,7 +1042,7 @@ def test_wcs1d_fits_hdus(tmp_path, hdu): flu = u.W / (u.m**2 * u.nm) flux = np.arange(1, 11)**2 * 1.e-14 * flu - spectrum = Spectrum1D(flux=flux, wcs=WCS(hdr)) + spectrum = Spectrum(flux=flux, wcs=WCS(hdr)) tmpfile = tmp_path / 'tst.fits' spectrum.write(tmpfile, hdu=hdu, format='wcs1d-fits') @@ -1081,11 +1081,11 @@ def test_wcs1d_fits_multid(tmp_path, spectral_axis): shape = [-1, 1] for i in range(2, 5): flux = flux * np.arange(i, i+5).reshape(*shape) - spectrum = Spectrum1D(flux=flux, wcs=WCS(hdr), spectral_axis_index=-1) + spectrum = Spectrum(flux=flux, wcs=WCS(hdr), spectral_axis_index=-1) tmpfile = tmp_path / f'wcs_{i}d.fits' spectrum.write(tmpfile, format='wcs1d-fits') - spec = Spectrum1D.read(tmpfile, format='wcs1d-fits', spectral_axis_index=-1) + spec = Spectrum.read(tmpfile, format='wcs1d-fits', spectral_axis_index=-1) assert spec.flux.ndim == i assert quantity_allclose(spec.spectral_axis, disp) assert quantity_allclose(spec.spectral_axis, spectrum.spectral_axis) @@ -1094,12 +1094,12 @@ def test_wcs1d_fits_multid(tmp_path, spectral_axis): # Test exception for NAXIS > 4 flux = flux * np.arange(i+1, i+6).reshape(*shape) - spectrum = Spectrum1D(flux=flux, wcs=WCS(hdr), spectral_axis_index=-1) + spectrum = Spectrum(flux=flux, wcs=WCS(hdr), spectral_axis_index=-1) tmpfile = tmp_path / f'wcs_{i+1}d.fits' spectrum.write(tmpfile, format='wcs1d-fits') with pytest.raises(ValueError, match='input to wcs1d_fits_loader is > 4D'): - spec = Spectrum1D.read(tmpfile, format='wcs1d-fits') + spec = Spectrum.read(tmpfile, format='wcs1d-fits') @pytest.mark.parametrize("spectral_axis", ['WAVE', 'FREQ']) @@ -1113,7 +1113,7 @@ def test_wcs1d_fits_non1d(tmp_path, spectral_axis): 'CRPIX1': 1, 'CRVAL1': 1, 'CDELT1': 0.01} # Create a small 2D data set flux = np.arange(1, 11)**2 * np.arange(4).reshape(-1, 1) * 1.e-14 * u.Jy - spectrum = Spectrum1D(flux=flux, wcs=WCS(hdr), spectral_axis_index=-1) + spectrum = Spectrum(flux=flux, wcs=WCS(hdr), spectral_axis_index=-1) tmpfile = tmp_path / f'wcs_{2}d.fits' spectrum.write(tmpfile, format='wcs1d-fits') @@ -1123,7 +1123,7 @@ def test_wcs1d_fits_non1d(tmp_path, spectral_axis): with pytest.raises(ValueError, match='Non-zero off-diagonal matrix elements excluded from the subimage.'): - Spectrum1D.read(tmpfile, format='wcs1d-fits') + Spectrum.read(tmpfile, format='wcs1d-fits') @pytest.mark.skipif('sys.platform.startswith("win")', @@ -1148,7 +1148,7 @@ def test_wcs1d_fits_compressed(compress, tmp_path): dwl = hdr['CDELT1'] disp = np.arange(wl0, wl0 + (len(flux) - 0.5) * dwl, dwl) * wlu - spectrum = Spectrum1D(flux=flux, wcs=WCS(hdr)) + spectrum = Spectrum(flux=flux, wcs=WCS(hdr)) tmpfile = tmp_path / 'wcs_tst.fits' spectrum.write(tmpfile, hdu=0) @@ -1156,9 +1156,9 @@ def test_wcs1d_fits_compressed(compress, tmp_path): with warnings.catch_warnings(): warnings.simplefilter('ignore', FITSFixedWarning) os.system(f'{compress} {tmpfile}') - spec = Spectrum1D.read(tmpfile.with_suffix(f'{tmpfile.suffix}{ext[compress]}')) + spec = Spectrum.read(tmpfile.with_suffix(f'{tmpfile.suffix}{ext[compress]}')) - assert isinstance(spec, Spectrum1D) + assert isinstance(spec, Spectrum) assert quantity_allclose(spec.spectral_axis, disp) assert quantity_allclose(spec.flux, spectrum.flux) @@ -1166,9 +1166,9 @@ def test_wcs1d_fits_compressed(compress, tmp_path): with warnings.catch_warnings(): warnings.simplefilter('ignore', FITSFixedWarning) shutil.move(tmpfile.with_suffix(f'{tmpfile.suffix}{ext[compress]}'), tmpfile) - spec = Spectrum1D.read(tmpfile) + spec = Spectrum.read(tmpfile) - assert isinstance(spec, Spectrum1D) + assert isinstance(spec, Spectrum) assert quantity_allclose(spec.spectral_axis, disp) assert quantity_allclose(spec.flux, spectrum.flux) @@ -1179,9 +1179,9 @@ def test_apstar_loader(): """ apstar_url = ("https://data.sdss.org/sas/dr16/apogee/spectro/redux/r12/" "stars/apo25m/N7789/apStar-r12-2M00005414+5522241.fits") - spec = Spectrum1D.read(apstar_url) + spec = Spectrum.read(apstar_url) - assert isinstance(spec, Spectrum1D) + assert isinstance(spec, Spectrum) assert spec.flux.size > 0 assert spec.flux.unit == 1e-17 * u.erg / (u.s * u.cm**2 * u.AA) assert spec.uncertainty.array.min() >= 0.0 @@ -1194,9 +1194,9 @@ def test_apvisit_loader(): apvisit_url = ("https://data.sdss.org/sas/dr16/apogee/spectro/redux/r12/" "visit/apo25m/N7789/5094/55874/" "apVisit-r12-5094-55874-123.fits") - spec = Spectrum1D.read(apvisit_url) + spec = Spectrum.read(apvisit_url) - assert isinstance(spec, Spectrum1D) + assert isinstance(spec, Spectrum) assert spec.flux.size > 0 assert spec.flux.unit == 1e-17 * u.erg / (u.s * u.cm**2 * u.AA) assert spec.uncertainty.array.min() >= 0.0 @@ -1208,9 +1208,9 @@ def test_aspcapstar_loader(): """ aspcap_url = ("https://data.sdss.org/sas/dr16/apogee/spectro/aspcap/r12/" "l33/apo25m/N7789/aspcapStar-r12-2M00005414+5522241.fits") - spec = Spectrum1D.read(aspcap_url) + spec = Spectrum.read(aspcap_url) - assert isinstance(spec, Spectrum1D) + assert isinstance(spec, Spectrum) assert spec.flux.size > 0 assert spec.uncertainty.array.min() >= 0.0 @@ -1222,9 +1222,9 @@ def test_muscles_loader(): """ url = ("https://archive.stsci.edu/missions/hlsp/muscles/gj1214/" "hlsp_muscles_multi_multi_gj1214_broadband_v22_const-res-sed.fits") - spec = Spectrum1D.read(url) + spec = Spectrum.read(url) - assert isinstance(spec, Spectrum1D) + assert isinstance(spec, Spectrum) assert len(spec.flux) == len(spec.spectral_axis) > 50000 assert spec.uncertainty.array.min() >= 0.0 assert spec.spectral_axis.unit == u.AA @@ -1232,8 +1232,8 @@ def test_muscles_loader(): # Read HDUList with fits.open(url) as hdulist: - spec = Spectrum1D.read(hdulist, format="MUSCLES SED") - assert isinstance(spec, Spectrum1D) + spec = Spectrum.read(hdulist, format="MUSCLES SED") + assert isinstance(spec, Spectrum) @pytest.mark.remote_data @@ -1252,11 +1252,11 @@ def test_subaru_pfs_loader(tmp_path): shutil.copyfileobj(response, fout) assert subaru_pfs_spec.identify_pfs_spec(pfs, open(tmpfile, mode='rb')) - spec = Spectrum1D.read(tmpfile, format='Subaru-pfsObject') - assert isinstance(spec, Spectrum1D) + spec = Spectrum.read(tmpfile, format='Subaru-pfsObject') + assert isinstance(spec, Spectrum) - spec = Spectrum1D.read(tmpfile) - assert isinstance(spec, Spectrum1D) + spec = Spectrum.read(tmpfile) + assert isinstance(spec, Spectrum) assert len(spec.flux) == len(spec.spectral_axis) > 10000 assert spec.spectral_axis.unit == u.nm assert spec.flux.unit == u.nJy @@ -1264,71 +1264,71 @@ def test_subaru_pfs_loader(tmp_path): @pytest.mark.filterwarnings(r'ignore:.*did not parse as fits unit') @remote_access([{'id': '3733958', 'filename': '1D-c0022498-344732.fits'}]) -def test_spectrum1d_6dfgs_tabular(remote_data_path): - spec = Spectrum1D.read(remote_data_path) +def test_spectrum_6dfgs_tabular(remote_data_path): + spec = Spectrum.read(remote_data_path) assert spec.spectral_axis.unit == u.Unit("Angstrom") assert spec.flux.unit == u.Unit("count/s") # Read from HDUList object with fits.open(remote_data_path) as hdulist: - spec = Spectrum1D.read(hdulist, format="6dFGS-tabular") - assert isinstance(spec, Spectrum1D) + spec = Spectrum.read(hdulist, format="6dFGS-tabular") + assert isinstance(spec, Spectrum) assert spec.flux.unit == u.Unit("count/s") assert spec.flux.size > 0 @pytest.mark.filterwarnings(r'ignore:.*did not parse as fits unit') @remote_access([{'id': '3733958', 'filename': 'all-c0022498-344732v_spectrum0.fits'}]) -def test_spectrum1d_6dfgs_split_v(remote_data_path): - spec = Spectrum1D.read(remote_data_path) +def test_spectrum_6dfgs_split_v(remote_data_path): + spec = Spectrum.read(remote_data_path) assert spec.spectral_axis.unit == u.Unit("Angstrom") assert spec.flux.unit == u.Unit("count/Angstrom") # Read from HDUList object with fits.open(remote_data_path) as hdulist: - spec = Spectrum1D.read(hdulist, format="6dFGS-split") - assert isinstance(spec, Spectrum1D) + spec = Spectrum.read(hdulist, format="6dFGS-split") + assert isinstance(spec, Spectrum) assert spec.flux.unit == u.Unit("count/Angstrom") assert spec.flux.size > 0 @pytest.mark.filterwarnings(r'ignore:.*did not parse as fits unit') @remote_access([{'id': '3733958', 'filename': 'all-c0022498-344732r_spectrum0.fits'}]) -def test_spectrum1d_6dfgs_split_r(remote_data_path): - spec = Spectrum1D.read(remote_data_path) +def test_spectrum_6dfgs_split_r(remote_data_path): + spec = Spectrum.read(remote_data_path) assert spec.spectral_axis.unit == u.Unit("Angstrom") assert spec.flux.unit == u.Unit("count/Angstrom") # Read from HDUList object with fits.open(remote_data_path) as hdulist: - spec = Spectrum1D.read(hdulist, format="6dFGS-split") - assert isinstance(spec, Spectrum1D) + spec = Spectrum.read(hdulist, format="6dFGS-split") + assert isinstance(spec, Spectrum) assert spec.flux.unit == u.Unit("count/Angstrom") assert spec.flux.size > 0 @pytest.mark.filterwarnings(r'ignore:.*did not parse as fits unit') @remote_access([{'id': '3733958', 'filename': 'all-c0022498-344732combined_spectrum0.fits'}]) -def test_spectrum1d_6dfgs_split_combined(remote_data_path): - spec = Spectrum1D.read(remote_data_path) +def test_spectrum_6dfgs_split_combined(remote_data_path): + spec = Spectrum.read(remote_data_path) assert spec.spectral_axis.unit == u.Unit("Angstrom") assert spec.flux.unit == u.Unit("count/Angstrom") # Read from HDUList object with fits.open(remote_data_path) as hdulist: - spec = Spectrum1D.read(hdulist, format="6dFGS-split") - assert isinstance(spec, Spectrum1D) + spec = Spectrum.read(hdulist, format="6dFGS-split") + assert isinstance(spec, Spectrum) assert spec.flux.unit == u.Unit("count/Angstrom") assert spec.flux.size > 0 @pytest.mark.filterwarnings(r'ignore:.*did not parse as fits unit') @remote_access([{'id': '3733958', 'filename': 'all-c0022498-344732.fits'}]) -def test_spectrum1d_6dfgs_combined(remote_data_path): +def test_spectrum_6dfgs_combined(remote_data_path): specs = SpectrumList.read(remote_data_path) for spec in specs: @@ -1341,7 +1341,7 @@ def test_spectrum1d_6dfgs_combined(remote_data_path): with fits.open(remote_data_path) as hdulist: specs = SpectrumList.read(hdulist, format="6dFGS-combined") for spec in specs: - assert isinstance(spec, Spectrum1D) + assert isinstance(spec, Spectrum) assert spec.flux.unit == u.Unit("count/Angstrom") assert spec.flux.size > 0 assert spec.meta["sky"].flux.unit == u.Unit("count/Angstrom") @@ -1357,7 +1357,7 @@ def test_spectrum1d_6dfgs_combined(remote_data_path): # """ # url = ("https://datacentral.org.au/services/sov/81480/download/" # "gama.dr2.spectra.2slaq-lrg.spectrum_1d/J143529.78-004306.4_1.fit/") -# spec = Spectrum1D.read(url) +# spec = Spectrum.read(url) # # assert spec.spectral_axis.unit == u.AA # assert spec.flux.unit == u.count / u.s @@ -1396,7 +1396,7 @@ def test_spectrum_list_2dfgrs_single(remote_data_path): with fits.open(remote_data_path) as hdulist: specs = SpectrumList.read(hdulist, format="2dFGRS") for spec in specs: - assert isinstance(spec, Spectrum1D) + assert isinstance(spec, Spectrum) assert spec.spectral_axis.unit == u.Unit("Angstrom") assert len(specs) == 1 @@ -1415,7 +1415,7 @@ def test_spectrum_list_2dfgrs_multiple(remote_data_path): with fits.open(remote_data_path) as hdulist: specs = SpectrumList.read(hdulist, format="2dFGRS") for spec in specs: - assert isinstance(spec, Spectrum1D) + assert isinstance(spec, Spectrum) assert spec.spectral_axis.unit == u.Unit("Angstrom") assert len(specs) == 2 @@ -1611,7 +1611,7 @@ def test_spectrum_list_names_miri_mrs(): assert len(specs) == 12 for spec in specs: - assert isinstance(spec, Spectrum1D) + assert isinstance(spec, Spectrum) assert spec.spectral_axis.unit == u.micron # Warn about missing file @@ -1619,7 +1619,7 @@ def test_spectrum_list_names_miri_mrs(): assert len(specs) == 12 for spec in specs: - assert isinstance(spec, Spectrum1D) + assert isinstance(spec, Spectrum) assert spec.spectral_axis.unit == u.Unit("um") # Auto-detect format @@ -1627,7 +1627,7 @@ def test_spectrum_list_names_miri_mrs(): assert len(specs) == 12 for spec in specs: - assert isinstance(spec, Spectrum1D) + assert isinstance(spec, Spectrum) assert spec.spectral_axis.unit == u.micron @@ -1647,7 +1647,7 @@ def test_spectrum_list_directory_miri_mrs(tmp_path): assert len(specs) == 12 for spec in specs: - assert isinstance(spec, Spectrum1D) + assert isinstance(spec, Spectrum) assert spec.spectral_axis.unit == u.micron @@ -1663,9 +1663,9 @@ def test_spectrum_list_directory_miri_mrs(tmp_path): ]) def test_jwst_x1d_c1d(remote_data_path): - data = Spectrum1D.read(remote_data_path) + data = Spectrum.read(remote_data_path) - assert isinstance(data, Spectrum1D) + assert isinstance(data, Spectrum) assert data.shape in [(388,), (5,), (1091,), (3843,)] assert data.unit == u.Jy assert data.spectral_axis.unit == u.um @@ -1690,7 +1690,7 @@ def test_jwst_nircam_x1d_multi_v1_2_3(remote_data_path): assert isinstance(data, SpectrumList) assert len(data) == 3 - [assert_multi_isinstance(d, Spectrum1D) for d in data] + [assert_multi_isinstance(d, Spectrum) for d in data] [assert_multi_equals(d.shape, r) for d,r in zip(data, [(459,), (336,), (962,)])] [assert_multi_equals(d.unit, u.Jy) for d in data] [assert_multi_equals(d.spectral_axis.unit, u.um) for d in data] @@ -1706,7 +1706,7 @@ def test_jwst_nircam_x1d_multi_v1_3_1(remote_data_path): assert isinstance(data, SpectrumList) assert len(data) == 4 - [assert_multi_isinstance(d, Spectrum1D) for d in data] + [assert_multi_isinstance(d, Spectrum) for d in data] [assert_multi_equals(d.shape, r) for d,r in zip(data, [(1166,), (786,), (1157,), (795,)])] [assert_multi_equals(d.unit, u.Jy) for d in data] [assert_multi_equals(d.spectral_axis.unit, u.um) for d in data] @@ -1721,7 +1721,7 @@ def test_jwst_nircam_c1d_v1_2_3(remote_data_path): assert isinstance(data, SpectrumList) assert len(data) == 2 - [assert_multi_isinstance(d, Spectrum1D) for d in data] + [assert_multi_isinstance(d, Spectrum) for d in data] [assert_multi_equals(d.shape, r) for d,r in zip(data, [(133,), (1139,)])] [assert_multi_equals(d.unit, u.MJy/u.sr) for d in data] [assert_multi_equals(d.spectral_axis.unit, u.um) for d in data] @@ -1736,7 +1736,7 @@ def test_jwst_niriss_c1d_v1_2_3(remote_data_path): assert isinstance(data, SpectrumList) assert len(data) == 2 - [assert_multi_isinstance(d, Spectrum1D) for d in data] + [assert_multi_isinstance(d, Spectrum) for d in data] [assert_multi_equals(d.shape, r) for d,r in zip(data, [(56,), (107,)])] [assert_multi_equals(d.unit, u.Jy) for d in data] [assert_multi_equals(d.spectral_axis.unit, u.um) for d in data] diff --git a/specutils/tests/test_manipulation.py b/specutils/tests/test_manipulation.py index dd20b7ea4..8efa1ce04 100644 --- a/specutils/tests/test_manipulation.py +++ b/specutils/tests/test_manipulation.py @@ -5,7 +5,7 @@ from astropy.nddata import StdDevUncertainty, NDData from ..utils.wcs_utils import gwcs_from_array -from ..spectra import Spectrum1D, SpectralRegion, SpectrumCollection +from ..spectra import Spectrum, SpectralRegion, SpectrumCollection from ..manipulation import snr_threshold, excise_regions, linear_exciser @@ -13,7 +13,7 @@ def test_true_exciser(): np.random.seed(84) spectral_axis = np.linspace(5000,5100,num=100)*u.AA flux = (np.random.randn(100) + 3) * u.Jy - spec = Spectrum1D(flux=flux, spectral_axis=spectral_axis) + spec = Spectrum(flux=flux, spectral_axis=spectral_axis) region = SpectralRegion([(5005,5010), (5060,5065)]*u.AA) excised_spec = excise_regions(spec, region) @@ -26,7 +26,7 @@ def test_linear_exciser(): np.random.seed(84) spectral_axis = np.linspace(5000,5100,num=100)*u.AA flux = (np.random.rand(100)*100) * u.Jy - spec = Spectrum1D(flux=flux, spectral_axis = spectral_axis) + spec = Spectrum(flux=flux, spectral_axis = spectral_axis) region = SpectralRegion([(5020,5030)]*u.AA) excised_spec = excise_regions(spec, region, exciser = linear_exciser) @@ -43,7 +43,7 @@ def test_snr_threshold(): wavelengths = np.arange(0, 10)*u.um flux = 100*np.abs(np.random.randn(10))*u.Jy uncertainty = StdDevUncertainty(np.abs(np.random.randn(10))*u.Jy) - spectrum = Spectrum1D(spectral_axis=wavelengths, flux=flux, uncertainty=uncertainty) + spectrum = Spectrum(spectral_axis=wavelengths, flux=flux, uncertainty=uncertainty) spectrum_masked = snr_threshold(spectrum, 50) assert all([x==y for x,y in zip(spectrum_masked.mask, [False, True, False, False, True, True, False, False, False, True])]) @@ -77,7 +77,7 @@ def test_snr_threshold(): wavelengths = np.arange(0, 10)*u.um flux = 100*np.abs(np.random.randn(3, 4, 10))*u.Jy uncertainty = StdDevUncertainty(np.abs(np.random.randn(3, 4, 10))*u.Jy) - spectrum = Spectrum1D(spectral_axis=wavelengths, flux=flux, uncertainty=uncertainty) + spectrum = Spectrum(spectral_axis=wavelengths, flux=flux, uncertainty=uncertainty) spectrum_masked = snr_threshold(spectrum, 50) diff --git a/specutils/tests/test_model_replace.py b/specutils/tests/test_model_replace.py index 64b265bdf..5c18ef514 100644 --- a/specutils/tests/test_model_replace.py +++ b/specutils/tests/test_model_replace.py @@ -6,7 +6,7 @@ from astropy.tests.helper import assert_quantity_allclose -from ..spectra.spectrum1d import Spectrum1D, SpectralRegion +from ..spectra.spectrum import Spectrum, SpectralRegion from ..manipulation.model_replace import model_replace from ..fitting import fit_lines @@ -15,7 +15,7 @@ def test_from_knots(): wave_val = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) flux_val = np.array([2, 4, 6, 8, 10, 12, 14, 16, 18, 20]) - input_spectrum = Spectrum1D(spectral_axis=wave_val * u.AA, flux=flux_val * u.mJy) + input_spectrum = Spectrum(spectral_axis=wave_val * u.AA, flux=flux_val * u.mJy) spline_knots = [3.5, 4.7, 6.8, 7.1] * u.AA @@ -43,7 +43,7 @@ def test_with_uncert_from_knots(): uncert = StdDevUncertainty(uncert_val * u.mJy) - input_spectrum = Spectrum1D(spectral_axis=wave_val * u.AA, flux=flux_val * u.mJy, + input_spectrum = Spectrum(spectral_axis=wave_val * u.AA, flux=flux_val * u.mJy, uncertainty=uncert) spline_knots = [3.5, 4.7, 6.8, 7.1] * u.AA @@ -72,7 +72,7 @@ def test_with_uncert_zerofill_from_knots(): uncert = StdDevUncertainty(uncert_val * u.mJy) - input_spectrum = Spectrum1D(spectral_axis=wave_val * u.AA, flux=flux_val * u.mJy, + input_spectrum = Spectrum(spectral_axis=wave_val * u.AA, flux=flux_val * u.mJy, uncertainty=uncert) spline_knots = [3.5, 4.7, 6.8, 7.1] * u.AA @@ -93,7 +93,7 @@ def test_from_region(): uncert = StdDevUncertainty(uncert_val * u.mJy) - input_spectrum = Spectrum1D(spectral_axis=wave_val * u.AA, flux=flux_val * u.mJy, + input_spectrum = Spectrum(spectral_axis=wave_val * u.AA, flux=flux_val * u.mJy, uncertainty=uncert) region = SpectralRegion(3.5*u.AA, 7.1*u.AA) @@ -114,7 +114,7 @@ def test_from_fitted_model(): uncert = StdDevUncertainty(uncert_val * u.mJy) - input_spectrum = Spectrum1D(spectral_axis=wave_val * u.AA, flux=flux_val * u.mJy, + input_spectrum = Spectrum(spectral_axis=wave_val * u.AA, flux=flux_val * u.mJy, uncertainty=uncert) model = models.Gaussian1D(10, 5.6, 1.2) diff --git a/specutils/tests/test_region_extract.py b/specutils/tests/test_region_extract.py index 3a7dc5f3d..337007ac6 100644 --- a/specutils/tests/test_region_extract.py +++ b/specutils/tests/test_region_extract.py @@ -5,7 +5,7 @@ from astropy.nddata import StdDevUncertainty from astropy.tests.helper import assert_quantity_allclose -from ..spectra import Spectrum1D, SpectralRegion +from ..spectra import Spectrum, SpectralRegion from ..manipulation import extract_region, extract_bounding_spectral_region, spectral_slab from ..manipulation.utils import linear_exciser @@ -35,12 +35,12 @@ def test_region_simple(simulated_spectra): def test_pixel_spectralaxis_extraction(): """ - Tests a region extraction on a Spectrum1D with a u.pix defined spectral axis + Tests a region extraction on a Spectrum with a u.pix defined spectral axis """ flux_unit = u.dimensionless_unscaled spec_unit = u.pix - spec1d = Spectrum1D(spectral_axis=np.arange(5100, 5300)*spec_unit, + spec1d = Spectrum(spectral_axis=np.arange(5100, 5300)*spec_unit, flux=np.random.randn(200)*flux_unit) # Case 1: Region is safely within the bounds of a continuously-defined Spec1D @@ -127,7 +127,7 @@ def test_slab_simple(simulated_spectra): def test_slab_pixels(): range_iter = range(5) - spectrum = Spectrum1D(flux=np.stack( + spectrum = Spectrum(flux=np.stack( [np.zeros((2, 2)) + i for i in range_iter], axis=-1) * u.nJy, spectral_axis_index=2) for i in range_iter: @@ -137,7 +137,7 @@ def test_slab_pixels(): def test_region_ghz(simulated_spectra): - spectrum = Spectrum1D(flux=simulated_spectra.s1_um_mJy_e1.flux, + spectrum = Spectrum(flux=simulated_spectra.s1_um_mJy_e1.flux, spectral_axis=simulated_spectra.s1_um_mJy_e1.frequency) region = SpectralRegion(499654.09666667*u.GHz, 374740.5725*u.GHz) @@ -152,7 +152,7 @@ def test_region_ghz(simulated_spectra): def test_region_simple_check_ends(simulated_spectra): np.random.seed(42) - spectrum = Spectrum1D(spectral_axis=np.linspace(1, 25, 25)*u.um, flux=np.random.random(25)*u.Jy) + spectrum = Spectrum(spectral_axis=np.linspace(1, 25, 25)*u.um, flux=np.random.random(25)*u.Jy) region = SpectralRegion(8*u.um, 15*u.um) sub_spectrum = extract_region(spectrum, region) @@ -172,10 +172,10 @@ def test_region_simple_check_ends(simulated_spectra): def test_region_empty(simulated_spectra): np.random.seed(42) - empty_spectrum = Spectrum1D(spectral_axis=[]*u.um, flux=[]*u.Jy) + empty_spectrum = Spectrum(spectral_axis=[]*u.um, flux=[]*u.Jy) # Region past upper range of spectrum - spectrum = Spectrum1D(spectral_axis=np.linspace(1, 25, 25)*u.um, flux=np.random.random(25)*u.Jy) + spectrum = Spectrum(spectral_axis=np.linspace(1, 25, 25)*u.um, flux=np.random.random(25)*u.Jy) region = SpectralRegion(28*u.um, 30*u.um) sub_spectrum = extract_region(spectrum, region) @@ -186,7 +186,7 @@ def test_region_empty(simulated_spectra): assert sub_spectrum.flux.unit == empty_spectrum.flux.unit # Region below lower range of spectrum - spectrum = Spectrum1D(spectral_axis=np.linspace(1, 25, 25)*u.um, flux=np.random.random(25)*u.Jy) + spectrum = Spectrum(spectral_axis=np.linspace(1, 25, 25)*u.um, flux=np.random.random(25)*u.Jy) region = SpectralRegion(0.1*u.um, 0.3*u.um) sub_spectrum = extract_region(spectrum, region) @@ -197,7 +197,7 @@ def test_region_empty(simulated_spectra): assert sub_spectrum.flux.unit == empty_spectrum.flux.unit # Region below lower range of spectrum and upper range in the spectrum. - spectrum = Spectrum1D(spectral_axis=np.linspace(1, 25, 25)*u.um, flux=2*np.linspace(1, 25, 25)*u.Jy) + spectrum = Spectrum(spectral_axis=np.linspace(1, 25, 25)*u.um, flux=2*np.linspace(1, 25, 25)*u.Jy) region = SpectralRegion(0.1*u.um, 3.3*u.um) sub_spectrum = extract_region(spectrum, region) @@ -317,7 +317,7 @@ def test_bounding_region(simulated_spectra): def test_extract_region_pixels(): - spectrum = Spectrum1D(spectral_axis=np.linspace(4000, 10000, 25)*u.AA, + spectrum = Spectrum(spectral_axis=np.linspace(4000, 10000, 25)*u.AA, flux=np.arange(25)*u.Jy) region = SpectralRegion(10*u.pixel, 12*u.pixel) @@ -327,7 +327,7 @@ def test_extract_region_pixels(): def test_extract_region_mismatched_units(): - spectrum = Spectrum1D(spectral_axis=np.arange(25)*u.nm, + spectrum = Spectrum(spectral_axis=np.arange(25)*u.nm, flux=np.arange(25)*u.Jy) region = SpectralRegion(100*u.AA, 119*u.AA) @@ -339,7 +339,7 @@ def test_extract_region_mismatched_units(): @pytest.mark.filterwarnings('ignore:A SpectralRegion with multiple subregions was provided') def test_linear_excise_invert_from_spectrum(): - spec = Spectrum1D(flux=np.random.sample(100) * u.Jy, + spec = Spectrum(flux=np.random.sample(100) * u.Jy, spectral_axis=np.arange(100) * u.AA) inc_regs = (SpectralRegion(0 * u.AA, 50 * u.AA) + SpectralRegion(60 * u.AA, 80 * u.AA) + @@ -359,7 +359,7 @@ def test_extract_masked(): flux = np.arange(4)*u.Jy mask = [False, False, True, True] - masked_spec = Spectrum1D(spectral_axis=wl, flux=flux, mask=mask) + masked_spec = Spectrum(spectral_axis=wl, flux=flux, mask=mask) region = SpectralRegion(1.5 * u.nm, 3.5 * u.nm) extracted = extract_region(masked_spec, region) @@ -370,7 +370,7 @@ def test_extract_masked(): def test_extract_multid_flux(): flux = np.random.sample((10, 49)) * 100 - spec = Spectrum1D(spectral_axis=np.arange(1, 50) * u.nm, + spec = Spectrum(spectral_axis=np.arange(1, 50) * u.nm, flux=flux * u.Jy) region = SpectralRegion(10 * u.nm, 20 * u.nm) @@ -382,7 +382,7 @@ def test_extract_multid_flux(): def test_slab_multid_flux(): flux = np.random.sample((10, 49)) * 100 - spec = Spectrum1D(spectral_axis=np.arange(1, 50) * u.nm, + spec = Spectrum(spectral_axis=np.arange(1, 50) * u.nm, flux=flux * u.Jy) extracted = spectral_slab(spec, 10 * u.nm, 20 * u.nm) diff --git a/specutils/tests/test_regions.py b/specutils/tests/test_regions.py index 0e65503a9..affbcbfcb 100644 --- a/specutils/tests/test_regions.py +++ b/specutils/tests/test_regions.py @@ -5,7 +5,7 @@ from astropy.tests.helper import assert_quantity_allclose from specutils.fitting import find_lines_derivative -from specutils.spectra import Spectrum1D, SpectralRegion +from specutils.spectra import Spectrum, SpectralRegion def test_lower_upper(): @@ -163,7 +163,7 @@ def test_invert(): assert sr_inverted.subregions[ii] == sr_inverted_expected[ii] # Invert from spectrum. - spectrum = Spectrum1D(spectral_axis=np.linspace(0.05, 3, 20)*u.um, + spectrum = Spectrum(spectral_axis=np.linspace(0.05, 3, 20)*u.um, flux=np.random.random(20)*u.Jy) sr_inverted = sr.invert_from_spectrum(spectrum) for ii, expected in enumerate(sr_inverted_expected): @@ -178,7 +178,7 @@ def test_from_list_list(): x = np.linspace(0, 10, 200) y = g1(x) + g2(x) + g3(x) - spectrum = Spectrum1D(flux=y * u.Jy, spectral_axis=x * u.um) + spectrum = Spectrum(flux=y * u.Jy, spectral_axis=x * u.um) lines = find_lines_derivative(spectrum, flux_threshold=0.01) diff --git a/specutils/tests/test_resample.py b/specutils/tests/test_resample.py index 45d9f2d6a..368c4cd80 100644 --- a/specutils/tests/test_resample.py +++ b/specutils/tests/test_resample.py @@ -4,7 +4,7 @@ from astropy.nddata import VarianceUncertainty, InverseVariance, StdDevUncertainty from astropy.tests.helper import assert_quantity_allclose -from ..spectra.spectrum1d import Spectrum1D +from ..spectra.spectrum import Spectrum from ..manipulation.resample import FluxConservingResampler, LinearInterpolatedResampler, SplineInterpolatedResampler @@ -41,7 +41,7 @@ def test_expanded_grid_fluxconserving(): flux_val = np.array([1, 3, 7, 6, 20]) wave_val = np.array([2, 4, 12, 16, 20]) - input_spectra = Spectrum1D(flux=flux_val * u.mJy, spectral_axis=wave_val * u.nm) + input_spectra = Spectrum(flux=flux_val * u.mJy, spectral_axis=wave_val * u.nm) resamp_grid = [1, 5, 9, 13, 14, 17, 21, 22, 23] * u.nm inst = FluxConservingResampler() @@ -58,7 +58,7 @@ def test_stddev_uncert_propogation(): """ flux_val = np.array([1, 3, 7, 6, 20]) wave_val = np.array([20, 30, 40, 50, 60]) - input_spectra = Spectrum1D(flux=flux_val * u.mJy, spectral_axis=wave_val * u.AA, + input_spectra = Spectrum(flux=flux_val * u.mJy, spectral_axis=wave_val * u.AA, uncertainty=StdDevUncertainty([0.1, 0.25, 0.1, 0.25, 0.1])) inst = FluxConservingResampler() @@ -97,7 +97,7 @@ def test_flux_conservation(specflux, specwavebins, outwavebins): specwave = (specwavebins[:-1] + specwavebins[1:])/2 outwave = (outwavebins[:-1] + outwavebins[1:])/2 - in_spec = Spectrum1D(spectral_axis=specwave, flux=specflux) + in_spec = Spectrum(spectral_axis=specwave, flux=specflux) out_spec = FluxConservingResampler()(in_spec, outwave) in_dwl = delta_wl(in_spec.spectral_axis) @@ -109,14 +109,14 @@ def test_flux_conservation(specflux, specwavebins, outwavebins): assert_quantity_allclose(flux_in, flux_out) -def test_multi_dim_spectrum1D(): +def test_multi_dim_spectrum(): """ - Test for input spectrum1Ds that have a two dimensional flux and + Test for input spectra that have a two dimensional flux and uncertainty. """ flux_2d = np.array([np.ones(10) * 5, np.ones(10) * 6, np.ones(10) * 7]) - input_spectra = Spectrum1D(spectral_axis=np.arange(5000, 5010) * u.AA, + input_spectra = Spectrum(spectral_axis=np.arange(5000, 5010) * u.AA, flux=flux_2d * u.Jy, uncertainty=StdDevUncertainty(flux_2d / 10)) @@ -140,7 +140,7 @@ def test_expanded_grid_interp_linear(): flux_val = np.array([1, 3, 7, 6, 20]) wave_val = np.array([2, 4, 12, 16, 20]) - input_spectra = Spectrum1D(spectral_axis=wave_val * u.AA, flux=flux_val * u.mJy) + input_spectra = Spectrum(spectral_axis=wave_val * u.AA, flux=flux_val * u.mJy) resamp_grid = [1, 5, 9, 13, 14, 17, 21, 22, 23] * u.AA inst = LinearInterpolatedResampler() @@ -164,7 +164,7 @@ def test_expanded_grid_interp_spline(): flux_val = np.array([1, 3, 7, 6, 20]) wave_val = np.array([2, 4, 12, 16, 20]) - input_spectra = Spectrum1D(spectral_axis=wave_val * u.AA, flux=flux_val * u.mJy) + input_spectra = Spectrum(spectral_axis=wave_val * u.AA, flux=flux_val * u.mJy) resamp_grid = [1, 5, 9, 13, 14, 17, 21, 22, 23] * u.AA inst = SplineInterpolatedResampler() @@ -176,7 +176,7 @@ def test_expanded_grid_interp_spline(): np.nan])*u.mJy) inst = SplineInterpolatedResampler(extrapolation_treatment="truncate") - input_spectra = Spectrum1D(spectral_axis=wave_val * u.AA, flux=flux_val * u.mJy) + input_spectra = Spectrum(spectral_axis=wave_val * u.AA, flux=flux_val * u.mJy) results = inst(input_spectra, resamp_grid) assert_quantity_allclose(results.flux, @@ -187,7 +187,7 @@ def test_expanded_grid_interp_spline(): @pytest.mark.parametrize("edgetype,lastvalue", [("nan_fill", np.nan), ("zero_fill", 0)]) def test_resample_edges(edgetype, lastvalue, all_resamplers): - input_spectrum = Spectrum1D(spectral_axis=[2, 4, 12, 16, 20] * u.micron, + input_spectrum = Spectrum(spectral_axis=[2, 4, 12, 16, 20] * u.micron, flux=[1, 3, 7, 6, 20] * u.mJy) resamp_grid = [1, 3, 7, 16, 20, 100] * u.micron @@ -200,7 +200,7 @@ def test_resample_edges(edgetype, lastvalue, all_resamplers): def test_resample_different_units(all_resamplers): - input_spectrum = Spectrum1D(spectral_axis=[5000, 6000, 7000] * u.AA, + input_spectrum = Spectrum(spectral_axis=[5000, 6000, 7000] * u.AA, flux=[1, 2, 3] * u.mJy) resampler = all_resamplers("nan_fill") if all_resamplers == FluxConservingResampler: @@ -217,7 +217,7 @@ def test_resample_different_units(all_resamplers): def test_resample_uncs(all_resamplers): sdunc = StdDevUncertainty([0.1, 0.2, 0.3]*u.mJy) - input_spectrum = Spectrum1D(spectral_axis=[5000, 6000, 7000] * u.AA, + input_spectrum = Spectrum(spectral_axis=[5000, 6000, 7000] * u.AA, flux=[1, 2, 3] * u.mJy, uncertainty=sdunc) @@ -243,7 +243,7 @@ def test_fluxconservingresampler_against_spectres(): spectral_axis = [1, 2, 3, 7, 9, 10, 14]*u.AA new_spec_axis = [2, 3, 4, 12]*u.AA errs = VarianceUncertainty([0.5, 0.25, 0.15, 0.45, 0.75, 1.5, 0.1]) - input_spectra = Spectrum1D(spectral_axis=spectral_axis, flux=flux, + input_spectra = Spectrum(spectral_axis=spectral_axis, flux=flux, uncertainty=errs) inst = FluxConservingResampler() diff --git a/specutils/tests/test_slicing.py b/specutils/tests/test_slicing.py index bc2ae676f..0135759c5 100644 --- a/specutils/tests/test_slicing.py +++ b/specutils/tests/test_slicing.py @@ -4,26 +4,26 @@ import numpy as np from numpy.testing import assert_allclose -from ..spectra.spectrum1d import Spectrum1D +from ..spectra.spectrum import Spectrum def test_spectral_axes(): - spec1 = Spectrum1D(spectral_axis=np.arange(1, 50) * u.nm, + spec1 = Spectrum(spectral_axis=np.arange(1, 50) * u.nm, flux=np.random.sample(49) * 100 * u.Jy) sliced_spec1 = spec1[0:2] - assert isinstance(sliced_spec1, Spectrum1D) + assert isinstance(sliced_spec1, Spectrum) assert_allclose(sliced_spec1.wcs.pixel_to_world(0), spec1.wcs.pixel_to_world(0)) flux2 = np.random.sample((10, 49)) * 100 - spec2 = Spectrum1D(spectral_axis=np.arange(1, 50) * u.nm, + spec2 = Spectrum(spectral_axis=np.arange(1, 50) * u.nm, flux=flux2 * u.Jy) sliced_spec2 = spec2[0] - assert isinstance(sliced_spec2, Spectrum1D) + assert isinstance(sliced_spec2, Spectrum) assert_allclose(sliced_spec2.wcs.pixel_to_world(np.arange(10)), spec2.wcs.pixel_to_world(np.arange(10))) assert sliced_spec2.flux.shape[0] == 49 @@ -31,7 +31,7 @@ def test_spectral_axes(): def test_slicing(): # Create the initial spectrum - spec = Spectrum1D(spectral_axis=np.arange(10) * u.um, flux=2*np.arange(10)*u.Jy) + spec = Spectrum(spectral_axis=np.arange(10) * u.um, flux=2*np.arange(10)*u.Jy) # Slice it. sub_spec = spec[4:8] @@ -78,17 +78,17 @@ def test_slicing_with_fits(): my_wcs = fitswcs.WCS(header={'CDELT1': 1, 'CRVAL1': 6562.8, 'CUNIT1': 'Angstrom', 'CTYPE1': 'WAVE', 'RESTFRQ': 1400000000, 'CRPIX1': 25}) - spec = Spectrum1D(flux=[5, 6, 7, 8, 9, 10] * u.Jy, wcs=my_wcs) + spec = Spectrum(flux=[5, 6, 7, 8, 9, 10] * u.Jy, wcs=my_wcs) spec_slice = spec[1:5] - assert isinstance(spec_slice, Spectrum1D) + assert isinstance(spec_slice, Spectrum) assert spec_slice.flux.size == 4 assert quantity_allclose(spec_slice.wcs.pixel_to_world([0, 1, 2, 3]), spec.wcs.pixel_to_world([1, 2, 3, 4])) def test_slicing_multidim(): - spec = Spectrum1D(spectral_axis=np.arange(10) * u.AA, + spec = Spectrum(spectral_axis=np.arange(10) * u.AA, flux=np.random.sample((5, 10)) * u.Jy, mask=np.random.sample((5, 10)) > 0.5) diff --git a/specutils/tests/test_spectral_axis.py b/specutils/tests/test_spectral_axis.py index f2c737fd1..10c39b529 100644 --- a/specutils/tests/test_spectral_axis.py +++ b/specutils/tests/test_spectral_axis.py @@ -7,7 +7,7 @@ from astropy.utils.exceptions import AstropyDeprecationWarning from ..spectra.spectral_axis import SpectralAxis -from ..spectra.spectrum1d import Spectrum1D +from ..spectra.spectrum import Spectrum from astropy.tests.helper import assert_quantity_allclose @@ -126,7 +126,7 @@ def test_create_from_spectral_axis(observer, target): def test_change_radial_velocity(): wave = np.linspace(100, 200, 100) * u.AA flux = np.ones(100) * u.one - spec = Spectrum1D(spectral_axis=wave, flux=flux, + spec = Spectrum(spectral_axis=wave, flux=flux, radial_velocity=0 * u.km / u.s) assert spec.radial_velocity == 0 * u.km/u.s @@ -139,7 +139,7 @@ def test_change_radial_velocity(): assert spec.radial_velocity == 1 * u.km/u.s - spec = Spectrum1D(spectral_axis=wave, flux=flux, + spec = Spectrum(spectral_axis=wave, flux=flux, radial_velocity=10 * u.km / u.s) assert spec.radial_velocity == 10 * u.km / u.s @@ -156,7 +156,7 @@ def test_change_radial_velocity(): def test_no_change_radial_velocity(): wave = np.linspace(100, 200, 100) * u.AA flux = np.ones(100) * u.one - spec = Spectrum1D(spectral_axis=wave, flux=flux, + spec = Spectrum(spectral_axis=wave, flux=flux, radial_velocity=0 * u.km / u.s) assert spec.radial_velocity == 0 * u.km/u.s @@ -168,7 +168,7 @@ def test_no_change_radial_velocity(): def test_change_redshift(): wave = np.linspace(100, 200, 100) * u.AA flux = np.ones(100) * u.one - spec = Spectrum1D(spectral_axis=wave, flux=flux, redshift=0) + spec = Spectrum(spectral_axis=wave, flux=flux, redshift=0) assert spec.redshift.unit.physical_type == 'dimensionless' assert_quantity_allclose(spec.redshift, u.Quantity(0)) @@ -184,7 +184,7 @@ def test_change_redshift(): assert_quantity_allclose(spec.redshift, u.Quantity(0.1)) assert isinstance(spec.spectral_axis, SpectralAxis) - spec = Spectrum1D(spectral_axis=wave, flux=flux, redshift=0.2) + spec = Spectrum(spectral_axis=wave, flux=flux, redshift=0.2) assert spec.redshift.unit.physical_type == 'dimensionless' assert_quantity_allclose(spec.redshift, u.Quantity(0.2)) @@ -204,7 +204,7 @@ def test_change_redshift(): def test_no_change_redshift(): wave = np.linspace(100, 200, 100) * u.AA flux = np.ones(100) * u.one - spec = Spectrum1D(spectral_axis=wave, flux=flux, redshift=0) + spec = Spectrum(spectral_axis=wave, flux=flux, redshift=0) assert spec.redshift.unit.physical_type == 'dimensionless' assert_quantity_allclose(spec.redshift, u.Quantity(0)) @@ -228,5 +228,5 @@ def test_pixel_descending_error(): spec_unit = u.pix with pytest.raises(ValueError, match="u.pix spectral axes should always be ascending"): - Spectrum1D(spectral_axis=(np.arange(5100, 5300)[::-1])*spec_unit, + Spectrum(spectral_axis=(np.arange(5100, 5300)[::-1])*spec_unit, flux=np.random.randn(200)*flux_unit) diff --git a/specutils/tests/test_spectrum1d.py b/specutils/tests/test_spectrum1d.py index 78ca5c07b..31c9ac9fb 100644 --- a/specutils/tests/test_spectrum1d.py +++ b/specutils/tests/test_spectrum1d.py @@ -7,14 +7,13 @@ from astropy.coordinates import SpectralCoord from astropy.tests.helper import quantity_allclose from astropy.wcs import WCS -from numpy.testing import assert_allclose from .conftest import remote_access -from ..spectra import Spectrum1D +from ..spectra import Spectrum def test_empty_spectrum(): - spec = Spectrum1D(spectral_axis=[]*u.um, + spec = Spectrum(spectral_axis=[]*u.um, flux=[]*u.Jy) assert isinstance(spec.spectral_axis, SpectralCoord) @@ -25,7 +24,7 @@ def test_empty_spectrum(): def test_create_from_arrays(): - spec = Spectrum1D(spectral_axis=np.arange(50) * u.AA, + spec = Spectrum(spectral_axis=np.arange(50) * u.AA, flux=np.random.randn(50) * u.Jy) assert isinstance(spec.spectral_axis, SpectralCoord) @@ -36,20 +35,20 @@ def test_create_from_arrays(): # Test creating spectrum with unknown arguments with pytest.raises(ValueError): - spec = Spectrum1D(wavelength=np.arange(1, 50) * u.nm, + spec = Spectrum(wavelength=np.arange(1, 50) * u.nm, flux=np.random.randn(48) * u.Jy) def test_create_from_multidimensional_arrays(): """ This is a test for a bug that was fixed by #283. It makes sure that - multidimensional flux arrays are handled properly when creating Spectrum1D + multidimensional flux arrays are handled properly when creating Spectrum objects. """ freqs = np.arange(50) * u.GHz flux = np.random.random((5, len(freqs))) * u.Jy - spec = Spectrum1D(spectral_axis=freqs, flux=flux) + spec = Spectrum(spectral_axis=freqs, flux=flux) assert (spec.frequency == freqs).all() assert (spec.flux == flux).all() @@ -59,11 +58,11 @@ def test_create_from_multidimensional_arrays(): freqs = np.arange(50) * u.GHz flux = np.random.random((5, len(freqs)-10)) * u.Jy with pytest.raises(ValueError): - spec = Spectrum1D(spectral_axis=freqs, flux=flux) + spec = Spectrum(spectral_axis=freqs, flux=flux) def test_create_from_quantities(): - spec = Spectrum1D(spectral_axis=np.arange(1, 50) * u.nm, + spec = Spectrum(spectral_axis=np.arange(1, 50) * u.nm, flux=np.random.randn(49) * u.Jy) assert isinstance(spec.spectral_axis, SpectralCoord) @@ -73,12 +72,12 @@ def test_create_from_quantities(): # Mis-matched lengths should raise an exception (unless freqs is one longer # than flux, in which case it's interpreted as bin edges) with pytest.raises(ValueError): - spec = Spectrum1D(spectral_axis=np.arange(1, 50) * u.nm, + spec = Spectrum(spectral_axis=np.arange(1, 50) * u.nm, flux=np.random.randn(47) * u.Jy) def test_create_implicit_wcs(): - spec = Spectrum1D(spectral_axis=np.arange(50) * u.AA, + spec = Spectrum(spectral_axis=np.arange(50) * u.AA, flux=np.random.randn(50) * u.Jy) assert isinstance(spec.wcs, gwcs.wcs.WCS) @@ -90,7 +89,7 @@ def test_create_implicit_wcs(): def test_create_implicit_wcs_with_spectral_unit(): - spec = Spectrum1D(spectral_axis=np.arange(1, 50) * u.nm, + spec = Spectrum(spectral_axis=np.arange(1, 50) * u.nm, flux=np.random.randn(49) * u.Jy) assert isinstance(spec.wcs, gwcs.wcs.WCS) @@ -105,7 +104,7 @@ def test_create_with_spectral_coord(): spectral_coord = SpectralCoord(np.arange(5100, 5150)*u.AA, radial_velocity=u.Quantity(1000.0, "km/s")) flux = np.random.randn(50)*u.Jy - spec = Spectrum1D(spectral_axis=spectral_coord, flux=flux) + spec = Spectrum(spectral_axis=spectral_coord, flux=flux) assert spec.radial_velocity == u.Quantity(1000.0, "km/s") assert isinstance(spec.spectral_axis, SpectralCoord) @@ -121,7 +120,7 @@ def test_create_from_cube(): "CRPIX1": 0, "CRPIX2": 0, "CRPIX3": 0} w = WCS(wcs_dict) - spec = Spectrum1D(flux=flux, wcs=w) + spec = Spectrum(flux=flux, wcs=w) spec_axis_from_wcs = (np.exp(np.array([1,2])*w.wcs.cdelt[-1]/w.wcs.crval[-1]) * w.wcs.crval[-1]*spec.spectral_axis.unit) @@ -130,16 +129,16 @@ def test_create_from_cube(): assert quantity_allclose(spec.spectral_axis, spec_axis_from_wcs) with pytest.raises(ValueError): - spec2 = Spectrum1D(flux=flux, wcs=w, move_spectral_axis='Bad string') + spec2 = Spectrum(flux=flux, wcs=w, move_spectral_axis='Bad string') # Test moving spectral axis from first to last - spec2 = Spectrum1D(flux=flux, wcs=w, move_spectral_axis='last') + spec2 = Spectrum(flux=flux, wcs=w, move_spectral_axis='last') assert spec2.flux.shape == (4,3,2) assert spec2.flux[3,2,1] == 23*u.Jy assert quantity_allclose(spec2.spectral_axis, spec_axis_from_wcs) # Test moving spectral axis from last to first - spec3 = Spectrum1D(flux=spec2.flux, wcs=spec2.wcs, move_spectral_axis='first') + spec3 = Spectrum(flux=spec2.flux, wcs=spec2.wcs, move_spectral_axis='first') assert spec3.flux.shape == (2,3,4) assert spec3.flux[1,2,3] == 23*u.Jy assert quantity_allclose(spec3.spectral_axis, spec_axis_from_wcs) @@ -147,18 +146,18 @@ def test_create_from_cube(): def test_spectral_axis_conversions(): # By default the spectral axis units should be set to angstroms - spec = Spectrum1D(flux=np.array([26.0, 44.5]) * u.Jy, + spec = Spectrum(flux=np.array([26.0, 44.5]) * u.Jy, spectral_axis=np.array([400, 500]) * u.AA) assert np.all(spec.spectral_axis == np.array([400, 500]) * u.angstrom) assert spec.spectral_axis.unit == u.angstrom - spec = Spectrum1D(spectral_axis=np.arange(50) * u.AA, + spec = Spectrum(spectral_axis=np.arange(50) * u.AA, flux=np.random.randn(50) * u.Jy) assert spec.wavelength.unit == u.AA - spec = Spectrum1D(spectral_axis=np.arange(1, 50) * u.nm, + spec = Spectrum(spectral_axis=np.arange(1, 50) * u.nm, flux=np.random.randn(49) * u.Jy) assert spec.frequency.unit == u.GHz @@ -166,7 +165,7 @@ def test_spectral_axis_conversions(): with pytest.raises(ValueError): spec.velocity - spec = Spectrum1D(spectral_axis=np.arange(100, 150) * u.nm, + spec = Spectrum(spectral_axis=np.arange(100, 150) * u.nm, flux=np.random.randn(49) * u.Jy) new_spec = spec.with_spectral_axis_unit(u.km/u.s, rest_value=125*u.um, @@ -180,7 +179,7 @@ def test_spectral_axis_conversions(): wcs_dict = {"CTYPE1": "WAVE", "CRVAL1": 3.622e3, "CDELT1": 8e-2, "CRPIX1": 0, "CUNIT1": "Angstrom"} - wcs_spec = Spectrum1D(flux=np.random.randn(49) * u.Jy, wcs=WCS(wcs_dict), + wcs_spec = Spectrum(flux=np.random.randn(49) * u.Jy, wcs=WCS(wcs_dict), meta={'header': wcs_dict.copy()}) new_spec = wcs_spec.with_spectral_axis_unit(u.km/u.s, rest_value=125*u.um, velocity_convention="relativistic") @@ -192,7 +191,7 @@ def test_spectral_axis_conversions(): def test_spectral_slice(): - spec = Spectrum1D(spectral_axis=np.linspace(100, 1000, 10) * u.nm, + spec = Spectrum(spectral_axis=np.linspace(100, 1000, 10) * u.nm, flux=np.random.random(10) * u.Jy) sliced_spec = spec[300*u.nm:600*u.nm] assert np.all(sliced_spec.spectral_axis == [300, 400, 500] * u.nm) @@ -207,7 +206,7 @@ def test_spectral_slice(): assert np.all(sliced_spec.spectral_axis == [800, 900, 1000] * u.nm) # Test higher dimensional slicing - spec = Spectrum1D(spectral_axis=np.linspace(100, 1000, 10) * u.nm, + spec = Spectrum(spectral_axis=np.linspace(100, 1000, 10) * u.nm, flux=np.random.random((10, 10)) * u.Jy, spectral_axis_index=1) sliced_spec = spec[300*u.nm:600*u.nm] @@ -222,14 +221,14 @@ def test_spectral_axis_equivalencies(unit): """Test that `u.spectral` equivalencies are enabled for `spectral_axis`.""" spectral_axis=np.array([3400, 5000, 6660]) * u.AA - spec = Spectrum1D(flux=np.array([26.0, 30.0, 44.5]) * u.Jy, spectral_axis=spectral_axis) + spec = Spectrum(flux=np.array([26.0, 30.0, 44.5]) * u.Jy, spectral_axis=spectral_axis) new_axis = spectral_axis.to(unit, equivalencies=u.spectral()) assert u.allclose(spec.spectral_axis.to(unit), new_axis) def test_redshift(): - spec = Spectrum1D(flux=np.array([26.0, 30., 44.5]) * u.Jy, + spec = Spectrum(flux=np.array([26.0, 30., 44.5]) * u.Jy, spectral_axis=np.array([4000, 6000, 8000]) * u.AA, velocity_convention='optical', rest_value=6000 * u.AA) @@ -237,7 +236,7 @@ def test_redshift(): assert u.allclose(spec.velocity, [-99930.8, 0, 99930.8]*u.km/u.s, atol=0.5*u.km/u.s) - spec = Spectrum1D(flux=np.array([26.0, 30., 44.5]) * u.Jy, + spec = Spectrum(flux=np.array([26.0, 30., 44.5]) * u.Jy, spectral_axis=np.array([4000, 6000, 8000]) * u.AA, velocity_convention='optical', rest_value=6000 * u.AA, @@ -248,7 +247,7 @@ def test_redshift(): # ------------------------- - spec = Spectrum1D(flux=np.array([26.0, 30.0, 44.5]) * u.Jy, + spec = Spectrum(flux=np.array([26.0, 30.0, 44.5]) * u.Jy, spectral_axis=np.array([10.5, 11.0, 11.5]) * u.GHz, velocity_convention='radio', rest_value=11.0 * u.GHz) @@ -256,7 +255,7 @@ def test_redshift(): assert u.allclose(spec.velocity, [13626., 0, -13626]*u.km/u.s, atol=1*u.km/u.s) - spec = Spectrum1D(flux=np.array([26.0, 30.0, 44.5]) * u.Jy, + spec = Spectrum(flux=np.array([26.0, 30.0, 44.5]) * u.Jy, spectral_axis=np.array([10.5, 11.0, 11.5]) * u.GHz, velocity_convention='radio', rest_value=11.0 * u.GHz, @@ -267,7 +266,7 @@ def test_redshift(): # ------------------------- radial velocity mode - spec = Spectrum1D(flux=np.array([26.0, 30., 44.5]) * u.Jy, + spec = Spectrum(flux=np.array([26.0, 30., 44.5]) * u.Jy, spectral_axis=np.array([4000, 6000, 8000]) * u.AA, velocity_convention='optical', rest_value=6000 * u.AA) @@ -275,7 +274,7 @@ def test_redshift(): assert u.allclose(spec.velocity, [-99930.8, 0.0, 99930.8]*u.km/u.s, atol=0.5*u.km/u.s) - spec = Spectrum1D(flux=np.array([26.0, 30., 44.5]) * u.Jy, + spec = Spectrum(flux=np.array([26.0, 30., 44.5]) * u.Jy, spectral_axis=np.array([4000, 6000, 8000]) * u.AA, velocity_convention='optical', rest_value=6000 * u.AA, @@ -287,13 +286,13 @@ def test_redshift(): def test_flux_unit_conversion(): # By default the flux units should be set to Jy - s = Spectrum1D(flux=np.array([26.0, 44.5]) * u.Jy, + s = Spectrum(flux=np.array([26.0, 44.5]) * u.Jy, spectral_axis=np.array([400, 500]) * u.nm) assert np.all(s.flux == np.array([26.0, 44.5]) * u.Jy) assert s.flux.unit == u.Jy # Simple Unit Conversion - s = Spectrum1D(flux=np.array([26.0, 44.5]) * u.Jy, spectral_axis=np.array([400, 500])*u.nm) + s = Spectrum(flux=np.array([26.0, 44.5]) * u.Jy, spectral_axis=np.array([400, 500])*u.nm) converted_spec = s.with_flux_unit(unit=u.uJy) assert ((26.0 * u.Jy).to(u.uJy) == converted_spec.flux[0]) @@ -302,7 +301,7 @@ def test_flux_unit_conversion(): s.with_flux_unit(unit=u.m) # Pass custom equivalencies - s = Spectrum1D(flux=np.array([26.0, 44.5]) * u.Jy, + s = Spectrum(flux=np.array([26.0, 44.5]) * u.Jy, spectral_axis=np.array([400, 500]) * u.nm) eq = [[u.Jy, u.m, lambda x: np.full_like(np.array(x), 1000.0, dtype=np.double), @@ -311,14 +310,14 @@ def test_flux_unit_conversion(): assert 1000.0 * u.m == converted_spec.flux[0] # Check if suppressing the unit conversion works - s = Spectrum1D(flux=np.array([26.0, 44.5]) * u.Jy, spectral_axis=np.array([400, 500]) * u.nm) + s = Spectrum(flux=np.array([26.0, 44.5]) * u.Jy, spectral_axis=np.array([400, 500]) * u.nm) new_spec = s.with_flux_unit("uJy", suppress_conversion=True) assert new_spec.flux[0] == 26.0 * u.uJy def test_wcs_transformations(): # Test with a GWCS - spec = Spectrum1D(spectral_axis=np.arange(1, 50) * u.nm, + spec = Spectrum(spectral_axis=np.arange(1, 50) * u.nm, flux=np.random.randn(49) * u.Jy) pix_axis = spec.wcs.world_to_pixel(np.arange(20, 30) * u.nm) @@ -336,7 +335,7 @@ def test_wcs_transformations(): 'CTYPE1': 'WAVE', 'RESTFRQ': 1400000000, 'CRPIX1': 25}, naxis=1) - spec = Spectrum1D(flux=[5,6,7] * u.Jy, wcs=my_wcs) + spec = Spectrum(flux=[5,6,7] * u.Jy, wcs=my_wcs) pix_axis = spec.wcs.world_to_pixel(20 * u.um) disp_axis = spec.wcs.pixel_to_world(np.arange(20, 30)) @@ -351,7 +350,7 @@ def test_create_explicit_fitswcs(): my_wcs = fitswcs.WCS(header={'CDELT1': 1, 'CRVAL1': 6562.8, 'CUNIT1': 'Angstrom', 'CTYPE1': 'WAVE', 'RESTFRQ': 1400000000, 'CRPIX1': 25}) - spec = Spectrum1D(flux=[5,6,7] * u.Jy, wcs=my_wcs) + spec = Spectrum(flux=[5,6,7] * u.Jy, wcs=my_wcs) spec = spec.with_velocity_convention("relativistic") assert isinstance(spec.spectral_axis, SpectralCoord) @@ -375,13 +374,13 @@ def test_create_explicit_fitswcs(): def test_create_with_uncertainty(): - spec = Spectrum1D(spectral_axis=np.arange(1, 50) * u.nm, + spec = Spectrum(spectral_axis=np.arange(1, 50) * u.nm, flux=np.random.sample(49) * u.Jy, uncertainty=StdDevUncertainty(np.random.sample(49) * 0.1)) assert isinstance(spec.uncertainty, StdDevUncertainty) - spec = Spectrum1D(spectral_axis=np.arange(1, 50) * u.nm, + spec = Spectrum(spectral_axis=np.arange(1, 50) * u.nm, flux=np.random.sample(49) * u.Jy, uncertainty=StdDevUncertainty(np.random.sample(49) * 0.1)) @@ -393,27 +392,27 @@ def test_create_with_uncertainty(): uncertainty = StdDevUncertainty(np.abs(np.random.randn(3, 2, 10))*u.Jy) with pytest.raises(ValueError): - Spectrum1D(spectral_axis=wavelengths*u.um, flux=flux, uncertainty=uncertainty) + Spectrum(spectral_axis=wavelengths*u.um, flux=flux, uncertainty=uncertainty) @pytest.mark.parametrize("flux_unit", ["adu", "ct/s", "count"]) def test_flux_unit_io_roundtrip(tmp_path, flux_unit): # regression test for https://github.com/astropy/specutils/pull/1018 fname = str(tmp_path / 'flux_unit_io_roundtrip.fits') - sp = Spectrum1D(flux=np.ones(11) * u.Unit(flux_unit), + sp = Spectrum(flux=np.ones(11) * u.Unit(flux_unit), spectral_axis=np.arange(1, 12) * u.Unit('Hz')) sp.write(fname, overwrite=True) - sp_load = Spectrum1D.read(fname) + sp_load = Spectrum.read(fname) assert sp_load.flux.unit == sp.flux.unit @pytest.mark.filterwarnings('ignore::astropy.io.fits.verify.VerifyWarning') @remote_access([{'id': '1481190', 'filename': 'L5g_0355+11_Cruz09.fits'}]) def test_read_linear_solution(remote_data_path): - spec = Spectrum1D.read(remote_data_path, format='wcs1d-fits') + spec = Spectrum.read(remote_data_path, format='wcs1d-fits') - assert isinstance(spec, Spectrum1D) + assert isinstance(spec, Spectrum) assert isinstance(spec.flux, u.Quantity) assert isinstance(spec.spectral_axis, SpectralCoord) @@ -423,7 +422,7 @@ def test_read_linear_solution(remote_data_path): def test_energy_photon_flux(): - spec = Spectrum1D(spectral_axis=np.linspace(100, 1000, 10) * u.nm, + spec = Spectrum(spectral_axis=np.linspace(100, 1000, 10) * u.nm, flux=np.random.randn(10)*u.Jy) assert spec.energy.size == 10 assert spec.photon_flux.size == 10 @@ -435,34 +434,34 @@ def test_flux_nans_propagate_to_mask(): flux = np.random.randn(10) nan_idx = [0, 3, 5] flux[nan_idx] = np.nan - spec = Spectrum1D(spectral_axis=np.linspace(100, 1000, 10) * u.nm, + spec = Spectrum(spectral_axis=np.linspace(100, 1000, 10) * u.nm, flux=flux * u.Jy) assert spec.mask[nan_idx].all() == True # noqa def test_repr(): - spec_with_wcs = Spectrum1D(spectral_axis=np.linspace(100, 1000, 10) * u.nm, + spec_with_wcs = Spectrum(spectral_axis=np.linspace(100, 1000, 10) * u.nm, flux=np.random.random(10) * u.Jy) result = repr(spec_with_wcs) - assert result.startswith('