sacc 1.0__py3-none-any.whl → 2.0__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.
- sacc/__init__.py +4 -1
- sacc/covariance.py +202 -96
- sacc/data_types.py +64 -9
- sacc/io.py +414 -0
- sacc/sacc.py +372 -149
- sacc/tracer_uncertainty/__init__.py +1 -0
- sacc/tracer_uncertainty/base.py +34 -0
- sacc/tracer_uncertainty/nz.py +287 -0
- sacc/tracers/__init__.py +6 -0
- sacc/tracers/base.py +127 -0
- sacc/tracers/clusters.py +332 -0
- sacc/tracers/maps.py +206 -0
- sacc/tracers/misc.py +87 -0
- sacc/tracers/nz.py +285 -0
- sacc/tracers/survey.py +75 -0
- sacc/utils.py +46 -2
- sacc/windows.py +116 -102
- {sacc-1.0.dist-info → sacc-2.0.dist-info}/METADATA +6 -4
- sacc-2.0.dist-info/RECORD +22 -0
- {sacc-1.0.dist-info → sacc-2.0.dist-info}/WHEEL +1 -1
- sacc/tracers.py +0 -1217
- sacc-1.0.dist-info/RECORD +0 -12
- {sacc-1.0.dist-info → sacc-2.0.dist-info}/licenses/LICENSE +0 -0
- {sacc-1.0.dist-info → sacc-2.0.dist-info}/top_level.txt +0 -0
sacc/tracers.py
DELETED
@@ -1,1217 +0,0 @@
|
|
1
|
-
import numpy as np
|
2
|
-
from astropy.table import Table
|
3
|
-
from .utils import (Namespace, hide_null_values,
|
4
|
-
remove_dict_null_values, unique_list)
|
5
|
-
|
6
|
-
standard_quantities = Namespace('galaxy_shear',
|
7
|
-
'galaxy_density',
|
8
|
-
'galaxy_convergence',
|
9
|
-
'cluster_density',
|
10
|
-
'cmb_temperature',
|
11
|
-
'cmb_polarization',
|
12
|
-
'cmb_convergence',
|
13
|
-
'cmb_tSZ',
|
14
|
-
'cmb_kSZ',
|
15
|
-
'cluster_mass_count_wl',
|
16
|
-
'cluster_mass_count_xray',
|
17
|
-
'cluster_mass_count_tSZ',
|
18
|
-
'generic')
|
19
|
-
|
20
|
-
|
21
|
-
class BaseTracer:
|
22
|
-
"""
|
23
|
-
A class representing some kind of tracer of astronomical objects.
|
24
|
-
|
25
|
-
Generically, SACC data points correspond to some combination of tracers
|
26
|
-
for example, tomographic two-point data has two tracers for each data
|
27
|
-
point, indicating the n(z) for the corresponding tomographic bin.
|
28
|
-
|
29
|
-
All Tracer objects have at least a name attribute. Different
|
30
|
-
subclassses have other requirements. For example, n(z) tracers
|
31
|
-
require z and n(z) arrays.
|
32
|
-
|
33
|
-
In general you don't need to create tracer objects yourself -
|
34
|
-
the Sacc.add_tracer method will construct them for you.
|
35
|
-
"""
|
36
|
-
_tracer_classes = {}
|
37
|
-
|
38
|
-
def __init__(self, name, **kwargs):
|
39
|
-
# We encourage people to use existing quantity names, and issue a
|
40
|
-
# warning if they do not to prod them in the right direction.
|
41
|
-
quantity = kwargs.pop('quantity', 'generic')
|
42
|
-
self.name = name
|
43
|
-
self.quantity = quantity
|
44
|
-
self.metadata = kwargs.pop('metadata', {})
|
45
|
-
|
46
|
-
def __init_subclass__(cls, tracer_type):
|
47
|
-
cls._tracer_classes[tracer_type.lower()] = cls
|
48
|
-
cls.tracer_type = tracer_type
|
49
|
-
|
50
|
-
@classmethod
|
51
|
-
def make(cls, tracer_type, name, *args, **kwargs):
|
52
|
-
"""
|
53
|
-
Select a Tracer subclass based on tracer_type
|
54
|
-
and instantiate in instance of it with the remaining
|
55
|
-
arguments.
|
56
|
-
|
57
|
-
Parameters
|
58
|
-
----------
|
59
|
-
tracer_type: str
|
60
|
-
Must correspond to the tracer_type of a subclass
|
61
|
-
|
62
|
-
name: str
|
63
|
-
The name for this specific tracer.
|
64
|
-
|
65
|
-
Returns
|
66
|
-
-------
|
67
|
-
instance: Tracer object
|
68
|
-
An instance of a Tracer subclass
|
69
|
-
"""
|
70
|
-
subclass = cls._tracer_classes[tracer_type.lower()]
|
71
|
-
obj = subclass(name, *args, **kwargs)
|
72
|
-
return obj
|
73
|
-
|
74
|
-
@classmethod
|
75
|
-
def to_tables(cls, instance_list):
|
76
|
-
"""Convert a list of tracers to a list of astropy tables
|
77
|
-
|
78
|
-
This is used when saving data to a file.
|
79
|
-
|
80
|
-
This class method converts a list of tracers, each of which
|
81
|
-
can instances of any subclass of BaseTracer, and turns them
|
82
|
-
into a list of astropy tables, ready to be saved to disk.
|
83
|
-
|
84
|
-
Some tracers generate a single table for all of the
|
85
|
-
different instances, and others generate one table per
|
86
|
-
instance.
|
87
|
-
|
88
|
-
Parameters
|
89
|
-
----------
|
90
|
-
instance_list: list
|
91
|
-
List of tracer instances
|
92
|
-
|
93
|
-
Returns
|
94
|
-
-------
|
95
|
-
tables: list
|
96
|
-
List of astropy tables
|
97
|
-
"""
|
98
|
-
tables = []
|
99
|
-
for name, subcls in cls._tracer_classes.items():
|
100
|
-
tracers = [t for t in instance_list if type(t) == subcls]
|
101
|
-
# If the list is empty, we don't want to append any tables.
|
102
|
-
if tracers:
|
103
|
-
tables += subcls.to_tables(tracers)
|
104
|
-
return tables
|
105
|
-
|
106
|
-
@classmethod
|
107
|
-
def from_tables(cls, table_list):
|
108
|
-
"""Convert a list of astropy tables into a dictionary of tracers
|
109
|
-
|
110
|
-
This is used when loading data from a file.
|
111
|
-
|
112
|
-
This class method takes a list of tracers, such as those
|
113
|
-
read from a file, and converts them into a list of instances.
|
114
|
-
|
115
|
-
It is not quite the inverse of the to_tables method, since it
|
116
|
-
returns a dict instead of a list.
|
117
|
-
|
118
|
-
Subclasses overrides of this method do the actual work, but
|
119
|
-
should *NOT* call this parent base method.
|
120
|
-
|
121
|
-
Parameters
|
122
|
-
----------
|
123
|
-
table_list: list
|
124
|
-
List of astropy tables
|
125
|
-
|
126
|
-
Returns
|
127
|
-
-------
|
128
|
-
tracers: dict
|
129
|
-
Dict mapping string names to tracer objects.
|
130
|
-
"""
|
131
|
-
tracers = {}
|
132
|
-
# Figure out the different subclasses that are present
|
133
|
-
subclass_names = unique_list(table.meta['SACCCLSS'].lower()
|
134
|
-
for table in table_list)
|
135
|
-
subclasses = [cls._tracer_classes[name]
|
136
|
-
for name in subclass_names]
|
137
|
-
|
138
|
-
# For each subclass find the tables representing that subclass.
|
139
|
-
# We do it like this because we might want to represent one tracer with
|
140
|
-
# multiple tables, or one table can have multiple tracers -
|
141
|
-
# it depends on the tracers class and how complicated it is.
|
142
|
-
for name, subcls in zip(subclass_names, subclasses):
|
143
|
-
subcls_table_list = [table for table in table_list
|
144
|
-
if table.meta['SACCCLSS'].lower() == name]
|
145
|
-
# and ask the subclass to read from those tables.
|
146
|
-
tracers.update(subcls.from_tables(subcls_table_list))
|
147
|
-
return tracers
|
148
|
-
|
149
|
-
|
150
|
-
class MiscTracer(BaseTracer, tracer_type='Misc'):
|
151
|
-
"""A Tracer type for miscellaneous other data points.
|
152
|
-
|
153
|
-
MiscTracers do not have any attributes except for their
|
154
|
-
name, so can be used for tagging external data, for example.
|
155
|
-
|
156
|
-
Parameters
|
157
|
-
----------
|
158
|
-
name: str
|
159
|
-
The name of the tracer
|
160
|
-
"""
|
161
|
-
|
162
|
-
def __init__(self, name, **kwargs):
|
163
|
-
super().__init__(name, **kwargs)
|
164
|
-
|
165
|
-
@classmethod
|
166
|
-
def to_tables(cls, instance_list):
|
167
|
-
"""Convert a list of MiscTracer instances to a astropy tables.
|
168
|
-
|
169
|
-
This is used when saving data to file.
|
170
|
-
|
171
|
-
All the instances are converted to a single table, which is
|
172
|
-
returned in a list with one element so that it can be used
|
173
|
-
in combination with the parent.
|
174
|
-
|
175
|
-
You can use the parent class to_tables class method to convert
|
176
|
-
a mixed list of different tracer types.
|
177
|
-
|
178
|
-
You shouldn't generally need to call this method directly.
|
179
|
-
|
180
|
-
Parameters
|
181
|
-
----------
|
182
|
-
instance_list: list
|
183
|
-
list of MiscTracer objects
|
184
|
-
|
185
|
-
Returns
|
186
|
-
-------
|
187
|
-
tables: list
|
188
|
-
List containing one astropy table
|
189
|
-
"""
|
190
|
-
metadata_cols = set()
|
191
|
-
for obj in instance_list:
|
192
|
-
metadata_cols.update(obj.metadata.keys())
|
193
|
-
metadata_cols = list(metadata_cols)
|
194
|
-
|
195
|
-
cols = [[obj.name for obj in instance_list],
|
196
|
-
[obj.quantity for obj in instance_list]]
|
197
|
-
for name in metadata_cols:
|
198
|
-
cols.append([obj.metadata.get(name) for obj in instance_list])
|
199
|
-
|
200
|
-
table = Table(data=cols,
|
201
|
-
names=['name', 'quantity'] + metadata_cols)
|
202
|
-
table.meta['SACCTYPE'] = 'tracer'
|
203
|
-
table.meta['SACCCLSS'] = cls.tracer_type
|
204
|
-
table.meta['EXTNAME'] = f'tracer:{cls.tracer_type}'
|
205
|
-
hide_null_values(table)
|
206
|
-
return [table]
|
207
|
-
|
208
|
-
@classmethod
|
209
|
-
def from_tables(cls, table_list):
|
210
|
-
"""Convert a list of astropy table into a dictionary of MiscTracer instances.
|
211
|
-
|
212
|
-
In general table_list should have a single element in, since all the
|
213
|
-
MiscTracers are stored in a single table during to_tables
|
214
|
-
|
215
|
-
Parameters
|
216
|
-
----------
|
217
|
-
table_list: List[astropy.table.Table]
|
218
|
-
|
219
|
-
Returns
|
220
|
-
-------
|
221
|
-
tracers: Dict[str: MiscTracer]
|
222
|
-
"""
|
223
|
-
tracers = {}
|
224
|
-
|
225
|
-
for table in table_list:
|
226
|
-
metadata_cols = [col for col in table.colnames
|
227
|
-
if col not in ['name', 'quantity']]
|
228
|
-
|
229
|
-
for row in table:
|
230
|
-
name = row['name']
|
231
|
-
quantity = row['quantity']
|
232
|
-
metadata = {key: row[key] for key in metadata_cols}
|
233
|
-
remove_dict_null_values(metadata)
|
234
|
-
tracers[name] = cls(name, quantity=quantity, metadata=metadata)
|
235
|
-
return tracers
|
236
|
-
|
237
|
-
|
238
|
-
class MapTracer(BaseTracer, tracer_type='Map'):
|
239
|
-
"""
|
240
|
-
A Tracer type for a sky map.
|
241
|
-
|
242
|
-
Takes at least two arguments, defining the map beam.
|
243
|
-
|
244
|
-
Parameters
|
245
|
-
----------
|
246
|
-
name: str
|
247
|
-
The name for this specific tracer object.
|
248
|
-
ell: array
|
249
|
-
Array of multipole values at which the beam is defined.
|
250
|
-
beam: array
|
251
|
-
Beam multipoles at each value of ell.
|
252
|
-
beam_extra: array
|
253
|
-
Other beam-related arrays
|
254
|
-
(e.g. uncertainties, principal components,
|
255
|
-
alternative measurements, whatever).
|
256
|
-
map_unit: str
|
257
|
-
Map units (e.g. 'uK_CMB'). 'none' by default.
|
258
|
-
"""
|
259
|
-
|
260
|
-
def __init__(self, name, spin, ell, beam,
|
261
|
-
beam_extra=None, map_unit='none', **kwargs):
|
262
|
-
super().__init__(name, **kwargs)
|
263
|
-
self.spin = spin
|
264
|
-
self.map_unit = map_unit
|
265
|
-
self.ell = np.array(ell)
|
266
|
-
self.beam = np.array(beam)
|
267
|
-
self.beam_extra = {} if beam_extra is None else beam_extra
|
268
|
-
|
269
|
-
@classmethod
|
270
|
-
def to_tables(cls, instance_list):
|
271
|
-
tables = []
|
272
|
-
for tracer in instance_list:
|
273
|
-
# Beams
|
274
|
-
names = ['ell', 'beam']
|
275
|
-
cols = [tracer.ell, tracer.beam]
|
276
|
-
for beam_id, col in tracer.beam_extra.items():
|
277
|
-
names.append(str(beam_id))
|
278
|
-
cols.append(col)
|
279
|
-
table = Table(data=cols, names=names)
|
280
|
-
table.meta['SACCTYPE'] = 'tracer'
|
281
|
-
table.meta['SACCCLSS'] = cls.tracer_type
|
282
|
-
table.meta['SACCNAME'] = tracer.name
|
283
|
-
table.meta['SACCQTTY'] = tracer.quantity
|
284
|
-
extname = f'tracer:{cls.tracer_type}:{tracer.name}:beam'
|
285
|
-
table.meta['EXTNAME'] = extname
|
286
|
-
table.meta['MAP_UNIT'] = tracer.map_unit
|
287
|
-
table.meta['SPIN'] = tracer.spin
|
288
|
-
for key, value in tracer.metadata.items():
|
289
|
-
table.meta['META_'+key] = value
|
290
|
-
remove_dict_null_values(table.meta)
|
291
|
-
tables.append(table)
|
292
|
-
return tables
|
293
|
-
|
294
|
-
@classmethod
|
295
|
-
def from_tables(cls, table_list):
|
296
|
-
tracers = {}
|
297
|
-
|
298
|
-
# Collect beam and bandpass tables describing the same tracer
|
299
|
-
tr_tables = {}
|
300
|
-
for table in table_list:
|
301
|
-
# Read name and table type
|
302
|
-
name = table.meta['SACCNAME']
|
303
|
-
tabtyp = table.meta['EXTNAME'].split(':')[-1]
|
304
|
-
if tabtyp not in ['beam']:
|
305
|
-
raise KeyError("Unknown table type " + table.meta['EXTNAME'])
|
306
|
-
|
307
|
-
# If not present yet, create new tracer entry
|
308
|
-
if name not in tr_tables:
|
309
|
-
tr_tables[name] = {}
|
310
|
-
# Add table
|
311
|
-
tr_tables[name][tabtyp] = table
|
312
|
-
|
313
|
-
# Now loop through different tracers and build them from their tables
|
314
|
-
for dt in tr_tables.values():
|
315
|
-
quantity = []
|
316
|
-
metadata = {}
|
317
|
-
map_unit = 'none'
|
318
|
-
ell = []
|
319
|
-
beam = []
|
320
|
-
beam_extra = {}
|
321
|
-
spin = 0
|
322
|
-
|
323
|
-
if 'beam' in dt:
|
324
|
-
table = dt['beam']
|
325
|
-
name = table.meta['SACCNAME']
|
326
|
-
quantity = table.meta.get('SACCQTTY', 'generic')
|
327
|
-
ell = table['ell']
|
328
|
-
beam = table['beam']
|
329
|
-
for col in table.columns.values():
|
330
|
-
if col.name not in ['ell', 'beam']:
|
331
|
-
beam_extra[col.name] = col.data
|
332
|
-
map_unit = table.meta['MAP_UNIT']
|
333
|
-
spin = table.meta['SPIN']
|
334
|
-
for key, value in table.meta.items():
|
335
|
-
if key.startswith("META_"):
|
336
|
-
metadata[key[5:]] = value
|
337
|
-
|
338
|
-
tracers[name] = cls(name, spin, ell, beam,
|
339
|
-
quantity=quantity, beam_extra=beam_extra,
|
340
|
-
map_unit=map_unit, metadata=metadata)
|
341
|
-
return tracers
|
342
|
-
|
343
|
-
|
344
|
-
class NuMapTracer(BaseTracer, tracer_type='NuMap'):
|
345
|
-
"""
|
346
|
-
A Tracer type for a sky map at a given frequency.
|
347
|
-
|
348
|
-
Takes at least four arguments, defining the bandpass and beam.
|
349
|
-
|
350
|
-
Parameters
|
351
|
-
----------
|
352
|
-
name: str
|
353
|
-
The name for this specific tracer, e.g. a frequency band
|
354
|
-
identifier.
|
355
|
-
spin: int
|
356
|
-
Spin for this observable. Either 0 (e.g. intensity)
|
357
|
-
or 2 (e.g. polarization).
|
358
|
-
nu: array
|
359
|
-
Array of frequencies.
|
360
|
-
bandpass: array
|
361
|
-
Bandpass transmission.
|
362
|
-
bandpass_extra: array
|
363
|
-
Other bandpass-related arrays
|
364
|
-
(e.g. uncertainties, principal components,
|
365
|
-
alternative measurements, whatever).
|
366
|
-
ell: array
|
367
|
-
Array of multipole values at which the beam is defined.
|
368
|
-
beam: array
|
369
|
-
Beam.
|
370
|
-
beam_extra: array
|
371
|
-
Other beam-related arrays
|
372
|
-
(e.g. uncertainties, principal components,
|
373
|
-
alternative measurements, whatever).
|
374
|
-
nu_unit: str
|
375
|
-
Frequency units ('GHz' by default).
|
376
|
-
map_unit: str
|
377
|
-
Map units (e.g. 'uK_CMB'). 'none' by default.
|
378
|
-
"""
|
379
|
-
|
380
|
-
def __init__(self, name, spin, nu, bandpass,
|
381
|
-
ell, beam, bandpass_extra=None,
|
382
|
-
beam_extra=None, nu_unit='GHz',
|
383
|
-
map_unit='none', **kwargs):
|
384
|
-
super().__init__(name, **kwargs)
|
385
|
-
self.spin = spin
|
386
|
-
self.nu = np.array(nu)
|
387
|
-
self.nu_unit = nu_unit
|
388
|
-
self.map_unit = map_unit
|
389
|
-
self.bandpass = np.array(bandpass)
|
390
|
-
self.bandpass_extra = {} if bandpass_extra is None else bandpass_extra
|
391
|
-
self.ell = np.array(ell)
|
392
|
-
self.beam = np.array(beam)
|
393
|
-
self.beam_extra = {} if beam_extra is None else beam_extra
|
394
|
-
|
395
|
-
@classmethod
|
396
|
-
def to_tables(cls, instance_list):
|
397
|
-
tables = []
|
398
|
-
for tracer in instance_list:
|
399
|
-
# Bandpasses
|
400
|
-
names = ['nu', 'bandpass']
|
401
|
-
cols = [tracer.nu, tracer.bandpass]
|
402
|
-
for bandpass_id, col in tracer.bandpass_extra.items():
|
403
|
-
names.append(str(bandpass_id))
|
404
|
-
cols.append(col)
|
405
|
-
table = Table(data=cols, names=names)
|
406
|
-
table.meta['SACCTYPE'] = 'tracer'
|
407
|
-
table.meta['SACCCLSS'] = cls.tracer_type
|
408
|
-
table.meta['SACCNAME'] = tracer.name
|
409
|
-
table.meta['SACCQTTY'] = tracer.quantity
|
410
|
-
extname = f'tracer:{cls.tracer_type}:{tracer.name}:bandpass'
|
411
|
-
table.meta['EXTNAME'] = extname
|
412
|
-
table.meta['NU_UNIT'] = tracer.nu_unit
|
413
|
-
table.meta['SPIN'] = tracer.spin
|
414
|
-
for key, value in tracer.metadata.items():
|
415
|
-
table.meta['META_'+key] = value
|
416
|
-
remove_dict_null_values(table.meta)
|
417
|
-
tables.append(table)
|
418
|
-
|
419
|
-
# Beams
|
420
|
-
names = ['ell', 'beam']
|
421
|
-
cols = [tracer.ell, tracer.beam]
|
422
|
-
for beam_id, col in tracer.beam_extra.items():
|
423
|
-
names.append(str(beam_id))
|
424
|
-
cols.append(col)
|
425
|
-
table = Table(data=cols, names=names)
|
426
|
-
table.meta['SACCTYPE'] = 'tracer'
|
427
|
-
table.meta['SACCCLSS'] = cls.tracer_type
|
428
|
-
table.meta['SACCNAME'] = tracer.name
|
429
|
-
table.meta['SACCQTTY'] = tracer.quantity
|
430
|
-
extname = f'tracer:{cls.tracer_type}:{tracer.name}:beam'
|
431
|
-
table.meta['EXTNAME'] = extname
|
432
|
-
table.meta['MAP_UNIT'] = tracer.map_unit
|
433
|
-
table.meta['SPIN'] = tracer.spin
|
434
|
-
for key, value in tracer.metadata.items():
|
435
|
-
table.meta['META_'+key] = value
|
436
|
-
remove_dict_null_values(table.meta)
|
437
|
-
tables.append(table)
|
438
|
-
return tables
|
439
|
-
|
440
|
-
@classmethod
|
441
|
-
def from_tables(cls, table_list):
|
442
|
-
tracers = {}
|
443
|
-
|
444
|
-
# Collect beam and bandpass tables describing the same tracer
|
445
|
-
tr_tables = {}
|
446
|
-
for table in table_list:
|
447
|
-
# Read name and table type
|
448
|
-
name = table.meta['SACCNAME']
|
449
|
-
tabtyp = table.meta['EXTNAME'].split(':')[-1]
|
450
|
-
if tabtyp not in ['bandpass', 'beam']:
|
451
|
-
raise KeyError("Unknown table type " + table.meta['EXTNAME'])
|
452
|
-
|
453
|
-
# If not present yet, create new tracer entry
|
454
|
-
if name not in tr_tables:
|
455
|
-
tr_tables[name] = {}
|
456
|
-
# Add table
|
457
|
-
tr_tables[name][tabtyp] = table
|
458
|
-
|
459
|
-
# Now loop through different tracers and build them from their tables
|
460
|
-
for dt in tr_tables.values():
|
461
|
-
quantity = []
|
462
|
-
metadata = {}
|
463
|
-
nu = []
|
464
|
-
bandpass = []
|
465
|
-
bandpass_extra = {}
|
466
|
-
nu_unit = 'GHz'
|
467
|
-
map_unit = 'none'
|
468
|
-
ell = []
|
469
|
-
beam = []
|
470
|
-
beam_extra = {}
|
471
|
-
spin = 0
|
472
|
-
|
473
|
-
if 'bandpass' in dt:
|
474
|
-
table = dt['bandpass']
|
475
|
-
name = table.meta['SACCNAME']
|
476
|
-
quantity = table.meta.get('SACCQTTY', 'generic')
|
477
|
-
nu = table['nu']
|
478
|
-
bandpass = table['bandpass']
|
479
|
-
for col in table.columns.values():
|
480
|
-
if col.name not in ['nu', 'bandpass']:
|
481
|
-
bandpass_extra[col.name] = col.data
|
482
|
-
nu_unit = table.meta['NU_UNIT']
|
483
|
-
spin = table.meta['SPIN']
|
484
|
-
for key, value in table.meta.items():
|
485
|
-
if key.startswith("META_"):
|
486
|
-
metadata[key[5:]] = value
|
487
|
-
|
488
|
-
if 'beam' in dt:
|
489
|
-
table = dt['beam']
|
490
|
-
name = table.meta['SACCNAME']
|
491
|
-
quantity = table.meta.get('SACCQTTY', 'generic')
|
492
|
-
ell = table['ell']
|
493
|
-
beam = table['beam']
|
494
|
-
for col in table.columns.values():
|
495
|
-
if col.name not in ['ell', 'beam']:
|
496
|
-
beam_extra[col.name] = col.data
|
497
|
-
map_unit = table.meta['MAP_UNIT']
|
498
|
-
spin = table.meta['SPIN']
|
499
|
-
for key, value in table.meta.items():
|
500
|
-
if key.startswith("META_"):
|
501
|
-
metadata[key[5:]] = value
|
502
|
-
|
503
|
-
tracers[name] = cls(name, spin,
|
504
|
-
nu, bandpass,
|
505
|
-
ell, beam,
|
506
|
-
quantity=quantity,
|
507
|
-
bandpass_extra=bandpass_extra,
|
508
|
-
beam_extra=beam_extra,
|
509
|
-
map_unit=map_unit,
|
510
|
-
nu_unit=nu_unit,
|
511
|
-
metadata=metadata)
|
512
|
-
return tracers
|
513
|
-
|
514
|
-
|
515
|
-
class NZTracer(BaseTracer, tracer_type='NZ'):
|
516
|
-
"""
|
517
|
-
A Tracer type for tomographic n(z) data.
|
518
|
-
|
519
|
-
Takes two arguments arrays of z and n(z)
|
520
|
-
|
521
|
-
Parameters
|
522
|
-
----------
|
523
|
-
name: str
|
524
|
-
The name for this specific tracer, e.g. a
|
525
|
-
tomographic bin identifier.
|
526
|
-
|
527
|
-
z: array
|
528
|
-
Redshift sample values
|
529
|
-
|
530
|
-
nz: array
|
531
|
-
Number density n(z) at redshift sample points.
|
532
|
-
|
533
|
-
extra_columns: dict[str: array] or dict[int: array]
|
534
|
-
Additional estimates of the same n(z), by name
|
535
|
-
"""
|
536
|
-
|
537
|
-
def __init__(self, name, z, nz,
|
538
|
-
extra_columns=None, **kwargs):
|
539
|
-
"""
|
540
|
-
Create a tracer corresponding to a distribution in redshift n(z),
|
541
|
-
for example of galaxies.
|
542
|
-
|
543
|
-
Parameters
|
544
|
-
----------
|
545
|
-
name: str
|
546
|
-
The name for this specific tracer, e.g. a
|
547
|
-
tomographic bin identifier.
|
548
|
-
|
549
|
-
z: array
|
550
|
-
Redshift sample values
|
551
|
-
|
552
|
-
nz: array
|
553
|
-
Number density n(z) at redshift sample points.
|
554
|
-
|
555
|
-
extra_columns: dict[str:array]
|
556
|
-
Optional, default=None. Additional realizations or
|
557
|
-
estimates of the same n(z), by name.
|
558
|
-
|
559
|
-
Returns
|
560
|
-
-------
|
561
|
-
instance: NZTracer object
|
562
|
-
An instance of this class
|
563
|
-
"""
|
564
|
-
super().__init__(name, **kwargs)
|
565
|
-
self.z = np.array(z)
|
566
|
-
self.nz = np.array(nz)
|
567
|
-
self.extra_columns = {} if extra_columns is None else extra_columns
|
568
|
-
|
569
|
-
@classmethod
|
570
|
-
def to_tables(cls, instance_list):
|
571
|
-
"""Convert a list of NZTracers to a list of astropy tables
|
572
|
-
|
573
|
-
This is used when saving data to a file.
|
574
|
-
One table is generated per tracer.
|
575
|
-
|
576
|
-
Parameters
|
577
|
-
----------
|
578
|
-
instance_list: list
|
579
|
-
List of tracer instances
|
580
|
-
|
581
|
-
Returns
|
582
|
-
-------
|
583
|
-
tables: list
|
584
|
-
List of astropy tables
|
585
|
-
"""
|
586
|
-
tables = []
|
587
|
-
for tracer in instance_list:
|
588
|
-
names = ['z', 'nz']
|
589
|
-
cols = [tracer.z, tracer.nz]
|
590
|
-
for nz_id, col in tracer.extra_columns.items():
|
591
|
-
names.append(str(nz_id))
|
592
|
-
cols.append(col)
|
593
|
-
table = Table(data=cols, names=names)
|
594
|
-
table.meta['SACCTYPE'] = 'tracer'
|
595
|
-
table.meta['SACCCLSS'] = cls.tracer_type
|
596
|
-
table.meta['SACCNAME'] = tracer.name
|
597
|
-
table.meta['SACCQTTY'] = tracer.quantity
|
598
|
-
table.meta['EXTNAME'] = f'tracer:{cls.tracer_type}:{tracer.name}'
|
599
|
-
for key, value in tracer.metadata.items():
|
600
|
-
table.meta['META_'+key] = value
|
601
|
-
remove_dict_null_values(table.meta)
|
602
|
-
tables.append(table)
|
603
|
-
return tables
|
604
|
-
|
605
|
-
@classmethod
|
606
|
-
def from_tables(cls, table_list):
|
607
|
-
"""Convert an astropy table into a dictionary of tracers
|
608
|
-
|
609
|
-
This is used when loading data from a file.
|
610
|
-
A single tracer object is read from the table.
|
611
|
-
|
612
|
-
Parameters
|
613
|
-
----------
|
614
|
-
table_list: list[astropy.table.Table]
|
615
|
-
Must contain the appropriate data, for example as saved
|
616
|
-
by to_table.
|
617
|
-
|
618
|
-
Returns
|
619
|
-
-------
|
620
|
-
tracers: dict
|
621
|
-
Dict mapping string names to tracer objects.
|
622
|
-
Only contains one key/value pair for the one tracer.
|
623
|
-
"""
|
624
|
-
tracers = {}
|
625
|
-
for table in table_list:
|
626
|
-
name = table.meta['SACCNAME']
|
627
|
-
quantity = table.meta.get('SACCQTTY', 'generic')
|
628
|
-
z = table['z']
|
629
|
-
nz = table['nz']
|
630
|
-
extra_columns = {}
|
631
|
-
for col in table.columns.values():
|
632
|
-
if col.name not in ['z', 'nz']:
|
633
|
-
extra_columns[col.name] = col.data
|
634
|
-
|
635
|
-
metadata = {}
|
636
|
-
for key, value in table.meta.items():
|
637
|
-
if key.startswith("META_"):
|
638
|
-
metadata[key[5:]] = value
|
639
|
-
tracers[name] = cls(name, z, nz,
|
640
|
-
quantity=quantity,
|
641
|
-
extra_columns=extra_columns,
|
642
|
-
metadata=metadata)
|
643
|
-
return tracers
|
644
|
-
|
645
|
-
|
646
|
-
class QPNZTracer(BaseTracer, tracer_type='QPNZ'):
|
647
|
-
"""
|
648
|
-
A Tracer type for tomographic n(z) data represented as a `qp.Ensemble`
|
649
|
-
|
650
|
-
Takes a `qp.Ensemble` and optionally a redshift array.
|
651
|
-
|
652
|
-
Requires the `qp` and `tables_io` packages to be installed.
|
653
|
-
|
654
|
-
Parameters
|
655
|
-
----------
|
656
|
-
name: str
|
657
|
-
The name for this specific tracer, e.g. a
|
658
|
-
tomographic bin identifier.
|
659
|
-
|
660
|
-
ensemble: qp.Ensemble
|
661
|
-
The qp.ensemble in questions
|
662
|
-
"""
|
663
|
-
|
664
|
-
def __init__(self, name, ens, z=None, **kwargs):
|
665
|
-
"""
|
666
|
-
Create a tracer corresponding to a distribution in redshift n(z),
|
667
|
-
for example of galaxies.
|
668
|
-
|
669
|
-
Parameters
|
670
|
-
----------
|
671
|
-
name: str
|
672
|
-
The name for this specific tracer, e.g. a
|
673
|
-
tomographic bin identifier.
|
674
|
-
|
675
|
-
ensemble: qp.Ensemble
|
676
|
-
The qp.ensemble in questions
|
677
|
-
|
678
|
-
z: array
|
679
|
-
Optional grid of redshift values at which to evaluate the ensemble.
|
680
|
-
If left as None then the ensemble metadata is checked for a grid.
|
681
|
-
If that is not present then no redshift grid is saved.
|
682
|
-
|
683
|
-
Returns
|
684
|
-
-------
|
685
|
-
instance: NZTracer object
|
686
|
-
An instance of this class
|
687
|
-
"""
|
688
|
-
super().__init__(name, **kwargs)
|
689
|
-
self.ensemble = ens
|
690
|
-
if z is None:
|
691
|
-
ens_meta = ens.metadata()
|
692
|
-
if 'bins' in list(ens_meta.keys()):
|
693
|
-
z = ens_meta['bins'][0]
|
694
|
-
self.z = z
|
695
|
-
if z is None:
|
696
|
-
self.nz = None
|
697
|
-
else:
|
698
|
-
self.nz = np.mean(ens.pdf(self.z),axis=0)
|
699
|
-
|
700
|
-
@classmethod
|
701
|
-
def to_tables(cls, instance_list):
|
702
|
-
"""Convert a list of NZTracers to a list of astropy tables
|
703
|
-
|
704
|
-
This is used when saving data to a file.
|
705
|
-
Two or three tables are generated per tracer.
|
706
|
-
|
707
|
-
Parameters
|
708
|
-
----------
|
709
|
-
instance_list: list
|
710
|
-
List of tracer instances
|
711
|
-
|
712
|
-
Returns
|
713
|
-
-------
|
714
|
-
tables: list
|
715
|
-
List of astropy tables
|
716
|
-
"""
|
717
|
-
from tables_io.convUtils import convertToApTables
|
718
|
-
|
719
|
-
tables = []
|
720
|
-
|
721
|
-
for tracer in instance_list:
|
722
|
-
if tracer.z is not None:
|
723
|
-
names = ['z', 'nz']
|
724
|
-
cols = [tracer.z, tracer.nz]
|
725
|
-
fid_table = Table(data=cols, names=names)
|
726
|
-
fid_table.meta['SACCTYPE'] = 'tracer'
|
727
|
-
fid_table.meta['SACCCLSS'] = cls.tracer_type
|
728
|
-
fid_table.meta['SACCNAME'] = tracer.name
|
729
|
-
fid_table.meta['SACCQTTY'] = tracer.quantity
|
730
|
-
fid_table.meta['EXTNAME'] = f'tracer:{cls.tracer_type}:{tracer.name}:fid'
|
731
|
-
|
732
|
-
table_dict = tracer.ensemble.build_tables()
|
733
|
-
ap_tables = convertToApTables(table_dict)
|
734
|
-
data_table = ap_tables['data']
|
735
|
-
meta_table = ap_tables['meta']
|
736
|
-
ancil_table = ap_tables.get('ancil', None)
|
737
|
-
meta_table.meta['SACCTYPE'] = 'tracer'
|
738
|
-
meta_table.meta['SACCCLSS'] = cls.tracer_type
|
739
|
-
meta_table.meta['SACCNAME'] = tracer.name
|
740
|
-
meta_table.meta['SACCQTTY'] = tracer.quantity
|
741
|
-
meta_table.meta['EXTNAME'] = f'tracer:{cls.tracer_type}:{tracer.name}:meta'
|
742
|
-
|
743
|
-
data_table.meta['SACCTYPE'] = 'tracer'
|
744
|
-
data_table.meta['SACCCLSS'] = cls.tracer_type
|
745
|
-
data_table.meta['SACCNAME'] = tracer.name
|
746
|
-
data_table.meta['SACCQTTY'] = tracer.quantity
|
747
|
-
data_table.meta['EXTNAME'] = f'tracer:{cls.tracer_type}:{tracer.name}:data'
|
748
|
-
|
749
|
-
for kk, vv in tracer.metadata.items():
|
750
|
-
meta_table.meta['META_'+kk] = vv
|
751
|
-
tables.append(data_table)
|
752
|
-
tables.append(meta_table)
|
753
|
-
if tracer.z is not None:
|
754
|
-
tables.append(fid_table)
|
755
|
-
if ancil_table:
|
756
|
-
ancil_table.meta['SACCTYPE'] = 'tracer'
|
757
|
-
ancil_table.meta['SACCCLSS'] = cls.tracer_type
|
758
|
-
ancil_table.meta['SACCNAME'] = tracer.name
|
759
|
-
ancil_table.meta['SACCQTTY'] = tracer.quantity
|
760
|
-
ancil_table.meta['EXTNAME'] = f'tracer:{cls.tracer_type}:{tracer.name}:ancil'
|
761
|
-
|
762
|
-
tables.append(ancil_table)
|
763
|
-
return tables
|
764
|
-
|
765
|
-
@classmethod
|
766
|
-
def from_tables(cls, table_list):
|
767
|
-
"""Convert an astropy table into a dictionary of tracers
|
768
|
-
|
769
|
-
This is used when loading data from a file.
|
770
|
-
A single tracer object is read from the table.
|
771
|
-
|
772
|
-
Parameters
|
773
|
-
----------
|
774
|
-
table_list: list[astropy.table.Table]
|
775
|
-
Must contain the appropriate data, for example as saved
|
776
|
-
by to_table.
|
777
|
-
|
778
|
-
Returns
|
779
|
-
-------
|
780
|
-
tracers: dict
|
781
|
-
Dict mapping string names to tracer objects.
|
782
|
-
Only contains one key/value pair for the one tracer.
|
783
|
-
"""
|
784
|
-
import qp
|
785
|
-
|
786
|
-
tracers = {}
|
787
|
-
sorted_dict = {}
|
788
|
-
for table_ in table_list:
|
789
|
-
tokens = table_.meta['EXTNAME'].split(':')
|
790
|
-
table_key = f'{tokens[0]}:{tokens[1]}:{tokens[2]}'
|
791
|
-
table_type = f'{tokens[3]}'
|
792
|
-
if table_key not in sorted_dict:
|
793
|
-
sorted_dict[table_key] = {table_type: table_}
|
794
|
-
else:
|
795
|
-
sorted_dict[table_key][table_type] = table_
|
796
|
-
|
797
|
-
for val in sorted_dict.values():
|
798
|
-
meta_table = val['meta']
|
799
|
-
if 'fid' in val:
|
800
|
-
z = val['fid']['z']
|
801
|
-
else:
|
802
|
-
z = None
|
803
|
-
ensemble = qp.from_tables(val)
|
804
|
-
name = meta_table.meta['SACCNAME']
|
805
|
-
quantity = meta_table.meta.get('SACCQTTY', 'generic')
|
806
|
-
ensemble = qp.from_tables(val)
|
807
|
-
metadata = {}
|
808
|
-
for key, value in meta_table.meta.items():
|
809
|
-
if key.startswith("META_"):
|
810
|
-
metadata[key[5:]] = value
|
811
|
-
tracers[name] = cls(name, ensemble, z=z,
|
812
|
-
quantity=quantity,
|
813
|
-
metadata=metadata)
|
814
|
-
return tracers
|
815
|
-
|
816
|
-
|
817
|
-
class BinZTracer(BaseTracer, tracer_type="bin_z"): # type: ignore
|
818
|
-
"""A tracer for a single redshift bin. The tracer shall
|
819
|
-
be used for binned data where we want a desired quantity
|
820
|
-
per interval of redshift, such that we only need the data
|
821
|
-
for a given interval instead of at individual redshifts."""
|
822
|
-
|
823
|
-
def __init__(self, name: str, lower: float, upper: float, **kwargs):
|
824
|
-
"""
|
825
|
-
Create a tracer corresponding to a single redshift bin.
|
826
|
-
|
827
|
-
:param name: The name of the tracer
|
828
|
-
:param lower: The lower bound of the redshift bin
|
829
|
-
:param upper: The upper bound of the redshift bin
|
830
|
-
"""
|
831
|
-
super().__init__(name, **kwargs)
|
832
|
-
self.lower = lower
|
833
|
-
self.upper = upper
|
834
|
-
|
835
|
-
def __eq__(self, other) -> bool:
|
836
|
-
"""Test for equality. If :python:`other` is not a
|
837
|
-
:python:`BinZTracer`, then it is not equal to :python:`self`.
|
838
|
-
Otherwise, they are equal if names, and the z-range of the bins,
|
839
|
-
are equal."""
|
840
|
-
if not isinstance(other, BinZTracer):
|
841
|
-
return False
|
842
|
-
return (
|
843
|
-
self.name == other.name
|
844
|
-
and self.lower == other.lower
|
845
|
-
and self.upper == other.upper
|
846
|
-
)
|
847
|
-
|
848
|
-
@classmethod
|
849
|
-
def to_tables(cls, instance_list):
|
850
|
-
"""Convert a list of BinZTracers to a single astropy table
|
851
|
-
|
852
|
-
This is used when saving data to a file.
|
853
|
-
One table is generated with the information for all the tracers.
|
854
|
-
|
855
|
-
:param instance_list: List of tracer instances
|
856
|
-
:return: List with a single astropy table
|
857
|
-
"""
|
858
|
-
|
859
|
-
names = ["name", "quantity", "lower", "upper"]
|
860
|
-
|
861
|
-
cols = [
|
862
|
-
[obj.name for obj in instance_list],
|
863
|
-
[obj.quantity for obj in instance_list],
|
864
|
-
[obj.lower for obj in instance_list],
|
865
|
-
[obj.upper for obj in instance_list],
|
866
|
-
]
|
867
|
-
|
868
|
-
table = Table(data=cols, names=names)
|
869
|
-
table.meta["SACCTYPE"] = "tracer"
|
870
|
-
table.meta["SACCCLSS"] = cls.tracer_type
|
871
|
-
table.meta["EXTNAME"] = f"tracer:{cls.tracer_type}"
|
872
|
-
return [table]
|
873
|
-
|
874
|
-
@classmethod
|
875
|
-
def from_tables(cls, table_list):
|
876
|
-
"""Convert an astropy table into a dictionary of tracers
|
877
|
-
|
878
|
-
This is used when loading data from a file.
|
879
|
-
One tracer object is created for each "row" in each table.
|
880
|
-
|
881
|
-
:param table_list: List of astropy tables
|
882
|
-
:return: Dictionary of tracers
|
883
|
-
"""
|
884
|
-
tracers = {}
|
885
|
-
|
886
|
-
for table in table_list:
|
887
|
-
for row in table:
|
888
|
-
name = row["name"]
|
889
|
-
quantity = row["quantity"]
|
890
|
-
lower = row["lower"]
|
891
|
-
upper = row["upper"]
|
892
|
-
tracers[name] = cls(name, quantity=quantity, lower=lower, upper=upper)
|
893
|
-
return tracers
|
894
|
-
|
895
|
-
class BinLogMTracer(BaseTracer, tracer_type="bin_logM"): # type: ignore
|
896
|
-
"""A tracer for a single log-mass bin. The tracer shall
|
897
|
-
be used for binned data where we want a desired quantity
|
898
|
-
per interval of log(mass), such that we only need the data
|
899
|
-
for a given interval instead of at individual masses."""
|
900
|
-
|
901
|
-
def __init__(self, name: str, lower: float, upper: float, **kwargs):
|
902
|
-
"""
|
903
|
-
Create a tracer corresponding to a single log-mass bin.
|
904
|
-
|
905
|
-
:param name: The name of the tracer
|
906
|
-
:param lower: The lower bound of the log-mass bin
|
907
|
-
:param upper: The upper bound of the log-mass bin
|
908
|
-
"""
|
909
|
-
super().__init__(name, **kwargs)
|
910
|
-
self.lower = lower
|
911
|
-
self.upper = upper
|
912
|
-
|
913
|
-
def __eq__(self, other) -> bool:
|
914
|
-
"""Test for equality. If :python:`other` is not a
|
915
|
-
:python:`BinLogMTracer`, then it is not equal to :python:`self`.
|
916
|
-
Otherwise, they are equal if names, and the z-range of the bins,
|
917
|
-
are equal."""
|
918
|
-
if not isinstance(other, BinLogMTracer):
|
919
|
-
return False
|
920
|
-
return (
|
921
|
-
self.name == other.name
|
922
|
-
and self.lower == other.lower
|
923
|
-
and self.upper == other.upper
|
924
|
-
)
|
925
|
-
|
926
|
-
@classmethod
|
927
|
-
def to_tables(cls, instance_list):
|
928
|
-
"""Convert a list of BinLogMTracers to a single astropy table
|
929
|
-
|
930
|
-
This is used when saving data to a file.
|
931
|
-
One table is generated with the information for all the tracers.
|
932
|
-
|
933
|
-
:param instance_list: List of tracer instances
|
934
|
-
:return: List with a single astropy table
|
935
|
-
"""
|
936
|
-
|
937
|
-
names = ["name", "quantity", "lower", "upper"]
|
938
|
-
|
939
|
-
cols = [
|
940
|
-
[obj.name for obj in instance_list],
|
941
|
-
[obj.quantity for obj in instance_list],
|
942
|
-
[obj.lower for obj in instance_list],
|
943
|
-
[obj.upper for obj in instance_list],
|
944
|
-
]
|
945
|
-
table = Table(data=cols, names=names)
|
946
|
-
table.meta["SACCTYPE"] = "tracer"
|
947
|
-
table.meta["SACCCLSS"] = cls.tracer_type
|
948
|
-
table.meta["EXTNAME"] = f"tracer:{cls.tracer_type}"
|
949
|
-
return [table]
|
950
|
-
|
951
|
-
@classmethod
|
952
|
-
def from_tables(cls, table_list):
|
953
|
-
"""Convert an astropy table into a dictionary of tracers
|
954
|
-
|
955
|
-
This is used when loading data from a file.
|
956
|
-
One tracer object is created for each "row" in each table.
|
957
|
-
|
958
|
-
:param table_list: List of astropy tables
|
959
|
-
:return: Dictionary of tracers
|
960
|
-
"""
|
961
|
-
tracers = {}
|
962
|
-
|
963
|
-
for table in table_list:
|
964
|
-
for row in table:
|
965
|
-
name = row["name"]
|
966
|
-
quantity = row["quantity"]
|
967
|
-
lower = row["lower"]
|
968
|
-
upper = row["upper"]
|
969
|
-
tracers[name] = cls(name, quantity=quantity, lower=lower, upper=upper)
|
970
|
-
return tracers
|
971
|
-
|
972
|
-
|
973
|
-
class BinRichnessTracer(BaseTracer, tracer_type="bin_richness"): # type: ignore
|
974
|
-
"""A tracer for a single richness bin. The tracer shall
|
975
|
-
be used for binned data where we want a desired quantity
|
976
|
-
per interval of log(richness), such that we only need the data
|
977
|
-
for a given interval instead of at individual richness."""
|
978
|
-
|
979
|
-
def __eq__(self, other) -> bool:
|
980
|
-
"""Test for equality. If :python:`other` is not a
|
981
|
-
:python:`BinRichnessTracer`, then it is not equal to :python:`self`.
|
982
|
-
Otherwise, they are equal if names and the richness-range of the
|
983
|
-
bins, are equal."""
|
984
|
-
if not isinstance(other, BinRichnessTracer):
|
985
|
-
return False
|
986
|
-
return (
|
987
|
-
self.name == other.name
|
988
|
-
and self.lower == other.lower
|
989
|
-
and self.upper == other.upper
|
990
|
-
)
|
991
|
-
|
992
|
-
def __init__(self, name: str, lower: float, upper: float, **kwargs):
|
993
|
-
"""
|
994
|
-
Create a tracer corresponding to a single richness bin.
|
995
|
-
|
996
|
-
:param name: The name of the tracer
|
997
|
-
:param lower: The lower bound of the richness bin in log10.
|
998
|
-
:param upper: The upper bound of the richness bin in log10.
|
999
|
-
"""
|
1000
|
-
super().__init__(name, **kwargs)
|
1001
|
-
self.lower = lower
|
1002
|
-
self.upper = upper
|
1003
|
-
|
1004
|
-
@classmethod
|
1005
|
-
def to_tables(cls, instance_list):
|
1006
|
-
"""Convert a list of BinZTracers to a list of astropy tables
|
1007
|
-
|
1008
|
-
This is used when saving data to a file.
|
1009
|
-
One table is generated with the information for all the tracers.
|
1010
|
-
|
1011
|
-
:param instance_list: List of tracer instances
|
1012
|
-
:return: List with a single astropy table
|
1013
|
-
"""
|
1014
|
-
names = ["name", "quantity", "lower", "upper"]
|
1015
|
-
|
1016
|
-
cols = [
|
1017
|
-
[obj.name for obj in instance_list],
|
1018
|
-
[obj.quantity for obj in instance_list],
|
1019
|
-
[obj.lower for obj in instance_list],
|
1020
|
-
[obj.upper for obj in instance_list],
|
1021
|
-
]
|
1022
|
-
|
1023
|
-
table = Table(data=cols, names=names)
|
1024
|
-
table.meta["SACCTYPE"] = "tracer"
|
1025
|
-
table.meta["SACCCLSS"] = cls.tracer_type
|
1026
|
-
table.meta["EXTNAME"] = f"tracer:{cls.tracer_type}"
|
1027
|
-
return [table]
|
1028
|
-
|
1029
|
-
@classmethod
|
1030
|
-
def from_tables(cls, table_list):
|
1031
|
-
"""Convert an astropy table into a dictionary of tracers
|
1032
|
-
|
1033
|
-
This is used when loading data from a file.
|
1034
|
-
One tracer object is created for each "row" in each table.
|
1035
|
-
|
1036
|
-
:param table_list: List of astropy tables
|
1037
|
-
:return: Dictionary of tracers
|
1038
|
-
"""
|
1039
|
-
tracers = {}
|
1040
|
-
|
1041
|
-
for table in table_list:
|
1042
|
-
for row in table:
|
1043
|
-
name = row["name"]
|
1044
|
-
quantity = row["quantity"]
|
1045
|
-
lower = row["lower"]
|
1046
|
-
upper = row["upper"]
|
1047
|
-
tracers[name] = cls(
|
1048
|
-
name,
|
1049
|
-
quantity=quantity,
|
1050
|
-
lower=lower,
|
1051
|
-
upper=upper,
|
1052
|
-
)
|
1053
|
-
return tracers
|
1054
|
-
|
1055
|
-
|
1056
|
-
class BinRadiusTracer(BaseTracer, tracer_type="bin_radius"): # type: ignore
|
1057
|
-
"""A tracer for a single radial bin, e.g. when dealing with cluster shear profiles.
|
1058
|
-
It gives the bin edges and the value of the bin "center". The latter would typically
|
1059
|
-
be returned by CLMM and correspond to the average radius of the galaxies in that
|
1060
|
-
radial bin. """
|
1061
|
-
|
1062
|
-
def __eq__(self, other) -> bool:
|
1063
|
-
"""Test for equality. If :python:`other` is not a
|
1064
|
-
:python:`BinRadiusTracer`, then it is not equal to :python:`self`.
|
1065
|
-
Otherwise, they are equal if names and the r-range and centers of the
|
1066
|
-
bins, are equal."""
|
1067
|
-
if not isinstance(other, BinRadiusTracer):
|
1068
|
-
return False
|
1069
|
-
return (
|
1070
|
-
self.name == other.name
|
1071
|
-
and self.lower == other.lower
|
1072
|
-
and self.center == other.center
|
1073
|
-
and self.upper == other.upper
|
1074
|
-
)
|
1075
|
-
|
1076
|
-
def __init__(self, name: str, lower: float, upper: float, center: float, **kwargs):
|
1077
|
-
"""
|
1078
|
-
Create a tracer corresponding to a single radial bin.
|
1079
|
-
|
1080
|
-
:param name: The name of the tracer
|
1081
|
-
:param lower: The lower bound of the radius bin
|
1082
|
-
:param upper: The upper bound of the radius bin
|
1083
|
-
:param center: The value to use if a single point-estimate is needed.
|
1084
|
-
|
1085
|
-
Note that :python:`center` need not be the midpoint between
|
1086
|
-
:python:`lower` and :python:`upper`'.
|
1087
|
-
"""
|
1088
|
-
super().__init__(name, **kwargs)
|
1089
|
-
self.lower = lower
|
1090
|
-
self.upper = upper
|
1091
|
-
self.center = center
|
1092
|
-
|
1093
|
-
@classmethod
|
1094
|
-
def to_tables(cls, instance_list):
|
1095
|
-
"""Convert a list of BinRadiusTracers to a single astropy table
|
1096
|
-
|
1097
|
-
This is used when saving data to a file.
|
1098
|
-
One table is generated with the information for all the tracers.
|
1099
|
-
|
1100
|
-
:param instance_list: List of tracer instances
|
1101
|
-
:return: List with a single astropy table
|
1102
|
-
"""
|
1103
|
-
|
1104
|
-
names = ["name", "quantity", "lower", "upper", "center"]
|
1105
|
-
|
1106
|
-
cols = [
|
1107
|
-
[obj.name for obj in instance_list],
|
1108
|
-
[obj.quantity for obj in instance_list],
|
1109
|
-
[obj.lower for obj in instance_list],
|
1110
|
-
[obj.upper for obj in instance_list],
|
1111
|
-
[obj.center for obj in instance_list],
|
1112
|
-
]
|
1113
|
-
|
1114
|
-
table = Table(data=cols, names=names)
|
1115
|
-
table.meta["SACCTYPE"] = "tracer"
|
1116
|
-
table.meta["SACCCLSS"] = cls.tracer_type
|
1117
|
-
table.meta["EXTNAME"] = f"tracer:{cls.tracer_type}"
|
1118
|
-
return [table]
|
1119
|
-
|
1120
|
-
@classmethod
|
1121
|
-
def from_tables(cls, table_list):
|
1122
|
-
"""Convert an astropy table into a dictionary of tracers
|
1123
|
-
|
1124
|
-
This is used when loading data from a file.
|
1125
|
-
One tracer object is created for each "row" in each table.
|
1126
|
-
|
1127
|
-
:param table_list: List of astropy tables
|
1128
|
-
:return: Dictionary of tracers
|
1129
|
-
"""
|
1130
|
-
tracers = {}
|
1131
|
-
|
1132
|
-
for table in table_list:
|
1133
|
-
for row in table:
|
1134
|
-
name = row["name"]
|
1135
|
-
quantity = row["quantity"]
|
1136
|
-
lower = row["lower"]
|
1137
|
-
upper = row["upper"]
|
1138
|
-
center = row["center"]
|
1139
|
-
tracers[name] = cls(
|
1140
|
-
name,
|
1141
|
-
quantity=quantity,
|
1142
|
-
lower=lower,
|
1143
|
-
upper=upper,
|
1144
|
-
center=center,
|
1145
|
-
)
|
1146
|
-
return tracers
|
1147
|
-
|
1148
|
-
class SurveyTracer(BaseTracer, tracer_type="survey"): # type: ignore
|
1149
|
-
"""A tracer for the survey definition. It shall
|
1150
|
-
be used to filter data related to a given survey
|
1151
|
-
and to provide the survey sky-area of analysis."""
|
1152
|
-
|
1153
|
-
def __eq__(self, other) -> bool:
|
1154
|
-
"""Test for equality. If :python:`other` is not a
|
1155
|
-
:python:`SurveyTracer`, then it is not equal to :python:`self`.
|
1156
|
-
Otherwise, they are equal if names and the sky-areas are equal."""
|
1157
|
-
if not isinstance(other, SurveyTracer):
|
1158
|
-
return False
|
1159
|
-
return self.name == other.name and self.sky_area == other.sky_area
|
1160
|
-
|
1161
|
-
def __init__(self, name: str, sky_area: float, **kwargs):
|
1162
|
-
"""
|
1163
|
-
Create a tracer corresponding to the survey definition.
|
1164
|
-
|
1165
|
-
:param name: The name of the tracer
|
1166
|
-
:param sky_area: The survey's sky area in square degrees
|
1167
|
-
"""
|
1168
|
-
super().__init__(name, **kwargs)
|
1169
|
-
self.sky_area = sky_area
|
1170
|
-
|
1171
|
-
@classmethod
|
1172
|
-
def to_tables(cls, instance_list):
|
1173
|
-
"""Convert a list of SurveyTracer to a list of astropy tables
|
1174
|
-
|
1175
|
-
This is used when saving data to a file.
|
1176
|
-
One table is generated with the information for all the tracers.
|
1177
|
-
|
1178
|
-
:param instance_list: List of tracer instances
|
1179
|
-
:return: List of astropy tables with one table
|
1180
|
-
"""
|
1181
|
-
names = ["name", "quantity", "sky_area"]
|
1182
|
-
|
1183
|
-
cols = [
|
1184
|
-
[obj.name for obj in instance_list],
|
1185
|
-
[obj.quantity for obj in instance_list],
|
1186
|
-
[obj.sky_area for obj in instance_list],
|
1187
|
-
]
|
1188
|
-
|
1189
|
-
table = Table(data=cols, names=names)
|
1190
|
-
table.meta["SACCTYPE"] = "tracer"
|
1191
|
-
table.meta["SACCCLSS"] = cls.tracer_type
|
1192
|
-
table.meta["EXTNAME"] = f"tracer:{cls.tracer_type}"
|
1193
|
-
return [table]
|
1194
|
-
|
1195
|
-
@classmethod
|
1196
|
-
def from_tables(cls, table_list):
|
1197
|
-
"""Convert an astropy table into a dictionary of tracers
|
1198
|
-
|
1199
|
-
This is used when loading data from a file.
|
1200
|
-
One tracer object is created for each "row" in each table.
|
1201
|
-
|
1202
|
-
:param table_list: List of astropy tables
|
1203
|
-
:return: Dictionary of tracers
|
1204
|
-
"""
|
1205
|
-
tracers = {}
|
1206
|
-
|
1207
|
-
for table in table_list:
|
1208
|
-
for row in table:
|
1209
|
-
name = row["name"]
|
1210
|
-
quantity = row["quantity"]
|
1211
|
-
sky_area = row["sky_area"]
|
1212
|
-
tracers[name] = cls(
|
1213
|
-
name,
|
1214
|
-
quantity=quantity,
|
1215
|
-
sky_area=sky_area,
|
1216
|
-
)
|
1217
|
-
return tracers
|