lisaanalysistools 1.0.0__cp312-cp312-macosx_10_9_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.

Files changed (37) hide show
  1. lisaanalysistools-1.0.0.dist-info/LICENSE +201 -0
  2. lisaanalysistools-1.0.0.dist-info/METADATA +80 -0
  3. lisaanalysistools-1.0.0.dist-info/RECORD +37 -0
  4. lisaanalysistools-1.0.0.dist-info/WHEEL +5 -0
  5. lisaanalysistools-1.0.0.dist-info/top_level.txt +2 -0
  6. lisatools/__init__.py +0 -0
  7. lisatools/_version.py +4 -0
  8. lisatools/analysiscontainer.py +438 -0
  9. lisatools/cutils/detector.cpython-312-darwin.so +0 -0
  10. lisatools/datacontainer.py +292 -0
  11. lisatools/detector.py +410 -0
  12. lisatools/diagnostic.py +976 -0
  13. lisatools/glitch.py +193 -0
  14. lisatools/sampling/__init__.py +0 -0
  15. lisatools/sampling/likelihood.py +882 -0
  16. lisatools/sampling/moves/__init__.py +0 -0
  17. lisatools/sampling/moves/gbgroupstretch.py +53 -0
  18. lisatools/sampling/moves/gbmultipletryrj.py +1287 -0
  19. lisatools/sampling/moves/gbspecialgroupstretch.py +671 -0
  20. lisatools/sampling/moves/gbspecialstretch.py +1836 -0
  21. lisatools/sampling/moves/mbhspecialmove.py +286 -0
  22. lisatools/sampling/moves/placeholder.py +16 -0
  23. lisatools/sampling/moves/skymodehop.py +110 -0
  24. lisatools/sampling/moves/specialforegroundmove.py +564 -0
  25. lisatools/sampling/prior.py +508 -0
  26. lisatools/sampling/stopping.py +320 -0
  27. lisatools/sampling/utility.py +324 -0
  28. lisatools/sensitivity.py +888 -0
  29. lisatools/sources/__init__.py +0 -0
  30. lisatools/sources/emri/__init__.py +1 -0
  31. lisatools/sources/emri/tdiwaveform.py +72 -0
  32. lisatools/stochastic.py +291 -0
  33. lisatools/utils/__init__.py +0 -0
  34. lisatools/utils/constants.py +40 -0
  35. lisatools/utils/multigpudataholder.py +730 -0
  36. lisatools/utils/pointeradjust.py +106 -0
  37. lisatools/utils/utility.py +240 -0
