lisaanalysistools 1.1.6__cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.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.
Potentially problematic release.
This version of lisaanalysistools might be problematic. Click here for more details.
- lisaanalysistools/git_version.py +7 -0
- lisaanalysistools-1.1.6.dist-info/METADATA +295 -0
- lisaanalysistools-1.1.6.dist-info/RECORD +42 -0
- lisaanalysistools-1.1.6.dist-info/WHEEL +6 -0
- lisaanalysistools-1.1.6.dist-info/licenses/LICENSE +201 -0
- lisatools/__init__.py +58 -0
- lisatools/_version.py +34 -0
- lisatools/analysiscontainer.py +474 -0
- lisatools/cutils/__init__.py +126 -0
- lisatools/datacontainer.py +312 -0
- lisatools/detector.py +704 -0
- lisatools/diagnostic.py +990 -0
- lisatools/git_version.py.in +7 -0
- lisatools/orbit_files/equalarmlength-orbits-best-fit-to-esa.h5 +0 -0
- lisatools/orbit_files/equalarmlength-orbits.h5 +0 -0
- lisatools/orbit_files/esa-trailing-orbits.h5 +0 -0
- lisatools/sampling/__init__.py +0 -0
- lisatools/sampling/likelihood.py +882 -0
- lisatools/sampling/moves/__init__.py +0 -0
- lisatools/sampling/moves/skymodehop.py +110 -0
- lisatools/sampling/prior.py +646 -0
- lisatools/sampling/stopping.py +320 -0
- lisatools/sampling/utility.py +411 -0
- lisatools/sensitivity.py +972 -0
- lisatools/sources/__init__.py +6 -0
- lisatools/sources/bbh/__init__.py +1 -0
- lisatools/sources/bbh/waveform.py +106 -0
- lisatools/sources/defaultresponse.py +36 -0
- lisatools/sources/emri/__init__.py +1 -0
- lisatools/sources/emri/waveform.py +79 -0
- lisatools/sources/gb/__init__.py +1 -0
- lisatools/sources/gb/waveform.py +69 -0
- lisatools/sources/utils.py +459 -0
- lisatools/sources/waveformbase.py +41 -0
- lisatools/stochastic.py +327 -0
- lisatools/utils/__init__.py +0 -0
- lisatools/utils/constants.py +54 -0
- lisatools/utils/exceptions.py +95 -0
- lisatools/utils/parallelbase.py +11 -0
- lisatools/utils/utility.py +245 -0
- lisatools_backend_cpu/git_version.py +7 -0
- lisatools_backend_cpu/pycppdetector.cpython-312-x86_64-linux-gnu.so +0 -0
|
@@ -0,0 +1,459 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
from typing import Any, Tuple, List, Optional
|
|
5
|
+
|
|
6
|
+
from ..diagnostic import snr as snr_func
|
|
7
|
+
from lisatools.diagnostic import (
|
|
8
|
+
covariance,
|
|
9
|
+
plot_covariance_corner,
|
|
10
|
+
plot_covariance_contour,
|
|
11
|
+
)
|
|
12
|
+
from ..sensitivity import A1TDISens, Sensitivity
|
|
13
|
+
from .waveformbase import SNRWaveform, AETTDIWaveform
|
|
14
|
+
from ..detector import LISAModel
|
|
15
|
+
from ..utils.constants import *
|
|
16
|
+
from eryn.utils import TransformContainer
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class CalculationController:
|
|
20
|
+
"""Wrapper class to controll investigative computations.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
aet_template_gen: Template waveform generator.
|
|
24
|
+
model: Model for LISA.
|
|
25
|
+
psd_kwargs: psd_kwargs for :func:`lisatools.sensitivity.get_sensitivity`.
|
|
26
|
+
Tobs: Observation time in **years**.
|
|
27
|
+
dt: Timestep in seconds.
|
|
28
|
+
psd: Sensitivity curve type to use. Default is :class:`A1TDISens`
|
|
29
|
+
because we ignore ``T`` in these simplified calculations and
|
|
30
|
+
the ``A`` and ``E`` sensitivities are equivalent.
|
|
31
|
+
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
def __init__(
|
|
35
|
+
self,
|
|
36
|
+
aet_template_gen: SNRWaveform | AETTDIWaveform,
|
|
37
|
+
model: LISAModel,
|
|
38
|
+
psd_kwargs: dict,
|
|
39
|
+
Tobs: float,
|
|
40
|
+
dt: float,
|
|
41
|
+
psd: Sensitivity = A1TDISens,
|
|
42
|
+
) -> None:
|
|
43
|
+
|
|
44
|
+
# Store everything.
|
|
45
|
+
self.aet_template_gen = aet_template_gen
|
|
46
|
+
self.psd_kwargs = psd_kwargs
|
|
47
|
+
self.model = model
|
|
48
|
+
self.psd = psd
|
|
49
|
+
self.Tobs = Tobs
|
|
50
|
+
self.dt = dt
|
|
51
|
+
|
|
52
|
+
@property
|
|
53
|
+
def parameter_transforms(self) -> TransformContainer:
|
|
54
|
+
"""Transform parameters from sampling basis to waveform basis."""
|
|
55
|
+
return self._parameter_transforms
|
|
56
|
+
|
|
57
|
+
@parameter_transforms.setter
|
|
58
|
+
def parameter_transforms(self, parameter_transforms: TransformContainer) -> None:
|
|
59
|
+
"""Set parameter transforms."""
|
|
60
|
+
assert isinstance(parameter_transforms, TransformContainer)
|
|
61
|
+
self._parameter_transforms = parameter_transforms
|
|
62
|
+
|
|
63
|
+
def get_snr(self, *params: Any, **kwargs: Any) -> float:
|
|
64
|
+
"""Compute the SNR.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
*params: Parameters to go into waveform generator.
|
|
68
|
+
**kwargs: Kwargs for waveform generator.
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
SNR.
|
|
72
|
+
|
|
73
|
+
"""
|
|
74
|
+
# generate waveform
|
|
75
|
+
a_chan, e_chan, t_chan = self.aet_template_gen(*params, **kwargs)
|
|
76
|
+
|
|
77
|
+
# ignore t channel for snr computation
|
|
78
|
+
# compute SNR
|
|
79
|
+
opt_snr = snr_func(
|
|
80
|
+
[a_chan, e_chan],
|
|
81
|
+
psd=self.psd,
|
|
82
|
+
psd_kwargs={**self.psd_kwargs, "model": self.model},
|
|
83
|
+
dt=self.aet_template_gen.dt,
|
|
84
|
+
f_arr=self.aet_template_gen.f_arr,
|
|
85
|
+
df=self.aet_template_gen.df,
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
# prepare outputs
|
|
89
|
+
self.f_arr = self.aet_template_gen.f_arr
|
|
90
|
+
self.last_output = (a_chan, e_chan)
|
|
91
|
+
|
|
92
|
+
return opt_snr
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def mT_q_to_m1_m2(mT: float, q: float) -> Tuple[float, float]:
|
|
96
|
+
"""
|
|
97
|
+
q <= 1.0
|
|
98
|
+
"""
|
|
99
|
+
return (mT / (1 + q), (q * mT) / (1 + q))
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def dist_convert(x: float) -> float:
|
|
103
|
+
return x * 1e9 * PC_SI
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def time_convert(x: float) -> float:
|
|
107
|
+
return x * YRSID_SI
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
class BBHCalculationController(CalculationController):
|
|
111
|
+
"""Calculation controller for BBHs.
|
|
112
|
+
|
|
113
|
+
Args:
|
|
114
|
+
*args: Args for :class:`CalculationController`.
|
|
115
|
+
*kwargs: Kwargs for :class:`CalculationController`.
|
|
116
|
+
|
|
117
|
+
"""
|
|
118
|
+
|
|
119
|
+
def __init__(self, *args: Any, **kwargs: Any):
|
|
120
|
+
|
|
121
|
+
# transforms from information matrix basis
|
|
122
|
+
parameter_transforms = {
|
|
123
|
+
0: np.exp,
|
|
124
|
+
4: dist_convert,
|
|
125
|
+
7: np.arccos,
|
|
126
|
+
9: np.arcsin,
|
|
127
|
+
11: time_convert,
|
|
128
|
+
(0, 1): mT_q_to_m1_m2,
|
|
129
|
+
}
|
|
130
|
+
self.transform_fn = TransformContainer(
|
|
131
|
+
parameter_transforms=parameter_transforms, fill_dict=None # fill_dict
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
super(BBHCalculationController, self).__init__(*args, **kwargs)
|
|
135
|
+
|
|
136
|
+
def get_snr(self, *args: Any, **kwargs: Any) -> float:
|
|
137
|
+
"""Compute the SNR.
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
*params: Parameters to go into waveform generator.
|
|
141
|
+
**kwargs: Kwargs for waveform generator.
|
|
142
|
+
|
|
143
|
+
Returns:
|
|
144
|
+
SNR.
|
|
145
|
+
|
|
146
|
+
"""
|
|
147
|
+
# adjust kwargs to simplify calculation
|
|
148
|
+
if "t_obs_start" not in kwargs:
|
|
149
|
+
kwargs["shift_t_limits"] = True
|
|
150
|
+
kwargs["t_obs_start"] = 0.0
|
|
151
|
+
kwargs["t_obs_end"] = self.Tobs
|
|
152
|
+
# compute snr
|
|
153
|
+
return super(BBHCalculationController, self).get_snr(*args, **kwargs)
|
|
154
|
+
|
|
155
|
+
def get_cov(
|
|
156
|
+
self,
|
|
157
|
+
*params: Any,
|
|
158
|
+
more_accurate: bool = False,
|
|
159
|
+
eps: float = 1e-9,
|
|
160
|
+
deriv_inds: np.ndarray = None,
|
|
161
|
+
precision: bool = False,
|
|
162
|
+
**kwargs: Any
|
|
163
|
+
) -> Tuple[np.ndarray, np.ndarray]:
|
|
164
|
+
"""Get covariance matrix.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
*params: Parameters for BBH. Must include ``f_ref``.
|
|
168
|
+
more_accurate: If ``True``, run a more accurate derivate requiring 2x more waveform generations.
|
|
169
|
+
eps: Absolute **derivative** step size. See :func:`lisatools.diagnostic.info_matrix`.
|
|
170
|
+
deriv_inds: Subset of parameters of interest for which to calculate the information matrix, by index.
|
|
171
|
+
If ``None``, it will be ``np.arange(len(params))``.
|
|
172
|
+
precision: If ``True``, uses 500-dps precision to compute the information matrix inverse (requires `mpmath <https://mpmath.org>`_).
|
|
173
|
+
This is typically a good idea as the information matrix can be highly ill-conditioned.
|
|
174
|
+
**kwargs: Kwargs for waveform generation.
|
|
175
|
+
|
|
176
|
+
Returns:
|
|
177
|
+
Parameters and covariance matrix.
|
|
178
|
+
|
|
179
|
+
"""
|
|
180
|
+
|
|
181
|
+
# setup all bbh specific quantities.
|
|
182
|
+
assert len(params) == 12
|
|
183
|
+
|
|
184
|
+
if isinstance(params, tuple):
|
|
185
|
+
params = list(params)
|
|
186
|
+
|
|
187
|
+
params = np.asarray(params)
|
|
188
|
+
|
|
189
|
+
m1 = params[0]
|
|
190
|
+
m2 = params[1]
|
|
191
|
+
mT = m1 + m2
|
|
192
|
+
|
|
193
|
+
if m2 > m1:
|
|
194
|
+
tmp = m2
|
|
195
|
+
m2 = m1
|
|
196
|
+
m1 = tmp
|
|
197
|
+
|
|
198
|
+
q = m2 / m1
|
|
199
|
+
|
|
200
|
+
params[0] = mT
|
|
201
|
+
params[1] = q
|
|
202
|
+
|
|
203
|
+
params[0] = np.log(params[0])
|
|
204
|
+
params[4] = params[4] / 1e9 / PC_SI
|
|
205
|
+
params[7] = np.cos(params[7])
|
|
206
|
+
params[9] = np.sin(params[9])
|
|
207
|
+
params[11] = params[11] / YRSID_SI
|
|
208
|
+
|
|
209
|
+
# default deriv inds
|
|
210
|
+
if deriv_inds is None:
|
|
211
|
+
deriv_inds = np.delete(np.arange(12), 6)
|
|
212
|
+
|
|
213
|
+
# remove f_ref derivative
|
|
214
|
+
if 6 in deriv_inds:
|
|
215
|
+
deriv_inds = np.delete(deriv_inds, np.where(deriv_inds == 6)[0])
|
|
216
|
+
|
|
217
|
+
kwargs["return_array"] = True
|
|
218
|
+
|
|
219
|
+
if "t_obs_start" not in kwargs:
|
|
220
|
+
kwargs["shift_t_limits"] = True
|
|
221
|
+
kwargs["t_obs_start"] = 0.0
|
|
222
|
+
kwargs["t_obs_end"] = self.Tobs
|
|
223
|
+
|
|
224
|
+
# compute covariance
|
|
225
|
+
cov = covariance(
|
|
226
|
+
eps,
|
|
227
|
+
self.aet_template_gen,
|
|
228
|
+
params,
|
|
229
|
+
parameter_transforms=self.transform_fn,
|
|
230
|
+
inner_product_kwargs=dict(
|
|
231
|
+
psd=self.psd,
|
|
232
|
+
psd_kwargs={**self.psd_kwargs, "model": self.model},
|
|
233
|
+
dt=self.aet_template_gen.dt,
|
|
234
|
+
f_arr=self.aet_template_gen.f_arr,
|
|
235
|
+
df=self.aet_template_gen.df,
|
|
236
|
+
),
|
|
237
|
+
waveform_kwargs=kwargs,
|
|
238
|
+
more_accurate=more_accurate,
|
|
239
|
+
deriv_inds=deriv_inds,
|
|
240
|
+
precision=precision,
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
# return parameters and their covariance
|
|
244
|
+
return params[deriv_inds], cov
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
class GBCalculationController(CalculationController):
|
|
248
|
+
"""Calculation controller for GBs.
|
|
249
|
+
|
|
250
|
+
Args:
|
|
251
|
+
*args: Args for :class:`CalculationController`.
|
|
252
|
+
*kwargs: Kwargs for :class:`CalculationController`.
|
|
253
|
+
|
|
254
|
+
"""
|
|
255
|
+
|
|
256
|
+
def __init__(self, *args: Any, **kwargs: Any):
|
|
257
|
+
|
|
258
|
+
# parameter transforms from sampling basis to waveform basis
|
|
259
|
+
parameter_transforms = {
|
|
260
|
+
0: lambda x: x * 1e-23,
|
|
261
|
+
1: lambda x: x / 1e3,
|
|
262
|
+
2: lambda x: x * 1e-18,
|
|
263
|
+
5: np.arccos,
|
|
264
|
+
8: np.arcsin,
|
|
265
|
+
# (1, 2, 3): lambda x, y, z: (x, y, 11.0 / 3.0 * y**2 / x),
|
|
266
|
+
}
|
|
267
|
+
self.transform_fn = TransformContainer(
|
|
268
|
+
parameter_transforms=parameter_transforms, fill_dict=None # fill_dict
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
super(GBCalculationController, self).__init__(*args, **kwargs)
|
|
272
|
+
# convert back to seconds
|
|
273
|
+
self.Tobs *= YRSID_SI
|
|
274
|
+
|
|
275
|
+
def get_cov(
|
|
276
|
+
self,
|
|
277
|
+
*params: np.ndarray | list,
|
|
278
|
+
more_accurate: bool = False,
|
|
279
|
+
eps: float = 1e-9,
|
|
280
|
+
deriv_inds: np.ndarray = None,
|
|
281
|
+
precision: bool = False,
|
|
282
|
+
**kwargs: Any
|
|
283
|
+
) -> Tuple[np.ndarray, np.ndarray]:
|
|
284
|
+
"""Get covariance matrix.
|
|
285
|
+
|
|
286
|
+
Args:
|
|
287
|
+
*params: Parameters for GB. Must include ``fddot``.
|
|
288
|
+
more_accurate: If ``True``, run a more accurate derivate requiring 2x more waveform generations.
|
|
289
|
+
eps: Absolute **derivative** step size. See :func:`lisatools.diagnostic.info_matrix`.
|
|
290
|
+
deriv_inds: Subset of parameters of interest for which to calculate the information matrix, by index.
|
|
291
|
+
If ``None``, it will be ``np.arange(len(params))``.
|
|
292
|
+
precision: If ``True``, uses 500-dps precision to compute the information matrix inverse (requires `mpmath <https://mpmath.org>`_).
|
|
293
|
+
This is typically a good idea as the information matrix can be highly ill-conditioned.
|
|
294
|
+
**kwargs: Kwargs for waveform generation.
|
|
295
|
+
|
|
296
|
+
Returns:
|
|
297
|
+
Parameters and covariance matrix.
|
|
298
|
+
|
|
299
|
+
"""
|
|
300
|
+
assert len(params) == 9
|
|
301
|
+
|
|
302
|
+
if isinstance(params, tuple):
|
|
303
|
+
params = list(params)
|
|
304
|
+
|
|
305
|
+
params = np.asarray(params)
|
|
306
|
+
|
|
307
|
+
# params[0] = np.log(params[0])
|
|
308
|
+
params[0] = params[0] / 1e-23
|
|
309
|
+
params[1] = params[1] * 1e3
|
|
310
|
+
params[2] = params[2] / 1e-18
|
|
311
|
+
|
|
312
|
+
if params[3] != 0.0:
|
|
313
|
+
raise NotImplementedError(
|
|
314
|
+
"This class has not been implemented for fddot != 0 yet."
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
params[5] = np.cos(params[5])
|
|
318
|
+
params[8] = np.cos(params[5])
|
|
319
|
+
|
|
320
|
+
if deriv_inds is None:
|
|
321
|
+
deriv_inds = np.delete(np.arange(9), 3)
|
|
322
|
+
|
|
323
|
+
# remove fddot for now
|
|
324
|
+
if 3 in deriv_inds:
|
|
325
|
+
deriv_inds = np.delete(deriv_inds, np.where(deriv_inds == 3)[0])
|
|
326
|
+
|
|
327
|
+
kwargs["return_array"] = True
|
|
328
|
+
|
|
329
|
+
kwargs["dt"] = self.dt
|
|
330
|
+
kwargs["T"] = self.Tobs
|
|
331
|
+
|
|
332
|
+
cov = covariance(
|
|
333
|
+
eps,
|
|
334
|
+
self.aet_template_gen,
|
|
335
|
+
params,
|
|
336
|
+
parameter_transforms=self.transform_fn,
|
|
337
|
+
inner_product_kwargs=dict(
|
|
338
|
+
psd=self.psd,
|
|
339
|
+
psd_kwargs={**self.psd_kwargs, "model": self.model},
|
|
340
|
+
dt=self.aet_template_gen.dt,
|
|
341
|
+
f_arr=self.aet_template_gen.f_arr,
|
|
342
|
+
df=self.aet_template_gen.df,
|
|
343
|
+
),
|
|
344
|
+
waveform_kwargs=kwargs,
|
|
345
|
+
more_accurate=more_accurate,
|
|
346
|
+
deriv_inds=deriv_inds,
|
|
347
|
+
precision=precision,
|
|
348
|
+
)
|
|
349
|
+
|
|
350
|
+
return params[deriv_inds], cov
|
|
351
|
+
|
|
352
|
+
def get_snr(self, *args: Any, **kwargs: Any) -> float:
|
|
353
|
+
"""Compute the SNR.
|
|
354
|
+
|
|
355
|
+
Args:
|
|
356
|
+
*params: Parameters to go into waveform generator.
|
|
357
|
+
**kwargs: Kwargs for waveform generator.
|
|
358
|
+
|
|
359
|
+
Returns:
|
|
360
|
+
SNR.
|
|
361
|
+
|
|
362
|
+
"""
|
|
363
|
+
# make sure it is TDI 2
|
|
364
|
+
if "tdi2" not in kwargs:
|
|
365
|
+
kwargs["tdi2"] = True
|
|
366
|
+
|
|
367
|
+
kwargs["dt"] = self.dt
|
|
368
|
+
kwargs["T"] = self.Tobs
|
|
369
|
+
|
|
370
|
+
# ensures tdi2 is added correctly for GBGPU
|
|
371
|
+
return super(GBCalculationController, self).get_snr(*args, **kwargs)
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
class EMRICalculationController(CalculationController):
|
|
375
|
+
"""Calculation controller for EMRIs.
|
|
376
|
+
|
|
377
|
+
Args:
|
|
378
|
+
*args: Args for :class:`CalculationController`.
|
|
379
|
+
*kwargs: Kwargs for :class:`CalculationController`.
|
|
380
|
+
|
|
381
|
+
"""
|
|
382
|
+
|
|
383
|
+
def __init__(self, *args: Any, **kwargs: Any):
|
|
384
|
+
|
|
385
|
+
# parameter transforms for EMRIs
|
|
386
|
+
parameter_transforms = {
|
|
387
|
+
0: np.exp,
|
|
388
|
+
5: np.arccos,
|
|
389
|
+
7: np.arccos,
|
|
390
|
+
9: np.arccos,
|
|
391
|
+
# (1, 2, 3): lambda x, y, z: (x, y, 11.0 / 3.0 * y**2 / x),
|
|
392
|
+
}
|
|
393
|
+
self.transform_fn = TransformContainer(
|
|
394
|
+
parameter_transforms=parameter_transforms, fill_dict=None # fill_dict
|
|
395
|
+
)
|
|
396
|
+
|
|
397
|
+
super(EMRICalculationController, self).__init__(*args, **kwargs)
|
|
398
|
+
|
|
399
|
+
def get_cov(
|
|
400
|
+
self,
|
|
401
|
+
*params: np.ndarray | list,
|
|
402
|
+
more_accurate: bool = False,
|
|
403
|
+
eps: float = 1e-9,
|
|
404
|
+
deriv_inds: np.ndarray = None,
|
|
405
|
+
precision: bool = False,
|
|
406
|
+
**kwargs: Any
|
|
407
|
+
) -> Tuple[np.ndarray, np.ndarray]:
|
|
408
|
+
"""Get covariance matrix.
|
|
409
|
+
|
|
410
|
+
Args:
|
|
411
|
+
*params: Parameters for EMRIs.
|
|
412
|
+
more_accurate: If ``True``, run a more accurate derivate requiring 2x more waveform generations.
|
|
413
|
+
eps: Absolute **derivative** step size. See :func:`lisatools.diagnostic.info_matrix`.
|
|
414
|
+
deriv_inds: Subset of parameters of interest for which to calculate the information matrix, by index.
|
|
415
|
+
If ``None``, it will be ``np.arange(len(params))``.
|
|
416
|
+
precision: If ``True``, uses 500-dps precision to compute the information matrix inverse (requires `mpmath <https://mpmath.org>`_).
|
|
417
|
+
This is typically a good idea as the information matrix can be highly ill-conditioned.
|
|
418
|
+
**kwargs: Kwargs for waveform generation.
|
|
419
|
+
|
|
420
|
+
Returns:
|
|
421
|
+
Parameters and covariance matrix.
|
|
422
|
+
|
|
423
|
+
"""
|
|
424
|
+
assert len(params) == 14
|
|
425
|
+
|
|
426
|
+
if isinstance(params, tuple):
|
|
427
|
+
params = list(params)
|
|
428
|
+
|
|
429
|
+
params = np.asarray(params)
|
|
430
|
+
|
|
431
|
+
params[0] = np.log(params[0])
|
|
432
|
+
params[5] = np.cos(params[5])
|
|
433
|
+
params[7] = np.cos(params[7])
|
|
434
|
+
params[9] = np.cos(params[9])
|
|
435
|
+
|
|
436
|
+
kwargs["return_array"] = True
|
|
437
|
+
|
|
438
|
+
assert self.aet_template_gen.response.dt == self.dt
|
|
439
|
+
assert self.aet_template_gen.response.T == self.Tobs
|
|
440
|
+
|
|
441
|
+
cov = covariance(
|
|
442
|
+
eps,
|
|
443
|
+
self.aet_template_gen,
|
|
444
|
+
params,
|
|
445
|
+
parameter_transforms=self.transform_fn,
|
|
446
|
+
inner_product_kwargs=dict(
|
|
447
|
+
psd=self.psd,
|
|
448
|
+
psd_kwargs={**self.psd_kwargs, "model": self.model},
|
|
449
|
+
dt=self.aet_template_gen.dt,
|
|
450
|
+
f_arr=self.aet_template_gen.f_arr,
|
|
451
|
+
df=self.aet_template_gen.df,
|
|
452
|
+
),
|
|
453
|
+
waveform_kwargs=kwargs,
|
|
454
|
+
more_accurate=more_accurate,
|
|
455
|
+
deriv_inds=deriv_inds,
|
|
456
|
+
precision=precision,
|
|
457
|
+
)
|
|
458
|
+
|
|
459
|
+
return params[deriv_inds], cov
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from abc import ABC
|
|
2
|
+
from typing import Union, Tuple
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class AETTDIWaveform(ABC):
|
|
7
|
+
"""Base class for an AET TDI Waveform."""
|
|
8
|
+
|
|
9
|
+
@property
|
|
10
|
+
def dt(self) -> float:
|
|
11
|
+
"""Timestep in seconds."""
|
|
12
|
+
return None
|
|
13
|
+
|
|
14
|
+
@property
|
|
15
|
+
def f_arr(self) -> np.ndarray:
|
|
16
|
+
"""Frequency array."""
|
|
17
|
+
return None
|
|
18
|
+
|
|
19
|
+
@property
|
|
20
|
+
def df(self) -> float:
|
|
21
|
+
"""Frequency bin size."""
|
|
22
|
+
return None
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class SNRWaveform(ABC):
|
|
26
|
+
"""Base class for a waveform built in a simpler fashion for SNR calculations."""
|
|
27
|
+
|
|
28
|
+
@property
|
|
29
|
+
def dt(self) -> float:
|
|
30
|
+
"""Timestep in seconds."""
|
|
31
|
+
return None
|
|
32
|
+
|
|
33
|
+
@property
|
|
34
|
+
def f_arr(self) -> np.ndarray:
|
|
35
|
+
"""Frequency array."""
|
|
36
|
+
return None
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
def df(self) -> float:
|
|
40
|
+
"""Frequency bin size."""
|
|
41
|
+
return None
|