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
@@ -0,0 +1,34 @@
|
|
1
|
+
from ..io import BaseIO
|
2
|
+
|
3
|
+
|
4
|
+
class BaseTracerUncertainty(BaseIO):
|
5
|
+
_sub_classes = {}
|
6
|
+
|
7
|
+
def __init__(
|
8
|
+
self,
|
9
|
+
name,
|
10
|
+
tracer_names,
|
11
|
+
):
|
12
|
+
"""
|
13
|
+
Base class for tracer uncertainties. All uncertainty subclasses
|
14
|
+
must define a list of tracer names to which the uncertainty applies.
|
15
|
+
|
16
|
+
This could be a single tracer or multiple tracers.
|
17
|
+
|
18
|
+
Parameters
|
19
|
+
----------
|
20
|
+
name : str
|
21
|
+
Name of the uncertainty.
|
22
|
+
tracer_names : list of str
|
23
|
+
List of tracer name(s) to which the uncertainty applies.
|
24
|
+
"""
|
25
|
+
super().__init__()
|
26
|
+
self.name = name
|
27
|
+
self.tracer_names = tracer_names
|
28
|
+
|
29
|
+
|
30
|
+
def names_to_table_metadata(self, table):
|
31
|
+
table.meta["N_TRACERS"] = len(self.tracer_names)
|
32
|
+
for i, tracer_name in enumerate(self.tracer_names):
|
33
|
+
table.meta[f"TRACER_NAME_{i}"] = tracer_name
|
34
|
+
return table
|
@@ -0,0 +1,287 @@
|
|
1
|
+
from .base import BaseTracerUncertainty
|
2
|
+
from ..io import ONE_OBJECT_PER_TABLE
|
3
|
+
from astropy.table import Table
|
4
|
+
import numpy as np
|
5
|
+
|
6
|
+
|
7
|
+
class BaseNZGaussianTracerUncertainty(BaseTracerUncertainty):
|
8
|
+
# _sub_classes = {}
|
9
|
+
|
10
|
+
def __init__(
|
11
|
+
self,
|
12
|
+
name,
|
13
|
+
tracer_names,
|
14
|
+
mean,
|
15
|
+
linear_transformation,
|
16
|
+
linear_transformation_type):
|
17
|
+
"""
|
18
|
+
Base class for tracer uncertainties that apply to N(z) tracers and act as transforms.
|
19
|
+
|
20
|
+
You don't normally need to instantiate this class directly;
|
21
|
+
instead use one of the subclasses.
|
22
|
+
|
23
|
+
Parameters
|
24
|
+
----------
|
25
|
+
name : str
|
26
|
+
Name of the uncertainty.
|
27
|
+
|
28
|
+
tracer_names : list of str
|
29
|
+
List of tracer name(s) to which the uncertainty applies.
|
30
|
+
|
31
|
+
mean : array-like
|
32
|
+
Mean values for the uncertainty parameters.
|
33
|
+
|
34
|
+
linear_transformation : array-like
|
35
|
+
Linear transformation matrix used to generate samples.
|
36
|
+
Includes the Cholesky factorization of the covariance matrix
|
37
|
+
Might include linear transformation of the parameters.
|
38
|
+
|
39
|
+
transformation_type : str
|
40
|
+
Type of transformation used for the uncertainty, currently
|
41
|
+
either "cholesky" or "linear_model".
|
42
|
+
Specifies if the transformation is a Cholesky factorization
|
43
|
+
or some other type of linear transformation.
|
44
|
+
|
45
|
+
If a 1D array is provided it is interpreted as the diagonal
|
46
|
+
of a matrix.
|
47
|
+
"""
|
48
|
+
super().__init__(name, tracer_names)
|
49
|
+
self.mean = np.array(mean)
|
50
|
+
linear_transformation = np.array(linear_transformation)
|
51
|
+
|
52
|
+
# If a 1D array is provided it is interpreted as the diagonal
|
53
|
+
if linear_transformation.ndim == 1:
|
54
|
+
linear_transformation = np.diag(linear_transformation)
|
55
|
+
elif linear_transformation.ndim != 2:
|
56
|
+
raise ValueError("linear_transformation must be 1D or 2D array")
|
57
|
+
|
58
|
+
self.linear_transformation = linear_transformation
|
59
|
+
self.linear_transformation_type = linear_transformation_type
|
60
|
+
|
61
|
+
# Check that the mean and chol have compatible shapes.
|
62
|
+
# Subclasses can do additional shape checks.
|
63
|
+
if len(self.mean) != self.linear_transformation.shape[0]:
|
64
|
+
raise ValueError(
|
65
|
+
f"Mean length {len(self.mean)} does not match "
|
66
|
+
f"linear transformation shape {self.linear_transformation.shape}"
|
67
|
+
)
|
68
|
+
|
69
|
+
# if the transformation is a Cholesky factorization
|
70
|
+
if linear_transformation_type == "cholesky":
|
71
|
+
if self.linear_transformation.shape[0] != self.linear_transformation.shape[1]:
|
72
|
+
raise ValueError("Cholesky matrix must be square")
|
73
|
+
|
74
|
+
elif linear_transformation_type == "linear_model":
|
75
|
+
# No additional checks needed for linear models
|
76
|
+
pass
|
77
|
+
else:
|
78
|
+
raise ValueError(f"Unknown transformation type: {linear_transformation_type}")
|
79
|
+
|
80
|
+
# Params per tracer
|
81
|
+
self.nparams = self.linear_transformation.shape[1] // len(tracer_names)
|
82
|
+
|
83
|
+
|
84
|
+
@classmethod
|
85
|
+
def from_table(cls, table):
|
86
|
+
"""
|
87
|
+
Create an instance of one of the NZGaussianTracerUncertainty subclasses
|
88
|
+
from an astropy table.
|
89
|
+
|
90
|
+
This method is inherited by all subclasses, so the cls argument will be the
|
91
|
+
subclass that calls this method.
|
92
|
+
|
93
|
+
Parameters
|
94
|
+
----------
|
95
|
+
table: astropy.table.Table
|
96
|
+
An astropy table containing the uncertainty data.
|
97
|
+
|
98
|
+
Returns
|
99
|
+
-------
|
100
|
+
instance: NZGaussianTracerUncertainty
|
101
|
+
An instance of a NZGaussianTracerUncertainty subclass.
|
102
|
+
"""
|
103
|
+
# All the subclasses have the same table structure
|
104
|
+
mean = table["mean"]
|
105
|
+
transformation_type = table.meta["LINEAR_TRANSFORMATION_TYPE"]
|
106
|
+
cholesky = table[transformation_type]
|
107
|
+
tracer_names = [table.meta[f"TRACER_NAME_{i}"] for i in range(table.meta["N_TRACERS"])]
|
108
|
+
name = table.meta["SACCNAME"]
|
109
|
+
return cls(name, tracer_names, mean, cholesky)
|
110
|
+
|
111
|
+
def to_table(self):
|
112
|
+
"""
|
113
|
+
Write an NZGaussianTracerUncertainty object to an astropy table.
|
114
|
+
|
115
|
+
Parameters
|
116
|
+
----------
|
117
|
+
None
|
118
|
+
|
119
|
+
Returns
|
120
|
+
-------
|
121
|
+
table: astropy.table.Table
|
122
|
+
An astropy table containing the uncertainty data.
|
123
|
+
"""
|
124
|
+
|
125
|
+
data = {
|
126
|
+
"mean": self.mean,
|
127
|
+
self.linear_transformation_type: self.linear_transformation,
|
128
|
+
}
|
129
|
+
table = Table(data=data)
|
130
|
+
|
131
|
+
# Add metadata - the superclass stores the list of tracer names
|
132
|
+
# to which this applies and here we add the rest of the metadata
|
133
|
+
self.names_to_table_metadata(table)
|
134
|
+
table.meta["LINEAR_TRANSFORMATION_TYPE"] = self.linear_transformation_type
|
135
|
+
for i, _ in enumerate(self.tracer_names):
|
136
|
+
table.meta[f"TRACER_NAME_{i}_NPARAMS"] = self.nparams
|
137
|
+
return table
|
138
|
+
|
139
|
+
|
140
|
+
|
141
|
+
class NZLinearUncertainty(
|
142
|
+
BaseNZGaussianTracerUncertainty,
|
143
|
+
type_name="nz_linear_uncertainty",
|
144
|
+
):
|
145
|
+
"""
|
146
|
+
Class to handle uncertainty in number density tracers represented
|
147
|
+
by a linear transformation model.
|
148
|
+
|
149
|
+
In this case to draw a sample of an n(z) you would generate a vector
|
150
|
+
of standard normal variables and apply:
|
151
|
+
|
152
|
+
n_i -> n_i + mean + matrix @ normal_vector
|
153
|
+
"""
|
154
|
+
|
155
|
+
storage_type = ONE_OBJECT_PER_TABLE
|
156
|
+
|
157
|
+
def __init__(
|
158
|
+
self,
|
159
|
+
name,
|
160
|
+
tracer_names,
|
161
|
+
mean,
|
162
|
+
matrix,
|
163
|
+
):
|
164
|
+
"""
|
165
|
+
Initialize the NZLinearUncertainty object.
|
166
|
+
|
167
|
+
Parameters
|
168
|
+
----------
|
169
|
+
tracer_names : list of str
|
170
|
+
List of tracer names to which the uncertainty applies.
|
171
|
+
|
172
|
+
mean: array-like
|
173
|
+
Intercept of the linear uncertainty model.
|
174
|
+
Can be interpreted as the mean of the parameters of the model.
|
175
|
+
|
176
|
+
matrix: array-like
|
177
|
+
Linear transformation matrix of the linear uncertainty model.
|
178
|
+
Includes the Cholesky factorization of the covariance matrix
|
179
|
+
as well as the linear transformation of the parameters.
|
180
|
+
"""
|
181
|
+
|
182
|
+
super().__init__(
|
183
|
+
name,
|
184
|
+
tracer_names,
|
185
|
+
mean,
|
186
|
+
matrix,
|
187
|
+
linear_transformation_type="linear_model"
|
188
|
+
)
|
189
|
+
|
190
|
+
|
191
|
+
class NZShiftUncertainty(
|
192
|
+
BaseNZGaussianTracerUncertainty,
|
193
|
+
type_name="nz_shift_uncertainty",
|
194
|
+
):
|
195
|
+
"""
|
196
|
+
Class to handle uncertainty in number density tracers represented
|
197
|
+
by a prior on a translation shift of the redshift distribution.
|
198
|
+
|
199
|
+
In this case to draw a sample of an n(z) you would generate a vector
|
200
|
+
of standard normal variables and compute
|
201
|
+
n_i(z) -> n_i(z - delta_z)
|
202
|
+
where
|
203
|
+
delta_z = mean + linear_transformation @ normal_vector
|
204
|
+
"""
|
205
|
+
storage_type = ONE_OBJECT_PER_TABLE
|
206
|
+
|
207
|
+
def __init__(
|
208
|
+
self,
|
209
|
+
name,
|
210
|
+
tracer_names,
|
211
|
+
mean,
|
212
|
+
cholesky_or_sigma):
|
213
|
+
"""
|
214
|
+
Initialize the NZShiftUncertainty object.
|
215
|
+
Parameters
|
216
|
+
----------
|
217
|
+
name: str
|
218
|
+
Name of the uncertainty object.
|
219
|
+
|
220
|
+
tracer_names : list of str
|
221
|
+
List of tracer names to which the uncertainty applies.
|
222
|
+
|
223
|
+
mean: array-like
|
224
|
+
Mean shift values for the tracers.
|
225
|
+
|
226
|
+
cholesky_or_sigma: array-like
|
227
|
+
cholesky factor of the covariance of the shift values for the tracers.
|
228
|
+
You can also supply a 1D array giving the standard deviations
|
229
|
+
of the shifts for each tracer.
|
230
|
+
"""
|
231
|
+
super().__init__(
|
232
|
+
name,
|
233
|
+
tracer_names,
|
234
|
+
mean,
|
235
|
+
cholesky_or_sigma,
|
236
|
+
linear_transformation_type="cholesky"
|
237
|
+
)
|
238
|
+
|
239
|
+
|
240
|
+
class NZShiftStretchUncertainty(
|
241
|
+
BaseNZGaussianTracerUncertainty,
|
242
|
+
type_name="nz_shift_stretch_uncertainty",
|
243
|
+
):
|
244
|
+
"""
|
245
|
+
Class to handle uncertainty in number density tracers represented
|
246
|
+
by a prior on a translation shift of the redshift distribution,
|
247
|
+
and on a stretch factor that modifies the width of the distribution.
|
248
|
+
|
249
|
+
In this case to draw a sample of an n(z) you would generate a vector
|
250
|
+
of standard normal variables and compute
|
251
|
+
n_i(z) -> n_i((z - mean_z) * w + mean_z - delta_z)
|
252
|
+
where
|
253
|
+
[delta_z_0, delta_z_1, ... delta_z_n, w_0, w_1, .. w_n] = mean + cholesky_or_sigma @ normal_vector
|
254
|
+
"""
|
255
|
+
|
256
|
+
storage_type = ONE_OBJECT_PER_TABLE
|
257
|
+
|
258
|
+
def __init__(
|
259
|
+
self,
|
260
|
+
name,
|
261
|
+
tracer_names,
|
262
|
+
mean,
|
263
|
+
cholesky_or_sigma):
|
264
|
+
"""
|
265
|
+
Initialize the NZShiftStretchUncertainty object.
|
266
|
+
Parameters
|
267
|
+
----------
|
268
|
+
name : str
|
269
|
+
Name of the uncertainty object.
|
270
|
+
tracer_names : list of str
|
271
|
+
List of tracer names to which the uncertainty applies.
|
272
|
+
mean : array-like
|
273
|
+
Mean ShiftStretch values for the tracers.
|
274
|
+
This is structured as (shift_1, stretch_1, shift_2, stretch_2, ...).
|
275
|
+
cholesky_or_sigma : array-like
|
276
|
+
Cholesky factor of the covariance of the ShiftStretch
|
277
|
+
values for the tracers. Follows the ordering of the mean.
|
278
|
+
Can also be a 1D array giving the standard deviations.
|
279
|
+
"""
|
280
|
+
|
281
|
+
super().__init__(
|
282
|
+
name,
|
283
|
+
tracer_names,
|
284
|
+
mean,
|
285
|
+
cholesky_or_sigma,
|
286
|
+
linear_transformation_type="cholesky"
|
287
|
+
)
|
sacc/tracers/__init__.py
ADDED
@@ -0,0 +1,6 @@
|
|
1
|
+
from .base import BaseTracer, standard_quantities
|
2
|
+
from .nz import NZTracer, QPNZTracer
|
3
|
+
from .clusters import BinZTracer, BinLogMTracer, BinRichnessTracer, BinRadiusTracer
|
4
|
+
from .maps import MapTracer, NuMapTracer
|
5
|
+
from .misc import MiscTracer
|
6
|
+
from .survey import SurveyTracer
|
sacc/tracers/base.py
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
import numpy as np
|
2
|
+
try:
|
3
|
+
from qp.core.ensemble import Ensemble
|
4
|
+
except:
|
5
|
+
Ensemble = None
|
6
|
+
from ..utils import Namespace
|
7
|
+
from ..io import BaseIO, ONE_OBJECT_PER_TABLE, MULTIPLE_OBJECTS_PER_TABLE, ONE_OBJECT_MULTIPLE_TABLES
|
8
|
+
|
9
|
+
|
10
|
+
standard_quantities = Namespace('galaxy_shear',
|
11
|
+
'galaxy_density',
|
12
|
+
'galaxy_convergence',
|
13
|
+
'cluster_density',
|
14
|
+
'cmb_temperature',
|
15
|
+
'cmb_polarization',
|
16
|
+
'cmb_convergence',
|
17
|
+
'cmb_tSZ',
|
18
|
+
'cmb_kSZ',
|
19
|
+
'cluster_mass_count_wl',
|
20
|
+
'cluster_mass_count_xray',
|
21
|
+
'cluster_mass_count_tSZ',
|
22
|
+
'generic')
|
23
|
+
|
24
|
+
|
25
|
+
class BaseTracer(BaseIO):
|
26
|
+
"""
|
27
|
+
A class representing some kind of tracer of astronomical objects.
|
28
|
+
|
29
|
+
Generically, SACC data points correspond to some combination of tracers
|
30
|
+
for example, tomographic two-point data has two tracers for each data
|
31
|
+
point, indicating the n(z) for the corresponding tomographic bin.
|
32
|
+
|
33
|
+
Concrete subclasses must implement to_tables and from_tables methods
|
34
|
+
|
35
|
+
All Tracer objects have at least a name attribute. Different
|
36
|
+
subclassses have other requirements. For example, n(z) tracers
|
37
|
+
require z and n(z) arrays.
|
38
|
+
|
39
|
+
In general you don't need to create tracer objects yourself -
|
40
|
+
the Sacc.add_tracer method will construct them for you.
|
41
|
+
"""
|
42
|
+
_sub_classes = {}
|
43
|
+
|
44
|
+
@property
|
45
|
+
def tracer_type(self):
|
46
|
+
"""Legacy value - this name has been replaced by type_name."""
|
47
|
+
return self.type_name
|
48
|
+
|
49
|
+
def __init__(self, name, **kwargs):
|
50
|
+
# We encourage people to use existing quantity names, and issue a
|
51
|
+
# warning if they do not to prod them in the right direction.
|
52
|
+
quantity = kwargs.pop('quantity', 'generic')
|
53
|
+
self.name = name
|
54
|
+
self.quantity = quantity
|
55
|
+
self.metadata = kwargs.pop('metadata', {})
|
56
|
+
|
57
|
+
def __eq__(self, other):
|
58
|
+
""""
|
59
|
+
Compare two Tracers for equality.
|
60
|
+
|
61
|
+
Tracers can only be equal if they have the same type.
|
62
|
+
Tracers of the same type are equal if they have all the same
|
63
|
+
attribute values.
|
64
|
+
|
65
|
+
There is no need to override this method in subclasses.
|
66
|
+
|
67
|
+
Parameters
|
68
|
+
----------
|
69
|
+
other: Tracer
|
70
|
+
The other Tracer to compare against.
|
71
|
+
|
72
|
+
Returns
|
73
|
+
-------
|
74
|
+
value: bool
|
75
|
+
True if the two Tracers are equal, else False
|
76
|
+
"""
|
77
|
+
if not isinstance(other, self.__class__):
|
78
|
+
return NotImplemented # not False, to help ensure symmetry
|
79
|
+
vars1, vars2 = vars(self), vars(other)
|
80
|
+
|
81
|
+
if len(vars1) != len(vars2):
|
82
|
+
return False
|
83
|
+
|
84
|
+
varnames1 = set(vars1.keys())
|
85
|
+
varnames2 = set(vars2.keys())
|
86
|
+
if varnames1 != varnames2:
|
87
|
+
return False
|
88
|
+
|
89
|
+
for name in varnames1:
|
90
|
+
v1 = vars1[name]
|
91
|
+
v2 = vars2[name]
|
92
|
+
# TODO: Remove this work-around one we have a way to test Ensembles for equality.
|
93
|
+
# If we do not have qp installed, then we do not attempt to compare Ensembles.
|
94
|
+
if Ensemble is not None and isinstance(v1, Ensemble):
|
95
|
+
continue
|
96
|
+
try:
|
97
|
+
if v1 != v2:
|
98
|
+
return False
|
99
|
+
except ValueError: # raised by numpy arrays
|
100
|
+
if not np.allclose(v1, v2):
|
101
|
+
return False
|
102
|
+
return True
|
103
|
+
|
104
|
+
|
105
|
+
@classmethod
|
106
|
+
def make(cls, tracer_type, name, *args, **kwargs):
|
107
|
+
"""
|
108
|
+
Select a Tracer subclass based on tracer_type
|
109
|
+
and instantiate in instance of it with the remaining
|
110
|
+
arguments.
|
111
|
+
|
112
|
+
Parameters
|
113
|
+
----------
|
114
|
+
tracer_type: str
|
115
|
+
Must correspond to the type_name of a subclass
|
116
|
+
|
117
|
+
name: str
|
118
|
+
The name for this specific tracer.
|
119
|
+
|
120
|
+
Returns
|
121
|
+
-------
|
122
|
+
instance: Tracer object
|
123
|
+
An instance of a Tracer subclass
|
124
|
+
"""
|
125
|
+
subclass = cls._sub_classes[tracer_type.lower()]
|
126
|
+
obj = subclass(name, *args, **kwargs)
|
127
|
+
return obj
|