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 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
- reordered records.
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
@@ -37,4 +37,5 @@ __all__ = ["client", "align_records"]
37
37
  #__version__ = "1.2.5"
38
38
  #__version__ = "1.2.6"
39
39
  #__version__ = "1.2.7"
40
- __version__ = "1.2.8b3"
40
+ #__version__ = "1.2.8"
41
+ __version__ = "1.2.9b1"
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
- POST http://localhost:8050/sparc/renew_token/
271
- Content-Type: application/json
272
- {
273
- "refresh_token": "..."
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
- >> client = SparclClient(announcement=False)
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 = [5840097619402313728, -8985592895187431424]
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.8b3
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>=2.2.6,<2.4.0
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=vnACjm8sp7MrsJ_5LTuKMuyRWqeBJxOxQM302cHmAlk,9159
2
- sparcl/__init__.py,sha256=4KD9qc6IPqsEaqooKvpCp3WsfVQMBjtSzc0wF-CmAHQ,1170
3
- sparcl/client.py,sha256=C9vYeHqZvl0lzVw1BRJeGCv5zk2W2XH1aLsFtBYeYk4,40013
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.8b3.dist-info/LICENSE,sha256=y10EluGMCzGs9X4oYCYyix3l6u-lawB_vlGR8qe442Q,1576
19
- sparclclient-1.2.8b3.dist-info/WHEEL,sha256=ssQ84EZ5gH1pCOujd3iW7HClo_O_aDaClUbX4B8bjKY,100
20
- sparclclient-1.2.8b3.dist-info/METADATA,sha256=zjPB9d8jusTW-Dks8sfmvKenYHhkTrC28GrT815Zts4,678
21
- sparclclient-1.2.8b3.dist-info/RECORD,,
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,,