lisaanalysistools 1.0.14__cp312-cp312-macosx_11_0_arm64.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-1.0.14.dist-info/LICENSE +201 -0
- lisaanalysistools-1.0.14.dist-info/METADATA +108 -0
- lisaanalysistools-1.0.14.dist-info/RECORD +43 -0
- lisaanalysistools-1.0.14.dist-info/WHEEL +5 -0
- lisaanalysistools-1.0.14.dist-info/top_level.txt +1 -0
- lisatools/__init__.py +0 -0
- lisatools/_version.py +4 -0
- lisatools/analysiscontainer.py +474 -0
- lisatools/cutils/__init__.py +0 -0
- lisatools/cutils/detector_cpu.cpython-312-darwin.so +0 -0
- lisatools/cutils/include/Detector.hpp +84 -0
- lisatools/cutils/include/__init__.py +0 -0
- lisatools/cutils/include/global.hpp +28 -0
- lisatools/cutils/src/Detector.cpp +307 -0
- lisatools/cutils/src/Detector.cu +307 -0
- lisatools/cutils/src/__init__.py +0 -0
- lisatools/cutils/src/pycppdetector.pyx +255 -0
- lisatools/datacontainer.py +312 -0
- lisatools/detector.py +706 -0
- lisatools/diagnostic.py +990 -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 +67 -0
- lisatools/sources/utils.py +456 -0
- lisatools/sources/waveformbase.py +41 -0
- lisatools/stochastic.py +327 -0
- lisatools/utils/__init__.py +0 -0
- lisatools/utils/constants.py +40 -0
- lisatools/utils/pointeradjust.py +106 -0
- lisatools/utils/utility.py +245 -0
lisatools/stochastic.py
ADDED
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
import warnings
|
|
3
|
+
from abc import ABC
|
|
4
|
+
from typing import Any, Tuple, Optional, List, Dict
|
|
5
|
+
|
|
6
|
+
import math
|
|
7
|
+
import numpy as np
|
|
8
|
+
from scipy import interpolate
|
|
9
|
+
|
|
10
|
+
try:
|
|
11
|
+
import cupy as cp
|
|
12
|
+
|
|
13
|
+
except (ModuleNotFoundError, ImportError):
|
|
14
|
+
import numpy as cp
|
|
15
|
+
|
|
16
|
+
from . import detector as lisa_models
|
|
17
|
+
from .utils.utility import AET
|
|
18
|
+
from .utils.constants import *
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class StochasticContribution(ABC):
|
|
22
|
+
"""Base Class for Stochastic Contributions to the PSD."""
|
|
23
|
+
|
|
24
|
+
ndim = None
|
|
25
|
+
added_stochastic_list = []
|
|
26
|
+
|
|
27
|
+
@classmethod
|
|
28
|
+
def _check_ndim(cls, params: np.ndarray | list) -> None:
|
|
29
|
+
"""Check the dimensionality of the parameters matches the model.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
params: Parameters for stochastic model.
|
|
33
|
+
|
|
34
|
+
"""
|
|
35
|
+
if cls.ndim is None:
|
|
36
|
+
raise ValueError(
|
|
37
|
+
"When subclassing the StochasticContribution class, must set `ndim` as a static attribute."
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
if len(params) != cls.ndim:
|
|
41
|
+
raise ValueError("length of parameters is not equivalent to class ndim.")
|
|
42
|
+
|
|
43
|
+
@classmethod
|
|
44
|
+
def get_Sh(
|
|
45
|
+
cls, f: float | np.ndarray, *params: np.ndarray | list, **kwargs: Any
|
|
46
|
+
) -> float | np.ndarray:
|
|
47
|
+
"""Calculate the power spectral density of the stochastic contribution.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
f: Frequency array.
|
|
51
|
+
*params: Parameters for the stochastic model.
|
|
52
|
+
**kwargs: Keyword arguments for the stochastic model.
|
|
53
|
+
|
|
54
|
+
"""
|
|
55
|
+
if len(cls.added_stochastic_list) > 0:
|
|
56
|
+
cls._check_ndim(params[0])
|
|
57
|
+
return cls.specific_Sh_function(f, *params, **kwargs)
|
|
58
|
+
|
|
59
|
+
@staticmethod
|
|
60
|
+
def specific_Sh_function(
|
|
61
|
+
f: float | np.ndarray, *args: Any, **kwargs: Any
|
|
62
|
+
) -> float | np.ndarray:
|
|
63
|
+
"""Calculate the power spectral density contained in a stochastic signal contribution.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
f: Frequency array.
|
|
67
|
+
*args: Any arguments for the function.
|
|
68
|
+
**kwargs: Any keyword arguments for the function.
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
Power spectral density contained in stochastic signal.
|
|
72
|
+
|
|
73
|
+
"""
|
|
74
|
+
raise NotImplementedError
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class StochasticContributionContainer:
|
|
78
|
+
"""Container for multiple Stochastic Contributions
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
stochastic_contribution_dict: Dictionary with multiple Stochastic entries.
|
|
82
|
+
Keys are the names and values are of type :class:`StochasticContribution`.
|
|
83
|
+
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
def __init__(
|
|
87
|
+
self, stochastic_contribution_dict: dict[StochasticContribution]
|
|
88
|
+
) -> None:
|
|
89
|
+
self.stochastic_contribution_dict = stochastic_contribution_dict
|
|
90
|
+
|
|
91
|
+
@property
|
|
92
|
+
def stochastic_contribution_dict(self) -> dict[StochasticContribution]:
|
|
93
|
+
"""Stochastic contribution storage."""
|
|
94
|
+
return self._stochastic_contribution_dict
|
|
95
|
+
|
|
96
|
+
@stochastic_contribution_dict.setter
|
|
97
|
+
def stochastic_contribution_dict(
|
|
98
|
+
self, stochastic_contribution_dict: dict[StochasticContribution]
|
|
99
|
+
) -> None:
|
|
100
|
+
"""Set stochastic_contribution_dict."""
|
|
101
|
+
assert isinstance(stochastic_contribution_dict, dict)
|
|
102
|
+
for key, value in stochastic_contribution_dict.items():
|
|
103
|
+
if not isinstance(value, StochasticContribution):
|
|
104
|
+
raise ValueError(
|
|
105
|
+
f"Stochastic model {key} is not of type StochasticContribution."
|
|
106
|
+
)
|
|
107
|
+
self._stochastic_contribution_dict = stochastic_contribution_dict
|
|
108
|
+
|
|
109
|
+
def get_Sh(
|
|
110
|
+
self, f: float | np.ndarray, params_dict: dict[tuple], kwargs_dict: dict[dict]
|
|
111
|
+
) -> np.ndarray:
|
|
112
|
+
"""Calculate Sh for stochastic contribution.
|
|
113
|
+
|
|
114
|
+
Args:
|
|
115
|
+
f: Frequency array.
|
|
116
|
+
params_dict: Dictionary with keys equivalent to ``self.stochastic_contribution_dict.keys()``.
|
|
117
|
+
Values are the parameters for each associated model.
|
|
118
|
+
kwargs_dict: Dictionary with keys equivalent to ``self.stochastic_contribution_dict.keys()``.
|
|
119
|
+
Values are the keyword argument dicts for each associated model.
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
Stochastic contribution.
|
|
123
|
+
|
|
124
|
+
"""
|
|
125
|
+
Sh_out = np.zeros_like(f)
|
|
126
|
+
for key in params_dict:
|
|
127
|
+
stochastic_contrib = self.stochastic_contribution_dict[key]
|
|
128
|
+
Sh_out += stochastic_contrib.get_Sh(
|
|
129
|
+
f, params_dict[key], **(kwargs_dict.get(key, {}))
|
|
130
|
+
)
|
|
131
|
+
return Sh_out
|
|
132
|
+
|
|
133
|
+
def __setitem__(self, key: str | int | tuple, val: StochasticContribution) -> None:
|
|
134
|
+
"""Set an item by directly indexing the class object."""
|
|
135
|
+
self.stochastic_contribution_dict[key] = val
|
|
136
|
+
|
|
137
|
+
def __getitem__(self, key: str | int | tuple) -> StochasticContribution:
|
|
138
|
+
"""Get item directly from dictionary."""
|
|
139
|
+
return self.stochastic_contribution_dict[key]
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
class HyperbolicTangentGalacticForeground(StochasticContribution):
|
|
143
|
+
"""Hyperbolic Tangent-based foreground fitting function."""
|
|
144
|
+
|
|
145
|
+
ndim = 5
|
|
146
|
+
|
|
147
|
+
@staticmethod
|
|
148
|
+
def specific_Sh_function(
|
|
149
|
+
f: float | np.ndarray, amp: float, fk: float, alpha: float, s1: float, s2: float
|
|
150
|
+
) -> float | np.ndarray:
|
|
151
|
+
"""Hyperbolic tangent model 1 for the Galaxy foreground noise
|
|
152
|
+
|
|
153
|
+
This model for the PSD contribution from the Galactic foreground noise is given by
|
|
154
|
+
|
|
155
|
+
.. math::
|
|
156
|
+
|
|
157
|
+
S_\\text{gal} = \\frac{A_\\text{gal}}{2}e^{-s_1f^\\alpha}f^{-7/3}\\left[ 1 + \\tanh{\\left(-s_2 (f - f_k)\\right)} \\right],
|
|
158
|
+
|
|
159
|
+
where :math:`A_\\text{gal}` is the amplitude of the stochastic signal, :math:`f_k` is the knee frequency at which a bend occurs,
|
|
160
|
+
math:`\\alpha` is a power law parameter, :math:`s_1` is a slope parameter below the knee,
|
|
161
|
+
and :math:`s_2` is a slope parameter after the knee.:
|
|
162
|
+
|
|
163
|
+
Args:
|
|
164
|
+
f: Frequency array.
|
|
165
|
+
amp: Amplitude parameter for the Galaxy.
|
|
166
|
+
fk: Knee frequency in Hz.
|
|
167
|
+
alpha: Power law parameter.
|
|
168
|
+
s1: Slope parameter below knee.
|
|
169
|
+
s2: Slope parameter above knee.
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
PSD of the Galaxy foreground noise
|
|
173
|
+
|
|
174
|
+
"""
|
|
175
|
+
Sgal = (
|
|
176
|
+
amp
|
|
177
|
+
* np.exp(-(f**alpha) * s1)
|
|
178
|
+
* (f ** (-7.0 / 3.0))
|
|
179
|
+
* 0.5
|
|
180
|
+
* (1.0 + np.tanh(-(f - fk) * s2))
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
return Sgal
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
class FittedHyperbolicTangentGalacticForeground(HyperbolicTangentGalacticForeground):
|
|
187
|
+
# TODO: need to verify this is still working
|
|
188
|
+
ndim = 1
|
|
189
|
+
amp = 3.26651613e-44
|
|
190
|
+
alpha = 1.18300266e00
|
|
191
|
+
# Tobs should be in sec.
|
|
192
|
+
day = 86400.0
|
|
193
|
+
month = day * 30.5
|
|
194
|
+
year = 365.25 * 24.0 * 3600.0 # hard coded for initial fits
|
|
195
|
+
|
|
196
|
+
Xobs = [
|
|
197
|
+
1.0 * day,
|
|
198
|
+
3.0 * month,
|
|
199
|
+
6.0 * month,
|
|
200
|
+
1.0 * year,
|
|
201
|
+
2.0 * year,
|
|
202
|
+
4.0 * year,
|
|
203
|
+
10.0 * year,
|
|
204
|
+
]
|
|
205
|
+
knee = [
|
|
206
|
+
1.15120924e-02,
|
|
207
|
+
4.01884128e-03,
|
|
208
|
+
3.47302482e-03,
|
|
209
|
+
2.77606177e-03,
|
|
210
|
+
2.41178384e-03,
|
|
211
|
+
2.09278117e-03,
|
|
212
|
+
1.57362626e-03,
|
|
213
|
+
]
|
|
214
|
+
Slope1 = [
|
|
215
|
+
9.41315118e02,
|
|
216
|
+
1.36887568e03,
|
|
217
|
+
1.68729474e03,
|
|
218
|
+
1.76327234e03,
|
|
219
|
+
2.32678814e03,
|
|
220
|
+
3.01430978e03,
|
|
221
|
+
3.74970124e03,
|
|
222
|
+
]
|
|
223
|
+
|
|
224
|
+
Slope2 = [
|
|
225
|
+
1.03239773e02,
|
|
226
|
+
1.03351646e03,
|
|
227
|
+
1.62204855e03,
|
|
228
|
+
1.68631844e03,
|
|
229
|
+
2.06821665e03,
|
|
230
|
+
2.95774596e03,
|
|
231
|
+
3.15199454e03,
|
|
232
|
+
]
|
|
233
|
+
Tmax = 10 * YRSID_SI
|
|
234
|
+
|
|
235
|
+
@classmethod
|
|
236
|
+
def specific_Sh_function(
|
|
237
|
+
cls, f: float | np.ndarray, Tobs: float
|
|
238
|
+
) -> float | np.ndarray:
|
|
239
|
+
"""Fitted hyperbolic tangent model 1 for the Galaxy foreground noise.
|
|
240
|
+
|
|
241
|
+
This class fits the parameters for :class:`HyperbolicTangentGalacticForeground`
|
|
242
|
+
using analytic estimates from (# TODO). The fit is a function of time, so the user
|
|
243
|
+
inputs ``Tobs``.
|
|
244
|
+
|
|
245
|
+
# Sgal_1d = 2.2e-44*np.exp(-(fr**1.2)*0.9e3)*(fr**(-7./3.))*0.5*(1.0 + np.tanh(-(fr-1.4e-2)*0.7e2))
|
|
246
|
+
# Sgal_3m = 2.2e-44*np.exp(-(fr**1.2)*1.7e3)*(fr**(-7./3.))*0.5*(1.0 + np.tanh(-(fr-4.8e-3)*5.4e2))
|
|
247
|
+
# Sgal_1y = 2.2e-44*np.exp(-(fr**1.2)*2.2e3)*(fr**(-7./3.))*0.5*(1.0 + np.tanh(-(fr-3.1e-3)*1.3e3))
|
|
248
|
+
# Sgal_2y = 2.2e-44*np.exp(-(fr**1.2)*2.2e3)*(fr**(-7./3.))*0.5*(1.0 + np.tanh(-(fr-2.3e-3)*1.8e3))
|
|
249
|
+
# Sgal_4y = 2.2e-44*np.exp(-(fr**1.2)*2.9e3)*(fr**(-7./3.))*0.5*(1.0 + np.tanh(-(fr-2.0e-3)*1.9e3))
|
|
250
|
+
|
|
251
|
+
Args:
|
|
252
|
+
f: Frequency array.
|
|
253
|
+
Tobs: Observation time in seconds.
|
|
254
|
+
|
|
255
|
+
Returns:
|
|
256
|
+
PSD of the Galaxy foreground noise
|
|
257
|
+
|
|
258
|
+
"""
|
|
259
|
+
|
|
260
|
+
if Tobs > cls.Tmax:
|
|
261
|
+
raise ValueError(
|
|
262
|
+
"Tobs is greater than the maximum allowable fit which is 10 years."
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
# Interpolate
|
|
266
|
+
tck1 = interpolate.splrep(cls.Xobs, cls.Slope1, s=0, k=1)
|
|
267
|
+
tck2 = interpolate.splrep(cls.Xobs, cls.knee, s=0, k=1)
|
|
268
|
+
tck3 = interpolate.splrep(cls.Xobs, cls.Slope2, s=0, k=1)
|
|
269
|
+
s1 = interpolate.splev(Tobs, tck1, der=0).item()
|
|
270
|
+
fk = interpolate.splev(Tobs, tck2, der=0).item()
|
|
271
|
+
s2 = interpolate.splev(Tobs, tck3, der=0).item()
|
|
272
|
+
|
|
273
|
+
return HyperbolicTangentGalacticForeground.specific_Sh_function(
|
|
274
|
+
f, cls.amp, fk, cls.alpha, s1, s2
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
__stock_gb_stochastic_options__ = [
|
|
279
|
+
"HyperbolicTangentGalacticForeground",
|
|
280
|
+
"FittedHyperbolicTangentGalacticForeground",
|
|
281
|
+
]
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def get_stock_gb_stochastic_options() -> List[StochasticContribution]:
|
|
285
|
+
"""Get stock options for stochastic contributions.
|
|
286
|
+
|
|
287
|
+
Returns:
|
|
288
|
+
List of stock stochastic options.
|
|
289
|
+
|
|
290
|
+
"""
|
|
291
|
+
return __stock_gb_stochastic_options__
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
def get_default_stochastic_from_str(stochastic: str) -> StochasticContribution:
|
|
295
|
+
"""Return a LISA stochastic from a ``str`` input.
|
|
296
|
+
|
|
297
|
+
Args:
|
|
298
|
+
stochastic: Stochastic contribution indicated with a ``str``.
|
|
299
|
+
|
|
300
|
+
Returns:
|
|
301
|
+
Stochastic contribution associated to that ``str``.
|
|
302
|
+
|
|
303
|
+
"""
|
|
304
|
+
if stochastic not in __stock_gb_stochastic_options__:
|
|
305
|
+
raise ValueError(
|
|
306
|
+
"Requested string stochastic is not available. See lisatools.stochastic documentation."
|
|
307
|
+
)
|
|
308
|
+
return globals()[stochastic]
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
def check_stochastic(stochastic: Any) -> StochasticContribution:
|
|
312
|
+
"""Check input stochastic contribution.
|
|
313
|
+
|
|
314
|
+
Args:
|
|
315
|
+
stochastic: Stochastic contribution to check.
|
|
316
|
+
|
|
317
|
+
Returns:
|
|
318
|
+
Stochastic contribution checked. Adjusted from ``str`` if ``str`` input.
|
|
319
|
+
|
|
320
|
+
"""
|
|
321
|
+
if isinstance(stochastic, str):
|
|
322
|
+
stochastic = get_default_stochastic_from_str(stochastic)
|
|
323
|
+
|
|
324
|
+
if not issubclass(stochastic, StochasticContribution):
|
|
325
|
+
raise ValueError("stochastic argument not given correctly.")
|
|
326
|
+
|
|
327
|
+
return stochastic
|
|
File without changes
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
MSUN_SI = 1.98848e30
|
|
2
|
+
YRSID_SI = 31558149.763545603
|
|
3
|
+
AU_SI = 149597870700.0
|
|
4
|
+
C_SI = 299792458.0
|
|
5
|
+
G_SI = 6.674080e-11
|
|
6
|
+
GMSUN = 1.3271244210789466e20
|
|
7
|
+
MTSUN_SI = 4.925491025873693e-06
|
|
8
|
+
MRSUN_SI = 1476.6250615036158
|
|
9
|
+
PC_SI = 3.0856775814913674e16
|
|
10
|
+
PI = 3.141592653589793238462643383279502884
|
|
11
|
+
PI_2 = 1.570796326794896619231321691639751442
|
|
12
|
+
PI_3 = 1.047197551196597746154214461093167628
|
|
13
|
+
PI_4 = 0.785398163397448309615660845819875721
|
|
14
|
+
SQRTPI = 1.772453850905516027298167483341145183
|
|
15
|
+
SQRTTWOPI = 2.506628274631000502415765284811045253
|
|
16
|
+
INVSQRTPI = 0.564189583547756286948079451560772585
|
|
17
|
+
INVSQRTTWOPI = 0.398942280401432677939946059934381868
|
|
18
|
+
GAMMA = 0.577215664901532860606512090082402431
|
|
19
|
+
SQRT2 = 1.414213562373095048801688724209698079
|
|
20
|
+
SQRT3 = 1.732050807568877293527446341505872367
|
|
21
|
+
SQRT6 = 2.449489742783178098197284074705891392
|
|
22
|
+
INVSQRT2 = 0.707106781186547524400844362104849039
|
|
23
|
+
INVSQRT3 = 0.577350269189625764509148780501957455
|
|
24
|
+
INVSQRT6 = 0.408248290463863016366214012450981898
|
|
25
|
+
F0 = 3.168753578687779e-08
|
|
26
|
+
Omega0 = 1.9909865927683788e-07
|
|
27
|
+
L_SI = 2.5e9
|
|
28
|
+
eorbit = 0.004824185218078991
|
|
29
|
+
ConstOmega = 1.99098659277e-7
|
|
30
|
+
|
|
31
|
+
#### Armlength
|
|
32
|
+
lisaL = 2.5e9 # LISA's arm meters
|
|
33
|
+
lisaLT = lisaL / C_SI # LISA's armn in sec
|
|
34
|
+
|
|
35
|
+
#### Noise levels
|
|
36
|
+
### Optical Metrology System noise
|
|
37
|
+
## Decomposition
|
|
38
|
+
Sloc = (1.7e-12) ** 2 # m^2/Hz
|
|
39
|
+
Ssci = (8.9e-12) ** 2 # m^2/Hz
|
|
40
|
+
Soth = (2.0e-12) ** 2 # m^2/Hz
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# check to see if cupy is available for gpus
|
|
2
|
+
import numpy as np
|
|
3
|
+
|
|
4
|
+
try:
|
|
5
|
+
import cupy as xp
|
|
6
|
+
|
|
7
|
+
gpu = True
|
|
8
|
+
|
|
9
|
+
except (ImportError, ModuleNotFoundError) as e:
|
|
10
|
+
import numpy as np
|
|
11
|
+
|
|
12
|
+
gpu = False
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def wrapper(*args, **kwargs):
|
|
16
|
+
"""Function to convert array and C/C++ class arguments to ptrs
|
|
17
|
+
|
|
18
|
+
This function checks the object type. If it is a cupy or numpy array,
|
|
19
|
+
it will determine its pointer by calling the proper attributes. If you design
|
|
20
|
+
a Cython class to be passed through python, it must have a :code:`ptr`
|
|
21
|
+
attribute.
|
|
22
|
+
|
|
23
|
+
If you use this function, you must convert input arrays to size_t data type in Cython and
|
|
24
|
+
then properly cast the pointer as it enters the c++ function. See the
|
|
25
|
+
Cython codes
|
|
26
|
+
`here <https://github.com/BlackHolePerturbationToolkit/FastEMRIWaveforms/tree/master/src>`_
|
|
27
|
+
for examples.
|
|
28
|
+
|
|
29
|
+
args:
|
|
30
|
+
*args (list): list of the arguments for a function.
|
|
31
|
+
**kwargs (dict): dictionary of keyword arguments to be converted.
|
|
32
|
+
|
|
33
|
+
returns:
|
|
34
|
+
Tuple: (targs, tkwargs) where t indicates target (with pointer values
|
|
35
|
+
rather than python objects).
|
|
36
|
+
|
|
37
|
+
"""
|
|
38
|
+
# declare target containers
|
|
39
|
+
targs = []
|
|
40
|
+
tkwargs = {}
|
|
41
|
+
|
|
42
|
+
# args first
|
|
43
|
+
for arg in args:
|
|
44
|
+
if gpu:
|
|
45
|
+
# cupy arrays
|
|
46
|
+
if isinstance(arg, xp.ndarray):
|
|
47
|
+
targs.append(arg.data.mem.ptr)
|
|
48
|
+
continue
|
|
49
|
+
|
|
50
|
+
# numpy arrays
|
|
51
|
+
if isinstance(arg, np.ndarray):
|
|
52
|
+
targs.append(arg.__array_interface__["data"][0])
|
|
53
|
+
continue
|
|
54
|
+
|
|
55
|
+
try:
|
|
56
|
+
# cython classes
|
|
57
|
+
targs.append(arg.ptr)
|
|
58
|
+
continue
|
|
59
|
+
except AttributeError:
|
|
60
|
+
# regular argument
|
|
61
|
+
targs.append(arg)
|
|
62
|
+
|
|
63
|
+
# kwargs next
|
|
64
|
+
for key, arg in kwargs.items():
|
|
65
|
+
if gpu:
|
|
66
|
+
# cupy arrays
|
|
67
|
+
if isinstance(arg, xp.ndarray):
|
|
68
|
+
tkwargs[key] = arg.data.mem.ptr
|
|
69
|
+
continue
|
|
70
|
+
|
|
71
|
+
if isinstance(arg, np.ndarray):
|
|
72
|
+
# numpy arrays
|
|
73
|
+
tkwargs[key] = arg.__array_interface__["data"][0]
|
|
74
|
+
continue
|
|
75
|
+
|
|
76
|
+
try:
|
|
77
|
+
# cython classes
|
|
78
|
+
tkwargs[key] = arg.ptr
|
|
79
|
+
continue
|
|
80
|
+
except AttributeError:
|
|
81
|
+
# other arguments
|
|
82
|
+
tkwargs[key] = arg
|
|
83
|
+
|
|
84
|
+
return (targs, tkwargs)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def pointer_adjust(func):
|
|
88
|
+
"""Decorator function for cupy/numpy agnostic cython
|
|
89
|
+
|
|
90
|
+
This decorator applies :func:`few.utils.utility.wrapper` to functions
|
|
91
|
+
via the decorator construction.
|
|
92
|
+
|
|
93
|
+
If you use this decorator, you must convert input arrays to size_t data type in Cython and
|
|
94
|
+
then properly cast the pointer as it enters the c++ function. See the
|
|
95
|
+
Cython codes
|
|
96
|
+
`here <https://github.com/BlackHolePerturbationToolkit/FastEMRIWaveforms/tree/master/src>`_
|
|
97
|
+
for examples.
|
|
98
|
+
|
|
99
|
+
"""
|
|
100
|
+
|
|
101
|
+
def func_wrapper(*args, **kwargs):
|
|
102
|
+
# get pointers
|
|
103
|
+
targs, tkwargs = wrapper(*args, **kwargs)
|
|
104
|
+
return func(*targs, **tkwargs)
|
|
105
|
+
|
|
106
|
+
return func_wrapper
|