sparclclient 1.2.8b3__py2.py3-none-any.whl → 1.2.9b1__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sparcl/Results.py +10 -4
- sparcl/__init__.py +2 -1
- sparcl/client.py +9 -11
- sparcl/specutils.py +245 -0
- {sparclclient-1.2.8b3.dist-info → sparclclient-1.2.9b1.dist-info}/METADATA +2 -2
- {sparclclient-1.2.8b3.dist-info → sparclclient-1.2.9b1.dist-info}/RECORD +8 -7
- {sparclclient-1.2.8b3.dist-info → sparclclient-1.2.9b1.dist-info}/LICENSE +0 -0
- {sparclclient-1.2.8b3.dist-info → sparclclient-1.2.9b1.dist-info}/WHEEL +0 -0
sparcl/Results.py
CHANGED
|
@@ -9,6 +9,7 @@ from sparcl.utils import _AttrDict
|
|
|
9
9
|
|
|
10
10
|
# from sparcl.gather_2d import bin_spectra_records
|
|
11
11
|
import sparcl.exceptions as ex
|
|
12
|
+
import sparcl.specutils as su
|
|
12
13
|
from warnings import warn
|
|
13
14
|
import re
|
|
14
15
|
|
|
@@ -139,9 +140,7 @@ class Results(UserList):
|
|
|
139
140
|
|
|
140
141
|
Returns:
|
|
141
142
|
reordered (:class:`~sparcl.Results.Retrieved`): Contains header and
|
|
142
|
-
|
|
143
|
-
# none_idx (:obj:`list`): List of indices where record is None.
|
|
144
|
-
|
|
143
|
+
reordered records.
|
|
145
144
|
"""
|
|
146
145
|
if len(ids_og) <= 0:
|
|
147
146
|
msg = (
|
|
@@ -198,6 +197,14 @@ class Results(UserList):
|
|
|
198
197
|
warn(msg, stacklevel=2)
|
|
199
198
|
return Results(reordered, client=self.client)
|
|
200
199
|
|
|
200
|
+
def to_specutils(self):
|
|
201
|
+
"""Convert results to a `specutils` object.
|
|
202
|
+
|
|
203
|
+
Returns:
|
|
204
|
+
to_specutils (:class:`~specutils.Spectrum`): a `specutils` object.
|
|
205
|
+
"""
|
|
206
|
+
return su.to_specutils(self)
|
|
207
|
+
|
|
201
208
|
|
|
202
209
|
# For results of retrieve()
|
|
203
210
|
class Retrieved(Results):
|
|
@@ -209,7 +216,6 @@ class Retrieved(Results):
|
|
|
209
216
|
def __repr__(self):
|
|
210
217
|
return f"Retrieved Results: {len(self.recs)} records"
|
|
211
218
|
|
|
212
|
-
|
|
213
219
|
#! def bin_spectra(self):
|
|
214
220
|
#! """Align flux from all records by common wavelength bin.
|
|
215
221
|
#!
|
sparcl/__init__.py
CHANGED
sparcl/client.py
CHANGED
|
@@ -267,11 +267,12 @@ class SparclClient: # was SparclApi()
|
|
|
267
267
|
|
|
268
268
|
def token_expired(self, renew=False):
|
|
269
269
|
"""
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
270
|
+
::
|
|
271
|
+
POST http://localhost:8050/sparc/renew_token/
|
|
272
|
+
Content-Type: application/json
|
|
273
|
+
{
|
|
274
|
+
"refresh_token": "..."
|
|
275
|
+
}
|
|
275
276
|
|
|
276
277
|
Returns an 'access' token
|
|
277
278
|
"""
|
|
@@ -308,9 +309,8 @@ class SparclClient: # was SparclApi()
|
|
|
308
309
|
None.
|
|
309
310
|
|
|
310
311
|
Example:
|
|
311
|
-
>>>
|
|
312
|
-
|
|
313
|
-
>> client.login('test_user@noirlab.edu', 'testpw')
|
|
312
|
+
>>> client = SparclClient(announcement=False)
|
|
313
|
+
>>> client.login('test_user@noirlab.edu', 'pw') # doctest: +SKIP
|
|
314
314
|
Logged in successfully with email='test_user@noirlab.edu'
|
|
315
315
|
"""
|
|
316
316
|
|
|
@@ -1021,11 +1021,9 @@ class SparclClient: # was SparclApi()
|
|
|
1021
1021
|
|
|
1022
1022
|
Example:
|
|
1023
1023
|
>>> client = SparclClient(announcement=False)
|
|
1024
|
-
>>> sids = [
|
|
1024
|
+
>>> sids = [4753625089450465280, 1254253099313293312]
|
|
1025
1025
|
>>> inc = ['specid', 'flux', 'wavelength', 'model']
|
|
1026
1026
|
>>> ret = client.retrieve_by_specid(specid_list=sids, include=inc)
|
|
1027
|
-
>>> len(ret.records[0].wavelength)
|
|
1028
|
-
4617
|
|
1029
1027
|
|
|
1030
1028
|
"""
|
|
1031
1029
|
#!specid_list = list(specid_list)
|
sparcl/specutils.py
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
"""Functions for converting SPARCL results to specutils objects.
|
|
2
|
+
"""
|
|
3
|
+
import warnings
|
|
4
|
+
import numpy as np
|
|
5
|
+
try:
|
|
6
|
+
# specutils >= 2.0
|
|
7
|
+
from specutils import Spectrum
|
|
8
|
+
except ImportError:
|
|
9
|
+
from specutils import Spectrum1D as Spectrum
|
|
10
|
+
from specutils import SpectrumCollection, SpectrumList
|
|
11
|
+
from astropy.nddata import InverseVariance
|
|
12
|
+
import astropy.units as u
|
|
13
|
+
|
|
14
|
+
def _validate_records(records, r0, collection):
|
|
15
|
+
"""Validate that records can be converted to Spectrum."""
|
|
16
|
+
|
|
17
|
+
# Check if the first record has wavelength data
|
|
18
|
+
if 'wavelength' not in r0:
|
|
19
|
+
raise ValueError("Results do not have a wavelength attribute. "
|
|
20
|
+
"Conversion is not possible.")
|
|
21
|
+
|
|
22
|
+
# Check if all records come from the same data release
|
|
23
|
+
if not all([r.data_release == r0.data_release for r in records]):
|
|
24
|
+
warnings.warn("Results are not all from the same data release, "
|
|
25
|
+
"conversion may not be possible.", UserWarning)
|
|
26
|
+
|
|
27
|
+
# Check if all records have the same number of wavelength points
|
|
28
|
+
if not all([len(r.wavelength) == len(r0.wavelength) for r in records]):
|
|
29
|
+
raise ValueError("Results do not have the same wavelength solution. "
|
|
30
|
+
"Consider using .to_SpectrumList instead.")
|
|
31
|
+
|
|
32
|
+
# If not creating a SpectrumCollection, check that wavelength values
|
|
33
|
+
# are identical across all records
|
|
34
|
+
if not collection and not all([(r.wavelength == r0.wavelength).all()
|
|
35
|
+
for r in records]):
|
|
36
|
+
raise ValueError("Results do not have the same wavelength pixels. "
|
|
37
|
+
"Consider using SpectrumCollection instead.")
|
|
38
|
+
|
|
39
|
+
def _extract_record_data(records, flux, uncertainty, mask, model, redshift,
|
|
40
|
+
meta, spectral_axis, has_model, has_redshift,
|
|
41
|
+
collection, single_record):
|
|
42
|
+
"""Extract all data from records into arrays."""
|
|
43
|
+
for k, record in enumerate(records):
|
|
44
|
+
if single_record:
|
|
45
|
+
# For single record, assign directly (1D)
|
|
46
|
+
flux[:] = record.flux
|
|
47
|
+
uncertainty[:] = record.ivar
|
|
48
|
+
mask[:] = record.mask
|
|
49
|
+
if has_model:
|
|
50
|
+
model[:] = record.model
|
|
51
|
+
else:
|
|
52
|
+
# For multiple records, assign to row (2D)
|
|
53
|
+
flux[k, :] = record.flux
|
|
54
|
+
uncertainty[k, :] = record.ivar
|
|
55
|
+
mask[k, :] = record.mask
|
|
56
|
+
if has_model:
|
|
57
|
+
model[k, :] = record.model
|
|
58
|
+
|
|
59
|
+
# Store redshift values if available
|
|
60
|
+
if has_redshift:
|
|
61
|
+
redshift.append(record.redshift)
|
|
62
|
+
|
|
63
|
+
# For collections, each record can have its own wavelength grid
|
|
64
|
+
if collection:
|
|
65
|
+
spectral_axis[k, :] = record.wavelength
|
|
66
|
+
|
|
67
|
+
# Extract all additional metadata attributes
|
|
68
|
+
for attribute, value in record.items():
|
|
69
|
+
if attribute not in ('flux', 'ivar', 'mask', 'model', 'redshift',
|
|
70
|
+
'wavelength'):
|
|
71
|
+
if single_record:
|
|
72
|
+
# For single record, store metadata values as scalars
|
|
73
|
+
meta[attribute] = value
|
|
74
|
+
else:
|
|
75
|
+
# For multiple records, accumulate metadata values into
|
|
76
|
+
# lists (creates list on first encounter, then appends)
|
|
77
|
+
meta.setdefault(attribute, []).append(value)
|
|
78
|
+
|
|
79
|
+
def to_Spectrum(results, *, collection=False):
|
|
80
|
+
"""Convert `results` to :class:`specutils.Spectrum`.
|
|
81
|
+
|
|
82
|
+
Parameters
|
|
83
|
+
----------
|
|
84
|
+
results : :class:`sparcl.Results.Retrieved`
|
|
85
|
+
Retrieved results, or a single record from a set of results.
|
|
86
|
+
collection : :class:`bool`, optional
|
|
87
|
+
If ``True``, attempt to convert to a
|
|
88
|
+
:class:`~specutils.SpectrumCollection` instead.
|
|
89
|
+
|
|
90
|
+
Returns
|
|
91
|
+
-------
|
|
92
|
+
:class:`~specutils.Spectrum` or :class:`~specutils.SpectrumCollection`
|
|
93
|
+
The requested object.
|
|
94
|
+
|
|
95
|
+
Raises
|
|
96
|
+
------
|
|
97
|
+
ValueError
|
|
98
|
+
If `results` can't be converted to a :class:`~specutils.Spectrum`
|
|
99
|
+
object in a valid way. For example, if some of the spectra have a
|
|
100
|
+
different wavelength solution.
|
|
101
|
+
"""
|
|
102
|
+
# Prepare records
|
|
103
|
+
if isinstance(results, dict):
|
|
104
|
+
records = [results]
|
|
105
|
+
r0 = results
|
|
106
|
+
else:
|
|
107
|
+
try:
|
|
108
|
+
records = results.records
|
|
109
|
+
if len(records) == 0:
|
|
110
|
+
raise ValueError("No records found in results. Cannot "
|
|
111
|
+
"convert empty results to Spectrum.")
|
|
112
|
+
r0 = results.records[0]
|
|
113
|
+
except (IndexError, AttributeError) as e:
|
|
114
|
+
raise ValueError("No records found in results. Cannot "
|
|
115
|
+
"convert empty results to Spectrum.") from e
|
|
116
|
+
|
|
117
|
+
# Validate
|
|
118
|
+
_validate_records(records, r0, collection)
|
|
119
|
+
|
|
120
|
+
# Determine which optional data components exist in records
|
|
121
|
+
has_redshift = 'redshift' in r0
|
|
122
|
+
has_model = 'model' in r0
|
|
123
|
+
n_pixels = r0.flux.shape[0]
|
|
124
|
+
single_record = len(records) == 1
|
|
125
|
+
|
|
126
|
+
# Set flux shape based on number of records
|
|
127
|
+
if single_record:
|
|
128
|
+
flux_shape = (n_pixels,)
|
|
129
|
+
else:
|
|
130
|
+
flux_shape = (len(records), n_pixels)
|
|
131
|
+
|
|
132
|
+
# Build spectral axis
|
|
133
|
+
if collection:
|
|
134
|
+
spectral_axis = np.zeros((len(records), r0.wavelength.shape[0]),
|
|
135
|
+
dtype=r0.wavelength.dtype)
|
|
136
|
+
else:
|
|
137
|
+
spectral_axis = r0.wavelength
|
|
138
|
+
|
|
139
|
+
# Initialize arrays
|
|
140
|
+
flux = np.zeros(flux_shape, dtype=r0.flux.dtype)
|
|
141
|
+
uncertainty = np.zeros(flux_shape, dtype=r0.ivar.dtype)
|
|
142
|
+
mask = np.zeros(flux_shape, dtype=r0.mask.dtype)
|
|
143
|
+
model = np.zeros(flux_shape, dtype=r0.model.dtype) if has_model else None
|
|
144
|
+
redshift = []
|
|
145
|
+
meta = {}
|
|
146
|
+
|
|
147
|
+
# Populate arrays by iterating through records
|
|
148
|
+
_extract_record_data(records, flux, uncertainty, mask, model, redshift,
|
|
149
|
+
meta, spectral_axis, has_model, has_redshift,
|
|
150
|
+
collection, single_record)
|
|
151
|
+
|
|
152
|
+
# Convert redshift list to numpy array if exists
|
|
153
|
+
if has_redshift:
|
|
154
|
+
redshift = np.array(redshift)
|
|
155
|
+
else:
|
|
156
|
+
redshift = None
|
|
157
|
+
|
|
158
|
+
# Add model to metadata if exists
|
|
159
|
+
if has_model:
|
|
160
|
+
meta['model'] = model
|
|
161
|
+
|
|
162
|
+
# Prepare arguments common to both Spectrum and SpectrumCollection
|
|
163
|
+
common_args = {
|
|
164
|
+
'flux': flux * u.Unit('1e-17 erg cm-2 s-1 AA-1'),
|
|
165
|
+
'spectral_axis': spectral_axis * u.AA,
|
|
166
|
+
'uncertainty': InverseVariance(uncertainty),
|
|
167
|
+
'mask': mask,
|
|
168
|
+
'meta': meta}
|
|
169
|
+
|
|
170
|
+
if collection:
|
|
171
|
+
return SpectrumCollection(**common_args)
|
|
172
|
+
|
|
173
|
+
return Spectrum(**common_args, redshift=redshift)
|
|
174
|
+
|
|
175
|
+
def to_SpectrumList(results):
|
|
176
|
+
"""Convert `results` to :class:`specutils.SpectrumList`.
|
|
177
|
+
|
|
178
|
+
Parameters
|
|
179
|
+
----------
|
|
180
|
+
results : :class:`sparcl.Results.Retrieved`
|
|
181
|
+
Retrieved results.
|
|
182
|
+
|
|
183
|
+
Returns
|
|
184
|
+
-------
|
|
185
|
+
:class:`~specutils.SpectrumList`
|
|
186
|
+
The requested object.
|
|
187
|
+
"""
|
|
188
|
+
s = SpectrumList()
|
|
189
|
+
if isinstance(results, dict):
|
|
190
|
+
records = [results]
|
|
191
|
+
else:
|
|
192
|
+
records = results.records
|
|
193
|
+
for r in records:
|
|
194
|
+
if 'redshift' in r:
|
|
195
|
+
redshift = r.redshift
|
|
196
|
+
else:
|
|
197
|
+
redshift = None
|
|
198
|
+
meta = dict()
|
|
199
|
+
for attribute in r:
|
|
200
|
+
if attribute not in ('flux', 'wavelength', 'ivar',
|
|
201
|
+
'redshift', 'mask'):
|
|
202
|
+
meta[attribute] = r[attribute]
|
|
203
|
+
s1 = Spectrum(flux=r.flux*u.Unit('1e-17 erg cm-2 s-1 AA-1'),
|
|
204
|
+
spectral_axis=r.wavelength*u.AA,
|
|
205
|
+
uncertainty=InverseVariance(r.ivar),
|
|
206
|
+
redshift=redshift,
|
|
207
|
+
mask=r.mask,
|
|
208
|
+
meta=meta)
|
|
209
|
+
s.append(s1)
|
|
210
|
+
return s
|
|
211
|
+
|
|
212
|
+
def to_specutils(results):
|
|
213
|
+
"""Convert `results` to a specutils object.
|
|
214
|
+
|
|
215
|
+
Parameters
|
|
216
|
+
----------
|
|
217
|
+
results : :class:`sparcl.Results.Retrieved`
|
|
218
|
+
Retrieved results.
|
|
219
|
+
|
|
220
|
+
Returns
|
|
221
|
+
-------
|
|
222
|
+
:class:`~specutils.Spectrum` or :class:`~specutils.SpectrumCollection`
|
|
223
|
+
or :class:`~specutils.SpectrumList`
|
|
224
|
+
The most natural conversion to a specutils object.
|
|
225
|
+
|
|
226
|
+
Raises
|
|
227
|
+
------
|
|
228
|
+
ValueError
|
|
229
|
+
If no valid conversion can be performed.
|
|
230
|
+
"""
|
|
231
|
+
try:
|
|
232
|
+
# Try standard Spectrum conversion first
|
|
233
|
+
s = to_Spectrum(results)
|
|
234
|
+
except ValueError as ve:
|
|
235
|
+
# Check the error message to determine appropriate alternative
|
|
236
|
+
if 'SpectrumList' in str(ve):
|
|
237
|
+
# Different wavelength array lengths use SpectrumList
|
|
238
|
+
s = to_SpectrumList(results)
|
|
239
|
+
elif 'SpectrumCollection' in str(ve):
|
|
240
|
+
# Same wavelength length but diff pixels use SpectrumCollection
|
|
241
|
+
s = to_Spectrum(results, collection=True)
|
|
242
|
+
else:
|
|
243
|
+
raise ValueError("Could not find a valid conversion to "
|
|
244
|
+
"specutils objects!")
|
|
245
|
+
return s
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: sparclclient
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.9b1
|
|
4
4
|
Summary: A client for getting spectra and meta-data from NOIRLab.
|
|
5
5
|
Author-email: "S. Pothier" <datalab-spectro@noirlab.edu>
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
7
7
|
Classifier: License :: OSI Approved :: MIT License
|
|
8
8
|
Requires-Dist: requests==2.31.0
|
|
9
|
-
Requires-Dist: numpy>=
|
|
9
|
+
Requires-Dist: numpy>=1.26,<2.4.0
|
|
10
10
|
Requires-Dist: spectres
|
|
11
11
|
Requires-Dist: pyjwt
|
|
12
12
|
Project-URL: Bug Tracker, https://github.com/pypa/sparclclient/issues
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
sparcl/Results.py,sha256=
|
|
2
|
-
sparcl/__init__.py,sha256=
|
|
3
|
-
sparcl/client.py,sha256=
|
|
1
|
+
sparcl/Results.py,sha256=IlnYZrDddARv3PJ3HPcyHJwTdMroqGdw-eaSrbmAA64,9290
|
|
2
|
+
sparcl/__init__.py,sha256=YqaePEJGAUXC3_s-RCRYbHQlTaC_Bd6W9ObvBHvQXJ8,1193
|
|
3
|
+
sparcl/client.py,sha256=OAY9F1KbyVc5kos7twqOFnQcGtoqraNG6-CJWqmVE3o,39976
|
|
4
4
|
sparcl/conf.py,sha256=GFNDelaiVIAkjNjvFlG7HAlPpU39nqZmTPohQGmOcgI,928
|
|
5
5
|
sparcl/exceptions.py,sha256=sznmOMGENHvxutSXlRVWqi87bR2Qiebka7LyR3mAII0,4244
|
|
6
6
|
sparcl/fields.py,sha256=NZUBqDidpbXfeX5F4b306F323xZY2CRIx8eVv-HWTVU,5127
|
|
7
7
|
sparcl/gather_2d.py,sha256=YTFVQl38dRZjUu0AEUFVZtQm7zC8mU3LVvUTDGxp6u8,8722
|
|
8
8
|
sparcl/resample_spectra.py,sha256=nk5HiyaGF-b9SiTmIC9yJBbYX4VYsiLFHyW186bPs2s,1310
|
|
9
9
|
sparcl/sparc.ini,sha256=q_wjo9DLnCYRxWFMl0CtMYp4DD1AXfEcK6BP6cmncwo,329
|
|
10
|
+
sparcl/specutils.py,sha256=IKI4VQ53_ay6kgfAGdvNkpseCH0eURes3RupGJ2-JVA,8738
|
|
10
11
|
sparcl/type_conversion.py,sha256=QmXNX9j_7QHnBu83f2ZBfREoql9wuo98ZbhQtSjRRWc,12965
|
|
11
12
|
sparcl/unsupported.py,sha256=bfkkZa-PuqwN-Bqo3vCIrLupbWMDTCiTHPMNfXnqmMc,1848
|
|
12
13
|
sparcl/utils.py,sha256=pDAk9roe7ezfVohnKcLMxFjjXHkp7EQLbgVNe5sSTrk,6259
|
|
@@ -15,7 +16,7 @@ sparcl/benchmarks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU
|
|
|
15
16
|
sparcl/benchmarks/benchmarks.py,sha256=OmlSdnAPLmcvGXsr-HzGyfAAcnoqlO0JQ4EIA7JGhZc,9424
|
|
16
17
|
sparcl/benchmarks/sparcl_benchmarking.ipynb,sha256=gwof2hqM9Qb49qzRX-mky7WNqXZCMSB7ry8bX8dImxc,17559
|
|
17
18
|
sparcl/notebooks/sparcl-examples.ipynb,sha256=gEwMKI1x7A1YsVeCsQn1QoMO0ZuIhMUAu3qedTiQ7hM,169268
|
|
18
|
-
sparclclient-1.2.
|
|
19
|
-
sparclclient-1.2.
|
|
20
|
-
sparclclient-1.2.
|
|
21
|
-
sparclclient-1.2.
|
|
19
|
+
sparclclient-1.2.9b1.dist-info/LICENSE,sha256=y10EluGMCzGs9X4oYCYyix3l6u-lawB_vlGR8qe442Q,1576
|
|
20
|
+
sparclclient-1.2.9b1.dist-info/WHEEL,sha256=ssQ84EZ5gH1pCOujd3iW7HClo_O_aDaClUbX4B8bjKY,100
|
|
21
|
+
sparclclient-1.2.9b1.dist-info/METADATA,sha256=0L79znAjI_0CMKc_AUJgjebyNgf1mdrvFHOQ7tpi20o,677
|
|
22
|
+
sparclclient-1.2.9b1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|