Skip to content

Commit cd50ffb

Browse files
committed
Merge branch 'main' into version-3-0-alpha
2 parents af31b03 + 8717596 commit cd50ffb

10 files changed

Lines changed: 157 additions & 130 deletions

File tree

docs/api/tom_dataproducts/data_processing.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ The ``DataProductUploadView`` calls ``run_data_processor`` upon saving the ``Dat
1111
instantiates the ``DATA_PROCESSOR_CLASS``, which can be specified in ``settings.py``. ``run_data_processor`` then
1212
processes the uploaded ``DataProduct`` based on the tag value, which can either be Photometry or Spectroscopy.
1313

14-
In the case of spectra, the default behavior is that ``DataProduct`` is converted into a ``specutils.Spectrum1D`` from
14+
In the case of spectra, the default behavior is that ``DataProduct`` is converted into a ``specutils.Spectrum`` from
1515
either a CSV or a FITS file. The spectrum is multiplied by the flux constant of the facility it was taken at, or not
16-
multiplied. The ``Spectrum1D`` is then serialized into JSON for database via the ``SpectrumSerializer``.
16+
multiplied. The ``Spectrum`` is then serialized into JSON for database via the ``SpectrumSerializer``.
1717

1818
For photometry, the default behavior is simply to read the CSV and convert it to JSON for database storage.
1919

docs/managing_data/customizing_data_processing.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ Just like the ``PhotometryProcessor``, this class inherits from
149149
``DataProcessor`` and implements ``process_data()``. This is a
150150
requirement for a custom DataProcessor! This ``process_data()`` method
151151
handles two file types, unlike the previous example, each of which calls
152-
an internal method that returns a ``Spectrum1D`` object. Again, like the
152+
an internal method that returns a ``Spectrum`` object. Again, like the
153153
``PhotometryProcessor``, a list of 2-tuples is created, with the first
154154
value being the timestamp, and the second being the JSON spectrum.
155155

poetry.lock