@@ -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
@@ -0,0 +1,240 @@
1
+ from multiprocessing.sharedctypes import Value
2
+ from types import ModuleType, NoneType
3
+ from typing import Tuple
4
+ import numpy as np
5
+
6
+ # from ..sensitivity import get_sensitivity
7
+
8
+ try:
9
+ import cupy as cp
10
+
11
+ except (ModuleNotFoundError, ImportError):
12
+ import numpy as cp
13
+
14
+ pass
15
+
16
+
17
+ def get_array_module(arr: np.ndarray | cp.ndarray) -> ModuleType:
18
+ """Return array library of an array (np/cp).
19
+
20
+ Args:
21
+ arr: Numpy or Cupy array.
22
+
23
+ """
24
+ if isinstance(arr, np.ndarray):
25
+ return np
26
+ elif isinstance(arr, cp.ndarray):
27
+ return cp
28
+ else:
29
+ raise ValueError("arr must be a numpy or cupy array.")
30
+
31
+
32
+ def generate_noise_fd(freqs, df, *sensitivity_args, func=None, **sensitivity_kwargs):
33
+ if func is None:
34
+ func = get_sensitivity
35
+
36
+ norm = 0.5 * (1.0 / df) ** 0.5
37
+ psd = func(freqs, *sensitivity_args, **sensitivity_kwargs)
38
+ noise_to_add = psd ** (1 / 2) * (
39
+ np.random.normal(0, norm, len(freqs))
40
+ + 1j * np.random.normal(0, norm, len(freqs))
41
+ )
42
+ return noise_to_add
43
+
44
+
45
+ def AET(
46
+ X: float | np.ndarray, Y: float | np.ndarray, Z: float | np.ndarray
47
+ ) -> Tuple[float | np.ndarray, float | np.ndarray, float | np.ndarray]:
48
+ """Transform to AET from XYZ
49
+
50
+ .. math::
51
+
52
+ A = (Z - X) / \\sqrt(2)
53
+
54
+ .. math::
55
+
56
+ E = (X - 2Y + Z) / \\sqrt(6)
57
+
58
+ .. math::
59
+
60
+ T = (X + Y + Z) / \\sqrt(3)
61
+
62
+ Args:
63
+ X: X-channel information.
64
+ Y: Y-channel information.
65
+ Z: Z-channel information.
66
+
67
+ Returns:
68
+ A, E, T Channels.
69
+
70
+ """
71
+ return (
72
+ (Z - X) / np.sqrt(2.0),
73
+ (X - 2.0 * Y + Z) / np.sqrt(6.0),
74
+ (X + Y + Z) / np.sqrt(3.0),
75
+ )
76
+
77
+
78
+ def searchsorted2d_vec(a, b, xp=None, gpu=None, **kwargs):
79
+ if xp is None:
80
+ xp = np
81
+ else:
82
+ try:
83
+ xp.cuda.runtime.setDevice(gpu)
84
+ except AttributeError:
85
+ pass
86
+
87
+ m, n = a.shape
88
+ max_num = xp.maximum(a.max() - a.min(), b.max() - b.min()) + 1
89
+ r = max_num * xp.arange(a.shape[0])[:, None]
90
+ p = xp.searchsorted((a + r).ravel(), (b + r).ravel(), **kwargs).reshape(m, -1)
91
+
92
+ out = p - n * (xp.arange(m)[:, None])
93
+ try:
94
+ xp.cuda.runtime.deviceSynchronize()
95
+ except AttributeError:
96
+ pass
97
+
98
+ return out
99
+
100
+
101
+ def get_groups_from_band_structure(
102
+ f0, band_edges, f0_2=None, xp=None, num_groups_base=3, fix_f_test=None, inds=None
103
+ ):
104
+ if num_groups_base not in [2, 3, 4]:
105
+ raise ValueError("num_groups_base must be 2 or 3 or 4.")
106
+ if xp is None:
107
+ xp = np
108
+
109
+ else:
110
+ try:
111
+ xp.cuda.runtime.setDevice(xp.cuda.runtime.getDevice())
112
+
113
+ except AttributeError:
114
+ # it is numpy
115
+ pass
116
+
117
+ if not isinstance(f0, xp.ndarray) or not isinstance(band_edges, xp.ndarray):
118
+ raise TypeError(
119
+ "f0 and band_edges must be xp.ndarray with xp as numpy or cupy as given by the xp kwarg."
120
+ )
121
+
122
+ shape = f0.shape
123
+
124
+ # remove any above or below bands
125
+ bad = (f0 < band_edges.min()) | (f0 > band_edges.max())
126
+
127
+ band_indices = xp.searchsorted(band_edges, f0.flatten()).reshape(shape) - 1
128
+
129
+ # sort the bands in, but keep places with inds_band_indices
130
+ band_indices_sorted = xp.sort(band_indices, axis=-1)
131
+ inds_band_indices = xp.argsort(band_indices, axis=-1)
132
+
133
+ if f0_2 is not None:
134
+ assert f0_2.shape == f0.shape
135
+ band_indices_2 = xp.searchsorted(band_edges, f0_2.flatten()).reshape(shape) - 1
136
+ band_indices_2_sorted = xp.take_along_axis(
137
+ band_indices_2, inds_band_indices, axis=-1
138
+ )
139
+
140
+ # very important: ensures the proposed new point is not further than 1 band away.
141
+ diff = 1 if num_groups_base > 2 else 0
142
+ keep = (
143
+ np.abs(band_indices_2_sorted.flatten() - band_indices_sorted.flatten())
144
+ <= diff
145
+ )
146
+ if fix_f_test is not None:
147
+ keep[fix_f_test.flatten()] = False
148
+ remove = ~keep
149
+
150
+ else:
151
+ keep = np.ones(np.prod(band_indices_sorted.shape), dtype=bool)
152
+
153
+ # temperature index associated with each band
154
+ temp_inds = xp.repeat(
155
+ xp.arange(band_indices_sorted.shape[0]), np.prod(band_indices_sorted.shape[1:])
156
+ )[
157
+ keep
158
+ ] # .reshape(shape)
159
+
160
+ # walker index associated with each band
161
+ walker_inds = (
162
+ xp.tile(
163
+ xp.arange(band_indices_sorted.shape[1]),
164
+ (band_indices_sorted.shape[0], band_indices_sorted.shape[2], 1),
165
+ )
166
+ .transpose((0, 2, 1))
167
+ .flatten()[keep]
168
+ )
169
+
170
+ if f0_2 is not None:
171
+ temp_inds_remove = xp.repeat(
172
+ xp.arange(band_indices_sorted.shape[0]),
173
+ np.prod(band_indices_sorted.shape[1:]),
174
+ )[
175
+ remove
176
+ ] # .reshape(shape)
177
+
178
+ # walker index associated with each band
179
+ walker_inds_remove = (
180
+ xp.tile(
181
+ xp.arange(band_indices_sorted.shape[1]),
182
+ (band_indices_sorted.shape[0], band_indices_sorted.shape[2], 1),
183
+ )
184
+ .transpose((0, 2, 1))
185
+ .flatten()[remove]
186
+ )
187
+ inds_band_indices_remove = inds_band_indices.flatten()[remove]
188
+
189
+ # special indexing method
190
+ band_indices_sorted_special = (
191
+ band_indices_sorted.flatten()[keep]
192
+ + int(1e12) * temp_inds
193
+ + int(1e6) * walker_inds
194
+ )
195
+
196
+ # get the unique special indicators
197
+ (
198
+ unique_special,
199
+ unique_special_start_inds,
200
+ unique_special_reverse,
201
+ unique_special_counts,
202
+ ) = np.unique(
203
+ band_indices_sorted_special,
204
+ return_index=True,
205
+ return_inverse=True,
206
+ return_counts=True,
207
+ )
208
+
209
+ # this basically makes mini arange setups for each band
210
+ # the added_contribution for the first unique band index is removed
211
+ added_contribution = xp.arange(band_indices_sorted_special.shape[0])
212
+
213
+ # gets the groups
214
+ combined = band_indices_sorted_special + added_contribution
215
+ groups = (
216
+ combined - (combined[unique_special_start_inds])[unique_special_reverse]
217
+ ) # .reshape(shape)
218
+
219
+ groups_even_odd_tmp = xp.asarray(
220
+ [
221
+ (num_groups_base * groups + i)
222
+ * (band_indices_sorted.flatten()[keep] % num_groups_base == i)
223
+ for i in range(num_groups_base)
224
+ ]
225
+ )
226
+ groups_even_odd = xp.sum(groups_even_odd_tmp, axis=0)
227
+
228
+ groups_out = -2 * xp.ones_like(f0, dtype=int)
229
+ groups_out[
230
+ (temp_inds, walker_inds, inds_band_indices.flatten()[keep])
231
+ ] = groups_even_odd
232
+
233
+ groups_out[bad] = -1
234
+
235
+ """if f0_2 is not None and not np.all(keep):
236
+ fix = (temp_inds_remove, walker_inds_remove, inds_band_indices_remove)
237
+ fix_2 = band_indices_2[fix]
238
+ fix_1 = band_indices[fix]"""
239
+
240
+ return groups_out