sacc 1.0.2__py3-none-any.whl → 2.0.1__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.
@@ -0,0 +1 @@
1
+ from .nz import NZLinearUncertainty, NZShiftUncertainty, NZShiftStretchUncertainty
@@ -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
+ )
@@ -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