subhaloscript 1.0.3__tar.gz → 1.0.5__tar.gz
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.
- {subhaloscript-1.0.3 → subhaloscript-1.0.5}/PKG-INFO +3 -2
- subhaloscript-1.0.5/README.md +11 -0
- subhaloscript-1.0.5/example-notebooks/basic-usage.ipynb +339 -0
- {subhaloscript-1.0.3 → subhaloscript-1.0.5}/meta.yaml +1 -1
- {subhaloscript-1.0.3 → subhaloscript-1.0.5}/pyproject.toml +1 -1
- {subhaloscript-1.0.3 → subhaloscript-1.0.5}/subscript/scripts/nfilters.py +1 -1
- {subhaloscript-1.0.3 → subhaloscript-1.0.5}/subscript/wrappers.py +5 -4
- {subhaloscript-1.0.3 → subhaloscript-1.0.5}/tests/test_wrappers.py +36 -4
- subhaloscript-1.0.3/README.md +0 -10
- {subhaloscript-1.0.3 → subhaloscript-1.0.5}/.github/workflows/main.yml +0 -0
- {subhaloscript-1.0.3 → subhaloscript-1.0.5}/.gitignore +0 -0
- {subhaloscript-1.0.3 → subhaloscript-1.0.5}/LICENSE +0 -0
- {subhaloscript-1.0.3 → subhaloscript-1.0.5}/subscript/defaults.py +0 -0
- {subhaloscript-1.0.3 → subhaloscript-1.0.5}/subscript/macros.py +0 -0
- {subhaloscript-1.0.3 → subhaloscript-1.0.5}/subscript/scripts/histograms.py +0 -0
- {subhaloscript-1.0.3 → subhaloscript-1.0.5}/subscript/scripts/nodes.py +0 -0
- {subhaloscript-1.0.3 → subhaloscript-1.0.5}/subscript/scripts/spatial.py +0 -0
- {subhaloscript-1.0.3 → subhaloscript-1.0.5}/subscript/tabulatehdf5.py +0 -0
- {subhaloscript-1.0.3 → subhaloscript-1.0.5}/subscript/util.py +0 -0
- {subhaloscript-1.0.3 → subhaloscript-1.0.5}/tests/test_histograms.py +0 -0
- {subhaloscript-1.0.3 → subhaloscript-1.0.5}/tests/test_macros.py +0 -0
- {subhaloscript-1.0.3 → subhaloscript-1.0.5}/tests/test_nfilters.py +0 -0
- {subhaloscript-1.0.3 → subhaloscript-1.0.5}/tests/test_nfilters_legacy.py +0 -0
- {subhaloscript-1.0.3 → subhaloscript-1.0.5}/tests/test_nodes.py +0 -0
- {subhaloscript-1.0.3 → subhaloscript-1.0.5}/tests/test_spatial.py +0 -0
- {subhaloscript-1.0.3 → subhaloscript-1.0.5}/tests/test_tabulatehdf5.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: subhaloscript
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.5
|
|
4
4
|
Summary: Utility functions for analyzing subhalo distributions.
|
|
5
5
|
Author-email: Charles Gannon <cgannon@ucmerced.edu>
|
|
6
6
|
License-File: LICENSE
|
|
@@ -15,7 +15,7 @@ Requires-Dist: scipy
|
|
|
15
15
|
Description-Content-Type: text/markdown
|
|
16
16
|
|
|
17
17
|
# SubScript
|
|
18
|
-
|
|
18
|
+
The ```subscript``` python package provides a library of ergonomic utility functions for analyzing Galacticus (https://github.com/galacticusorg/galacticus) subhalo data.
|
|
19
19
|
|
|
20
20
|
## Installation
|
|
21
21
|
|
|
@@ -24,3 +24,4 @@ Utility functions for analyzing subhalo distributions, focusing on the Galacticu
|
|
|
24
24
|
|
|
25
25
|
### Install via conda
|
|
26
26
|
```conda install cgannonucm::subhaloscript```
|
|
27
|
+
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# SubScript
|
|
2
|
+
The ```subscript``` python package provides a library of ergonomic utility functions for analyzing Galacticus (https://github.com/galacticusorg/galacticus) subhalo data.
|
|
3
|
+
|
|
4
|
+
## Installation
|
|
5
|
+
|
|
6
|
+
### Install via pip
|
|
7
|
+
```pip install subhaloscript```
|
|
8
|
+
|
|
9
|
+
### Install via conda
|
|
10
|
+
```conda install cgannonucm::subhaloscript```
|
|
11
|
+
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cells": [
|
|
3
|
+
{
|
|
4
|
+
"cell_type": "markdown",
|
|
5
|
+
"id": "410260d7",
|
|
6
|
+
"metadata": {},
|
|
7
|
+
"source": [
|
|
8
|
+
"# Example Notebook\n",
|
|
9
|
+
"Author: Charles Gannon\n",
|
|
10
|
+
"\n",
|
|
11
|
+
"Contact: cgannon@ucmerced.edu\n",
|
|
12
|
+
"\n",
|
|
13
|
+
"## Introduction\n",
|
|
14
|
+
"The ```subscript``` python package provides a library of ergonomic utility functions for analyzing Galacticus (https://github.com/galacticusorg/galacticus) subhalo data. This notebook provides an introduction to the functionality provided in this package. More examples are provided in the test folder. \n",
|
|
15
|
+
"\n",
|
|
16
|
+
"# Installation \n",
|
|
17
|
+
"\n",
|
|
18
|
+
"### Install via pip\n",
|
|
19
|
+
"```pip install subhaloscript```\n",
|
|
20
|
+
"\n",
|
|
21
|
+
"### Install via conda\n",
|
|
22
|
+
"```conda install cgannonucm::subhaloscript```"
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"cell_type": "markdown",
|
|
27
|
+
"id": "cd324615",
|
|
28
|
+
"metadata": {},
|
|
29
|
+
"source": [
|
|
30
|
+
"## Data From File\n",
|
|
31
|
+
"```subscript``` integrates with h5py"
|
|
32
|
+
]
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"cell_type": "code",
|
|
36
|
+
"execution_count": 1,
|
|
37
|
+
"id": "2caf02a4",
|
|
38
|
+
"metadata": {},
|
|
39
|
+
"outputs": [],
|
|
40
|
+
"source": [
|
|
41
|
+
"import h5py\n",
|
|
42
|
+
"gout = h5py.File('data/test.hdf5')"
|
|
43
|
+
]
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"cell_type": "markdown",
|
|
47
|
+
"id": "57c0468a",
|
|
48
|
+
"metadata": {},
|
|
49
|
+
"source": [
|
|
50
|
+
"## Node Data\n",
|
|
51
|
+
"In Galacticus each subhalo is represented as a node on the primary halo's merger tree. To access properties of each node, use the ```nodedata``` function. Galacticus can contain multiple trees in a single output file, subscript automatically seperates the output nodes into their respective trees."
|
|
52
|
+
]
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"cell_type": "code",
|
|
56
|
+
"execution_count": 2,
|
|
57
|
+
"id": "fd9fdbe4",
|
|
58
|
+
"metadata": {},
|
|
59
|
+
"outputs": [
|
|
60
|
+
{
|
|
61
|
+
"name": "stdout",
|
|
62
|
+
"output_type": "stream",
|
|
63
|
+
"text": [
|
|
64
|
+
"[7.21810428e+09 1.49945391e+09 3.45035586e+09 3.10940712e+09\n",
|
|
65
|
+
" 2.28942716e+10]\n",
|
|
66
|
+
"[2.51769675e+09 6.33693813e+09 1.88133845e+09 1.02403051e+09\n",
|
|
67
|
+
" 1.48554503e+09]\n"
|
|
68
|
+
]
|
|
69
|
+
}
|
|
70
|
+
],
|
|
71
|
+
"source": [
|
|
72
|
+
"from subscript.scripts.nodes import nodedata\n",
|
|
73
|
+
"\n",
|
|
74
|
+
"mass = nodedata(gout, key='basicMass')\n",
|
|
75
|
+
"\n",
|
|
76
|
+
"# The infall mass of the first 5 subhalos in the 1st galacticus output tree\n",
|
|
77
|
+
"print(mass[0][:5])\n",
|
|
78
|
+
"\n",
|
|
79
|
+
"# The infall mass of the first 5 subhalos in the 2nd galacticus output tree\n",
|
|
80
|
+
"print(mass[1][:5])"
|
|
81
|
+
]
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"cell_type": "markdown",
|
|
85
|
+
"id": "018f16ee",
|
|
86
|
+
"metadata": {},
|
|
87
|
+
"source": [
|
|
88
|
+
"Multiple keys can be passed at once"
|
|
89
|
+
]
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"cell_type": "code",
|
|
93
|
+
"execution_count": 3,
|
|
94
|
+
"id": "e53ac8e2",
|
|
95
|
+
"metadata": {},
|
|
96
|
+
"outputs": [
|
|
97
|
+
{
|
|
98
|
+
"name": "stdout",
|
|
99
|
+
"output_type": "stream",
|
|
100
|
+
"text": [
|
|
101
|
+
"0.5666598142807098\n"
|
|
102
|
+
]
|
|
103
|
+
}
|
|
104
|
+
],
|
|
105
|
+
"source": [
|
|
106
|
+
"import numpy as np\n",
|
|
107
|
+
"mass_basic, mass_bound = nodedata(gout, key=['basicMass', 'massBound'])[0]\n",
|
|
108
|
+
"mass_ratio = np.mean(mass_bound/mass_basic)\n",
|
|
109
|
+
"\n",
|
|
110
|
+
"# The average mass at infall to bound masss for the first tree\n",
|
|
111
|
+
"print(mass_ratio)"
|
|
112
|
+
]
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
"cell_type": "markdown",
|
|
116
|
+
"id": "06d4750c",
|
|
117
|
+
"metadata": {},
|
|
118
|
+
"source": [
|
|
119
|
+
"Count number of nodes"
|
|
120
|
+
]
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"cell_type": "code",
|
|
124
|
+
"execution_count": 4,
|
|
125
|
+
"id": "5812266f",
|
|
126
|
+
"metadata": {},
|
|
127
|
+
"outputs": [
|
|
128
|
+
{
|
|
129
|
+
"name": "stdout",
|
|
130
|
+
"output_type": "stream",
|
|
131
|
+
"text": [
|
|
132
|
+
"246.05357142857142\n"
|
|
133
|
+
]
|
|
134
|
+
}
|
|
135
|
+
],
|
|
136
|
+
"source": [
|
|
137
|
+
"from subscript.scripts.nodes import nodecount\n",
|
|
138
|
+
"\n",
|
|
139
|
+
"# Average number of nodes per tree\n",
|
|
140
|
+
"print(np.mean(nodecount(gout)))"
|
|
141
|
+
]
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
"cell_type": "markdown",
|
|
145
|
+
"id": "7279057e",
|
|
146
|
+
"metadata": {},
|
|
147
|
+
"source": [
|
|
148
|
+
"## Filters\n",
|
|
149
|
+
"```subscript``` supports filtering nodes by passing a ```nfilter``` function or numpy array of booleans."
|
|
150
|
+
]
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
"cell_type": "code",
|
|
154
|
+
"execution_count": 5,
|
|
155
|
+
"id": "f88029f9",
|
|
156
|
+
"metadata": {},
|
|
157
|
+
"outputs": [
|
|
158
|
+
{
|
|
159
|
+
"name": "stdout",
|
|
160
|
+
"output_type": "stream",
|
|
161
|
+
"text": [
|
|
162
|
+
"13.0\n"
|
|
163
|
+
]
|
|
164
|
+
}
|
|
165
|
+
],
|
|
166
|
+
"source": [
|
|
167
|
+
"# Get the average host halo mass\n",
|
|
168
|
+
"import subscript.scripts.nfilters as nf\n",
|
|
169
|
+
"# Only include host halo nodes\n",
|
|
170
|
+
"host_halo_mass = nodedata(gout, key='basicMass', nfilter=nf.hosthalos)\n",
|
|
171
|
+
"\n",
|
|
172
|
+
"# Log 10 of average host halo mass\n",
|
|
173
|
+
"print(np.log10(np.mean(host_halo_mass)))"
|
|
174
|
+
]
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
"cell_type": "markdown",
|
|
178
|
+
"id": "44f816e1",
|
|
179
|
+
"metadata": {},
|
|
180
|
+
"source": [
|
|
181
|
+
"### Combining filters"
|
|
182
|
+
]
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
"cell_type": "markdown",
|
|
186
|
+
"id": "caa435ed",
|
|
187
|
+
"metadata": {},
|
|
188
|
+
"source": [
|
|
189
|
+
"Filters can be combined or modified using boolean logic. We can use the ```logical_and``` or ```logical_not``` function to combine two filters or the ```logical_not``` function to invert the filter."
|
|
190
|
+
]
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
"cell_type": "code",
|
|
194
|
+
"execution_count": 6,
|
|
195
|
+
"id": "1368ab7d",
|
|
196
|
+
"metadata": {},
|
|
197
|
+
"outputs": [
|
|
198
|
+
{
|
|
199
|
+
"name": "stdout",
|
|
200
|
+
"output_type": "stream",
|
|
201
|
+
"text": [
|
|
202
|
+
"0.04988945595354875\n"
|
|
203
|
+
]
|
|
204
|
+
}
|
|
205
|
+
],
|
|
206
|
+
"source": [
|
|
207
|
+
"from subscript.scripts.spatial import project3d\n",
|
|
208
|
+
"# Only get subhalos within 50 kpc of the host \n",
|
|
209
|
+
"# Note ```subscript``` uses default units of galacticus which is MPC\n",
|
|
210
|
+
"filter_combined = nf.logical_and(\n",
|
|
211
|
+
" nf.subhalos,\n",
|
|
212
|
+
" nf.r3d(None, 0, 5E-2) # Passing 'None' as a first argument 'freezes' the filter, saving the key word arguments\n",
|
|
213
|
+
" )\n",
|
|
214
|
+
"\n",
|
|
215
|
+
"# Now we have no subhalos outside of 0.05 MPC from the center of the host\n",
|
|
216
|
+
"print(np.max(project3d(gout, nfilter=filter_combined)[0])) "
|
|
217
|
+
]
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
"cell_type": "markdown",
|
|
221
|
+
"id": "00dce686",
|
|
222
|
+
"metadata": {},
|
|
223
|
+
"source": [
|
|
224
|
+
"## Statistical Analysis\n",
|
|
225
|
+
"\n",
|
|
226
|
+
"Perform statistical analysis over multiple trees by passing the argument ```summarize=true``` and optionally pass a list of functions, for statistical analysis passing the ```statfuncs``` argument. The default option is ```statfuncs=[np.mean]```, but if the standard deviation is required, you can pass ```statfuncts=[np.mean, np.std]```"
|
|
227
|
+
]
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
"cell_type": "code",
|
|
231
|
+
"execution_count": 7,
|
|
232
|
+
"id": "72a2eb62",
|
|
233
|
+
"metadata": {},
|
|
234
|
+
"outputs": [
|
|
235
|
+
{
|
|
236
|
+
"data": {
|
|
237
|
+
"text/plain": [
|
|
238
|
+
"[]"
|
|
239
|
+
]
|
|
240
|
+
},
|
|
241
|
+
"execution_count": 7,
|
|
242
|
+
"metadata": {},
|
|
243
|
+
"output_type": "execute_result"
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
"data": {
|
|
247
|
+
"image/png": "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",
|
|
248
|
+
"text/plain": [
|
|
249
|
+
"<Figure size 640x480 with 1 Axes>"
|
|
250
|
+
]
|
|
251
|
+
},
|
|
252
|
+
"metadata": {},
|
|
253
|
+
"output_type": "display_data"
|
|
254
|
+
}
|
|
255
|
+
],
|
|
256
|
+
"source": [
|
|
257
|
+
"# Subhalo massfunction\n",
|
|
258
|
+
"from subscript.scripts.histograms import massfunction\n",
|
|
259
|
+
"# Provides galacticus default parameter keys\n",
|
|
260
|
+
"from subscript.defaults import ParamKeys\n",
|
|
261
|
+
"import matplotlib.pyplot as plt\n",
|
|
262
|
+
"\n",
|
|
263
|
+
"\n",
|
|
264
|
+
"out = massfunction(\n",
|
|
265
|
+
" gout,\n",
|
|
266
|
+
" bins=np.logspace(9, 13, 30), \n",
|
|
267
|
+
" key_mass = ParamKeys.mass_bound, # The default key for bound mass of the subhalo\n",
|
|
268
|
+
" nfilter=nf.subhalos, # Only consider subhalos \n",
|
|
269
|
+
" summarize=True, # Take statistics over multiple trees\n",
|
|
270
|
+
" statfuncs=[np.mean, np.std] # Get the mean and std\n",
|
|
271
|
+
" )\n",
|
|
272
|
+
"\n",
|
|
273
|
+
"dndm_mean, mbine = out[0]\n",
|
|
274
|
+
"dndm_std , _ = out[1]\n",
|
|
275
|
+
"\n",
|
|
276
|
+
"# Plot the mean mass function over all trees, show the standard deviation at each point\n",
|
|
277
|
+
"plt.errorbar(mbine[:-1], dndm_mean, dndm_std)\n",
|
|
278
|
+
"plt.loglog()"
|
|
279
|
+
]
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
"cell_type": "markdown",
|
|
283
|
+
"id": "a5a8888c",
|
|
284
|
+
"metadata": {},
|
|
285
|
+
"source": [
|
|
286
|
+
"### Custom Analysis Functions\n",
|
|
287
|
+
"\n",
|
|
288
|
+
"Use the ```gscript``` decerator to create analysis functions"
|
|
289
|
+
]
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
"cell_type": "code",
|
|
293
|
+
"execution_count": 8,
|
|
294
|
+
"id": "ba018c49",
|
|
295
|
+
"metadata": {},
|
|
296
|
+
"outputs": [
|
|
297
|
+
{
|
|
298
|
+
"name": "stdout",
|
|
299
|
+
"output_type": "stream",
|
|
300
|
+
"text": [
|
|
301
|
+
"0.5539299558467177\n"
|
|
302
|
+
]
|
|
303
|
+
}
|
|
304
|
+
],
|
|
305
|
+
"source": [
|
|
306
|
+
"from subscript.wrappers import gscript\n",
|
|
307
|
+
"\n",
|
|
308
|
+
"# Custom analysis function to take the ratio between bound and infall mass\n",
|
|
309
|
+
"@gscript\n",
|
|
310
|
+
"def massratio_avg(gout, **kwargs):\n",
|
|
311
|
+
" return np.mean(gout[ParamKeys.mass_bound] / gout[ParamKeys.mass_basic])\n",
|
|
312
|
+
"\n",
|
|
313
|
+
"# Average bound to infall mass ratio\n",
|
|
314
|
+
"print(massratio_avg(gout, nfilter=nf.subhalos, summarize=True))"
|
|
315
|
+
]
|
|
316
|
+
}
|
|
317
|
+
],
|
|
318
|
+
"metadata": {
|
|
319
|
+
"kernelspec": {
|
|
320
|
+
"display_name": ".venv",
|
|
321
|
+
"language": "python",
|
|
322
|
+
"name": "python3"
|
|
323
|
+
},
|
|
324
|
+
"language_info": {
|
|
325
|
+
"codemirror_mode": {
|
|
326
|
+
"name": "ipython",
|
|
327
|
+
"version": 3
|
|
328
|
+
},
|
|
329
|
+
"file_extension": ".py",
|
|
330
|
+
"mimetype": "text/x-python",
|
|
331
|
+
"name": "python",
|
|
332
|
+
"nbconvert_exporter": "python",
|
|
333
|
+
"pygments_lexer": "ipython3",
|
|
334
|
+
"version": "3.13.3"
|
|
335
|
+
}
|
|
336
|
+
},
|
|
337
|
+
"nbformat": 4,
|
|
338
|
+
"nbformat_minor": 5
|
|
339
|
+
}
|
|
@@ -278,7 +278,7 @@ def nfilter_virialized(*args, **kwargs):
|
|
|
278
278
|
return withinrv(*args, **kwargs)
|
|
279
279
|
|
|
280
280
|
@gscript
|
|
281
|
-
def subhalos_valid(gout, mass_min, mass_max, key_mass=ParamKeys.mass,
|
|
281
|
+
def subhalos_valid(gout, mass_min=-np.inf, mass_max=np.inf, key_mass=ParamKeys.mass,
|
|
282
282
|
kwargs_nfilter_subhalos=None, kwargs_nfilter_virialized=None, kwargs_nfilter_range=None, **kwargs):
|
|
283
283
|
"""
|
|
284
284
|
Select subhalos within the virial radius and a given mass range.
|
|
@@ -230,14 +230,15 @@ def gscript_proj(func):
|
|
|
230
230
|
|
|
231
231
|
## This wrapped as well so we can call with None
|
|
232
232
|
def wrap_inner(gout, **kwargs2):
|
|
233
|
-
_gout = format_nodedata(gout)
|
|
233
|
+
_gout = format_nodedata(gout)
|
|
234
234
|
|
|
235
235
|
_input = []
|
|
236
236
|
for n, _ in enumerate(normvector):
|
|
237
237
|
_in = copy(_gout)
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
238
|
+
for i in _in:
|
|
239
|
+
_i = copy(i)
|
|
240
|
+
_i.data['__custom_proj_iter__'] = n * np.ones(i.data[next(i.data.__iter__())].shape[0], dtype=int)
|
|
241
|
+
_input.append(_i)
|
|
241
242
|
|
|
242
243
|
return wrap_inner_main(_input, **(kwargs | kwargs2))
|
|
243
244
|
|
|
@@ -53,12 +53,10 @@ def test_multi_proj():
|
|
|
53
53
|
out_expected_yz = np.asarray((4, 3, 0), dtype=int)
|
|
54
54
|
|
|
55
55
|
out_expected = np.mean(np.asarray((out_expected_xy, out_expected_xz, out_expected_yz)), axis=0)
|
|
56
|
-
print(out_expected)
|
|
57
56
|
|
|
58
57
|
out = spatial2d_dn(mockdata, bins=bins, normvector=norm, summarize=True)
|
|
59
|
-
print(out)
|
|
60
|
-
out_actual, dn_r = out
|
|
61
58
|
|
|
59
|
+
out_actual, dn_r = out
|
|
62
60
|
|
|
63
61
|
testing.assert_allclose(dn_r, bins)
|
|
64
62
|
testing.assert_allclose(out_actual, out_expected)
|
|
@@ -170,11 +168,45 @@ def test_multiproj():
|
|
|
170
168
|
|
|
171
169
|
|
|
172
170
|
def test_multiproj_file():
|
|
171
|
+
# Test that combining multiple projections is the same as
|
|
172
|
+
# passing multiple projection vectors
|
|
173
|
+
path_dmo = "tests/data/test.hdf5"
|
|
174
|
+
gout = h5py.File(path_dmo)
|
|
175
|
+
|
|
176
|
+
nfproj = freeze(r2d, rmin=1E-1, rmax=2E-2)
|
|
177
|
+
|
|
178
|
+
nv = np.identity(3)
|
|
179
|
+
n_actual = multiproj(nodecount, nfilter=nfproj)(gout, summarize=True, normvector=nv)
|
|
180
|
+
|
|
181
|
+
ncomb = []
|
|
182
|
+
ncomb += nodecount(gout, nfilter=nfproj, normvector=nv[0])
|
|
183
|
+
ncomb = nodecount(gout, nfilter=nfproj, normvector=nv[0])
|
|
184
|
+
ncomb = nodecount(gout, nfilter=nfproj, normvector=nv[0])
|
|
185
|
+
|
|
186
|
+
n_expected = np.mean(ncomb)
|
|
187
|
+
|
|
188
|
+
testing.assert_allclose(n_actual, n_expected)
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def test_multiproj_file():
|
|
192
|
+
# Test that projections are treated as trees in output shape
|
|
173
193
|
path_dmo = "tests/data/test.hdf5"
|
|
174
194
|
gout = h5py.File(path_dmo)
|
|
175
195
|
|
|
176
196
|
nfproj = freeze(r2d, rmin=1E-1, rmax=2E-2)
|
|
177
|
-
|
|
197
|
+
|
|
198
|
+
nprojv = 6
|
|
199
|
+
|
|
200
|
+
nv = np.random.random(18).reshape(nprojv,3)
|
|
201
|
+
nproj = multiproj(nodecount, nfilter=nfproj)(gout, normvector=nv)
|
|
202
|
+
|
|
203
|
+
ntrees = len(nodecount(gout))
|
|
204
|
+
|
|
205
|
+
testing.assert_equal(len(nproj), ntrees * nprojv)
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
|
|
178
210
|
|
|
179
211
|
def test_gscript_unfilter():
|
|
180
212
|
# Ensure the expected behaviour occours when calling a script within a script
|
subhaloscript-1.0.3/README.md
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
# SubScript
|
|
2
|
-
Utility functions for analyzing subhalo distributions, focusing on the Galacticus (https://github.com/galacticusorg/galacticus) output format. The goal of this package is to facilitate quick statistical analysis of subhalo distributions across multiple trees.
|
|
3
|
-
|
|
4
|
-
## Installation
|
|
5
|
-
|
|
6
|
-
### Install via pip
|
|
7
|
-
```pip install subhaloscript```
|
|
8
|
-
|
|
9
|
-
### Install via conda
|
|
10
|
-
```conda install cgannonucm::subhaloscript```
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|