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/__init__.py +9 -0
- orpheus/catalog.py +1216 -0
- orpheus/covariance.py +153 -0
- orpheus/direct.py +1091 -0
- orpheus/flat2dgrid.py +68 -0
- orpheus/npcf_base.py +766 -0
- orpheus/npcf_fourth.py +1716 -0
- orpheus/npcf_second.py +620 -0
- orpheus/npcf_third.py +1684 -0
- orpheus/orpheus_clib.cpython-310-x86_64-linux-gnu.so +0 -0
- orpheus/patchutils.py +369 -0
- orpheus/utils.py +198 -0
- orpheus_npcf-0.2.1.dist-info/METADATA +67 -0
- orpheus_npcf-0.2.1.dist-info/RECORD +19 -0
- orpheus_npcf-0.2.1.dist-info/WHEEL +5 -0
- orpheus_npcf-0.2.1.dist-info/licenses/LICENSE +674 -0
- orpheus_npcf-0.2.1.dist-info/sboms/auditwheel.cdx.json +1 -0
- orpheus_npcf-0.2.1.dist-info/top_level.txt +1 -0
- orpheus_npcf.libs/libgomp-8949ffbe.so.1.0.0 +0 -0
orpheus/catalog.py
ADDED
|
@@ -0,0 +1,1216 @@
|
|
|
1
|
+
# TODO Reactivate gridded catalog instances?
|
|
2
|
+
|
|
3
|
+
import ctypes as ct
|
|
4
|
+
import numpy as np
|
|
5
|
+
from numpy.ctypeslib import ndpointer
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
import glob
|
|
8
|
+
from .utils import get_site_packages_dir, search_file_in_site_package, convertunits
|
|
9
|
+
from .flat2dgrid import FlatPixelGrid_2D, FlatDataGrid_2D
|
|
10
|
+
from .patchutils import gen_cat_patchindices, frompatchindices_preparerot
|
|
11
|
+
import sys
|
|
12
|
+
import time
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
__all__ = ["Catalog", "ScalarTracerCatalog", "SpinTracerCatalog"]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
##############################################
|
|
19
|
+
## Classes that deal with discrete catalogs ##
|
|
20
|
+
##############################################
|
|
21
|
+
class Catalog:
|
|
22
|
+
|
|
23
|
+
r"""Class containing variables and methods of a catalog of tracers.
|
|
24
|
+
Attributes
|
|
25
|
+
----------
|
|
26
|
+
pos1: numpy.ndarray
|
|
27
|
+
The :math:`x`-positions of the tracer objects
|
|
28
|
+
pos2: numpy.ndarray
|
|
29
|
+
The :math:`y`-positions of the tracer objects
|
|
30
|
+
weight: numpy.ndarray, optional, defaults to ``None``
|
|
31
|
+
The weights of the tracer objects. If set to ``None`` all weights are assumed to be unity.
|
|
32
|
+
zbins: numpy.ndarray, optional, defaults to ``None``
|
|
33
|
+
The tomographic redshift bins of the tracer objects. If set to ``None`` all zbins are assumed to be zero.
|
|
34
|
+
nbinsz: int
|
|
35
|
+
The number of tomographic bins
|
|
36
|
+
isinner: numpy.ndarray
|
|
37
|
+
A flag signaling wheter a tracer is within the interior part of the footprint
|
|
38
|
+
units_pos1: string, defaults to ``None``
|
|
39
|
+
The unit of the :math:`x`-positions, should be in [None, 'rad', 'deg', 'arcmin'].
|
|
40
|
+
For non-spherical catalogs we auto-set this to None. Spherical catalogs are internally transformed to units of degrees.
|
|
41
|
+
units_pos2: string, defaults to ``None``
|
|
42
|
+
The unit of the :math:`y`-positions, should be in [None, 'rad', 'deg', 'arcmin'].
|
|
43
|
+
For non-spherical catalogs we auto-set this to None. Spherical catalogs are internally transformed to units of degrees.
|
|
44
|
+
geometry: string, defualts to ``'flat2d'``
|
|
45
|
+
Specifies the topology of the space the points are located in. Should be in ['flat2d', 'spherical'].
|
|
46
|
+
min1: float
|
|
47
|
+
The smallest :math:`x`-value appearing in the catalog
|
|
48
|
+
max1: float
|
|
49
|
+
The largest :math:`x`-value appearing in the catalog
|
|
50
|
+
min2: float
|
|
51
|
+
The smallest :math:`y`-value appearing in the catalog
|
|
52
|
+
max2: float
|
|
53
|
+
The largest :math:`y`-value appearing in the catalog
|
|
54
|
+
len1: float
|
|
55
|
+
The extent of the catalog in :math:`x`-direction.
|
|
56
|
+
len2: float
|
|
57
|
+
The extent of the catalog in :math:`y`-direction.
|
|
58
|
+
hasspatialhash: bool
|
|
59
|
+
Flag on wheter a spatial hash structure has been allocated for the catalog
|
|
60
|
+
index_matcher: numpy.ndarray
|
|
61
|
+
Indicates on whether there is a tracer in each of the pixels in the spatial hash.
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
.. note::
|
|
65
|
+
|
|
66
|
+
The ``zbins`` parameter can also be used for other characteristics of the tracers (i.e. color cuts).
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
def __init__(self, pos1, pos2, weight=None, zbins=None, isinner=None,
|
|
70
|
+
units_pos1=None, units_pos2=None, geometry='flat2d',
|
|
71
|
+
mask=None, zbins_mean=None, zbins_std=None):
|
|
72
|
+
|
|
73
|
+
self.pos1 = pos1.astype(np.float64)
|
|
74
|
+
self.pos2 = pos2.astype(np.float64)
|
|
75
|
+
self.weight = weight
|
|
76
|
+
self.zbins = zbins
|
|
77
|
+
self.ngal = len(self.pos1)
|
|
78
|
+
# Allocate weights
|
|
79
|
+
if self.weight is None:
|
|
80
|
+
self.weight = np.ones(self.ngal)
|
|
81
|
+
self.weight = self.weight.astype(np.float64)
|
|
82
|
+
#self.weight /= np.mean(self.weight)
|
|
83
|
+
# Require zbins to only contain elements in {0, 1, ..., nbinsz-1}
|
|
84
|
+
if self.zbins is None:
|
|
85
|
+
self.zbins = np.zeros(self.ngal)
|
|
86
|
+
self.zbins = self.zbins.astype(np.int32)
|
|
87
|
+
self.nbinsz = len(np.unique(self.zbins))
|
|
88
|
+
assert(np.max(self.zbins)-np.min(self.zbins)==self.nbinsz-1)
|
|
89
|
+
self.zbins -= (np.min( self.zbins))
|
|
90
|
+
if isinner is None:
|
|
91
|
+
isinner = np.ones(self.ngal, dtype=np.float64)
|
|
92
|
+
self.isinner = np.asarray(isinner, dtype=np.float64)
|
|
93
|
+
self.units_pos1 = units_pos1
|
|
94
|
+
self.units_pos2 = units_pos2
|
|
95
|
+
self.geometry = geometry
|
|
96
|
+
assert(self.geometry in ['flat2d','spherical'])
|
|
97
|
+
if self.geometry == 'flat2d':
|
|
98
|
+
self.units_pos1 = None
|
|
99
|
+
self.units_pos2 = None
|
|
100
|
+
if self.geometry == 'spherical':
|
|
101
|
+
assert(self.units_pos1 in ['rad', 'deg', 'arcmin'])
|
|
102
|
+
assert(self.units_pos2 in ['rad', 'deg', 'arcmin'])
|
|
103
|
+
self.pos1 *= convertunits(self.units_pos1, 'deg')
|
|
104
|
+
self.pos2 *= convertunits(self.units_pos2, 'deg')
|
|
105
|
+
self.units_pos1 = 'deg'
|
|
106
|
+
self.units_pos2 = 'deg'
|
|
107
|
+
# Make sure that footprint is contiguous
|
|
108
|
+
# 1) Compute internal distance between tracers
|
|
109
|
+
# 2) Compute distance around the origin
|
|
110
|
+
# 3) If largest distance is internal, i.e. catalog not contiguous
|
|
111
|
+
# split catalog at this boundary and shift one side by 360 deg
|
|
112
|
+
# Note that this algorithm only works for truly contiguous fields,
|
|
113
|
+
# but might fail for catalogues consisting of multiple disconnected
|
|
114
|
+
# (yet contiguous) patches covering the whole range of ra...
|
|
115
|
+
ra_sorted = np.sort(self.pos1)
|
|
116
|
+
diffs = np.diff(ra_sorted)
|
|
117
|
+
wrap_diff = (360.0 - ra_sorted[-1]) + ra_sorted[0]
|
|
118
|
+
if wrap_diff <= np.max(diffs):
|
|
119
|
+
max_gap_idx = np.argmax(diffs)
|
|
120
|
+
split_value = ra_sorted[max_gap_idx]
|
|
121
|
+
self.pos1[self.pos1 > split_value] -= 360
|
|
122
|
+
print('NOTE: Catalog not contiguous, shifted RA coordinates > %.2f deg by -360 deg.'%split_value)
|
|
123
|
+
|
|
124
|
+
self.mask = mask
|
|
125
|
+
assert(isinstance(self.mask, FlatDataGrid_2D) or self.mask is None)
|
|
126
|
+
if isinstance(self.mask, FlatDataGrid_2D):
|
|
127
|
+
self.__checkmask()
|
|
128
|
+
assert(np.min(self.isinner) >= 0.)
|
|
129
|
+
assert(np.max(self.isinner) <= 1.)
|
|
130
|
+
assert(len(self.isinner)==self.ngal)
|
|
131
|
+
assert(len(self.pos2)==self.ngal)
|
|
132
|
+
assert(len(self.weight)==self.ngal)
|
|
133
|
+
assert(len(self.zbins)==self.ngal)
|
|
134
|
+
assert(np.min(self.weight)>0.)
|
|
135
|
+
|
|
136
|
+
self.zbins_mean = zbins_mean
|
|
137
|
+
self.zbins_std = zbins_std
|
|
138
|
+
for _ in [self.zbins_mean, self.zbins_mean]:
|
|
139
|
+
if _ is not None:
|
|
140
|
+
assert(isinstance(_,np.ndarray))
|
|
141
|
+
assert(len(_)==self.nbinsz)
|
|
142
|
+
|
|
143
|
+
self.min1 = np.min(self.pos1)
|
|
144
|
+
self.min2 = np.min(self.pos2)
|
|
145
|
+
self.max1 = np.max(self.pos1)
|
|
146
|
+
self.max2 = np.max(self.pos2)
|
|
147
|
+
self.len1 = self.max1-self.min1
|
|
148
|
+
self.len2 = self.max2-self.min2
|
|
149
|
+
|
|
150
|
+
self.spatialhash = None # Check whether needed not in docs
|
|
151
|
+
self.hasspatialhash = False
|
|
152
|
+
self.index_matcher = None
|
|
153
|
+
self.pixs_galind_bounds = None
|
|
154
|
+
self.pix_gals = None
|
|
155
|
+
self.pix1_start = None
|
|
156
|
+
self.pix1_d = None
|
|
157
|
+
self.pix1_n = None
|
|
158
|
+
self.pix2_start = None
|
|
159
|
+
self.pix2_d = None
|
|
160
|
+
self.pix2_n = None
|
|
161
|
+
|
|
162
|
+
self.patchinds = None
|
|
163
|
+
|
|
164
|
+
self.assign_methods = {"NGP":0, "CIC":1, "TSC":2}
|
|
165
|
+
|
|
166
|
+
## Link compiled libraries ##
|
|
167
|
+
# Method that works for LP
|
|
168
|
+
target_path = __import__('orpheus').__file__
|
|
169
|
+
self.library_path = str(Path(__import__('orpheus').__file__).parent.absolute())
|
|
170
|
+
self.clib = ct.CDLL(glob.glob(self.library_path+"/orpheus_clib*.so")[0])
|
|
171
|
+
# Method that works for RR (but not for LP with a local HPC install)
|
|
172
|
+
#self.clib = ct.CDLL(search_file_in_site_package(get_site_packages_dir(),"orpheus_clib"))
|
|
173
|
+
#self.library_path = str(Path(__import__('orpheus').__file__).parent.parent.absolute())
|
|
174
|
+
#print(self.library_path)
|
|
175
|
+
#self.clib = ct.CDLL(glob.glob(self.library_path+"/orpheus_clib*.so")[0])
|
|
176
|
+
#self.library_path = str(Path(__file__).parent.absolute()) + "/src/"
|
|
177
|
+
#self.clib = ct.CDLL(self.library_path + "clibrary.so")
|
|
178
|
+
p_c128 = ndpointer(np.complex128, flags="C_CONTIGUOUS")
|
|
179
|
+
p_f64 = ndpointer(np.float64, flags="C_CONTIGUOUS")
|
|
180
|
+
p_f32 = ndpointer(np.float32, flags="C_CONTIGUOUS")
|
|
181
|
+
p_i32 = ndpointer(np.int32, flags="C_CONTIGUOUS")
|
|
182
|
+
p_f64_nof = ndpointer(np.float64)
|
|
183
|
+
|
|
184
|
+
# Assigns a set of tomographic fields over a grid
|
|
185
|
+
# Safely called within 'togrid' function
|
|
186
|
+
self.clib.assign_fields.restype = ct.c_void_p
|
|
187
|
+
self.clib.assign_fields.argtypes = [
|
|
188
|
+
p_f64, p_f64, p_i32, p_f64, p_f64, ct.c_int32, ct.c_int32, ct.c_int32,
|
|
189
|
+
ct.c_int32, ct.c_double, ct.c_double, ct.c_double, ct.c_int32, ct.c_int32,
|
|
190
|
+
ct.c_int32, np.ctypeslib.ndpointer(dtype=np.float64)]
|
|
191
|
+
|
|
192
|
+
# Assigns a set of tomographic fields over a grid
|
|
193
|
+
# Safely called within 'togrid' function
|
|
194
|
+
self.clib.gen_weightgrid2d.restype = ct.c_void_p
|
|
195
|
+
self.clib.gen_weightgrid2d.argtypes = [
|
|
196
|
+
p_f64, p_f64, ct.c_int32, ct.c_int32,
|
|
197
|
+
ct.c_double, ct.c_double, ct.c_double, ct.c_int32, ct.c_int32, ct.c_int32,
|
|
198
|
+
np.ctypeslib.ndpointer(dtype=np.int32),
|
|
199
|
+
np.ctypeslib.ndpointer(dtype=np.float64)]
|
|
200
|
+
|
|
201
|
+
# Generate pixel --> galaxy mapping
|
|
202
|
+
# Safely called within other wrapped functions
|
|
203
|
+
self.clib.build_spatialhash.restype = ct.c_void_p
|
|
204
|
+
self.clib.build_spatialhash.argtypes = [
|
|
205
|
+
p_f64, p_f64, ct.c_int32, ct.c_double, ct.c_double, ct.c_double, ct.c_double,
|
|
206
|
+
ct.c_int32, ct.c_int32,
|
|
207
|
+
np.ctypeslib.ndpointer(dtype=np.int32)]
|
|
208
|
+
|
|
209
|
+
self.clib.reducecat.restype = ct.c_void_p
|
|
210
|
+
self.clib.reducecat.argtypes = [
|
|
211
|
+
p_f64, p_f64, p_f64, p_f64, p_f64, ct.c_int32, ct.c_int32, ct.c_int32,
|
|
212
|
+
ct.c_double, ct.c_double, ct.c_double, ct.c_double, ct.c_int32, ct.c_int32, ct.c_int32,
|
|
213
|
+
p_f64_nof, p_f64_nof, p_f64_nof, p_f64_nof, p_f64_nof,ct.c_int32]
|
|
214
|
+
|
|
215
|
+
def topatches(self, npatches=None, area_patch_deg2_target=None, patchextend_deg=2.,other_cats=None,
|
|
216
|
+
nside_hash=128, verbose=False, method='kmeans_healpix',
|
|
217
|
+
kmeanshp_maxiter=1000, kmeanshp_tol=1e-10, kmeanshp_randomstate=42,healpix_nside=8):
|
|
218
|
+
r""" Decomposes a full-sky catalog into patches.
|
|
219
|
+
"""
|
|
220
|
+
|
|
221
|
+
# We are only dealing with a single catalog
|
|
222
|
+
if other_cats is None:
|
|
223
|
+
assert(self.geometry in ['spherical'])
|
|
224
|
+
self.patchinds = gen_cat_patchindices(ra_deg=self.pos1,
|
|
225
|
+
dec_deg=self.pos2,
|
|
226
|
+
npatches=npatches,
|
|
227
|
+
patchextend_arcmin=patchextend_deg*60.,
|
|
228
|
+
nside_hash=nside_hash,
|
|
229
|
+
verbose=verbose,
|
|
230
|
+
method=method,
|
|
231
|
+
kmeanshp_maxiter=kmeanshp_maxiter,
|
|
232
|
+
kmeanshp_tol=kmeanshp_tol,
|
|
233
|
+
kmeanshp_randomstate=kmeanshp_randomstate,
|
|
234
|
+
healpix_nside=healpix_nside
|
|
235
|
+
)
|
|
236
|
+
if method=='healpix':
|
|
237
|
+
self.npatches = 12*healpix_nside*healpix_nside
|
|
238
|
+
else:
|
|
239
|
+
self.npatches = npatches
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
# We want to create equivalent patches for multiple catalogs
|
|
243
|
+
else:
|
|
244
|
+
# Make sure that each catalog is a child of Catalog and has the same geometry
|
|
245
|
+
# As each spherical catalog per definition has ra/dec in units of degrees, this is sufficient.
|
|
246
|
+
ntracer_tot = self.ngal
|
|
247
|
+
cumngals = np.zeros(2+len(other_cats),dtype=int)
|
|
248
|
+
cumngals[1] = self.ngal
|
|
249
|
+
for elcat, cat in enumerate(other_cats):
|
|
250
|
+
if not isinstance(cat, Catalog):
|
|
251
|
+
raise ValueError('Each catalog should be inherited from orpheus.Catalog class.')
|
|
252
|
+
if not cat.geometry=='spherical':
|
|
253
|
+
raise ValueError('Patch decomposition only available for spherical catlogs')
|
|
254
|
+
ntracer_tot += cat.ngal
|
|
255
|
+
cumngals[elcat+2] = ntracer_tot
|
|
256
|
+
|
|
257
|
+
# Build a joint catalog collecting all positions of the different catalogs
|
|
258
|
+
jointpos1 = np.zeros(ntracer_tot)
|
|
259
|
+
jointpos2 = np.zeros(ntracer_tot)
|
|
260
|
+
jointweight = np.zeros(ntracer_tot)
|
|
261
|
+
jointpos1[:cumngals[1]] += self.pos1
|
|
262
|
+
jointpos2[:cumngals[1]] += self.pos2
|
|
263
|
+
jointweight[:cumngals[1]] += self.weight
|
|
264
|
+
for elcat, cat in enumerate(other_cats):
|
|
265
|
+
jointpos1[cumngals[elcat+1]:cumngals[elcat+2]] += cat.pos1
|
|
266
|
+
jointpos2[cumngals[elcat+1]:cumngals[elcat+2]] += cat.pos2
|
|
267
|
+
jointweight[cumngals[elcat+1]:cumngals[elcat+2]] += cat.weight
|
|
268
|
+
jointcat = Catalog(pos1=jointpos1, pos2=jointpos2, weight=jointweight,
|
|
269
|
+
geometry='spherical', units_pos1='deg', units_pos2='deg')
|
|
270
|
+
|
|
271
|
+
# Build patches of joint catalog
|
|
272
|
+
jointcat.topatches(npatches=npatches,
|
|
273
|
+
patchextend_deg=patchextend_deg,
|
|
274
|
+
other_cats=None,
|
|
275
|
+
nside_hash=nside_hash,
|
|
276
|
+
verbose=verbose,
|
|
277
|
+
method=method,
|
|
278
|
+
kmeanshp_maxiter=kmeanshp_maxiter,
|
|
279
|
+
kmeanshp_tol=kmeanshp_tol,
|
|
280
|
+
kmeanshp_randomstate=kmeanshp_randomstate)
|
|
281
|
+
|
|
282
|
+
# Distribute the patchindices of the joint catalog to the individual instances
|
|
283
|
+
self.patchinds = {}
|
|
284
|
+
self.patchinds['info'] = {}
|
|
285
|
+
self.patchinds['info']['patchextend_deg'] = jointcat.patchinds['info']['patchextend_deg']
|
|
286
|
+
self.patchinds['info']['nside_hash'] = jointcat.patchinds['info']['nside_hash']
|
|
287
|
+
self.patchinds['info']['method'] = jointcat.patchinds['info']['method']
|
|
288
|
+
self.patchinds['info']['kmeanshp_maxiter'] = jointcat.patchinds['info']['kmeanshp_maxiter']
|
|
289
|
+
self.patchinds['info']['kmeanshp_tol'] = jointcat.patchinds['info']['kmeanshp_tol']
|
|
290
|
+
self.patchinds['info']['kmeanshp_randomstate'] = jointcat.patchinds['info']['kmeanshp_randomstate']
|
|
291
|
+
self.patchinds['info']['healpix_nside'] = jointcat.patchinds['info']['healpix_nside']
|
|
292
|
+
self.patchinds['info']['patchcenters'] = jointcat.patchinds['info']['patchcenters']
|
|
293
|
+
self.patchinds['info']['patchareas'] = jointcat.patchinds['info']['patchareas']
|
|
294
|
+
self.patchinds['info']['patch_ngalsinner'] = np.zeros(jointcat.npatches)
|
|
295
|
+
self.patchinds['info']['patch_ngalsouter'] = np.zeros(jointcat.npatches)
|
|
296
|
+
self.patchinds['patches'] = {}
|
|
297
|
+
for elp in range(jointcat.npatches):
|
|
298
|
+
_inds = jointcat.patchinds['patches'][elp]
|
|
299
|
+
seli = (_inds['inner']>=cumngals[0])*(_inds['inner']<cumngals[1])
|
|
300
|
+
selo = (_inds['outer']>=cumngals[0])*(_inds['outer']<cumngals[1])
|
|
301
|
+
self.patchinds['info']['patch_ngalsinner'][elp] = np.sum(seli)
|
|
302
|
+
self.patchinds['info']['patch_ngalsouter'][elp] = np.sum(selo)
|
|
303
|
+
self.patchinds['patches'][elp] = {}
|
|
304
|
+
self.patchinds['patches'][elp]['inner'] = _inds['inner'][seli]
|
|
305
|
+
self.patchinds['patches'][elp]['outer'] = _inds['outer'][selo]
|
|
306
|
+
for elcat, cat in enumerate(other_cats):
|
|
307
|
+
cat.patchinds = {}
|
|
308
|
+
cat.patchinds['info'] = {}
|
|
309
|
+
cat.patchinds['info']['patchextend_deg'] = jointcat.patchinds['info']['patchextend_deg']
|
|
310
|
+
cat.patchinds['info']['nside_hash'] = jointcat.patchinds['info']['nside_hash']
|
|
311
|
+
cat.patchinds['info']['method'] = jointcat.patchinds['info']['method']
|
|
312
|
+
cat.patchinds['info']['kmeanshp_maxiter'] = jointcat.patchinds['info']['kmeanshp_maxiter']
|
|
313
|
+
cat.patchinds['info']['kmeanshp_tol'] = jointcat.patchinds['info']['kmeanshp_tol']
|
|
314
|
+
cat.patchinds['info']['kmeanshp_randomstate'] = jointcat.patchinds['info']['kmeanshp_randomstate']
|
|
315
|
+
cat.patchinds['info']['healpix_nside'] = jointcat.patchinds['info']['healpix_nside']
|
|
316
|
+
cat.patchinds['info']['patchcenters'] = jointcat.patchinds['info']['patchcenters']
|
|
317
|
+
cat.patchinds['info']['patchareas'] = jointcat.patchinds['info']['patchareas']
|
|
318
|
+
cat.patchinds['info']['patch_ngalsinner'] = np.zeros(jointcat.npatches)
|
|
319
|
+
cat.patchinds['info']['patch_ngalsouter'] = np.zeros(jointcat.npatches)
|
|
320
|
+
cat.patchinds['patches'] = {}
|
|
321
|
+
for elp in range(jointcat.npatches):
|
|
322
|
+
_inds = jointcat.patchinds['patches'][elp]
|
|
323
|
+
seli = (_inds['inner']>=cumngals[elcat+1])*(_inds['inner']<cumngals[elcat+2])
|
|
324
|
+
selo = (_inds['outer']>=cumngals[elcat+1])*(_inds['outer']<cumngals[elcat+2])
|
|
325
|
+
cat.patchinds['info']['patch_ngalsinner'][elp] = np.sum(seli)
|
|
326
|
+
cat.patchinds['info']['patch_ngalsouter'][elp] = np.sum(selo)
|
|
327
|
+
cat.patchinds['patches'][elp] = {}
|
|
328
|
+
cat.patchinds['patches'][elp]['inner'] = _inds['inner'][seli]-cumngals[elcat+1]
|
|
329
|
+
cat.patchinds['patches'][elp]['outer'] = _inds['outer'][selo]-cumngals[elcat+1]
|
|
330
|
+
|
|
331
|
+
# Finalize setting attributes for all instances
|
|
332
|
+
self.npatches = npatches
|
|
333
|
+
for cat in other_cats:
|
|
334
|
+
cat.npatches = npatches
|
|
335
|
+
|
|
336
|
+
def _patchind_preparerot(self, index, rotsignflip=False):
|
|
337
|
+
|
|
338
|
+
assert(self.patchinds is not None)
|
|
339
|
+
assert(self.geometry in ['spherical'])
|
|
340
|
+
|
|
341
|
+
return frompatchindices_preparerot(index, self.patchinds, self.pos1, self.pos2, rotsignflip)
|
|
342
|
+
|
|
343
|
+
# Reduces catalog to smaller catalog where positions & quantities are
|
|
344
|
+
# averaged over regular grid
|
|
345
|
+
def _reduce(self, fields, dpix, dpix2=None, relative_to_hash=None, normed=True, shuffle=0,
|
|
346
|
+
extent=[None,None,None,None], forcedivide=1,
|
|
347
|
+
ret_inst=False):
|
|
348
|
+
r"""Paints a catalog onto a grid with equal-area cells
|
|
349
|
+
|
|
350
|
+
Parameters
|
|
351
|
+
----------
|
|
352
|
+
fields: list
|
|
353
|
+
The fields to be painted to the grid. Each field is given as a 1D array of float.
|
|
354
|
+
dpix: float
|
|
355
|
+
The sidelength of a grid cell.
|
|
356
|
+
dpix2: float, optional
|
|
357
|
+
The sidelength of a grid cell in :math:`y`-direction. Defaults to ``None``.
|
|
358
|
+
If set to ``None`` the pixels are assumed to be squares.
|
|
359
|
+
relative_to_hash: int, optional
|
|
360
|
+
Forces the cell size to be an integer multiple of the cell size of the spatial hash.
|
|
361
|
+
Defaults to ``None``. If set to ``None`` the pixelsize is unrelated to the cell
|
|
362
|
+
size of the spatial hash.
|
|
363
|
+
normed: bool, optional
|
|
364
|
+
Decide on whether to average or to sum the field over pixels. Defaults to ``True``.
|
|
365
|
+
shuffle: int, optional
|
|
366
|
+
Choose a definition on how to set the central point of each pixel. Defaults to zero.
|
|
367
|
+
extent: list, optional
|
|
368
|
+
Sets custom boundaries ``[xmin, xmax, ymin, ymax]`` for the grid. Each element defaults
|
|
369
|
+
to ``None``. Each element equal to ``None`` sets the grid boundary as the smallest value
|
|
370
|
+
fully containing the discrete field tracers.
|
|
371
|
+
forcedivide: int, optional
|
|
372
|
+
Forces the number of cells in each dimensions to be divisible by some number.
|
|
373
|
+
Defaults to ``1``.
|
|
374
|
+
ret_inst: bool, optional
|
|
375
|
+
Decides on wheter to return the output as a list of arrays containing the reduced catalog or
|
|
376
|
+
on returning a new ``Catalog`` instance. Defaults to ``False``.
|
|
377
|
+
"""
|
|
378
|
+
|
|
379
|
+
# Initialize grid
|
|
380
|
+
if relative_to_hash is None:
|
|
381
|
+
if dpix2 is None:
|
|
382
|
+
dpix2 = dpix
|
|
383
|
+
start1, start2, n1, n2 = self._gengridprops(dpix, dpix2, forcedivide, extent)
|
|
384
|
+
else:
|
|
385
|
+
assert(self.hasspatialhash)
|
|
386
|
+
assert(isinstance(relative_to_hash,np.int32))
|
|
387
|
+
start1 = self.pix1_start
|
|
388
|
+
start2 = self.pix2_start
|
|
389
|
+
dpix = self.pix1_d/np.float64(relative_to_hash)
|
|
390
|
+
dpix2 = self.pix2_d/np.float64(relative_to_hash)
|
|
391
|
+
n1 = self.pix1_n*relative_to_hash
|
|
392
|
+
n2 = self.pix2_n*relative_to_hash
|
|
393
|
+
|
|
394
|
+
# Prepare arguments
|
|
395
|
+
zbinarr = self.zbins.astype(np.int32)
|
|
396
|
+
nbinsz = len(np.unique(zbinarr))
|
|
397
|
+
ncompfields = []
|
|
398
|
+
scalarquants = []
|
|
399
|
+
nfields = 0
|
|
400
|
+
for field in fields:
|
|
401
|
+
if type(field[0].item()) is float:
|
|
402
|
+
scalarquants.append(field)
|
|
403
|
+
nfields += 1
|
|
404
|
+
ncompfields.append(1)
|
|
405
|
+
if type(field[0].item()) is complex:
|
|
406
|
+
scalarquants.append(field.real)
|
|
407
|
+
scalarquants.append(field.imag)
|
|
408
|
+
nfields += 2
|
|
409
|
+
ncompfields.append(2)
|
|
410
|
+
scalarquants = np.asarray(scalarquants)
|
|
411
|
+
|
|
412
|
+
# Compute reduction (individually for each zbin)
|
|
413
|
+
assert(shuffle in [True, False, 0, 1, 2, 3, 4])
|
|
414
|
+
isinner_red = np.zeros(self.ngal, dtype=np.float64)
|
|
415
|
+
w_red = np.zeros(self.ngal, dtype=np.float64)
|
|
416
|
+
pos1_red = np.zeros(self.ngal, dtype=np.float64)
|
|
417
|
+
pos2_red = np.zeros(self.ngal, dtype=np.float64)
|
|
418
|
+
zbins_red = np.zeros(self.ngal, dtype=np.int32)
|
|
419
|
+
scalarquants_red = np.zeros((nfields, self.ngal), dtype=np.float64)
|
|
420
|
+
ind_start = 0
|
|
421
|
+
for elz in range(nbinsz):
|
|
422
|
+
sel_z = zbinarr==elz
|
|
423
|
+
ngal_z = np.sum(sel_z)
|
|
424
|
+
ngal_red_z = 0
|
|
425
|
+
red_shape = (len(fields), ngal_z)
|
|
426
|
+
isinner_red_z = np.zeros(ngal_z, dtype=np.float64)
|
|
427
|
+
w_red_z = np.zeros(ngal_z, dtype=np.float64)
|
|
428
|
+
pos1_red_z = np.zeros(ngal_z, dtype=np.float64)
|
|
429
|
+
pos2_red_z = np.zeros(ngal_z, dtype=np.float64)
|
|
430
|
+
scalarquants_red_z = np.zeros(nfields*ngal_z, dtype=np.float64)
|
|
431
|
+
self.clib.reducecat(self.isinner[sel_z].astype(np.float64),
|
|
432
|
+
self.weight[sel_z].astype(np.float64),
|
|
433
|
+
self.pos1[sel_z].astype(np.float64),
|
|
434
|
+
self.pos2[sel_z].astype(np.float64),
|
|
435
|
+
scalarquants[:,sel_z].flatten().astype(np.float64),
|
|
436
|
+
ngal_z, nfields, np.int32(normed),
|
|
437
|
+
dpix, dpix2, start1, start2, n1, n2, np.int32(shuffle),
|
|
438
|
+
isinner_red_z, w_red_z, pos1_red_z, pos2_red_z, scalarquants_red_z, ngal_red_z)
|
|
439
|
+
isinner_red[ind_start:ind_start+ngal_z] = isinner_red_z
|
|
440
|
+
w_red[ind_start:ind_start+ngal_z] = w_red_z
|
|
441
|
+
pos1_red[ind_start:ind_start+ngal_z] = pos1_red_z
|
|
442
|
+
pos2_red[ind_start:ind_start+ngal_z] = pos2_red_z
|
|
443
|
+
zbins_red[ind_start:ind_start+ngal_z] = elz*np.ones(ngal_z, dtype=np.int32)
|
|
444
|
+
scalarquants_red[:,ind_start:ind_start+ngal_z] = scalarquants_red_z.reshape((nfields, ngal_z))
|
|
445
|
+
ind_start += ngal_z
|
|
446
|
+
|
|
447
|
+
# Accumulate reduced atalog
|
|
448
|
+
sel_nonzero = w_red>0
|
|
449
|
+
isinner_red = isinner_red[sel_nonzero]
|
|
450
|
+
w_red = w_red[sel_nonzero]
|
|
451
|
+
pos1_red = pos1_red[sel_nonzero]
|
|
452
|
+
pos2_red = pos2_red[sel_nonzero]
|
|
453
|
+
zbins_red = zbins_red[sel_nonzero]
|
|
454
|
+
scalarquants_red = scalarquants_red[:,sel_nonzero]
|
|
455
|
+
fields_red = []
|
|
456
|
+
tmpcomp = 0
|
|
457
|
+
for elf in range(len(fields)):
|
|
458
|
+
if ncompfields[elf]==1:
|
|
459
|
+
fields_red.append(scalarquants_red[tmpcomp])
|
|
460
|
+
if ncompfields[elf]==2:
|
|
461
|
+
fields_red.append(scalarquants_red[tmpcomp]+1J*scalarquants_red[tmpcomp+1])
|
|
462
|
+
tmpcomp += ncompfields[elf]
|
|
463
|
+
#isinner_red[isinner_red<0.5] = 0
|
|
464
|
+
#isinner_red[isinner_red>=0.5] = 1
|
|
465
|
+
if ret_inst:
|
|
466
|
+
return Catalog(pos1=pos1_red, pos2=pos2_red, weight=w_red, zbins=zbins_red,
|
|
467
|
+
isinner=isinner_red.astype(np.float64)), fields_red
|
|
468
|
+
|
|
469
|
+
return w_red, pos1_red, pos2_red, zbins_red, isinner_red, fields_red
|
|
470
|
+
|
|
471
|
+
def _multihash(self, dpixs, fields, dpix_hash=None, normed=True, shuffle=0,
|
|
472
|
+
extent=[None,None,None,None], forcedivide=1):
|
|
473
|
+
r"""Builds spatialhash for a base catalog and its reductions.
|
|
474
|
+
|
|
475
|
+
Parameters
|
|
476
|
+
----------
|
|
477
|
+
dpixs: list
|
|
478
|
+
The pixel sizes on which the hierarchy of reduced catalogs is constructed.
|
|
479
|
+
fields: list
|
|
480
|
+
The fields for which the multihash is constructed. Each field is given as a 1D array of float.
|
|
481
|
+
dpix_hash: float, optional
|
|
482
|
+
The size of the pixels used for the spatial hash of the hierarchy of catalogs. Defaults
|
|
483
|
+
to ``None``. If set to ``None`` uses the largest value of ``dpixs``.
|
|
484
|
+
normed: bool, optional
|
|
485
|
+
Decide on whether to average or to sum the field over pixels. Defaults to ``True``.
|
|
486
|
+
shuffle: int, optional
|
|
487
|
+
Choose a definition on how to set the central point of each pixel. Defaults to zero.
|
|
488
|
+
extent: list, optional
|
|
489
|
+
Sets custom boundaries ``[xmin, xmax, ymin, ymax]`` for the grid. Each element defaults
|
|
490
|
+
to ``None``. Each element equal to ``None`` sets the grid boundary as the smallest value
|
|
491
|
+
fully containing the discrete field tracers.
|
|
492
|
+
forcedivide: int, optional
|
|
493
|
+
Forces the number of cells in each dimensions to be divisible by some number.
|
|
494
|
+
Defaults to ``1``.
|
|
495
|
+
|
|
496
|
+
Returns
|
|
497
|
+
-------
|
|
498
|
+
ngals: list
|
|
499
|
+
Contains the number of galaxies for each of the catalogs in the hierarchy.
|
|
500
|
+
pos1s: list
|
|
501
|
+
Contains the :math:`x`-positions for each of the catalogs in the hierarchy.
|
|
502
|
+
pos2s: list
|
|
503
|
+
Contains the :math:`y`-positions for each of the catalogs in the hierarchy.
|
|
504
|
+
weights: list
|
|
505
|
+
Contains the tracer weights for each of the catalogs in the hierarchy.
|
|
506
|
+
zbins: list
|
|
507
|
+
Contains the tomographic redshift bins for each of the catalogs in the hierarchy.
|
|
508
|
+
isinners: list
|
|
509
|
+
Contains the flag on wheter a tracer is within the interior part of the footprint
|
|
510
|
+
for each of the catalogs in the hierarchy.
|
|
511
|
+
allfields: list
|
|
512
|
+
Contains the tracer fields for each of the catalogs in the hierarchy.
|
|
513
|
+
index_matchers: list
|
|
514
|
+
Contains the ``index_matchers`` arrays for each of the catalogs in the hierarchy.
|
|
515
|
+
See the ```index_matcher`` attribute for more information.
|
|
516
|
+
pixs_galind_bounds: list
|
|
517
|
+
Contains the ``pixs_galind_bounds`` arrays for each of the catalogs in the hierarchy.
|
|
518
|
+
See the ```pixs_galind_bounds`` attribute for more information.
|
|
519
|
+
pix_gals: list
|
|
520
|
+
Contains the ``pix_gals`` arrays for each of the catalogs in the hierarchy.
|
|
521
|
+
See the ```pix_gals`` attribute for more information.
|
|
522
|
+
dpixs1_true: list
|
|
523
|
+
Contains final values of the pixel sidelength along the :math:`x`-direction for each
|
|
524
|
+
of the catalogs in the hierarchy.
|
|
525
|
+
dpixs2_true: list
|
|
526
|
+
Contains final values of the pixel sidelength along the :math:`y`-direction for each
|
|
527
|
+
of the catalogs in the hierarchy.
|
|
528
|
+
"""
|
|
529
|
+
|
|
530
|
+
dpixs = sorted(dpixs)
|
|
531
|
+
if dpix_hash is None:
|
|
532
|
+
dpix_hash = dpixs[-1]
|
|
533
|
+
if extent[0] is None:
|
|
534
|
+
extent = [self.min1-dpix_hash, self.max1+dpix_hash, self.min2-dpix_hash, self.max2+dpix_hash]
|
|
535
|
+
|
|
536
|
+
|
|
537
|
+
# Initialize spatial hash for discrete catalog
|
|
538
|
+
self.build_spatialhash(dpix=dpix_hash, extent=extent)
|
|
539
|
+
ngals = [self.ngal]
|
|
540
|
+
isinners = [self.isinner]
|
|
541
|
+
pos1s = [self.pos1]
|
|
542
|
+
pos2s = [self.pos2]
|
|
543
|
+
weights = [self.weight]
|
|
544
|
+
zbins = [self.zbins]
|
|
545
|
+
allfields = [fields]
|
|
546
|
+
if not normed:
|
|
547
|
+
allfields[0] *= self.weight
|
|
548
|
+
index_matchers = [self.index_matcher]
|
|
549
|
+
pixs_galind_bounds = [self.pixs_galind_bounds]
|
|
550
|
+
pix_gals = [self.pix_gals]
|
|
551
|
+
|
|
552
|
+
# Build spatial hashes for reduced catalogs
|
|
553
|
+
fac_pix1 = self.pix1_d/dpix_hash
|
|
554
|
+
fac_pix2 = self.pix2_d/dpix_hash
|
|
555
|
+
dpixs1_true = np.zeros_like(np.asarray(dpixs))
|
|
556
|
+
dpixs2_true = np.zeros_like(np.asarray(dpixs))
|
|
557
|
+
#print(len(fields),fields)
|
|
558
|
+
for elreso in range(len(dpixs)):
|
|
559
|
+
#print("Doing reso %i"%elreso)
|
|
560
|
+
dpixs1_true[elreso]=fac_pix1*dpixs[elreso]
|
|
561
|
+
dpixs2_true[elreso]=fac_pix2*dpixs[elreso]
|
|
562
|
+
#print(dpixs[elreso], dpixs1_true[elreso], dpixs2_true[elreso], len(self.pos1))
|
|
563
|
+
nextcat, fields_red = self._reduce(fields=fields,
|
|
564
|
+
dpix=dpixs1_true[elreso],
|
|
565
|
+
dpix2=dpixs2_true[elreso],
|
|
566
|
+
relative_to_hash=np.int32(2**(len(dpixs)-elreso-1)),
|
|
567
|
+
#relative_to_hash=None,
|
|
568
|
+
normed=normed,
|
|
569
|
+
shuffle=shuffle,
|
|
570
|
+
extent=extent,
|
|
571
|
+
forcedivide=forcedivide,
|
|
572
|
+
ret_inst=True)
|
|
573
|
+
nextcat.build_spatialhash(dpix=dpix_hash, extent=extent)
|
|
574
|
+
ngals.append(nextcat.ngal)
|
|
575
|
+
isinners.append(nextcat.isinner)
|
|
576
|
+
pos1s.append(nextcat.pos1)
|
|
577
|
+
pos2s.append(nextcat.pos2)
|
|
578
|
+
weights.append(nextcat.weight)
|
|
579
|
+
zbins.append(nextcat.zbins)
|
|
580
|
+
allfields.append(fields_red)
|
|
581
|
+
index_matchers.append(nextcat.index_matcher)
|
|
582
|
+
pixs_galind_bounds.append(nextcat.pixs_galind_bounds)
|
|
583
|
+
pix_gals.append(nextcat.pix_gals)
|
|
584
|
+
|
|
585
|
+
return ngals, pos1s, pos2s, weights, zbins, isinners, allfields, index_matchers, pixs_galind_bounds, pix_gals, dpixs1_true, dpixs2_true
|
|
586
|
+
|
|
587
|
+
def _jointextent(self, others, extend=0):
|
|
588
|
+
r"""Draws largest possible rectangle over set of catalogs.
|
|
589
|
+
|
|
590
|
+
Parameters
|
|
591
|
+
----------
|
|
592
|
+
others: list
|
|
593
|
+
Contains ``Catalog`` instances over which the joint extent will
|
|
594
|
+
be drawn
|
|
595
|
+
extend: float, optional
|
|
596
|
+
Include an additional boundary layer around the joint extent
|
|
597
|
+
of the catalogs. Defaults to ``0`` (no extension).
|
|
598
|
+
|
|
599
|
+
Returns
|
|
600
|
+
-------
|
|
601
|
+
xlo: float
|
|
602
|
+
The lower ``x``-boundary of the joint extent.
|
|
603
|
+
xhi: float
|
|
604
|
+
The upper ``x``-boundary of the joint extent.
|
|
605
|
+
ylo: float
|
|
606
|
+
The lower ``y``-boundary of the joint extent.
|
|
607
|
+
yhi: float
|
|
608
|
+
The upper ``y``-boundary of the joint extent.
|
|
609
|
+
|
|
610
|
+
"""
|
|
611
|
+
for other in others:
|
|
612
|
+
assert(isinstance(other, Catalog))
|
|
613
|
+
|
|
614
|
+
xlo = self.min1
|
|
615
|
+
xhi = self.max1
|
|
616
|
+
ylo = self.min2
|
|
617
|
+
yhi = self.max2
|
|
618
|
+
for other in others:
|
|
619
|
+
xlo = min(xlo, other.min1)
|
|
620
|
+
xhi = max(xhi, other.max1)
|
|
621
|
+
ylo = min(ylo, other.min2)
|
|
622
|
+
yhi = max(yhi, other.max2)
|
|
623
|
+
|
|
624
|
+
return (xlo-extend, xhi+extend, ylo-extend, yhi+extend)
|
|
625
|
+
|
|
626
|
+
|
|
627
|
+
def create_mask(self, method="Basic", pixsize=1., apply=False, extend=0.):
|
|
628
|
+
|
|
629
|
+
assert(method in ["Basic", "Density", "Random"])
|
|
630
|
+
|
|
631
|
+
if method=="Basic":
|
|
632
|
+
npix_1 = int(np.ceil((self.max1-self.min1)/pixsize))
|
|
633
|
+
npix_2 = int(np.ceil((self.max2-self.min2)/pixsize))
|
|
634
|
+
self.mask = FlatDataGrid_2D(np.zeros((npix_2,npix_1), dtype=np.float64),
|
|
635
|
+
self.min1, self.min2, pixsize, pixsize)
|
|
636
|
+
if method=="Density":
|
|
637
|
+
start1, start2, n1, n2 = self._gengridprops(pixsize, pixsize)
|
|
638
|
+
reduced = self.togrid(dpix=pixsize,method="NGP",fields=[], tomo=False)
|
|
639
|
+
mask = (reduced[0].reshape((n2,n1))==0).astype(np.float64)
|
|
640
|
+
self.mask = FlatDataGrid_2D(mask, start1, start2, pixsize, pixsize)
|
|
641
|
+
|
|
642
|
+
# Add a masked buffer region around enclosing rectangle
|
|
643
|
+
if extend>0.:
|
|
644
|
+
npix_ext = int(np.ceil(extend/pixsize))
|
|
645
|
+
extstart1 = self.mask.start_1 - npix_ext*pixsize
|
|
646
|
+
extstart2 = self.mask.start_2 - npix_ext*pixsize
|
|
647
|
+
extmask = np.ones((self.mask.npix_2+2*npix_ext, self.mask.npix_1+2*npix_ext))
|
|
648
|
+
extmask[npix_ext:-npix_ext,npix_ext:-npix_ext] = self.mask.data
|
|
649
|
+
self.mask = FlatDataGrid_2D(extmask, extstart1, extstart2, pixsize, pixsize)
|
|
650
|
+
|
|
651
|
+
self. __checkmask()
|
|
652
|
+
|
|
653
|
+
self. __applymask(apply)
|
|
654
|
+
|
|
655
|
+
def __checkmask(self):
|
|
656
|
+
assert(self.mask.start_1 <= self.min1)
|
|
657
|
+
assert(self.mask.start_2 <= self.min2)
|
|
658
|
+
assert(self.mask.pix1_lbounds[-1] >= self.max1-self.mask.dpix_1)
|
|
659
|
+
assert(self.mask.pix2_lbounds[-1] >= self.max2-self.mask.dpix_2)
|
|
660
|
+
|
|
661
|
+
def __applymask(self, method):
|
|
662
|
+
assert(method in [False, True, "WeightsOnly"])
|
|
663
|
+
|
|
664
|
+
|
|
665
|
+
|
|
666
|
+
# Maps catalog to grid
|
|
667
|
+
def togrid(self, fields, dpix, normed=False, weighted=True, tomo=True,
|
|
668
|
+
extent=[None,None,None,None], method="CIC", forcedivide=1,
|
|
669
|
+
asgrid=None, nthreads=1, ret_inst=False):
|
|
670
|
+
r"""Paints a catalog of discrete tracers to a grid.
|
|
671
|
+
|
|
672
|
+
Parameters
|
|
673
|
+
----------
|
|
674
|
+
fields: list
|
|
675
|
+
The fields to be painted to the grid. Each field is given as a 1D array of float.
|
|
676
|
+
dpix: float
|
|
677
|
+
The sidelength of a grid cell.
|
|
678
|
+
normed: bool, optional
|
|
679
|
+
Decide on whether to average or to sum the field over pixels. Defaults to ``True``.
|
|
680
|
+
weighted: bool, optional
|
|
681
|
+
Whether to apply the tracer weights of the catalog. Defaults to ``True``.
|
|
682
|
+
extent: list, optional
|
|
683
|
+
Sets custom boundaries ``[xmin, xmax, ymin, ymax]`` for the grid. Each element defaults
|
|
684
|
+
to ``None``. Each element equal to ``None`` sets the grid boundary as the smallest value
|
|
685
|
+
fully containing the discrete field tracers.
|
|
686
|
+
method: str, optional
|
|
687
|
+
The chosen mass assignment method applied to each of the fields. Currently supported methods
|
|
688
|
+
are ``NGP``, ``CIC`` and ``TSC`` assignment. Defaults to ``CIC``.
|
|
689
|
+
forcedivide: int, optional
|
|
690
|
+
Forces the number of cells in each dimensions to be divisible by some number.
|
|
691
|
+
Defaults to ``1``.
|
|
692
|
+
ret_inst: bool, optional
|
|
693
|
+
Decides on wheter to return the output as a list of arrays containing the reduced catalog or
|
|
694
|
+
on returning a new ``Catalog`` instance. Defaults to ``False``.
|
|
695
|
+
asgrid: bool, optional
|
|
696
|
+
Deprecated.
|
|
697
|
+
nthreads: int, optional
|
|
698
|
+
The number of openmp threads used for the reduction procedure. Defaults to ``1``.
|
|
699
|
+
ret_inst: bool, optional
|
|
700
|
+
Deprecated.
|
|
701
|
+
|
|
702
|
+
Returns
|
|
703
|
+
-------
|
|
704
|
+
projectedfields: list
|
|
705
|
+
A list of the 2D arrays containing the reduced fields
|
|
706
|
+
start1: float
|
|
707
|
+
The :math:`x`-position of the first columns' left edge
|
|
708
|
+
start2: float
|
|
709
|
+
The :math:`y`-position of the first rows' lower edge
|
|
710
|
+
dpix: float
|
|
711
|
+
The sidelength of each pixel in the grid. Note that this
|
|
712
|
+
value might slightly differ from the one provided in the parameters.
|
|
713
|
+
normed: bool
|
|
714
|
+
Same as the ``normed`` parameter
|
|
715
|
+
method: str
|
|
716
|
+
Same as the ``method`` parameter
|
|
717
|
+
"""
|
|
718
|
+
|
|
719
|
+
if asgrid is not None:
|
|
720
|
+
raise NotImplementedError
|
|
721
|
+
|
|
722
|
+
# Choose index of method for c wrapper
|
|
723
|
+
assert(method in ["NGP", "CIC", "TSC"])
|
|
724
|
+
elmethod = self.assign_methods[method]
|
|
725
|
+
start1, start2, n1, n2 = self._gengridprops(dpix, dpix, forcedivide, extent)
|
|
726
|
+
|
|
727
|
+
# Prepare arguments
|
|
728
|
+
zbinarr = self.zbins.astype(np.int32)
|
|
729
|
+
if not tomo:
|
|
730
|
+
zbinarr = np.zeros_like(zbinarr)
|
|
731
|
+
nbinsz = len(np.unique(zbinarr))
|
|
732
|
+
nfields = len(fields)
|
|
733
|
+
if not weighted:
|
|
734
|
+
weightarr = np.ones(self.ngal, dtype=np.float64)
|
|
735
|
+
else:
|
|
736
|
+
weightarr = self.weight.astype(np.float64)
|
|
737
|
+
fieldarr = np.zeros(nfields*self.ngal, dtype=np.float64)
|
|
738
|
+
for _ in range(nfields):
|
|
739
|
+
fieldarr[_*self.ngal:(1+_)*self.ngal] = fields[_]
|
|
740
|
+
|
|
741
|
+
# Call wrapper and reshape output to (zbins, nfields, size_field)
|
|
742
|
+
proj_shape = (nbinsz, (nfields+1), n2, n1)
|
|
743
|
+
projectedfields = np.zeros((nbinsz*(nfields+1)*n2*n1), dtype=np.float64)
|
|
744
|
+
self.clib.assign_fields(self.pos1.astype(np.float64),
|
|
745
|
+
self.pos2.astype(np.float64),
|
|
746
|
+
zbinarr, weightarr, fieldarr,
|
|
747
|
+
nbinsz, nfields, self.ngal,
|
|
748
|
+
elmethod, start1, start2, dpix,
|
|
749
|
+
n1, n2, nthreads, projectedfields)
|
|
750
|
+
projectedfields = projectedfields.reshape(proj_shape)
|
|
751
|
+
if normed:
|
|
752
|
+
projectedfields[:,1:] = np.nan_to_num(projectedfields[:,1:]/projectedfields[:,0])
|
|
753
|
+
|
|
754
|
+
if not ret_inst:
|
|
755
|
+
return projectedfields, start1, start2, dpix, normed, method
|
|
756
|
+
|
|
757
|
+
return GriddedCatalog(projectedfields,
|
|
758
|
+
start1, start2, dpix, normed, method)
|
|
759
|
+
|
|
760
|
+
def gen_weightgrid2d(self, dpix,
|
|
761
|
+
extent=[None,None,None,None], method="CIC", forcedivide=1,
|
|
762
|
+
nthreads=1):
|
|
763
|
+
|
|
764
|
+
# Choose index of method for c wrapper
|
|
765
|
+
assert(method in ["NGP", "CIC", "TSC"])
|
|
766
|
+
elmethod = self.assign_methods[method]
|
|
767
|
+
start1, start2, n1, n2 = self._gengridprops(dpix, dpix, forcedivide, extent)
|
|
768
|
+
|
|
769
|
+
#void gen_weightgrid2d(
|
|
770
|
+
# double *pos1, double *pos2, int ngal, int method,
|
|
771
|
+
# double min1, double min2, int dpix, int n1, int n2,
|
|
772
|
+
# int nthreads, int *pixinds, double *pixweights){
|
|
773
|
+
|
|
774
|
+
self.ngal
|
|
775
|
+
nsubs = 2*elmethod+1
|
|
776
|
+
pixinds = np.zeros(nsubs*nsubs*self.ngal, dtype=np.int32)
|
|
777
|
+
pixweights = np.zeros(nsubs*nsubs*self.ngal, dtype=np.float64)
|
|
778
|
+
self.clib.gen_weightgrid2d(self.pos1.astype(np.float64),
|
|
779
|
+
self.pos2.astype(np.float64),
|
|
780
|
+
self.ngal, elmethod,
|
|
781
|
+
start1, start2, dpix, n1, n2,
|
|
782
|
+
nthreads, pixinds, pixweights)
|
|
783
|
+
return pixinds, pixweights
|
|
784
|
+
|
|
785
|
+
|
|
786
|
+
|
|
787
|
+
def build_spatialhash(self, dpix=1., extent=[None, None, None, None]):
|
|
788
|
+
r"""Adds a spatial hashing data structure to the catalog.
|
|
789
|
+
|
|
790
|
+
Parameters
|
|
791
|
+
----------
|
|
792
|
+
dpix: float
|
|
793
|
+
The sidelength of each cell of the hash. Defaults to ``1``.
|
|
794
|
+
extent: list, optional
|
|
795
|
+
Sets custom boundaries ``[xmin, xmax, ymin, ymax]`` for the grid. Each element defaults
|
|
796
|
+
to ``None``. Each element equal to ``None`` sets the grid boundary as the smallest value
|
|
797
|
+
fully containing the discrete field tracers.
|
|
798
|
+
|
|
799
|
+
Note
|
|
800
|
+
----
|
|
801
|
+
Calling this method (re-)allocates the ``index_matcher``, ``pixs_galind_bounds``, ``pix_gals``,
|
|
802
|
+
``pix1_start``, ``pix2_start``, ``pix1_n``, ``pix2_n``, ``pix1_d`` and ``pix2_d``
|
|
803
|
+
attributes of the instance.
|
|
804
|
+
"""
|
|
805
|
+
|
|
806
|
+
# Build extent
|
|
807
|
+
if extent[0] is None:
|
|
808
|
+
thismin1 = self.min1
|
|
809
|
+
else:
|
|
810
|
+
thismin1 = extent[0]
|
|
811
|
+
assert(thismin1 <= self.min1)
|
|
812
|
+
if extent[1] is None:
|
|
813
|
+
thismax1 = self.max1
|
|
814
|
+
else:
|
|
815
|
+
thismax1 = extent[1]
|
|
816
|
+
assert(thismax1 >= self.max1)
|
|
817
|
+
if extent[2] is None:
|
|
818
|
+
thismin2 = self.min2
|
|
819
|
+
else:
|
|
820
|
+
thismin2 = extent[2]
|
|
821
|
+
assert(thismin2 <= self.min2)
|
|
822
|
+
if extent[3] is None:
|
|
823
|
+
thismax2 = self.max2
|
|
824
|
+
else:
|
|
825
|
+
thismax2 = extent[3]
|
|
826
|
+
assert(thismax2 >= self.max2)
|
|
827
|
+
|
|
828
|
+
# Collect arguments
|
|
829
|
+
# Note that the C function assumes the mask to start at zero, that's why we shift
|
|
830
|
+
# the galaxy positions
|
|
831
|
+
self.pix1_start = thismin1 - dpix/1.
|
|
832
|
+
self.pix2_start = thismin2 - dpix/1.
|
|
833
|
+
stop1 = thismax1 + dpix/1.
|
|
834
|
+
stop2 = thismax2 + dpix/1.
|
|
835
|
+
self.pix1_n = int(np.ceil((stop1-self.pix1_start)/dpix))
|
|
836
|
+
self.pix2_n = int(np.ceil((stop2-self.pix2_start)/dpix))
|
|
837
|
+
npix = self.pix1_n * self.pix2_n
|
|
838
|
+
self.pix1_d = (stop1-self.pix1_start)/(self.pix1_n)
|
|
839
|
+
self.pix2_d = (stop2-self.pix2_start)/(self.pix2_n)
|
|
840
|
+
|
|
841
|
+
# Compute hashtable
|
|
842
|
+
result = np.zeros(2 * npix + 3 * self.ngal + 1).astype(np.int32)
|
|
843
|
+
self.clib.build_spatialhash(self.pos1, self.pos2, self.ngal,
|
|
844
|
+
self.pix1_d, self.pix2_d,
|
|
845
|
+
self.pix1_start, self.pix2_start,
|
|
846
|
+
self.pix1_n, self.pix2_n,
|
|
847
|
+
result)
|
|
848
|
+
|
|
849
|
+
# Allocate result
|
|
850
|
+
start_isoutside = 0
|
|
851
|
+
start_index_matcher = self.ngal
|
|
852
|
+
start_pixs_galind_bounds = self.ngal + npix
|
|
853
|
+
start_pixs_gals = self.ngal + npix + self.ngal + 1
|
|
854
|
+
start_ngalinpix = self.ngal + npix + self.ngal + 1 + self.ngal
|
|
855
|
+
self.index_matcher = result[start_index_matcher:start_pixs_galind_bounds]
|
|
856
|
+
self.pixs_galind_bounds = result[start_pixs_galind_bounds:start_pixs_gals]
|
|
857
|
+
self.pix_gals = result[start_pixs_gals:start_ngalinpix]
|
|
858
|
+
self.hasspatialhash = True
|
|
859
|
+
|
|
860
|
+
|
|
861
|
+
def _gengridprops(self, dpix, dpix2=None, forcedivide=1, extent=[None,None,None,None]):
|
|
862
|
+
r"""Gives some basic properties of grids created from the discrete tracers.
|
|
863
|
+
|
|
864
|
+
Parameters
|
|
865
|
+
----------
|
|
866
|
+
dpix: float
|
|
867
|
+
The sidelength of a grid cell.
|
|
868
|
+
dpix2: float, optional
|
|
869
|
+
The sidelength of a grid cell in :math:`y`-direction. Defaults to ``None``.
|
|
870
|
+
If set to ``None`` the pixels are assumed to be squares.
|
|
871
|
+
forcedivide: int, optional
|
|
872
|
+
Forces the number of cells in each dimensions to be divisible by some number.
|
|
873
|
+
Defaults to ``1``.
|
|
874
|
+
extent: list, optional
|
|
875
|
+
Sets custom boundaries ``[xmin, xmax, ymin, ymax]`` for the grid. Each element defaults
|
|
876
|
+
to ``None``. Each element equal to ``None`` sets the grid boundary as the smallest value
|
|
877
|
+
fully containing the discrete field tracers.
|
|
878
|
+
|
|
879
|
+
Returns
|
|
880
|
+
-------
|
|
881
|
+
start1: float
|
|
882
|
+
The :math:``x``-position of the first column.
|
|
883
|
+
start2: float
|
|
884
|
+
The :math:``y``-position of the first row.
|
|
885
|
+
n1: int
|
|
886
|
+
The number of pixels in the :math:``x``-position.
|
|
887
|
+
n2: int
|
|
888
|
+
The number of pixels in the :math:``y``-position.
|
|
889
|
+
"""
|
|
890
|
+
|
|
891
|
+
# Define inner extent of the grid
|
|
892
|
+
fixedsize = False
|
|
893
|
+
if extent[0] is not None:
|
|
894
|
+
fixedsize = True
|
|
895
|
+
if extent[0] is None:
|
|
896
|
+
thismin1 = self.min1
|
|
897
|
+
else:
|
|
898
|
+
thismin1 = extent[0]
|
|
899
|
+
assert(thismin1 <= self.min1)
|
|
900
|
+
if extent[1] is None:
|
|
901
|
+
thismax1 = self.max1
|
|
902
|
+
else:
|
|
903
|
+
thismax1 = extent[1]
|
|
904
|
+
assert(thismax1 >= self.max1)
|
|
905
|
+
if extent[2] is None:
|
|
906
|
+
thismin2 = self.min2
|
|
907
|
+
else:
|
|
908
|
+
thismin2 = extent[2]
|
|
909
|
+
assert(thismin2 <= self.min2)
|
|
910
|
+
if extent[3] is None:
|
|
911
|
+
thismax2 = self.max2
|
|
912
|
+
else:
|
|
913
|
+
thismax2 = extent[3]
|
|
914
|
+
assert(thismax2 >= self.max2)
|
|
915
|
+
|
|
916
|
+
if dpix2 is None:
|
|
917
|
+
dpix2 = dpix
|
|
918
|
+
|
|
919
|
+
# Add buffer to grid and get associated pixelization
|
|
920
|
+
if not fixedsize:
|
|
921
|
+
start1 = thismin1 - 4*dpix
|
|
922
|
+
start2 = thismin2 - 4*dpix2
|
|
923
|
+
n1 = int(np.ceil((thismax1+4*dpix - start1)/dpix))
|
|
924
|
+
n2 = int(np.ceil((thismax2+4*dpix2 - start2)/dpix2))
|
|
925
|
+
n1 += (forcedivide - n1%forcedivide)%forcedivide
|
|
926
|
+
n2 += (forcedivide - n2%forcedivide)%forcedivide
|
|
927
|
+
else:
|
|
928
|
+
start1=extent[0]
|
|
929
|
+
start2=extent[2]
|
|
930
|
+
n1 = int((thismax1-thismin1)/dpix)
|
|
931
|
+
n2 = int((thismax2-thismin2)/dpix2)
|
|
932
|
+
assert(not n1%forcedivide)
|
|
933
|
+
assert(not n2%forcedivide)
|
|
934
|
+
|
|
935
|
+
return start1, start2, n1, n2
|
|
936
|
+
|
|
937
|
+
class ScalarTracerCatalog(Catalog):
|
|
938
|
+
r"""Class constructor.
|
|
939
|
+
|
|
940
|
+
Attributes
|
|
941
|
+
----------
|
|
942
|
+
pos1: numpy.ndarray
|
|
943
|
+
The :math:`x`-positions of the tracer objects
|
|
944
|
+
pos2: numpy.ndarray
|
|
945
|
+
The :math:`y`-positions of the tracer objects
|
|
946
|
+
tracer: numpy.ndarray
|
|
947
|
+
The values of the scalar tracer field, i.e. galaxy weights or cosmic convergence.
|
|
948
|
+
|
|
949
|
+
Notes
|
|
950
|
+
-----
|
|
951
|
+
Inherits all other parameters and attributes from :class:`Catalog`.
|
|
952
|
+
Additional child-specific parameters can be passed via ``kwargs``.
|
|
953
|
+
"""
|
|
954
|
+
|
|
955
|
+
def __init__(self, pos1, pos2, tracer, **kwargs):
|
|
956
|
+
super().__init__(pos1=pos1, pos2=pos2, **kwargs)
|
|
957
|
+
self.tracer = tracer
|
|
958
|
+
self.spin = 0
|
|
959
|
+
|
|
960
|
+
def reduce(self, dpix, dpix2=None, relative_to_hash=None, normed=True, shuffle=0,
|
|
961
|
+
extent=[None,None,None,None], forcedivide=1,
|
|
962
|
+
ret_inst=False):
|
|
963
|
+
r"""Paints the catalog onto a grid with equal-area cells
|
|
964
|
+
|
|
965
|
+
Parameters
|
|
966
|
+
----------
|
|
967
|
+
dpix: float
|
|
968
|
+
The sidelength of a grid cell.
|
|
969
|
+
dpix2: float, optional
|
|
970
|
+
The sidelength of a grid cell in :math:`y`-direction. Defaults to ``None``.
|
|
971
|
+
If set to ``None`` the pixels are assumed to be squares.
|
|
972
|
+
relative_to_hash: int, optional
|
|
973
|
+
Forces the cell size to be an integer multiple of the cell size of the spatial hash.
|
|
974
|
+
Defaults to ``None``. If set to ``None`` the pixelsize is unrelated to the cell
|
|
975
|
+
size of the spatial hash.
|
|
976
|
+
normed: bool, optional
|
|
977
|
+
Decide on whether to average or to sum the field over pixels. Defaults to ``True``.
|
|
978
|
+
shuffle: int, optional
|
|
979
|
+
Choose a definition on how to set the central point of each pixel. Defaults to zero.
|
|
980
|
+
extent: list, optional
|
|
981
|
+
Sets custom boundaries ``[xmin, xmax, ymin, ymax]`` for the grid. Each element defaults
|
|
982
|
+
to ``None``. Each element equal to ``None`` sets the grid boundary as the smallest value
|
|
983
|
+
fully containing the discrete field tracers.
|
|
984
|
+
forcedivide: int, optional
|
|
985
|
+
Forces the number of cells in each dimensions to be divisible by some number.
|
|
986
|
+
Defaults to ``1``.
|
|
987
|
+
ret_inst: bool, optional
|
|
988
|
+
Decides on wheter to return the output as a list of arrays containing the reduced catalog or
|
|
989
|
+
on returning a new ``Catalog`` instance. Defaults to ``False``.
|
|
990
|
+
"""
|
|
991
|
+
res = super()._reduce(
|
|
992
|
+
dpix=dpix,
|
|
993
|
+
dpix2=None,
|
|
994
|
+
relative_to_hash=None,
|
|
995
|
+
fields=[self.tracer],
|
|
996
|
+
normed=normed,
|
|
997
|
+
shuffle=shuffle,
|
|
998
|
+
extent=extent,
|
|
999
|
+
forcedivide=forcedivide,
|
|
1000
|
+
ret_inst=False)
|
|
1001
|
+
(w_red, pos1_red, pos2_red, zbins_red, isinner_red, fields_red) = res
|
|
1002
|
+
if ret_inst:
|
|
1003
|
+
return ScalarTracerCatalog(self.spin, pos1_red, pos2_red,
|
|
1004
|
+
fields_red[0],
|
|
1005
|
+
weight=w_red, zbins=zbins_red, isinner=isinner_red)
|
|
1006
|
+
return res
|
|
1007
|
+
|
|
1008
|
+
def multihash(self, dpixs, dpix_hash=None, normed=True, shuffle=0,
|
|
1009
|
+
extent=[None,None,None,None], forcedivide=1):
|
|
1010
|
+
r"""Builds spatialhash for a base catalog and its reductions.
|
|
1011
|
+
|
|
1012
|
+
Parameters
|
|
1013
|
+
----------
|
|
1014
|
+
dpixs: list
|
|
1015
|
+
The pixel sizes on which the hierarchy of reduced catalogs is constructed.
|
|
1016
|
+
dpix_hash: float, optional
|
|
1017
|
+
The size of the pixels used for the spatial hash of the hierarchy of catalogs. Defaults
|
|
1018
|
+
to ``None``. If set to ``None`` uses the largest value of ``dpixs``.
|
|
1019
|
+
normed: bool, optional
|
|
1020
|
+
Decide on whether to average or to sum the field over pixels. Defaults to ``True``.
|
|
1021
|
+
shuffle: int, optional
|
|
1022
|
+
Choose a definition on how to set the central point of each pixel. Defaults to zero.
|
|
1023
|
+
extent: list, optional
|
|
1024
|
+
Sets custom boundaries ``[xmin, xmax, ymin, ymax]`` for the grid. Each element defaults
|
|
1025
|
+
to ``None``. Each element equal to ``None`` sets the grid boundary as the smallest value
|
|
1026
|
+
fully containing the discrete field tracers.
|
|
1027
|
+
forcedivide: int, optional
|
|
1028
|
+
Forces the number of cells in each dimensions to be divisible by some number.
|
|
1029
|
+
Defaults to ``1``.
|
|
1030
|
+
|
|
1031
|
+
Returns
|
|
1032
|
+
-------
|
|
1033
|
+
res: tuple
|
|
1034
|
+
Contains the output of the ```Catalog._multihash method```
|
|
1035
|
+
"""
|
|
1036
|
+
res = super()._multihash(
|
|
1037
|
+
dpixs=dpixs.astype(np.float64),
|
|
1038
|
+
fields=[self.tracer],
|
|
1039
|
+
dpix_hash=dpix_hash,
|
|
1040
|
+
normed=normed,
|
|
1041
|
+
shuffle=shuffle,
|
|
1042
|
+
extent=extent,
|
|
1043
|
+
forcedivide=forcedivide)
|
|
1044
|
+
return res
|
|
1045
|
+
|
|
1046
|
+
|
|
1047
|
+
def frompatchind(self, index):
|
|
1048
|
+
|
|
1049
|
+
prepare = super()._patchind_preparerot(index, rotsignflip=False)
|
|
1050
|
+
inds_extpatch, patch_isinner, rotangle, ra_rot, dec_rot, rotangle_polars = prepare
|
|
1051
|
+
|
|
1052
|
+
patchcat = ScalarTracerCatalog(
|
|
1053
|
+
pos1=ra_rot*60.,
|
|
1054
|
+
pos2=dec_rot*60.,
|
|
1055
|
+
tracer=self.tracer[inds_extpatch],
|
|
1056
|
+
weight=self.weight[inds_extpatch],
|
|
1057
|
+
zbins=self.zbins[inds_extpatch],
|
|
1058
|
+
isinner=patch_isinner,
|
|
1059
|
+
units_pos1='arcmin',
|
|
1060
|
+
units_pos2='arcmin',
|
|
1061
|
+
geometry='flat2d',
|
|
1062
|
+
mask=None,
|
|
1063
|
+
zbins_mean=None,
|
|
1064
|
+
zbins_std=None)
|
|
1065
|
+
|
|
1066
|
+
return patchcat
|
|
1067
|
+
|
|
1068
|
+
class SpinTracerCatalog(Catalog):
|
|
1069
|
+
r"""Class constructor.
|
|
1070
|
+
|
|
1071
|
+
Attributes
|
|
1072
|
+
----------
|
|
1073
|
+
pos1: numpy.ndarray
|
|
1074
|
+
The :math:`x`-positions of the tracer objects
|
|
1075
|
+
pos2: numpy.ndarray
|
|
1076
|
+
The :math:`y`-positions of the tracer objects
|
|
1077
|
+
tracer_1: numpy.ndarray
|
|
1078
|
+
The values of the real part of the tracer field, i.e. galaxy ellipticities.
|
|
1079
|
+
tracer_2: numpy.ndarray
|
|
1080
|
+
The values of the imaginary part of the tracer field, i.e. galaxy ellipticities.
|
|
1081
|
+
|
|
1082
|
+
Notes
|
|
1083
|
+
-----
|
|
1084
|
+
Inherits all other parameters and attributes from :class:`Catalog`.
|
|
1085
|
+
Additional child-specific parameters can be passed via ``kwargs``.
|
|
1086
|
+
"""
|
|
1087
|
+
|
|
1088
|
+
def __init__(self, spin, pos1, pos2, tracer_1, tracer_2, **kwargs):
|
|
1089
|
+
super().__init__(pos1=pos1, pos2=pos2, **kwargs)
|
|
1090
|
+
self.tracer_1 = tracer_1.astype(np.float64)
|
|
1091
|
+
self.tracer_2 = tracer_2.astype(np.float64)
|
|
1092
|
+
self.spin = int(spin)
|
|
1093
|
+
|
|
1094
|
+
def reduce(self, dpix, dpix2=None, relative_to_hash=None, normed=True, shuffle=0,
|
|
1095
|
+
extent=[None,None,None,None], forcedivide=1, w2field=True,
|
|
1096
|
+
ret_inst=False):
|
|
1097
|
+
r"""Paints the catalog onto a grid with equal-area cells
|
|
1098
|
+
|
|
1099
|
+
Parameters
|
|
1100
|
+
----------
|
|
1101
|
+
dpix: float
|
|
1102
|
+
The sidelength of a grid cell.
|
|
1103
|
+
dpix2: float, optional
|
|
1104
|
+
The sidelength of a grid cell in :math:`y`-direction. Defaults to ``None``.
|
|
1105
|
+
If set to ``None`` the pixels are assumed to be squares.
|
|
1106
|
+
relative_to_hash: int, optional
|
|
1107
|
+
Forces the cell size to be an integer multiple of the cell size of the spatial hash.
|
|
1108
|
+
Defaults to ``None``. If set to ``None`` the pixelsize is unrelated to the cell
|
|
1109
|
+
size of the spatial hash.
|
|
1110
|
+
normed: bool, optional
|
|
1111
|
+
Decide on whether to average or to sum the field over pixels. Defaults to ``True``.
|
|
1112
|
+
shuffle: int, optional
|
|
1113
|
+
Choose a definition on how to set the central point of each pixel. Defaults to zero.
|
|
1114
|
+
extent: list, optional
|
|
1115
|
+
Sets custom boundaries ``[xmin, xmax, ymin, ymax]`` for the grid. Each element defaults
|
|
1116
|
+
to ``None``. Each element equal to ``None`` sets the grid boundary as the smallest value
|
|
1117
|
+
fully containing the discrete field tracers.
|
|
1118
|
+
forcedivide: int, optional
|
|
1119
|
+
Forces the number of cells in each dimensions to be divisible by some number.
|
|
1120
|
+
Defaults to ``1``.
|
|
1121
|
+
w2field: bool, optional
|
|
1122
|
+
Adds an additional field equivalent to the squared weight of the tracers to the reduced
|
|
1123
|
+
catalog. Defaaullts to ``True``.
|
|
1124
|
+
ret_inst: bool, optional
|
|
1125
|
+
Decides on wheter to return the output as a list of arrays containing the reduced catalog or
|
|
1126
|
+
on returning a new ``Catalog`` instance. Defaults to ``False``.
|
|
1127
|
+
"""
|
|
1128
|
+
|
|
1129
|
+
if not w2field:
|
|
1130
|
+
fields=(self.tracer_1, self.tracer_2,)
|
|
1131
|
+
else:
|
|
1132
|
+
fields=(self.tracer_1, self.tracer_2, self.weight**2, )
|
|
1133
|
+
res = super()._reduce(
|
|
1134
|
+
dpix=dpix,
|
|
1135
|
+
dpix2=None,
|
|
1136
|
+
relative_to_hash=None,
|
|
1137
|
+
fields=fields,
|
|
1138
|
+
normed=normed,
|
|
1139
|
+
shuffle=shuffle,
|
|
1140
|
+
extent=extent,
|
|
1141
|
+
forcedivide=forcedivide,
|
|
1142
|
+
ret_inst=False)
|
|
1143
|
+
(w_red, pos1_red, pos2_red, zbins_red, isinner_red, fields_red) = res
|
|
1144
|
+
if ret_inst:
|
|
1145
|
+
return SpinTracerCatalog(spin=self.spin, pos1=pos1_red, pos2=pos2_red,
|
|
1146
|
+
tracer_1=fields_red[0], tracer_2=fields_red[1],
|
|
1147
|
+
weight=w_red, zbins=zbins_red, isinner=isinner_red)
|
|
1148
|
+
return res
|
|
1149
|
+
|
|
1150
|
+
def multihash(self, dpixs, dpix_hash=None, normed=True, shuffle=0, w2field=True,
|
|
1151
|
+
extent=[None,None,None,None], forcedivide=1):
|
|
1152
|
+
r"""Builds spatialhash for a base catalog and its reductions.
|
|
1153
|
+
|
|
1154
|
+
Parameters
|
|
1155
|
+
----------
|
|
1156
|
+
dpixs: list
|
|
1157
|
+
The pixel sizes on which the hierarchy of reduced catalogs is constructed.
|
|
1158
|
+
dpix_hash: float, optional
|
|
1159
|
+
The size of the pixels used for the spatial hash of the hierarchy of catalogs. Defaults
|
|
1160
|
+
to ``None``. If set to ``None`` uses the largest value of ``dpixs``.
|
|
1161
|
+
normed: bool, optional
|
|
1162
|
+
Decide on whether to average or to sum the field over pixels. Defaults to ``True``.
|
|
1163
|
+
shuffle: int, optional
|
|
1164
|
+
Choose a definition on how to set the central point of each pixel. Defaults to zero.
|
|
1165
|
+
extent: list, optional
|
|
1166
|
+
Sets custom boundaries ``[xmin, xmax, ymin, ymax]`` for the grid. Each element defaults
|
|
1167
|
+
to ``None``. Each element equal to ``None`` sets the grid boundary as the smallest value
|
|
1168
|
+
fully containing the discrete field tracers.
|
|
1169
|
+
forcedivide: int, optional
|
|
1170
|
+
Forces the number of cells in each dimensions to be divisible by some number.
|
|
1171
|
+
Defaults to ``1``.
|
|
1172
|
+
w2field: bool, optional
|
|
1173
|
+
Adds an additional field equivalent to the squared weight of the tracers to the reduced
|
|
1174
|
+
catalog. Defaaullts to ``True``.
|
|
1175
|
+
|
|
1176
|
+
Returns
|
|
1177
|
+
-------
|
|
1178
|
+
res: tuple
|
|
1179
|
+
Contains the output of the ```Catalog._multihash method```
|
|
1180
|
+
"""
|
|
1181
|
+
if not w2field:
|
|
1182
|
+
fields=(self.tracer_1, self.tracer_2,)
|
|
1183
|
+
else:
|
|
1184
|
+
fields=(self.tracer_1, self.tracer_2, self.weight**2,)
|
|
1185
|
+
res = super()._multihash(
|
|
1186
|
+
dpixs=dpixs,
|
|
1187
|
+
fields=fields,
|
|
1188
|
+
dpix_hash=dpix_hash,
|
|
1189
|
+
normed=normed,
|
|
1190
|
+
shuffle=shuffle,
|
|
1191
|
+
extent=extent,
|
|
1192
|
+
forcedivide=forcedivide)
|
|
1193
|
+
return res
|
|
1194
|
+
|
|
1195
|
+
|
|
1196
|
+
def frompatchind(self, index, rotsignflip=False):
|
|
1197
|
+
|
|
1198
|
+
prepare = super()._patchind_preparerot(index, rotsignflip=rotsignflip)
|
|
1199
|
+
inds_extpatch, patch_isinner, rotangle, ra_rot, dec_rot, rotangle_polars = prepare
|
|
1200
|
+
spintracer_rot = (self.tracer_1[inds_extpatch] + 1j*self.tracer_2[inds_extpatch])*rotangle_polars
|
|
1201
|
+
|
|
1202
|
+
patchcat = SpinTracerCatalog(
|
|
1203
|
+
spin=self.spin,
|
|
1204
|
+
pos1=ra_rot*60.,
|
|
1205
|
+
pos2=dec_rot*60.,
|
|
1206
|
+
tracer_1=spintracer_rot.real,
|
|
1207
|
+
tracer_2=spintracer_rot.imag,
|
|
1208
|
+
weight=self.weight[inds_extpatch],
|
|
1209
|
+
zbins=self.zbins[inds_extpatch],
|
|
1210
|
+
isinner=patch_isinner,
|
|
1211
|
+
units_pos1='arcmin',
|
|
1212
|
+
units_pos2='arcmin',
|
|
1213
|
+
geometry='flat2d',
|
|
1214
|
+
mask=None)
|
|
1215
|
+
|
|
1216
|
+
return patchcat
|