orpheus-npcf 0.2.1__cp310-cp310-musllinux_1_2_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.
orpheus/npcf_base.py ADDED
@@ -0,0 +1,766 @@
1
+ import ctypes as ct
2
+ import glob
3
+ import numpy as np
4
+ from numpy.ctypeslib import ndpointer
5
+ from pathlib import Path
6
+
7
+
8
+ __all__ = ["BinnedNPCF"]
9
+
10
+ ################################################
11
+ ## BASE CLASSES FOR NPCF AND THEIR MULTIPOLES ##
12
+ ################################################
13
+ class BinnedNPCF:
14
+ r"""Class of an binned N-point correlation function of various arbitrary tracer catalogs.
15
+ This class contains attributes and metods that can be used across any its children.
16
+
17
+ Attributes
18
+ ----------
19
+ order: int
20
+ The order of the correlation function.
21
+ spins: list
22
+ The spins of the tracer fields of which the NPCF is computed.
23
+ n_cfs: int
24
+ The number of independent components of the NPCF.
25
+ min_sep: float
26
+ The smallest distance of each vertex for which the NPCF is computed.
27
+ max_sep: float
28
+ The largest distance of each vertex for which the NPCF is computed.
29
+ nbinsr: int, optional
30
+ The number of radial bins for each vertex of the NPCF. If set to
31
+ ``None`` this attribute is inferred from the ``binsize`` attribute.
32
+ binsize: int, optional
33
+ The logarithmic slize of the radial bins for each vertex of the NPCF. If set to
34
+ ``None`` this attribute is inferred from the ``nbinsr`` attribute.
35
+ nbinsphi: float, optional
36
+ The number of angular bins for the NPCF in the real-space basis.
37
+ Defaults to ``100``.
38
+ nmaxs: list, optional
39
+ The largest multipole component considered for the NPCF in the multipole basis.
40
+ Defaults to ``30``.
41
+ method: str, optional
42
+ The method to be employed for the estimator. Defaults to ``DoubleTree``.
43
+ multicountcorr: bool, optional
44
+ Flag on whether to subtract of multiplets in which the same tracer appears more
45
+ than once. Defaults to ``True``.
46
+ shuffle_pix: int, optional
47
+ Choice of how to define centers of the cells in the spatial hash structure.
48
+ Defaults to ``0``, i.e. position at pixel center of mass.
49
+ tree_resos: list, optional
50
+ The cell sizes of the hierarchical spatial hash structure
51
+ tree_redges: list, optional
52
+ List of radii where the tree changes resolution.
53
+ rmin_pixsize: int, optional
54
+ The limiting radial distance relative to the cell of the spatial hash
55
+ after which one switches to the next hash in the hierarchy. Defaults to ``20``.
56
+ resoshift_leafs: int, optional
57
+ Allows for a difference in how the hierarchical spatial hash is traversed for
58
+ pixels at the base of the NPCF and pixels at leafs. I.e. positive values indicate
59
+ that leafs will be evaluated at a courser resolutions than the base. Defaults to ``0``.
60
+ minresoind_leaf: int, optional
61
+ Sets the smallest resolution in the spatial hash hierarchy which can be used to access
62
+ tracers at leaf positions. If set to ``None`` uses the smallest specified cell size.
63
+ Defaults to ``None``.
64
+ maxresoind_leaf: int, optional
65
+ Sets the largest resolution in the spatial hash hierarchy which can be used to access
66
+ tracers at leaf positions. If set to ``None`` uses the largest specified cell size.
67
+ Defaults to ``None``.
68
+ verbosity: int, optional
69
+ The level of verbosity during the computation. Level 0: No verbosity, 1: Progress verbosity
70
+ on python layer, 2: Progress verbosity also on C level, 3: Debug verbosity. Defaults to ``0``.
71
+ nthreads: int, optional
72
+ The number of openmp threads used for the reduction procedure. Defaults to ``16``.
73
+ bin_centers: numpy.ndarray
74
+ The centers of the radial bins for each combination of tomographic redshifts.
75
+ bin_centers_mean: numpy.ndarray
76
+ The centers of the radial bins averaged over all combination of tomographic redshifts.
77
+ phis: list
78
+ The bin centers for the N-2 angles describing the NPCF
79
+ in the real-space basis.
80
+ npcf: numpy.ndarray
81
+ The natural components of the NPCF in the real space basis. The different axes
82
+ are specified as follows: ``(component, zcombi, rbin_1, ..., rbin_N-1, phiin_1, phibin_N-2)``.
83
+ npcf_norm: numpy.ndarray
84
+ The normalization of the natural components of the NPCF in the real space basis. The different axes
85
+ are specified as follows: ``(zcombi, rbin_1, ..., rbin_N-1, phiin_1, phibin_N-2)``.
86
+ npcf_multipoles: numpy.ndarray
87
+ The natural components of the NPCF in the multipole basis. The different axes
88
+ are specified as follows: ``(component, zcombi, multipole_1, ..., multipole_N-2, rbin_1, ..., rbin_N-1)``.
89
+ npcf_multipoles_norm: numpy.ndarray
90
+ The normalization of the natural components of the NPCF in the multipole basis. The different axes
91
+ are specified as follows: ``(zcombi, multipole_1, ..., multipole_N-2, rbin_1, ..., rbin_N-1)``.
92
+ is_edge_corrected: bool, optional
93
+ Flag signifying on wheter the NPCF multipoles have beed edge-corrected. Defaults to ``False``.
94
+ """
95
+
96
+ def __init__(self, order, spins, n_cfs, min_sep, max_sep, nbinsr=None, binsize=None, nbinsphi=100,
97
+ nmaxs=30, method="DoubleTree", multicountcorr=True, shuffle_pix=0,
98
+ tree_resos=[0,0.25,0.5,1.,2.], tree_redges=None, rmin_pixsize=20,
99
+ resoshift_leafs=0, minresoind_leaf=None, maxresoind_leaf=None,
100
+ methods_avail=["Discrete", "Tree", "BaseTree", "DoubleTree"], verbosity=0, nthreads=16):
101
+
102
+ self.order = int(order)
103
+ self.n_cfs = int(n_cfs)
104
+ self.min_sep = min_sep
105
+ self.max_sep = max_sep
106
+ self.nbinsphi = nbinsphi
107
+ self.nmaxs = nmaxs
108
+ self.method = method
109
+ self.multicountcorr = int(multicountcorr)
110
+ self.shuffle_pix = shuffle_pix
111
+ self.methods_avail = methods_avail
112
+ self.tree_resos = np.asarray(tree_resos, dtype=np.float64)
113
+ self.tree_nresos = int(len(self.tree_resos))
114
+ self.tree_redges = tree_redges
115
+ self.rmin_pixsize = rmin_pixsize
116
+ self.resoshift_leafs = resoshift_leafs
117
+ self.minresoind_leaf = minresoind_leaf
118
+ self.maxresoind_leaf = maxresoind_leaf
119
+ self.verbosity = np.int32(verbosity)
120
+ self.nthreads = np.int32(max(1,nthreads))
121
+
122
+ self.tree_resosatr = None
123
+ self.bin_centers = None
124
+ self.bin_centers_mean = None
125
+ self.phis = [None]*self.order
126
+ self.dphis = [None]*self.order
127
+ self.npcf = None
128
+ self.npcf_norm = None
129
+ self.npcf_multipoles = None
130
+ self.npcf_multipoles_norm = None
131
+ self.is_edge_corrected = False
132
+ self._verbose_python = self.verbosity > 0
133
+ self._verbose_c = self.verbosity > 1
134
+ self._verbose_debug = self.verbosity > 2
135
+
136
+ # Check types or arguments
137
+ if isinstance(self.nbinsphi, int):
138
+ self.nbinsphi = self.nbinsphi*np.ones(order-2)
139
+ self.nbinsphi = self.nbinsphi.astype(np.int32)
140
+ if isinstance(self.nmaxs, int):
141
+ self.nmaxs = self.nmaxs*np.ones(order-2)
142
+ self.nmaxs = self.nmaxs.astype(np.int32)
143
+ if isinstance(spins, int):
144
+ spins = spins*np.ones(order).astype(np.int32)
145
+ self.spins = np.asarray(spins, dtype=np.int32)
146
+ assert(isinstance(self.order, int))
147
+ assert(isinstance(self.spins, np.ndarray))
148
+ assert(isinstance(self.spins[0], np.int32))
149
+ assert(len(spins)==self.order)
150
+ assert(isinstance(self.n_cfs, int))
151
+ assert(isinstance(self.min_sep, float))
152
+ assert(isinstance(self.max_sep, float))
153
+ if self.order>2:
154
+ assert(isinstance(self.nbinsphi, np.ndarray))
155
+ assert(isinstance(self.nbinsphi[0], np.int32))
156
+ assert(len(self.nbinsphi)==self.order-2)
157
+ assert(isinstance(self.nmaxs, np.ndarray))
158
+ assert(isinstance(self.nmaxs[0], np.int32))
159
+ assert(len(self.nmaxs)==self.order-2)
160
+ assert(self.method in self.methods_avail)
161
+ assert(isinstance(self.tree_resos, np.ndarray))
162
+ assert(isinstance(self.tree_resos[0], np.float64))
163
+
164
+ # Setup radial bins
165
+ # Note that we always have self.binsize <= binsize
166
+ assert((binsize!=None) or (nbinsr!=None))
167
+ if nbinsr != None:
168
+ self.nbinsr = int(nbinsr)
169
+ if binsize != None:
170
+ assert(isinstance(binsize, float))
171
+ self.nbinsr = int(np.ceil(np.log(self.max_sep/self.min_sep)/binsize))
172
+ assert(isinstance(self.nbinsr, int))
173
+ self.bin_edges = np.geomspace(self.min_sep, self.max_sep, self.nbinsr+1)
174
+ self.binsize = np.log(self.bin_edges[1]/self.bin_edges[0])
175
+ # Setup variable for tree estimator according to input
176
+ if self.tree_redges != None:
177
+ assert(isinstance(self.tree_redges, np.ndarray))
178
+ self.tree_redges = self.tree_redges.astype(np.float64)
179
+ assert(len(self.tree_redges)==self.tree_resos+1)
180
+ self.tree_redges = np.sort(self.tree_redges)
181
+ assert(self.tree_redges[0]==self.min_sep)
182
+ assert(self.tree_redges[-1]==self.max_sep)
183
+ else:
184
+ self.tree_redges = np.zeros(len(self.tree_resos)+1)
185
+ self.tree_redges[-1] = self.max_sep
186
+ for elreso, reso in enumerate(self.tree_resos):
187
+ self.tree_redges[elreso] = (reso==0.)*self.min_sep + (reso!=0.)*self.rmin_pixsize*reso
188
+ _tmpreso = 0
189
+ self.tree_resosatr = np.zeros(self.nbinsr, dtype=np.int32)
190
+ for elbin, rbin in enumerate(self.bin_edges[:-1]):
191
+ if rbin > self.tree_redges[_tmpreso+1]:
192
+ _tmpreso += 1
193
+ self.tree_resosatr[elbin] = _tmpreso
194
+ # Update tree resolutions to make sure that `tree_redges` is monotonous
195
+ # (This is i.e. not fulfilled for a default tree setup and a large value of `rmin`)
196
+ _resomin = self.tree_resosatr[0]
197
+ _resomax = self.tree_resosatr[-1]
198
+ self._updatetree(self.tree_resos[_resomin:_resomax+1])
199
+
200
+ # Prepare leaf resolutions
201
+ if np.abs(self.resoshift_leafs)>=self.tree_nresos:
202
+ self.resoshift_leafs = np.int32((self.tree_nresos-1) * np.sign(self.resoshift_leafs))
203
+ print("Error: Parameter resoshift_leafs is out of bounds. Set to %i."%self.resoshift_leafs)
204
+ if self.minresoind_leaf is None:
205
+ self.minresoind_leaf=0
206
+ if self.maxresoind_leaf is None:
207
+ self.maxresoind_leaf=self.tree_nresos-1
208
+ if self.minresoind_leaf<0:
209
+ self.minresoind_leaf = 0
210
+ print("Error: Parameter minreso_leaf is out of bounds. Set to 0.")
211
+ if self.minresoind_leaf>=self.tree_nresos:
212
+ self.minresoind_leaf = self.tree_nresos-1
213
+ print("Error: Parameter minreso_leaf is out of bounds. Set to %i."%self.minresoint_leaf)
214
+ if self.maxresoind_leaf<0:
215
+ self.maxresoind_leaf = 0
216
+ print("Error: Parameter minreso_leaf is out of bounds. Set to 0.")
217
+ if self.maxresoind_leaf>=self.tree_nresos:
218
+ self.maxresoind_leaf = self.tree_nresos-1
219
+ print("Error: Parameter minreso_leaf is out of bounds. Set to %i."%self.maxresoint_leaf)
220
+ if self.maxresoind_leaf<self.minresoind_leaf:
221
+ print("Error: Parameter maxreso_leaf is smaller than minreso_leaf. Set to %i."%self.minreso_leaf)
222
+
223
+ # Setup phi bins
224
+ for elp in range(self.order-2):
225
+ _ = np.linspace(0,2*np.pi,self.nbinsphi[elp]+1)
226
+ self.phis[elp] = .5*(_[1:] + _[:-1])
227
+ self.dphis[elp] = _[1:] - _[:-1]
228
+
229
+ #############################
230
+ ## Link compiled libraries ##
231
+ #############################
232
+ # Method that works for LP
233
+ target_path = __import__('orpheus').__file__
234
+ self.library_path = str(Path(__import__('orpheus').__file__).parent.absolute())
235
+ self.clib = ct.CDLL(glob.glob(self.library_path+"/orpheus_clib*.so")[0])
236
+
237
+ # In case the environment is weird, compile code manually and load it here...
238
+ #self.clib = ct.CDLL("/vol/euclidraid4/data/lporth/HigherOrderLensing/Estimator/orpheus/orpheus/src/discrete.so")
239
+
240
+ # Method that works for RR (but not for LP with a local HPC install)
241
+ #self.clib = ct.CDLL(search_file_in_site_package(get_site_packages_dir(),"orpheus_clib"))
242
+ #self.library_path = str(Path(__import__('orpheus').__file__).parent.parent.absolute())
243
+ #print(self.library_path)
244
+ #print(self.clib)
245
+ p_c128 = ndpointer(complex, flags="C_CONTIGUOUS")
246
+ p_f64 = ndpointer(np.float64, flags="C_CONTIGUOUS")
247
+ p_f32 = ndpointer(np.float32, flags="C_CONTIGUOUS")
248
+ p_i32 = ndpointer(np.int32, flags="C_CONTIGUOUS")
249
+ p_f64_nof = ndpointer(np.float64)
250
+
251
+ ## Second order scalar-scalar statistics ##
252
+ if self.order==2 and np.array_equal(self.spins, np.array([0, 0], dtype=np.int32)):
253
+ self.clib.alloc_nn_doubletree.restype = ct.c_void_p
254
+ self.clib.alloc_nn_doubletree.argtypes = [
255
+ ct.c_int32, ct.c_int32, p_f64, p_f64, p_f64,
256
+ ct.c_int32, ct.c_int32, ct.c_int32,
257
+ p_i32, ct.c_int32, p_f64, p_f64, p_f64, p_f64, p_i32,
258
+ p_i32, p_i32, p_i32,
259
+ ct.c_double, ct.c_double, ct.c_int32, ct.c_double, ct.c_double, ct.c_int32, ct.c_int32, p_i32,
260
+ ct.c_double, ct.c_double, ct.c_int32, ct.c_int32, ct.c_int32, ct.c_int32,
261
+ np.ctypeslib.ndpointer(dtype=np.float64),
262
+ np.ctypeslib.ndpointer(dtype=np.float64),
263
+ np.ctypeslib.ndpointer(dtype=np.int64)]
264
+
265
+ ## Second order shear-shear statistics ##
266
+ if self.order==2 and np.array_equal(self.spins, np.array([2, 2], dtype=np.int32)):
267
+ # Doubletree-based estimator of second-order shear correlation function
268
+ self.clib.alloc_xipm_doubletree.restype = ct.c_void_p
269
+ self.clib.alloc_xipm_doubletree.argtypes = [
270
+ ct.c_int32, ct.c_int32, p_f64, p_f64, p_f64,
271
+ ct.c_int32, ct.c_int32, ct.c_int32,
272
+ p_i32, ct.c_int32, p_f64, p_f64, p_f64, p_f64, p_f64, p_f64, p_i32,
273
+ p_i32, p_i32, p_i32,
274
+ ct.c_double, ct.c_double, ct.c_int32, ct.c_double, ct.c_double, ct.c_int32, ct.c_int32, p_i32,
275
+ ct.c_double, ct.c_double, ct.c_int32, ct.c_int32, ct.c_int32, ct.c_int32,
276
+ np.ctypeslib.ndpointer(dtype=np.float64),
277
+ np.ctypeslib.ndpointer(dtype=np.complex128),
278
+ np.ctypeslib.ndpointer(dtype=np.complex128),
279
+ np.ctypeslib.ndpointer(dtype=np.float64),
280
+ np.ctypeslib.ndpointer(dtype=np.int64)]
281
+
282
+ ## Third order shear-shear-shear statistics ##
283
+ if self.order==3 and np.array_equal(self.spins, np.array([2, 2, 2], dtype=np.int32)):
284
+ # Discrete estimator of third-order shear correlation function
285
+ self.clib.alloc_Gammans_discrete_ggg.restype = ct.c_void_p
286
+ self.clib.alloc_Gammans_discrete_ggg.argtypes = [
287
+ p_f64, p_f64, p_f64, p_f64, p_f64, p_f64, p_i32, ct.c_int32, ct.c_int32,
288
+ ct.c_int32, ct.c_int32, ct.c_double, ct.c_double, p_f64, ct.c_int32, ct.c_int32,
289
+ p_i32, p_i32, p_i32, ct.c_double, ct.c_double, ct.c_int32,
290
+ ct.c_double, ct.c_double, ct.c_int32, ct.c_int32, ct.c_int32,
291
+ np.ctypeslib.ndpointer(dtype=np.float64),
292
+ np.ctypeslib.ndpointer(dtype=np.complex128),
293
+ np.ctypeslib.ndpointer(dtype=np.complex128)]
294
+
295
+ # Tree-based estimator of third-order shear correlation function
296
+ self.clib.alloc_Gammans_tree_ggg.restype = ct.c_void_p
297
+ self.clib.alloc_Gammans_tree_ggg.argtypes = [
298
+ p_f64, p_f64, p_f64, p_f64, p_f64, p_f64, p_i32, ct.c_int32, ct.c_int32,
299
+ ct.c_int32, p_f64, p_i32,
300
+ p_f64, p_f64, p_f64, p_f64, p_f64, p_i32, p_f64,
301
+ p_i32, p_i32, p_i32, ct.c_double, ct.c_double, ct.c_int32, ct.c_double, ct.c_double, ct.c_int32,
302
+ ct.c_int32, ct.c_int32, ct.c_double, ct.c_double, p_f64, ct.c_int32, ct.c_int32, ct.c_int32, ct.c_int32,
303
+ np.ctypeslib.ndpointer(dtype=np.float64),
304
+ np.ctypeslib.ndpointer(dtype=np.complex128),
305
+ np.ctypeslib.ndpointer(dtype=np.complex128)]
306
+
307
+ # Basetree-based estimator of third-order shear correlation function
308
+ self.clib.alloc_Gammans_basetree_ggg.restype = ct.c_void_p
309
+ self.clib.alloc_Gammans_basetree_ggg.argtypes = [
310
+ ct.c_int32, ct.c_int32, p_f64, p_f64, p_f64, p_i32, ct.c_int32,
311
+ p_f64, p_f64, p_f64, p_f64, p_f64, p_f64, p_i32, p_f64,
312
+ p_i32, p_i32, p_i32,
313
+ ct.c_double, ct.c_double, ct.c_int32, ct.c_double, ct.c_double, ct.c_int32,
314
+ p_i32, ct.c_int32, p_i32, ct.c_int32,
315
+ ct.c_int32, ct.c_double, ct.c_double, ct.c_int32, ct.c_int32, ct.c_int32, ct.c_int32,
316
+ np.ctypeslib.ndpointer(dtype=np.float64),
317
+ np.ctypeslib.ndpointer(dtype=np.complex128),
318
+ np.ctypeslib.ndpointer(dtype=np.complex128)]
319
+
320
+ # Doubletree-based estimator of third-order shear correlation function
321
+ self.clib.alloc_Gammans_doubletree_ggg.restype = ct.c_void_p
322
+ self.clib.alloc_Gammans_doubletree_ggg.argtypes = [
323
+ ct.c_int32, ct.c_int32, p_f64, p_f64, p_f64,
324
+ ct.c_int32, ct.c_int32, ct.c_int32,
325
+ p_i32, ct.c_int32, p_f64, p_f64, p_f64, p_f64, p_f64, p_f64, p_i32, p_f64,
326
+ p_i32, p_i32, p_i32,
327
+ ct.c_double, ct.c_double, ct.c_int32, ct.c_double, ct.c_double, ct.c_int32,
328
+ p_i32, ct.c_int32, p_i32, ct.c_int32,
329
+ ct.c_int32, ct.c_double, ct.c_double, ct.c_int32, ct.c_int32, ct.c_int32, ct.c_int32,
330
+ np.ctypeslib.ndpointer(dtype=np.float64),
331
+ np.ctypeslib.ndpointer(dtype=np.complex128),
332
+ np.ctypeslib.ndpointer(dtype=np.complex128)]
333
+
334
+ # Conversion between 3pcf multipoles and 3pcf
335
+ self.clib.multipoles2npcf_ggg.restype = ct.c_void_p
336
+ self.clib.multipoles2npcf_ggg.argtypes = [
337
+ p_c128, p_c128, ct.c_int32, ct.c_int32,
338
+ p_f64, ct.c_int32, p_f64, ct.c_int32, ct.c_int32,
339
+ ct.c_int32,
340
+ np.ctypeslib.ndpointer(dtype=np.complex128),
341
+ np.ctypeslib.ndpointer(dtype=np.complex128)]
342
+
343
+ # Change projection of 3pcf between x and centroid
344
+ self.clib._x2centroid_ggg.restype = ct.c_void_p
345
+ self.clib._x2centroid_ggg.argtypes = [
346
+ p_c128, ct.c_int32,
347
+ p_f64, ct.c_int32, p_f64, ct.c_int32, ct.c_int32]
348
+
349
+ ## Third-order source-lens-lens statistics ##
350
+ if self.order==3 and np.array_equal(self.spins, np.array([2, 0, 0], dtype=np.int32)):
351
+ # Discrete estimator of third-order source-lens-lens (G3L) correlation function
352
+ self.clib.alloc_Gammans_discrete_GNN.restype = ct.c_void_p
353
+ self.clib.alloc_Gammans_discrete_GNN.argtypes = [
354
+ p_f64, p_f64, p_f64, p_f64, p_f64, p_f64, p_i32, ct.c_int32, ct.c_int32,
355
+ p_f64, p_f64, p_f64, p_i32, ct.c_int32, ct.c_int32,
356
+ ct.c_int32, ct.c_double, ct.c_double, ct.c_int32, ct.c_int32,
357
+ p_i32, p_i32, p_i32, p_i32, p_i32, p_i32, ct.c_int32,
358
+ ct.c_double, ct.c_double, ct.c_int32, ct.c_double, ct.c_double, ct.c_int32, ct.c_int32, ct.c_int32,
359
+ np.ctypeslib.ndpointer(dtype=np.float64),
360
+ np.ctypeslib.ndpointer(dtype=np.complex128),
361
+ np.ctypeslib.ndpointer(dtype=np.complex128)]
362
+
363
+ # Doubletree-based estimator of third-order source-lens-lens (G3L) correlation function
364
+ self.clib.alloc_Gammans_doubletree_GNN.restype = ct.c_void_p
365
+ self.clib.alloc_Gammans_doubletree_GNN.argtypes = [
366
+ ct.c_int32, ct.c_int32, p_f64, p_f64, p_f64,
367
+ ct.c_int32, ct.c_int32, ct.c_int32,
368
+ p_f64, p_f64, p_f64, p_f64, p_f64, p_f64, p_i32, p_i32, ct.c_int32,
369
+ p_f64, p_f64, p_f64, p_f64, p_i32, p_i32, ct.c_int32,
370
+ ct.c_int32, ct.c_double, ct.c_double, ct.c_int32, ct.c_int32,
371
+ p_i32, p_i32, p_i32, p_i32, p_i32, p_i32, p_i32, ct.c_int32,
372
+ ct.c_double, ct.c_double, ct.c_int32, ct.c_double, ct.c_double, ct.c_int32, ct.c_int32, ct.c_int32,
373
+ np.ctypeslib.ndpointer(dtype=np.float64),
374
+ np.ctypeslib.ndpointer(dtype=np.complex128),
375
+ np.ctypeslib.ndpointer(dtype=np.complex128)]
376
+
377
+ ## Third-order lens-source-source statistics ##
378
+ if self.order==3 and np.array_equal(self.spins, np.array([0, 2, 2], dtype=np.int32)):
379
+ # Discrete estimator of third-order lens-source-source correlation function
380
+ self.clib.alloc_Gammans_discrete_NGG.restype = ct.c_void_p
381
+ self.clib.alloc_Gammans_discrete_NGG.argtypes = [
382
+ p_f64, p_f64, p_f64, p_f64, p_f64, p_i32, ct.c_int32, ct.c_int32,
383
+ p_f64, p_f64, p_f64, p_f64, p_i32, ct.c_int32, ct.c_int32,
384
+ ct.c_int32, ct.c_double, ct.c_double, ct.c_int32, ct.c_int32,
385
+ p_i32, p_i32, p_i32, p_i32, p_i32, p_i32, ct.c_int32,
386
+ ct.c_double, ct.c_double, ct.c_int32, ct.c_double, ct.c_double, ct.c_int32, ct.c_int32, ct.c_int32,
387
+ np.ctypeslib.ndpointer(dtype=np.float64),
388
+ np.ctypeslib.ndpointer(dtype=np.complex128),
389
+ np.ctypeslib.ndpointer(dtype=np.complex128)]
390
+
391
+ self.clib.alloc_Gammans_tree_NGG.restype = ct.c_void_p
392
+ self.clib.alloc_Gammans_tree_NGG.argtypes = [
393
+ ct.c_int32, p_f64,
394
+ p_f64, p_f64, p_f64, p_f64, p_f64, p_i32, ct.c_int32, p_i32,
395
+ p_f64, p_f64, p_f64, p_f64, p_i32, ct.c_int32, ct.c_int32,
396
+ p_i32, p_i32, p_i32, p_i32, p_i32, p_i32, ct.c_int32,
397
+ ct.c_double, ct.c_double, ct.c_int32, ct.c_double, ct.c_double, ct.c_int32,
398
+ ct.c_int32, ct.c_double, ct.c_double, ct.c_int32, ct.c_int32, ct.c_int32, ct.c_int32,
399
+ np.ctypeslib.ndpointer(dtype=np.float64),
400
+ np.ctypeslib.ndpointer(dtype=np.complex128),
401
+ np.ctypeslib.ndpointer(dtype=np.complex128)]
402
+
403
+ self.clib.alloc_Gammans_doubletree_NGG.restype = ct.c_void_p
404
+ self.clib.alloc_Gammans_doubletree_NGG.argtypes = [
405
+ ct.c_int32, ct.c_int32, p_f64, p_f64, p_f64,
406
+ ct.c_int32, ct.c_int32, ct.c_int32,
407
+ p_f64, p_f64, p_f64, p_f64, p_f64, p_f64, p_i32, p_i32, ct.c_int32,
408
+ p_f64, p_f64, p_f64, p_f64, p_i32, p_i32, ct.c_int32,
409
+ ct.c_int32, ct.c_double, ct.c_double, ct.c_int32, ct.c_int32,
410
+ p_i32, p_i32, p_i32, p_i32, p_i32, p_i32, p_i32, ct.c_int32,
411
+ ct.c_double, ct.c_double, ct.c_int32, ct.c_double, ct.c_double, ct.c_int32, ct.c_int32, ct.c_int32,
412
+ np.ctypeslib.ndpointer(dtype=np.float64),
413
+ np.ctypeslib.ndpointer(dtype=np.complex128),
414
+ np.ctypeslib.ndpointer(dtype=np.complex128)]
415
+
416
+ ## Fourth-order counts-counts-counts-counts statistics ##
417
+ if self.order==4 and np.array_equal(self.spins, np.array([0, 0, 0, 0], dtype=np.int32)):
418
+
419
+ # Tree estimator of non-tomographic fourth-order counts correlation function
420
+ self.clib.alloc_notomoGammans_tree_nnnn.restype = ct.c_void_p
421
+ self.clib.alloc_notomoGammans_tree_nnnn.argtypes = [
422
+ p_f64, p_f64, p_f64, p_f64, ct.c_int32,
423
+ ct.c_int32, ct.c_double, ct.c_double, ct.c_int32, ct.c_int32, ct.c_int32,
424
+ p_i32, ct.c_int32,
425
+ ct.c_int32, p_f64, p_i32,
426
+ p_f64, p_f64, p_f64, p_f64,
427
+ p_i32, p_i32, p_i32, ct.c_int32,
428
+ ct.c_double, ct.c_double, ct.c_int32, ct.c_double, ct.c_double, ct.c_int32, ct.c_int32, ct.c_int32,
429
+ np.ctypeslib.ndpointer(dtype=np.float64),
430
+ np.ctypeslib.ndpointer(dtype=np.complex128)]
431
+
432
+ # Tree-based estimator of non-tomographic Map^4 statistics (low-mem)
433
+ self.clib.alloc_notomoNap4_tree_nnnn.restype = ct.c_void_p
434
+ self.clib.alloc_notomoNap4_tree_nnnn.argtypes = [
435
+ p_f64, p_f64, p_f64, p_f64, ct.c_int32,
436
+ ct.c_int32, ct.c_double, ct.c_double, ct.c_int32, ct.c_int32,
437
+ p_i32, ct.c_int32, p_f64, p_f64, ct.c_int32,
438
+ ct.c_int32, p_f64, p_i32,
439
+ p_f64, p_f64, p_f64, p_f64,
440
+ p_i32, p_i32, p_i32, ct.c_int32,
441
+ ct.c_double, ct.c_double, ct.c_int32, ct.c_double, ct.c_double, ct.c_int32,
442
+ p_i32, p_i32, p_i32, ct.c_int32,
443
+ ct.c_int32, p_f64, ct.c_int32, np.ctypeslib.ndpointer(dtype=np.complex128),
444
+ ct.c_int32, ct.c_int32,
445
+ np.ctypeslib.ndpointer(dtype=np.float64),
446
+ np.ctypeslib.ndpointer(dtype=np.complex128),np.ctypeslib.ndpointer(dtype=np.complex128)]
447
+
448
+ # Transformation between 4PCF from multipole-basis tp real-space basis for a fixed
449
+ # combination of radial bins
450
+ self.clib.multipoles2npcf_nnnn_singletheta.restype = ct.c_void_p
451
+ self.clib.multipoles2npcf_nnnn_singletheta.argtypes = [
452
+ p_c128, ct.c_int32, ct.c_int32,
453
+ ct.c_double, ct.c_double, ct.c_double,
454
+ p_f64, p_f64, ct.c_int32, ct.c_int32,
455
+ np.ctypeslib.ndpointer(dtype=np.complex128)]
456
+
457
+ ## Fourth-order galaxy-galaxy-galaxy-shear statistics ##
458
+ if self.order==4 and np.array_equal(self.spins, np.array([2, 0, 0, 0], dtype=np.int32)):
459
+
460
+ # Discrete estimator of non-tomographic GNNN statistics
461
+ self.clib.alloc_notomoGammans_discrete_gnnn.restype = ct.c_void_p
462
+ self.clib.alloc_notomoGammans_discrete_gnnn.argtypes = [
463
+ p_f64, p_f64, p_f64, p_f64, p_f64, p_f64, ct.c_int32,
464
+ p_f64, p_f64, p_f64, ct.c_int32,
465
+ p_i32, p_i32, p_i32, ct.c_int32,
466
+ ct.c_double, ct.c_double, ct.c_int32, ct.c_double, ct.c_double, ct.c_int32,
467
+ ct.c_int32, ct.c_double, ct.c_double, ct.c_int32, ct.c_int32,
468
+ ct.c_int32, np.ctypeslib.ndpointer(dtype=np.float64),
469
+ np.ctypeslib.ndpointer(dtype=np.complex128),np.ctypeslib.ndpointer(dtype=np.complex128)]
470
+
471
+ # Tree-based estimator of non-tomographic GNNN statistics
472
+ self.clib.alloc_notomoGammans_tree_gnnn.restype = ct.c_void_p
473
+ self.clib.alloc_notomoGammans_tree_gnnn.argtypes = [
474
+ ct.c_int32, p_f64,
475
+ p_f64, p_f64, p_f64, p_f64, p_f64, p_f64, ct.c_int32,
476
+ p_f64, p_f64, p_f64, p_i32,
477
+ p_i32, p_i32, p_i32, p_i32, p_i32, p_i32, ct.c_int32,
478
+ ct.c_double, ct.c_double, ct.c_int32, ct.c_double, ct.c_double, ct.c_int32,
479
+ ct.c_int32, ct.c_double, ct.c_double, ct.c_int32, ct.c_int32, ct.c_int32,
480
+ p_i32, ct.c_int32,
481
+ ct.c_int32, ct.c_int32, np.ctypeslib.ndpointer(dtype=np.float64),
482
+ np.ctypeslib.ndpointer(dtype=np.complex128),np.ctypeslib.ndpointer(dtype=np.complex128)]
483
+
484
+ # Tree-based estimator of non-tomographic MapNap^3 statistics (low-mem)
485
+ self.clib.alloc_notomoMapNap3_tree_gnnn.restype = ct.c_void_p
486
+ self.clib.alloc_notomoMapNap3_tree_gnnn.argtypes = [
487
+ ct.c_int32, p_f64,
488
+ p_f64, p_f64, p_f64, p_f64, p_f64, p_f64, ct.c_int32,
489
+ p_f64, p_f64, p_f64, p_i32,
490
+ p_i32, p_i32, p_i32, p_i32, p_i32, p_i32, ct.c_int32,
491
+ ct.c_double, ct.c_double, ct.c_int32, ct.c_double, ct.c_double, ct.c_int32,
492
+ ct.c_int32, ct.c_double, ct.c_double, ct.c_int32, ct.c_int32,
493
+ p_i32, ct.c_int32, p_f64, p_f64, ct.c_int32,
494
+ p_i32, p_i32, p_i32, ct.c_int32,
495
+ ct.c_int32, p_f64, ct.c_int32, np.ctypeslib.ndpointer(dtype=np.complex128),
496
+ ct.c_int32, ct.c_int32, np.ctypeslib.ndpointer(dtype=np.float64),
497
+ np.ctypeslib.ndpointer(dtype=np.complex128),np.ctypeslib.ndpointer(dtype=np.complex128),
498
+ np.ctypeslib.ndpointer(dtype=np.complex128),np.ctypeslib.ndpointer(dtype=np.complex128)]
499
+
500
+ # Transformaton between 4pcf multipoles and MN3 correlators of MapNap3 statistics
501
+ self.clib.fourpcfmultipoles2MN3correlators.restype = ct.c_void_p
502
+ self.clib.fourpcfmultipoles2MN3correlators.argtypes = [
503
+ ct.c_int32, ct.c_int32,
504
+ p_f64, p_f64, ct.c_int32,
505
+ p_f64, ct.c_int32,
506
+ p_f64, p_f64, p_f64, p_f64, ct.c_int32, ct.c_int32,
507
+ ct.c_int32, ct.c_int32,
508
+ p_c128, p_c128, np.ctypeslib.ndpointer(dtype=np.complex128)]
509
+
510
+ # Transformation between G4L from multipole-basis tp real-space basis for a fixed
511
+ # combination of radial bins
512
+ self.clib.multipoles2npcf_gnnn_singletheta.restype = ct.c_void_p
513
+ self.clib.multipoles2npcf_gnnn_singletheta.argtypes = [
514
+ p_c128, p_c128, ct.c_int32, ct.c_int32,
515
+ ct.c_double, ct.c_double, ct.c_double,
516
+ p_f64, p_f64, ct.c_int32, ct.c_int32,
517
+ np.ctypeslib.ndpointer(dtype=np.complex128),np.ctypeslib.ndpointer(dtype=np.complex128)]
518
+
519
+ self.clib.multipoles2npcf_gnnn_singletheta_nconvergence.restype = ct.c_void_p
520
+ self.clib.multipoles2npcf_gnnn_singletheta_nconvergence.argtypes = [
521
+ p_c128, p_c128, ct.c_int32, ct.c_int32,
522
+ ct.c_double, ct.c_double, ct.c_double,
523
+ p_f64, p_f64, ct.c_int32, ct.c_int32,
524
+ np.ctypeslib.ndpointer(dtype=np.complex128),np.ctypeslib.ndpointer(dtype=np.complex128)]
525
+
526
+ self.clib.alloc_notomoMapNap3_corrections.restype = ct.c_void_p
527
+ self.clib.alloc_notomoMapNap3_corrections.argtypes = [
528
+ p_f64, p_f64, ct.c_int32, p_f64, p_f64, ct.c_int32, ct.c_int32,
529
+ ct.c_int32, p_f64, ct.c_int32,
530
+ np.ctypeslib.ndpointer(dtype=np.float64),
531
+ np.ctypeslib.ndpointer(dtype=np.complex128),
532
+ ct.c_int32, ct.c_int32, np.ctypeslib.ndpointer(dtype=np.complex128)]
533
+
534
+ self.clib.alloc_notomoMapNap3_analytic.restype = ct.c_void_p
535
+ self.clib.alloc_notomoMapNap3_analytic.argtypes = [
536
+ ct.c_double, ct.c_double, ct.c_int32, p_f64, p_f64, ct.c_int32, ct.c_int32,
537
+ p_i32, p_i32, p_i32, ct.c_int32,
538
+ ct.c_int32, p_f64, ct.c_int32,
539
+ p_f64, p_f64, ct.c_double, ct.c_double, ct.c_int32, ct.c_int32,
540
+ np.ctypeslib.ndpointer(dtype=np.complex128)]
541
+
542
+ self.clib.gtilde4pcf_corrections.restype = ct.c_void_p
543
+ self.clib.gtilde4pcf_corrections.argtypes = [
544
+ ct.c_int32, ct.c_int32, ct.c_int32, ct.c_int32, p_f64, ct.c_int32, ct.c_int32,
545
+ ct.c_int32, ct.c_int32, p_f64, p_c128,
546
+ np.ctypeslib.ndpointer(dtype=np.complex128)]
547
+
548
+ self.clib.gtilde4pcf_analytic_integrated.restype = ct.c_void_p
549
+ self.clib.gtilde4pcf_analytic_integrated.argtypes = [
550
+ ct.c_int32, ct.c_int32, ct.c_int32, ct.c_int32, p_f64, ct.c_int32, p_f64, ct.c_int32,
551
+ p_f64, p_f64, ct.c_double, ct.c_double, ct.c_double,
552
+ np.ctypeslib.ndpointer(dtype=np.complex128)]
553
+
554
+ ## Fourth-order shear-shear-shear-shear statistics ##
555
+ if self.order==4 and np.array_equal(self.spins, np.array([2, 2, 2, 2], dtype=np.int32)):
556
+
557
+ # Discrete estimator of non-tomographic fourth-order shear correlation function
558
+ self.clib.alloc_notomoGammans_discrete_gggg.restype = ct.c_void_p
559
+ self.clib.alloc_notomoGammans_discrete_gggg.argtypes = [
560
+ p_f64, p_f64, p_f64, p_f64, p_f64, p_f64, ct.c_int32,
561
+ ct.c_int32, ct.c_double, ct.c_double, p_f64, ct.c_int32, ct.c_int32,
562
+ p_i32, p_i32, p_i32, ct.c_int32,
563
+ ct.c_double, ct.c_double, ct.c_int32, ct.c_double, ct.c_double, ct.c_int32, ct.c_int32, ct.c_int32,
564
+ np.ctypeslib.ndpointer(dtype=np.float64),
565
+ np.ctypeslib.ndpointer(dtype=np.complex128),
566
+ np.ctypeslib.ndpointer(dtype=np.complex128)]
567
+
568
+ # Tree estimator of non-tomographic fourth-order shear correlation function
569
+ self.clib.alloc_notomoGammans_tree_gggg.restype = ct.c_void_p
570
+ self.clib.alloc_notomoGammans_tree_gggg.argtypes = [
571
+ p_f64, p_f64, p_f64, p_f64, p_f64, p_f64, ct.c_int32,
572
+ ct.c_int32, ct.c_double, ct.c_double, ct.c_int32, ct.c_int32, ct.c_int32,
573
+ p_i32, ct.c_int32,
574
+ ct.c_int32, p_f64, p_i32,
575
+ p_f64, p_f64, p_f64, p_f64, p_f64, p_f64,
576
+ p_i32, p_i32, p_i32, ct.c_int32,
577
+ ct.c_double, ct.c_double, ct.c_int32, ct.c_double, ct.c_double, ct.c_int32, ct.c_int32, ct.c_int32,
578
+ np.ctypeslib.ndpointer(dtype=np.float64),
579
+ np.ctypeslib.ndpointer(dtype=np.complex128),
580
+ np.ctypeslib.ndpointer(dtype=np.complex128)]
581
+
582
+ # Discrete estimator of non-tomographic Map^4 statistics (low-mem)
583
+ self.clib.alloc_notomoMap4_disc_gggg.restype = ct.c_void_p
584
+ self.clib.alloc_notomoMap4_disc_gggg.argtypes = [
585
+ p_f64, p_f64, p_f64, p_f64, p_f64, p_f64, ct.c_int32,
586
+ ct.c_int32, ct.c_double, ct.c_double, ct.c_int32, ct.c_int32, p_f64, p_f64, ct.c_int32,
587
+ p_i32, p_i32, p_i32, ct.c_int32,
588
+ ct.c_double, ct.c_double, ct.c_int32, ct.c_double, ct.c_double, ct.c_int32,
589
+ p_i32, p_i32, p_i32, ct.c_int32,
590
+ ct.c_int32, ct.c_int32, ct.c_int32, p_f64, ct.c_int32, np.ctypeslib.ndpointer(dtype=np.complex128),
591
+ ct.c_int32, ct.c_int32, np.ctypeslib.ndpointer(dtype=np.float64),
592
+ np.ctypeslib.ndpointer(dtype=np.complex128),np.ctypeslib.ndpointer(dtype=np.complex128),
593
+ np.ctypeslib.ndpointer(dtype=np.complex128),np.ctypeslib.ndpointer(dtype=np.complex128)]
594
+
595
+ # Tree-based estimator of non-tomographic Map^4 statistics (low-mem)
596
+ self.clib.alloc_notomoMap4_tree_gggg.restype = ct.c_void_p
597
+ self.clib.alloc_notomoMap4_tree_gggg.argtypes = [
598
+ p_f64, p_f64, p_f64, p_f64, p_f64, p_f64, ct.c_int32,
599
+ ct.c_int32, ct.c_double, ct.c_double, ct.c_int32, ct.c_int32,
600
+ p_i32, ct.c_int32, p_f64, p_f64, ct.c_int32,
601
+ ct.c_int32, p_f64, p_i32,
602
+ p_f64, p_f64, p_f64, p_f64, p_f64, p_f64,
603
+ p_i32, p_i32, p_i32, ct.c_int32,
604
+ ct.c_double, ct.c_double, ct.c_int32, ct.c_double, ct.c_double, ct.c_int32,
605
+ p_i32, p_i32, p_i32, ct.c_int32,
606
+ ct.c_int32, ct.c_int32, ct.c_int32, p_f64, ct.c_int32, np.ctypeslib.ndpointer(dtype=np.complex128),
607
+ ct.c_int32, ct.c_int32, np.ctypeslib.ndpointer(dtype=np.float64),
608
+ np.ctypeslib.ndpointer(dtype=np.complex128),np.ctypeslib.ndpointer(dtype=np.complex128),
609
+ np.ctypeslib.ndpointer(dtype=np.complex128),np.ctypeslib.ndpointer(dtype=np.complex128)]
610
+
611
+ self.clib.multipoles2npcf_gggg.restype = ct.c_void_p
612
+ self.clib.multipoles2npcf_gggg.argtypes = [
613
+ p_c128, p_c128, p_f64, ct.c_int32,
614
+ ct.c_int32, ct.c_int32, ct.c_int32, p_f64, ct.c_int32, p_f64, ct.c_int32,
615
+ ct.c_int32, p_c128, p_c128]
616
+
617
+ # Transformation between 4PCF from multipole-basis tp real-space basis for a fixed
618
+ # combination of radial bins
619
+ self.clib.multipoles2npcf_gggg_singletheta.restype = ct.c_void_p
620
+ self.clib.multipoles2npcf_gggg_singletheta.argtypes = [
621
+ p_c128, p_c128, ct.c_int32, ct.c_int32,
622
+ ct.c_double, ct.c_double, ct.c_double,
623
+ p_f64, p_f64, ct.c_int32, ct.c_int32,
624
+ ct.c_int32,
625
+ np.ctypeslib.ndpointer(dtype=np.complex128),np.ctypeslib.ndpointer(dtype=np.complex128)]
626
+
627
+ # Transformation between 4PCF from multipole-basis tp real-space basis for a fixed
628
+ # combination of radial bins. Explicitly checks convergence for orders of multipoles included
629
+ self.clib.multipoles2npcf_gggg_singletheta_nconvergence.restype = ct.c_void_p
630
+ self.clib.multipoles2npcf_gggg_singletheta_nconvergence.argtypes = [
631
+ p_c128, p_c128, ct.c_int32, ct.c_int32,
632
+ ct.c_double, ct.c_double, ct.c_double,
633
+ p_f64, p_f64, ct.c_int32, ct.c_int32,
634
+ ct.c_int32,
635
+ np.ctypeslib.ndpointer(dtype=np.complex128),np.ctypeslib.ndpointer(dtype=np.complex128)]
636
+
637
+ # Reconstruction of all 4pcf multipoles from symmetry properties given a set of
638
+ # multipoles with theta1<=theta2<=theta3
639
+ self.clib.getMultipolesFromSymm.restype = ct.c_void_p
640
+ self.clib.getMultipolesFromSymm.argtypes = [
641
+ p_c128, p_c128,
642
+ ct.c_int32, ct.c_int32, p_i32, ct.c_int32,
643
+ np.ctypeslib.ndpointer(dtype=np.complex128),np.ctypeslib.ndpointer(dtype=np.complex128)]
644
+
645
+ # Transformaton between 4pcf multipoles and M4 correlators of Map4 statistics
646
+ self.clib.fourpcfmultipoles2M4correlators.restype = ct.c_void_p
647
+ self.clib.fourpcfmultipoles2M4correlators.argtypes = [
648
+ ct.c_int32, ct.c_int32,
649
+ p_f64, p_f64, ct.c_int32,
650
+ p_f64, ct.c_int32,
651
+ p_f64, p_f64, p_f64, p_f64, ct.c_int32, ct.c_int32,
652
+ ct.c_int32, ct.c_int32,
653
+ p_c128, p_c128, np.ctypeslib.ndpointer(dtype=np.complex128)]
654
+
655
+ # [DEBUG]: Shear 4pt function in terms of xip/xim
656
+ self.clib.gauss4pcf_analytic.restype = ct.c_void_p
657
+ self.clib.gauss4pcf_analytic.argtypes = [
658
+ ct.c_double, ct.c_double, ct.c_double, p_f64, ct.c_int32,
659
+ p_f64, p_f64, ct.c_double, ct.c_double, ct.c_double,
660
+ np.ctypeslib.ndpointer(dtype=np.complex128)]
661
+
662
+ # [DEBUG]: Shear 4pt function in terms of xip/xim, subsampled within the 4pcf bins
663
+ self.clib.gauss4pcf_analytic_integrated.restype = ct.c_void_p
664
+ self.clib.gauss4pcf_analytic_integrated.argtypes = [
665
+ ct.c_int32, ct.c_int32, ct.c_int32, ct.c_int32,
666
+ p_f64, ct.c_int32, p_f64, ct.c_int32,
667
+ p_f64, p_f64, ct.c_double, ct.c_double, ct.c_double,
668
+ np.ctypeslib.ndpointer(dtype=np.complex128)]
669
+
670
+ # [DEBUG]: Map4 via analytic gaussian 4pcf
671
+ self.clib.alloc_notomoMap4_analytic.restype = ct.c_void_p
672
+ self.clib.alloc_notomoMap4_analytic.argtypes = [
673
+ ct.c_double, ct.c_double, ct.c_int32, p_f64, p_f64, ct.c_int32, ct.c_int32,
674
+ p_i32, p_i32, p_i32, ct.c_int32,
675
+ ct.c_int32, p_f64, ct.c_int32,
676
+ p_f64, p_f64, ct.c_double, ct.c_double, ct.c_int32, ct.c_int32,
677
+ np.ctypeslib.ndpointer(dtype=np.complex128)]
678
+
679
+ # [DEBUG]: Map4 filter function for single combination
680
+ self.clib.filter_Map4.restype = ct.c_void_p
681
+ self.clib.filter_Map4.argtypes = [
682
+ ct.c_double, ct.c_double, ct.c_double, ct.c_double, ct.c_double,
683
+ np.ctypeslib.ndpointer(dtype=np.complex128)]
684
+
685
+ # [DEBUG]: Conversion between 4pcf and Map4 for (theta1,theta2,theta3) subset
686
+ self.clib.fourpcf2M4correlators_parallel.restype = ct.c_void_p
687
+ self.clib.fourpcf2M4correlators_parallel.argtypes = [
688
+ ct.c_int32,
689
+ ct.c_double, ct.c_double, ct.c_double, ct.c_double, ct.c_double, ct.c_double,
690
+ p_f64, p_f64, p_f64, p_f64, ct.c_int32, ct.c_int32,
691
+ ct.c_int32,
692
+ np.ctypeslib.ndpointer(dtype=np.complex128), np.ctypeslib.ndpointer(dtype=np.complex128)]
693
+
694
+ ############################################################
695
+ ## Functions that deal with different projections of NPCF ##
696
+ ############################################################
697
+ def _initprojections(self, child):
698
+ assert(child.projection in child.projections_avail)
699
+ child.project = {}
700
+ for proj in child.projections_avail:
701
+ child.project[proj] = {}
702
+ for proj2 in child.projections_avail:
703
+ if proj==proj2:
704
+ child.project[proj][proj2] = lambda: child.npcf
705
+ else:
706
+ child.project[proj][proj2] = None
707
+
708
+ def _projectnpcf(self, child, projection):
709
+ """
710
+ Projects npcf to a new basis.
711
+ """
712
+ assert(child.npcf is not None)
713
+ if projection not in child.projections_avail:
714
+ print(f"Projection {projection} is not yet supported.")
715
+ self._print_npcfprojections_avail()
716
+ return
717
+
718
+ projection_func = child.project[child.projection].get(projection)
719
+ if projection_func is not None:
720
+ child.npcf = projection_func()
721
+ child.projection = projection
722
+ else:
723
+ print(f"Projection from {child.projection} to {projection} is not yet implemented.")
724
+ self._print_npcfprojections_avail(child)
725
+
726
+ def _print_npcfprojections_avail(self, child):
727
+ print(f"The following projections are available in the class {child.__class__.__name__}:")
728
+ for proj in child.projections_avail:
729
+ for proj2 in child.projections_avail:
730
+ if child.project[proj].get(proj2) is not None:
731
+ print(f" {proj} --> {proj2}")
732
+
733
+ ####################
734
+ ## MISC FUNCTIONS ##
735
+ ####################
736
+ def _checkcats(self, cats, spins):
737
+ if isinstance(cats, list):
738
+ assert(len(cats)==self.order)
739
+ for els, s in enumerate(self.spins):
740
+ if not isinstance(cats, list):
741
+ thiscat = cats
742
+ else:
743
+ thiscat = cats[els]
744
+ assert(thiscat.spin == s)
745
+
746
+ def _updatetree(self, new_resos):
747
+
748
+ new_resos = np.asarray(new_resos, dtype=np.float64)
749
+ new_nresos = int(len(new_resos))
750
+
751
+ new_redges = np.zeros(len(new_resos)+1)
752
+ new_redges[0] = self.min_sep
753
+ new_redges[-1] = self.max_sep
754
+ for elreso, reso in enumerate(new_resos[1:]):
755
+ new_redges[elreso+1] = self.rmin_pixsize*reso
756
+ _tmpreso = 0
757
+ new_resosatr = np.zeros(self.nbinsr, dtype=np.int32)
758
+ for elbin, rbin in enumerate(self.bin_edges[:-1]):
759
+ if rbin > new_redges[_tmpreso+1]:
760
+ _tmpreso += 1
761
+ new_resosatr[elbin] = _tmpreso
762
+
763
+ self.tree_resos = new_resos
764
+ self.tree_nresos = new_nresos
765
+ self.tree_redges = new_redges
766
+ self.tree_resosatr = new_resosatr