Lines changed: 114 additions & 87 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ dependencies = [
5757
"crispy-bootstrap4 >=2023.1,<2024.11",
5858
"django-extensions >=3.0.0,<4.0.0",
5959
"django-filter >=23,<25",
60-
"django-tables2 <3",
60+
"django-tables2 >=3.0,<4",
6161
"django-gravatar2 >=1.0.0,<2.0.0",
6262
"django-guardian >=2.0.0,<3.0.0",
6363
"django-htmx >=1.0.0,<2.0.0",
@@ -67,7 +67,7 @@ dependencies = [
6767
"plotly <6",
6868
"python-dateutil <3",
6969
"requests <3",
70-
"specutils <2",
70+
"specutils >=1.20.0,<3",
7171
"importlib-resources >=6.4.5,<6.5.0",
7272
"django-tasks (>=0.6.1,<0.7.0)",
7373
"alerce >=2.0,<3.0",

tom_common/templates/tom_common/bootstrap_htmx.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
<tr>
1414
{% for column in table.columns %}
1515
<th {{ column.attrs.th.as_html }}
16-
hx-get="{% querystring table.prefixed_order_by_field=column.order_by_alias.next %}"
16+
hx-get="{% querystring_replace table.prefixed_order_by_field=column.order_by_alias.next %}"
1717
hx-trigger="click"
1818
hx-target="div.table-container"
1919
hx-swap="outerHTML"
@@ -30,7 +30,7 @@
3030
{# Pagination block overrides #}
3131
{% block pagination.previous %}
3232
<li class="previous page-item">
33-
<div hx-get="{% querystring table.prefixed_page_field=table.page.previous_page_number %}"
33+
<div hx-get="{% querystring_replace table.prefixed_page_field=table.page.previous_page_number %}"
3434
hx-trigger="click"
3535
hx-target="div.table-container"
3636
hx-swap="outerHTML"
@@ -45,7 +45,7 @@
4545
{% for p in table.page|table_page_range:table.paginator %}
4646
<li class="page-item{% if table.page.number == p %} active{% endif %}">
4747
<div class="page-link"
48-
{% if p != '...' %}hx-get="{% querystring table.prefixed_page_field=p %}"{% endif %}
48+
{% if p != '...' %}hx-get="{% querystring_replace table.prefixed_page_field=p %}"{% endif %}
4949
hx-trigger="click"
5050
hx-target="div.table-container"
5151
hx-swap="outerHTML"
@@ -57,7 +57,7 @@
5757
{% endblock pagination.range %}
5858
{% block pagination.next %}
5959
<li class="next page-item">
60-
<div hx-get="{% querystring table.prefixed_page_field=table.page.next_page_number %}"
60+
<div hx-get="{% querystring_replace table.prefixed_page_field=table.page.next_page_number %}"
6161
hx-trigger="click"
6262
hx-target="div.table-container"
6363
hx-swap="outerHTML"

tom_dataproducts/migrations/0010_manual_20210305_fix_spectroscopy.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from astropy.units import photon, Quantity, spectral_density
22
from django.db import migrations
3-
from specutils import Spectrum1D
3+
from specutils import Spectrum
44

55
from tom_dataproducts.processors.data_serializers import SpectrumSerializer
66

@@ -11,9 +11,9 @@ def photon_spectrum_to_energy_spectrum(apps, schema_editor):
1111
of this code.
1212
1313
def photon_spectrum_to_energy_spectrum(wavelength, photon_counts):
14-
photon_spectrum = specutils.Spectrum1D(flux=photon_counts, spectral_axis=wavelength)
14+
photon_spectrum = specutils.Spectrum(flux=photon_counts, spectral_axis=wavelength)
1515
energy_spectrum = photon_spectrum.flux * (photon_spectrum.energy / u.photon)
16-
return specutils.Spectrum1D(spectral_axis=wavelength,
16+
return specutils.Spectrum(spectral_axis=wavelength,
1717
flux=energy_spectrum.to('erg / (s cm2 AA)', u.spectral_density(wavelength)))
1818
"""
1919
reduced_datum = apps.get_model('tom_dataproducts', 'ReducedDatum')
@@ -24,9 +24,9 @@ def photon_spectrum_to_energy_spectrum(wavelength, photon_counts):
2424
if all(k in row.value.keys() for k in ['photon_flux', 'photon_flux_units', 'wavelength', 'wavelength_units']):
2525
photon_counts = Quantity(value=row.value['photon_flux'], unit=row.value['photon_flux_units'])
2626
wavelength = Quantity(value=row.value['wavelength'], unit=row.value['wavelength_units'])
27-
photon_spectrum = Spectrum1D(flux=photon_counts, spectral_axis=wavelength)
27+
photon_spectrum = Spectrum(flux=photon_counts, spectral_axis=wavelength)
2828
energy_spectrum = photon_spectrum.flux * (photon_spectrum.energy / photon)
29-
energy_spectrum_object = Spectrum1D(
29+
energy_spectrum_object = Spectrum(
3030
spectral_axis=wavelength,
3131
flux=energy_spectrum.to('erg / (s cm2 AA)', spectral_density(wavelength)))
3232
row.value = spectrum_serializer.serialize(energy_spectrum_object)
Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
from specutils import Spectrum1D
1+
from specutils import Spectrum
22
from astropy.units import Quantity
33

44

55
class SpectrumSerializer():
66

7-
def serialize(self, spectrum: Spectrum1D) -> dict:
7+
def serialize(self, spectrum: Spectrum) -> dict:
88
"""
9-
Serializes a Spectrum1D in order to store in a ReducedDatum object. The serialization stores only what's
10-
necessary to rebuild the Spectrum1D--namely, flux and wavelength, and their respective units.
9+
Serializes a Spectrum in order to store in a ReducedDatum object. The serialization stores only what's
10+
necessary to rebuild the Spectrum--namely, flux and wavelength, and their respective units.
1111
12-
:param spectrum: Spectrum1D to be serialized
13-
:type spectrum: specutils.Spectrum1D
12+
:param spectrum: Spectrum to be serialized
13+
:type spectrum: specutils.Spectrum
1414
1515
:returns: JSON representation of spectrum
1616
:rtype: dict
@@ -22,17 +22,17 @@ def serialize(self, spectrum: Spectrum1D) -> dict:
2222
serialized['wavelength_units'] = spectrum.wavelength.unit.to_string()
2323
return serialized
2424

25-
def deserialize(self, spectrum: dict) -> Spectrum1D:
25+
def deserialize(self, spectrum: dict) -> Spectrum:
2626
"""
27-
Constructs a Spectrum1D from the spectrum value stored in a ReducedDatum
27+
Constructs a Spectrum from the spectrum value stored in a ReducedDatum
2828
29-
:param spectrum: JSON representation used to construct the Spectrum1D
29+
:param spectrum: JSON representation used to construct the Spectrum
3030
:type spectrum: dict
3131
32-
:returns: Spectrum1D representing the spectrum information
33-
:rtype: specutil.Spectrum1D
32+
:returns: Spectrum representing the spectrum information
33+
:rtype: specutil.Spectrum
3434
"""
3535
flux = Quantity(value=spectrum['flux'], unit=spectrum['flux_units'])
3636
wavelength = Quantity(value=spectrum['wavelength'], unit=spectrum['wavelength_units'])
37-
spectrum = Spectrum1D(flux=flux, spectral_axis=wavelength)
37+
spectrum = Spectrum(flux=flux, spectral_axis=wavelength)
3838
return spectrum

tom_dataproducts/processors/spectroscopy_processor.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from astropy.io import fits, ascii as astropy_ascii
88
from astropy.time import Time
99
from astropy.wcs import WCS
10-
from specutils import Spectrum1D
10+
from specutils import Spectrum
1111

1212
from tom_dataproducts.data_processor import DataProcessor
1313
from tom_dataproducts.exceptions import InvalidFileFormatException
@@ -46,16 +46,16 @@ def process_data(self, data_product):
4646

4747
def _process_spectrum_from_fits(self, data_product):
4848
"""
49-
Processes the data from a spectrum from a fits file into a Spectrum1D object, which can then be serialized and
49+
Processes the data from a spectrum from a fits file into a Spectrum object, which can then be serialized and
5050
stored as a ReducedDatum for further processing or display. File is read using specutils as specified in the
5151
below documentation.
5252
# https://specutils.readthedocs.io/en/doc-testing/specutils/read_fits.html
5353
54-
:param data_product: Spectroscopic DataProduct which will be processed into a Spectrum1D
54+
:param data_product: Spectroscopic DataProduct which will be processed into a Spectrum
5555
:type data_product: tom_dataproducts.models.DataProduct
5656
57-
:returns: Spectrum1D object containing the data from the DataProduct
58-
:rtype: specutils.Spectrum1D
57+
:returns: Spectrum object containing the data from the DataProduct
58+
:rtype: specutils.Spectrum
5959
6060
:returns: Datetime of observation, if it is in the header and the file is from a supported facility, current
6161
datetime otherwise
@@ -86,13 +86,13 @@ def _process_spectrum_from_fits(self, data_product):
8686
header['CUNIT1'] = 'Angstrom'
8787
wcs = WCS(header=header, naxis=1)
8888

89-
spectrum = Spectrum1D(flux=flux, wcs=wcs)
89+
spectrum = Spectrum(flux=flux, wcs=wcs)
9090

9191
return spectrum, Time(date_obs).to_datetime(), facility_name
9292

9393
def _process_spectrum_from_plaintext(self, data_product):
9494
"""
95-
Processes the data from a spectrum from a plaintext file into a Spectrum1D object, which can then be serialized
95+
Processes the data from a spectrum from a plaintext file into a Spectrum object, which can then be serialized
9696
and stored as a ReducedDatum for further processing or display. File is read using astropy as specified in
9797
the below documentation. The file is expected to be a multi-column delimited file, with headers for wavelength
9898
and flux. The file also requires comments containing, at minimum, 'DATE-OBS: [value]', where value is an
@@ -102,11 +102,11 @@ def _process_spectrum_from_plaintext(self, data_product):
102102
103103
Parameters
104104
----------
105-
:param data_product: Spectroscopic DataProduct which will be processed into a Spectrum1D
105+
:param data_product: Spectroscopic DataProduct which will be processed into a Spectrum
106106
:type data_product: tom_dataproducts.models.DataProduct
107107
108-
:returns: Spectrum1D object containing the data from the DataProduct
109-
:rtype: specutils.Spectrum1D
108+
:returns: Spectrum object containing the data from the DataProduct
109+
:rtype: specutils.Spectrum
110110
111111
:returns: Datetime of observation, if it is in the comments and the file is from a supported facility, current
112112
datetime otherwise
@@ -132,6 +132,6 @@ def _process_spectrum_from_plaintext(self, data_product):
132132

133133
spectral_axis = np.array(data['wavelength']) * wavelength_units
134134
flux = np.array(data['flux']) * flux_constant
135-
spectrum = Spectrum1D(flux=flux, spectral_axis=spectral_axis)
135+
spectrum = Spectrum(flux=flux, spectral_axis=spectral_axis)
136136

137137
return spectrum, Time(date_obs).to_datetime(), facility_name

tom_dataproducts/tests/tests.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from django.utils import timezone, text
1818
from guardian.shortcuts import assign_perm
1919
import numpy as np
20-
from specutils import Spectrum1D
20+
from specutils import Spectrum
2121
from unittest.mock import patch
2222

2323
from tom_dataproducts.exceptions import InvalidFileFormatException
@@ -417,7 +417,7 @@ def setUp(self):
417417
def test_serialize_spectrum(self):
418418
flux = np.arange(1, 200) * units.Jy
419419
wavelength = np.arange(1, 200) * units.Angstrom
420-
spectrum = Spectrum1D(spectral_axis=wavelength, flux=flux)
420+
spectrum = Spectrum(spectral_axis=wavelength, flux=flux)
421421
serialized = self.serializer.serialize(spectrum)
422422

423423
self.assertTrue(isinstance(serialized, dict))
@@ -439,7 +439,7 @@ def test_deserialize_spectrum(self):
439439
}
440440
deserialized = self.serializer.deserialize(serialized_spectrum)
441441

442-
self.assertTrue(isinstance(deserialized, Spectrum1D))
442+
self.assertTrue(isinstance(deserialized, Spectrum))
443443
self.assertEqual(deserialized.flux.mean().value, 1.5)
444444
self.assertEqual(deserialized.wavelength.mean().value, 1.5)
445445

@@ -484,15 +484,15 @@ def test_process_spectrum_from_fits(self):
484484
with open('tom_dataproducts/tests/test_data/test_spectrum.fits', 'rb') as spectrum_file:
485485
self.data_product.data.save('spectrum.fits', spectrum_file)
486486
spectrum, _, _ = self.spectrum_data_processor._process_spectrum_from_fits(self.data_product)
487-
self.assertTrue(isinstance(spectrum, Spectrum1D))
487+
self.assertTrue(isinstance(spectrum, Spectrum))
488488
self.assertAlmostEqual(spectrum.flux.mean().value, 2.295068e-14, places=19)
489489
self.assertAlmostEqual(spectrum.wavelength.mean().value, 6600.478789, places=5)
490490

491491
def test_process_spectrum_from_plaintext(self):
492492
with open('tom_dataproducts/tests/test_data/test_spectrum.csv', 'rb') as spectrum_file:
493493
self.data_product.data.save('spectrum.csv', spectrum_file)
494494
spectrum, _, _ = self.spectrum_data_processor._process_spectrum_from_plaintext(self.data_product)
495-
self.assertTrue(isinstance(spectrum, Spectrum1D))
495+
self.assertTrue(isinstance(spectrum, Spectrum))
496496
self.assertAlmostEqual(spectrum.flux.mean().value, 1.166619e-14, places=19)
497497
self.assertAlmostEqual(spectrum.wavelength.mean().value, 3250.744489, places=5)
498498

tom_observations/facilities/gemini.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
VALID_OBSERVING_STATES = ['TRIGGERED', 'ON_HOLD']
4444
TERMINAL_OBSERVING_STATES = ['TRIGGERED', 'ON_HOLD']
4545

46-
# Units of flux and wavelength for converting to Specutils Spectrum1D objects
46+
# Units of flux and wavelength for converting to Specutils Spectrum objects
4747
FLUX_CONSTANT = (1 * u.erg) / (u.cm ** 2 * u.second * u.angstrom)
4848
WAVELENGTH_UNITS = u.angstrom
4949

0 commit comments

Comments
 (0)