opencosmo 1.0.0__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.
Files changed (94) hide show
  1. opencosmo-1.0.0/LICENSE.md +11 -0
  2. opencosmo-1.0.0/PKG-INFO +182 -0
  3. opencosmo-1.0.0/README.md +160 -0
  4. opencosmo-1.0.0/pyproject.toml +121 -0
  5. opencosmo-1.0.0/src/opencosmo/__init__.py +26 -0
  6. opencosmo-1.0.0/src/opencosmo/analysis/__init__.py +42 -0
  7. opencosmo-1.0.0/src/opencosmo/analysis/cli.py +32 -0
  8. opencosmo-1.0.0/src/opencosmo/analysis/diffsky.py +20 -0
  9. opencosmo-1.0.0/src/opencosmo/analysis/install/__init__.py +5 -0
  10. opencosmo-1.0.0/src/opencosmo/analysis/install/install.py +91 -0
  11. opencosmo-1.0.0/src/opencosmo/analysis/install/source.py +52 -0
  12. opencosmo-1.0.0/src/opencosmo/analysis/install/specs/__init__.py +50 -0
  13. opencosmo-1.0.0/src/opencosmo/analysis/install/specs/diffsky.json +39 -0
  14. opencosmo-1.0.0/src/opencosmo/analysis/install/specs/vizualize.json +16 -0
  15. opencosmo-1.0.0/src/opencosmo/analysis/install/versions.py +23 -0
  16. opencosmo-1.0.0/src/opencosmo/analysis/yt_utils.py +282 -0
  17. opencosmo-1.0.0/src/opencosmo/analysis/yt_viz.py +543 -0
  18. opencosmo-1.0.0/src/opencosmo/collection/__init__.py +16 -0
  19. opencosmo-1.0.0/src/opencosmo/collection/io.py +85 -0
  20. opencosmo-1.0.0/src/opencosmo/collection/lightcone/__init__.py +4 -0
  21. opencosmo-1.0.0/src/opencosmo/collection/lightcone/healpix_map.py +1075 -0
  22. opencosmo-1.0.0/src/opencosmo/collection/lightcone/lightcone.py +1161 -0
  23. opencosmo-1.0.0/src/opencosmo/collection/lightcone/stack.py +222 -0
  24. opencosmo-1.0.0/src/opencosmo/collection/protocols.py +53 -0
  25. opencosmo-1.0.0/src/opencosmo/collection/simulation/__init__.py +3 -0
  26. opencosmo-1.0.0/src/opencosmo/collection/simulation/simulation.py +477 -0
  27. opencosmo-1.0.0/src/opencosmo/collection/structure/__init__.py +5 -0
  28. opencosmo-1.0.0/src/opencosmo/collection/structure/evaluate.py +218 -0
  29. opencosmo-1.0.0/src/opencosmo/collection/structure/handler.py +290 -0
  30. opencosmo-1.0.0/src/opencosmo/collection/structure/io.py +242 -0
  31. opencosmo-1.0.0/src/opencosmo/collection/structure/structure.py +1314 -0
  32. opencosmo-1.0.0/src/opencosmo/column/__init__.py +4 -0
  33. opencosmo-1.0.0/src/opencosmo/column/cache.py +300 -0
  34. opencosmo-1.0.0/src/opencosmo/column/column.py +633 -0
  35. opencosmo-1.0.0/src/opencosmo/column/evaluate.py +131 -0
  36. opencosmo-1.0.0/src/opencosmo/column/stock.py +145 -0
  37. opencosmo-1.0.0/src/opencosmo/cosmology.py +80 -0
  38. opencosmo-1.0.0/src/opencosmo/dataset/__init__.py +3 -0
  39. opencosmo-1.0.0/src/opencosmo/dataset/build.py +116 -0
  40. opencosmo-1.0.0/src/opencosmo/dataset/dataset.py +854 -0
  41. opencosmo-1.0.0/src/opencosmo/dataset/derived.py +189 -0
  42. opencosmo-1.0.0/src/opencosmo/dataset/evaluate.py +185 -0
  43. opencosmo-1.0.0/src/opencosmo/dataset/formats.py +110 -0
  44. opencosmo-1.0.0/src/opencosmo/dataset/handler.py +203 -0
  45. opencosmo-1.0.0/src/opencosmo/dataset/im.py +31 -0
  46. opencosmo-1.0.0/src/opencosmo/dataset/mpi.py +50 -0
  47. opencosmo-1.0.0/src/opencosmo/dataset/state.py +622 -0
  48. opencosmo-1.0.0/src/opencosmo/evaluate.py +67 -0
  49. opencosmo-1.0.0/src/opencosmo/file.py +108 -0
  50. opencosmo-1.0.0/src/opencosmo/header.py +374 -0
  51. opencosmo-1.0.0/src/opencosmo/index/__init__.py +35 -0
  52. opencosmo-1.0.0/src/opencosmo/index/build.py +31 -0
  53. opencosmo-1.0.0/src/opencosmo/index/get.py +73 -0
  54. opencosmo-1.0.0/src/opencosmo/index/in_range.py +74 -0
  55. opencosmo-1.0.0/src/opencosmo/index/mask.py +58 -0
  56. opencosmo-1.0.0/src/opencosmo/index/project.py +56 -0
  57. opencosmo-1.0.0/src/opencosmo/index/take.py +139 -0
  58. opencosmo-1.0.0/src/opencosmo/index/unary.py +61 -0
  59. opencosmo-1.0.0/src/opencosmo/io/__init__.py +20 -0
  60. opencosmo-1.0.0/src/opencosmo/io/file.py +152 -0
  61. opencosmo-1.0.0/src/opencosmo/io/io.py +274 -0
  62. opencosmo-1.0.0/src/opencosmo/io/mpi.py +473 -0
  63. opencosmo-1.0.0/src/opencosmo/io/parquet.py +90 -0
  64. opencosmo-1.0.0/src/opencosmo/io/protocols.py +53 -0
  65. opencosmo-1.0.0/src/opencosmo/io/schema.py +48 -0
  66. opencosmo-1.0.0/src/opencosmo/io/serial.py +33 -0
  67. opencosmo-1.0.0/src/opencosmo/io/updaters.py +77 -0
  68. opencosmo-1.0.0/src/opencosmo/io/verify.py +164 -0
  69. opencosmo-1.0.0/src/opencosmo/io/writer.py +169 -0
  70. opencosmo-1.0.0/src/opencosmo/mpi.py +18 -0
  71. opencosmo-1.0.0/src/opencosmo/parameters/__init__.py +12 -0
  72. opencosmo-1.0.0/src/opencosmo/parameters/cosmology.py +74 -0
  73. opencosmo-1.0.0/src/opencosmo/parameters/diffsky.py +15 -0
  74. opencosmo-1.0.0/src/opencosmo/parameters/dtype.py +23 -0
  75. opencosmo-1.0.0/src/opencosmo/parameters/file.py +83 -0
  76. opencosmo-1.0.0/src/opencosmo/parameters/hacc.py +276 -0
  77. opencosmo-1.0.0/src/opencosmo/parameters/origin.py +8 -0
  78. opencosmo-1.0.0/src/opencosmo/parameters/parameters.py +52 -0
  79. opencosmo-1.0.0/src/opencosmo/parameters/units.py +70 -0
  80. opencosmo-1.0.0/src/opencosmo/spatial/__init__.py +5 -0
  81. opencosmo-1.0.0/src/opencosmo/spatial/builders.py +118 -0
  82. opencosmo-1.0.0/src/opencosmo/spatial/check.py +102 -0
  83. opencosmo-1.0.0/src/opencosmo/spatial/healpix.py +50 -0
  84. opencosmo-1.0.0/src/opencosmo/spatial/models.py +26 -0
  85. opencosmo-1.0.0/src/opencosmo/spatial/octree.py +268 -0
  86. opencosmo-1.0.0/src/opencosmo/spatial/protocols.py +70 -0
  87. opencosmo-1.0.0/src/opencosmo/spatial/region.py +390 -0
  88. opencosmo-1.0.0/src/opencosmo/spatial/tree.py +245 -0
  89. opencosmo-1.0.0/src/opencosmo/spatial/utils.py +33 -0
  90. opencosmo-1.0.0/src/opencosmo/units/__init__.py +13 -0
  91. opencosmo-1.0.0/src/opencosmo/units/convention.py +14 -0
  92. opencosmo-1.0.0/src/opencosmo/units/converters.py +209 -0
  93. opencosmo-1.0.0/src/opencosmo/units/get.py +192 -0
  94. opencosmo-1.0.0/src/opencosmo/units/handler.py +217 -0
@@ -0,0 +1,11 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2026, OpenCosmo Project All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6
+
7
+ Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8
+ Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9
+ Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
10
+
11
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,182 @@
1
+ Metadata-Version: 2.3
2
+ Name: opencosmo
3
+ Version: 1.0.0
4
+ Summary: OpenCosmo Python Toolkit
5
+ Author: Patrick Wells, Will Hicks, Patricia Larsen, Michael Buehlmann
6
+ Author-email: Patrick Wells <pwells@anl.gov>, Will Hicks <whicks@anl.gov>, Patricia Larsen <prlarsen@anl.gov>, Michael Buehlmann <mbuehlmann@anl.gov>
7
+ Requires-Dist: h5py>=3.12.1,<4.0.0
8
+ Requires-Dist: astropy>=7.2.0,<8.0.0
9
+ Requires-Dist: pydantic>=2.10.6,<3.0.0
10
+ Requires-Dist: hdf5plugin>=5.0.0,<6.0.0
11
+ Requires-Dist: healpy>=1.18.1,<2.0.0
12
+ Requires-Dist: healsparse==1.11.1
13
+ Requires-Dist: deprecated>=1.2.18,<2.0.0
14
+ Requires-Dist: numpy>=2.0,<2.4
15
+ Requires-Dist: click>=8.2.1,<9.0.0
16
+ Requires-Dist: numba>=0.62.1
17
+ Requires-Dist: rustworkx>=0.17.1
18
+ Requires-Dist: pyarrow>=21.0.0 ; extra == 'io'
19
+ Requires-Python: >=3.11, <3.15
20
+ Provides-Extra: io
21
+ Description-Content-Type: text/markdown
22
+
23
+ <h1 align="center">
24
+ <picture>
25
+ <source srcset="https://raw.githubusercontent.com/ArgonneCPAC/opencosmo/main/branding/opencosmo_dark.png" media="(prefers-color-scheme: dark)">
26
+ <source srcset="https://raw.githubusercontent.com/ArgonneCPAC/opencosmo/main/branding/opencosmo_light.png" media="(prefers-color-scheme: light)">
27
+ <img src="https://raw.githubusercontent.com/ArgonneCPAC/opencosmo/main/branding/opencosmo_light.png" alt="OpenCosmo">
28
+ </picture>
29
+ </h1><br>
30
+
31
+ [![CI](https://github.com/ArgonneCPAC/OpenCosmo/actions/workflows/merge.yaml/badge.svg)](https://github.com/ArgonneCPAC/OpenCosmo/actions/workflows/merge.yaml)
32
+ [![PyPI - Version](https://img.shields.io/pypi/v/opencosmo)](https://pypi.org/project/opencosmo/)
33
+ [![Conda Version](https://img.shields.io/conda/vn/conda-forge/opencosmo)](https://anaconda.org/conda-forge/opencosmo)
34
+ [![GitHub License](https://img.shields.io/github/license/ArgonneCPAC/opencosmo)](https://github.com/ArgonneCPAC/OpenCosmo/blob/main/LICENSE.md)
35
+
36
+
37
+ The OpenCosmo Python Toolkit provides utilities for reading, writing and manipulating data from cosmological simulations produced by the Cosmolgical Physics and Advanced Computing (CPAC) group at Argonne National Laboratory. It can be used to work with smaller quantities data retrieved with the CosmoExplorer, as well as the much larget datasets these queries draw from. The OpenCosmo toolkit integrates with standard tools such as AstroPy, and allows you to manipulate data in a fully-consistent cosmological context.
38
+
39
+ ### Installation
40
+
41
+ The OpenCosmo library is available for Python 3.11 and up on Linux and MacOS (and Windows via [WSL](https://learn.microsoft.com/en-us/windows/wsl/setup/environment)). It can be installed easily with `pip`:
42
+
43
+ ```bash
44
+ pip install opencosmo
45
+ ```
46
+
47
+
48
+ There's a good chance the default version of Python on your system is less than 3.11. Whether or not this is the case, we recommend installing `opencosmo` into a virtual environment. If you're using [Conda](https://docs.conda.io/projects/conda/en/stable/user-guide/getting-started.html), you can create a new environment and install `opencosmo` into it automatically:
49
+
50
+ ```bash
51
+ conda create -n opencosmo_env conda-forge::opencosmo
52
+ conda activate opencosmo_env
53
+ ```
54
+
55
+ or if you already have a virtual environment to use:
56
+
57
+ ```bash
58
+ conda install conda-forge::opencosmo
59
+ ```
60
+
61
+ If you plan to use `opencosmo` in a Jupyter notebook, you can install the `ipykernel` package to make the environment available as a kernel:
62
+
63
+ ```bash
64
+ pip install ipykernel # can also be installed with conda
65
+ python -m ipykernel install --user --name=opencosmo
66
+ ```
67
+
68
+ Be sure you have run the "activate" command shown above before running the `ipykernel` command.
69
+
70
+ ## Getting Started
71
+
72
+ To get started, download the "haloproperites.hdf5" from the [OpenCosmo Google Drive](https://drive.google.com/drive/folders/1CYmZ4sE-RdhRdLhGuYR3rFfgyA3M1mU-?usp=sharing). This file contains properties of dark-matter halos from a small hydrodynamical simulation run with HACC. You can easily open the data with the `open` command:
73
+
74
+ ```python
75
+ import opencosmo as oc
76
+
77
+ dataset = oc.open("haloproperties.hdf5")
78
+ print(dataset)
79
+ ```
80
+
81
+ ```text
82
+ OpenCosmo Dataset (length=237441)
83
+ Cosmology: FlatLambdaCDM(name=None, H0=<Quantity 67.66 km / (Mpc s)>, Om0=0.3096446816186967, Tcmb0=<Quantity 0. K>, Neff=3.04, m_nu=None, Ob0=0.04897468161869667)
84
+ First 10 rows:
85
+ block fof_halo_1D_vel_disp fof_halo_center_x ... sod_halo_sfr unique_tag
86
+ km / s Mpc ... solMass / yr
87
+ int32 float32 float32 ... float32 int64
88
+ ----- -------------------- ----------------- ... ------------ ----------
89
+ 0 32.088795 1.4680439 ... -101.0 21674
90
+ 0 41.14525 0.19616994 ... -101.0 44144
91
+ 0 73.82962 1.5071135 ... 3.1447952 48226
92
+ 0 31.17231 0.7526525 ... -101.0 58472
93
+ 0 23.038841 5.3246417 ... -101.0 60550
94
+ 0 37.071426 0.5153746 ... -101.0 537760
95
+ 0 26.203058 2.1734374 ... -101.0 542858
96
+ 0 78.7636 2.1477687 ... 0.0 548994
97
+ 0 37.12636 6.9660196 ... -101.0 571540
98
+ 0 58.09235 6.072006 ... 1.5439711 576648
99
+ ```
100
+
101
+ The `open` function returns a `Dataset` object, which holds the raw data as well as information about the simulation. You can easily access the data and cosmology as Astropy objects:
102
+ ```python
103
+ dataset.data
104
+ dataset.cosmology
105
+ ```
106
+
107
+ The first will return an astropy table of the data, with all associated units already applied. The second will return the astropy cosmology object that represents the cosmology the simulation was run with.
108
+
109
+ ### Basic Querying
110
+
111
+ Although you can access data directly, `opencosmo` provides tools for querying and transforming the data in a fully cosmology-aware context. For example, suppose we wanted to plot the concentration-mass relationship for the halos in our simulation above a certain mass. One way to perform this would be as follows:
112
+
113
+ ```python
114
+ dataset = dataset
115
+ .filter(oc.col("fof_halo_mass") > 1e13)
116
+ .take(1000, at="random")
117
+ .select(("fof_halo_mass", "sod_halo_cdelta"))
118
+
119
+ print(dataset)
120
+
121
+ ```
122
+
123
+ ```text
124
+ OpenCosmo Dataset (length=1000)
125
+ Cosmology: FlatLambdaCDM(name=None, H0=<Quantity 67.66 km / (Mpc s)>, Om0=0.3096446816186967, Tcmb0=<Quantity 0. K>, Neff=3.04, m_nu=None, Ob0=0.04897468161869667)
126
+ First 10 rows:
127
+ fof_halo_mass sod_halo_cdelta
128
+ solMass
129
+ float32 float32
130
+ ---------------- ---------------
131
+ 11220446000000.0 4.5797048
132
+ 17266723000000.0 7.4097505
133
+ 51242150000000.0 1.8738283
134
+ 70097712000000.0 4.2764015
135
+ 51028305000000.0 2.678151
136
+ 11960567000000.0 3.9594727
137
+ 15276915000000.0 5.793542
138
+ 16002001000000.0 2.4318497
139
+ 47030307000000.0 3.7146702
140
+ 15839942000000.0 3.245569
141
+ ```
142
+
143
+ We could then plot the data, or perform further transformations. This is cool on its own, but the real power of `opencosmo` comes from its ability to work with different data types. Go ahead and download the "haloparticles" file from the [OpenCosmo Google Drive](https://drive.google.com/drive/folders/1CYmZ4sE-RdhRdLhGuYR3rFfgyA3M1mU-?usp=sharing) and try the following:
144
+
145
+ ```python
146
+ import opencosmo as oc
147
+
148
+ data = oc.open("haloproperties.hdf5", "haloparticles.hdf5")
149
+ ```
150
+ This will return a data *collection* that will allow you to query and transform the data as before, but will associate the halos with their particles.
151
+
152
+ ```python
153
+
154
+ data = data
155
+ .filter(oc.col("fof_halo_mass") > 1e13)
156
+ .take(1000, at="random")
157
+
158
+ for halo in data.halos():
159
+ halo_properties = halo["halo_properties"]
160
+ dm_particles = halo["dm_particles"]
161
+ star_particles = halo["star_particles"]
162
+ ```
163
+
164
+ In each iteration, "halo properties" will be a dictionary containing the properties of the halo (such as its total mass), while "dm_particles" and "star_particles" will be OpenCosmo datasets containing the dark matter and stars associated with the halo, respectively. Because these are just like the dataset object we saw eariler, we can further query and transform the particles as needed for our analysis. For more details on how to use the library, check out the [full documentation](https://opencosmo.readthedocs.io/en/latest/).
165
+
166
+ ### Testing
167
+
168
+ To run tests, first download the test data [from Google Drive](https://drive.google.com/drive/folders/1CYmZ4sE-RdhRdLhGuYR3rFfgyA3M1mU-?usp=sharing). Set environment variable `OPENCOSMO_DATA_PATH` to the path where the data is stored. Then run the tests with `pytest`:
169
+
170
+ ```bash
171
+ export OPENCOSMO_DATA_PATH=/path/to/data
172
+ # From the repository root
173
+ pytest --ignore test/parallel
174
+ ```
175
+
176
+ Although opencosmo does support multi-core processing via MPI, the default installation does not include the necessary dependencies to work in an MPI environment. If you need these capabilities, check out the guide in our documentation.
177
+
178
+ ### Contributing
179
+
180
+ We welcome bug reports and feature requests from the community. If you would like to contribute to the project, please check out the [contributing guide](CONTRIBUTING.md) for more information.
181
+
182
+ ```
@@ -0,0 +1,160 @@
1
+ <h1 align="center">
2
+ <picture>
3
+ <source srcset="https://raw.githubusercontent.com/ArgonneCPAC/opencosmo/main/branding/opencosmo_dark.png" media="(prefers-color-scheme: dark)">
4
+ <source srcset="https://raw.githubusercontent.com/ArgonneCPAC/opencosmo/main/branding/opencosmo_light.png" media="(prefers-color-scheme: light)">
5
+ <img src="https://raw.githubusercontent.com/ArgonneCPAC/opencosmo/main/branding/opencosmo_light.png" alt="OpenCosmo">
6
+ </picture>
7
+ </h1><br>
8
+
9
+ [![CI](https://github.com/ArgonneCPAC/OpenCosmo/actions/workflows/merge.yaml/badge.svg)](https://github.com/ArgonneCPAC/OpenCosmo/actions/workflows/merge.yaml)
10
+ [![PyPI - Version](https://img.shields.io/pypi/v/opencosmo)](https://pypi.org/project/opencosmo/)
11
+ [![Conda Version](https://img.shields.io/conda/vn/conda-forge/opencosmo)](https://anaconda.org/conda-forge/opencosmo)
12
+ [![GitHub License](https://img.shields.io/github/license/ArgonneCPAC/opencosmo)](https://github.com/ArgonneCPAC/OpenCosmo/blob/main/LICENSE.md)
13
+
14
+
15
+ The OpenCosmo Python Toolkit provides utilities for reading, writing and manipulating data from cosmological simulations produced by the Cosmolgical Physics and Advanced Computing (CPAC) group at Argonne National Laboratory. It can be used to work with smaller quantities data retrieved with the CosmoExplorer, as well as the much larget datasets these queries draw from. The OpenCosmo toolkit integrates with standard tools such as AstroPy, and allows you to manipulate data in a fully-consistent cosmological context.
16
+
17
+ ### Installation
18
+
19
+ The OpenCosmo library is available for Python 3.11 and up on Linux and MacOS (and Windows via [WSL](https://learn.microsoft.com/en-us/windows/wsl/setup/environment)). It can be installed easily with `pip`:
20
+
21
+ ```bash
22
+ pip install opencosmo
23
+ ```
24
+
25
+
26
+ There's a good chance the default version of Python on your system is less than 3.11. Whether or not this is the case, we recommend installing `opencosmo` into a virtual environment. If you're using [Conda](https://docs.conda.io/projects/conda/en/stable/user-guide/getting-started.html), you can create a new environment and install `opencosmo` into it automatically:
27
+
28
+ ```bash
29
+ conda create -n opencosmo_env conda-forge::opencosmo
30
+ conda activate opencosmo_env
31
+ ```
32
+
33
+ or if you already have a virtual environment to use:
34
+
35
+ ```bash
36
+ conda install conda-forge::opencosmo
37
+ ```
38
+
39
+ If you plan to use `opencosmo` in a Jupyter notebook, you can install the `ipykernel` package to make the environment available as a kernel:
40
+
41
+ ```bash
42
+ pip install ipykernel # can also be installed with conda
43
+ python -m ipykernel install --user --name=opencosmo
44
+ ```
45
+
46
+ Be sure you have run the "activate" command shown above before running the `ipykernel` command.
47
+
48
+ ## Getting Started
49
+
50
+ To get started, download the "haloproperites.hdf5" from the [OpenCosmo Google Drive](https://drive.google.com/drive/folders/1CYmZ4sE-RdhRdLhGuYR3rFfgyA3M1mU-?usp=sharing). This file contains properties of dark-matter halos from a small hydrodynamical simulation run with HACC. You can easily open the data with the `open` command:
51
+
52
+ ```python
53
+ import opencosmo as oc
54
+
55
+ dataset = oc.open("haloproperties.hdf5")
56
+ print(dataset)
57
+ ```
58
+
59
+ ```text
60
+ OpenCosmo Dataset (length=237441)
61
+ Cosmology: FlatLambdaCDM(name=None, H0=<Quantity 67.66 km / (Mpc s)>, Om0=0.3096446816186967, Tcmb0=<Quantity 0. K>, Neff=3.04, m_nu=None, Ob0=0.04897468161869667)
62
+ First 10 rows:
63
+ block fof_halo_1D_vel_disp fof_halo_center_x ... sod_halo_sfr unique_tag
64
+ km / s Mpc ... solMass / yr
65
+ int32 float32 float32 ... float32 int64
66
+ ----- -------------------- ----------------- ... ------------ ----------
67
+ 0 32.088795 1.4680439 ... -101.0 21674
68
+ 0 41.14525 0.19616994 ... -101.0 44144
69
+ 0 73.82962 1.5071135 ... 3.1447952 48226
70
+ 0 31.17231 0.7526525 ... -101.0 58472
71
+ 0 23.038841 5.3246417 ... -101.0 60550
72
+ 0 37.071426 0.5153746 ... -101.0 537760
73
+ 0 26.203058 2.1734374 ... -101.0 542858
74
+ 0 78.7636 2.1477687 ... 0.0 548994
75
+ 0 37.12636 6.9660196 ... -101.0 571540
76
+ 0 58.09235 6.072006 ... 1.5439711 576648
77
+ ```
78
+
79
+ The `open` function returns a `Dataset` object, which holds the raw data as well as information about the simulation. You can easily access the data and cosmology as Astropy objects:
80
+ ```python
81
+ dataset.data
82
+ dataset.cosmology
83
+ ```
84
+
85
+ The first will return an astropy table of the data, with all associated units already applied. The second will return the astropy cosmology object that represents the cosmology the simulation was run with.
86
+
87
+ ### Basic Querying
88
+
89
+ Although you can access data directly, `opencosmo` provides tools for querying and transforming the data in a fully cosmology-aware context. For example, suppose we wanted to plot the concentration-mass relationship for the halos in our simulation above a certain mass. One way to perform this would be as follows:
90
+
91
+ ```python
92
+ dataset = dataset
93
+ .filter(oc.col("fof_halo_mass") > 1e13)
94
+ .take(1000, at="random")
95
+ .select(("fof_halo_mass", "sod_halo_cdelta"))
96
+
97
+ print(dataset)
98
+
99
+ ```
100
+
101
+ ```text
102
+ OpenCosmo Dataset (length=1000)
103
+ Cosmology: FlatLambdaCDM(name=None, H0=<Quantity 67.66 km / (Mpc s)>, Om0=0.3096446816186967, Tcmb0=<Quantity 0. K>, Neff=3.04, m_nu=None, Ob0=0.04897468161869667)
104
+ First 10 rows:
105
+ fof_halo_mass sod_halo_cdelta
106
+ solMass
107
+ float32 float32
108
+ ---------------- ---------------
109
+ 11220446000000.0 4.5797048
110
+ 17266723000000.0 7.4097505
111
+ 51242150000000.0 1.8738283
112
+ 70097712000000.0 4.2764015
113
+ 51028305000000.0 2.678151
114
+ 11960567000000.0 3.9594727
115
+ 15276915000000.0 5.793542
116
+ 16002001000000.0 2.4318497
117
+ 47030307000000.0 3.7146702
118
+ 15839942000000.0 3.245569
119
+ ```
120
+
121
+ We could then plot the data, or perform further transformations. This is cool on its own, but the real power of `opencosmo` comes from its ability to work with different data types. Go ahead and download the "haloparticles" file from the [OpenCosmo Google Drive](https://drive.google.com/drive/folders/1CYmZ4sE-RdhRdLhGuYR3rFfgyA3M1mU-?usp=sharing) and try the following:
122
+
123
+ ```python
124
+ import opencosmo as oc
125
+
126
+ data = oc.open("haloproperties.hdf5", "haloparticles.hdf5")
127
+ ```
128
+ This will return a data *collection* that will allow you to query and transform the data as before, but will associate the halos with their particles.
129
+
130
+ ```python
131
+
132
+ data = data
133
+ .filter(oc.col("fof_halo_mass") > 1e13)
134
+ .take(1000, at="random")
135
+
136
+ for halo in data.halos():
137
+ halo_properties = halo["halo_properties"]
138
+ dm_particles = halo["dm_particles"]
139
+ star_particles = halo["star_particles"]
140
+ ```
141
+
142
+ In each iteration, "halo properties" will be a dictionary containing the properties of the halo (such as its total mass), while "dm_particles" and "star_particles" will be OpenCosmo datasets containing the dark matter and stars associated with the halo, respectively. Because these are just like the dataset object we saw eariler, we can further query and transform the particles as needed for our analysis. For more details on how to use the library, check out the [full documentation](https://opencosmo.readthedocs.io/en/latest/).
143
+
144
+ ### Testing
145
+
146
+ To run tests, first download the test data [from Google Drive](https://drive.google.com/drive/folders/1CYmZ4sE-RdhRdLhGuYR3rFfgyA3M1mU-?usp=sharing). Set environment variable `OPENCOSMO_DATA_PATH` to the path where the data is stored. Then run the tests with `pytest`:
147
+
148
+ ```bash
149
+ export OPENCOSMO_DATA_PATH=/path/to/data
150
+ # From the repository root
151
+ pytest --ignore test/parallel
152
+ ```
153
+
154
+ Although opencosmo does support multi-core processing via MPI, the default installation does not include the necessary dependencies to work in an MPI environment. If you need these capabilities, check out the guide in our documentation.
155
+
156
+ ### Contributing
157
+
158
+ We welcome bug reports and feature requests from the community. If you would like to contribute to the project, please check out the [contributing guide](CONTRIBUTING.md) for more information.
159
+
160
+ ```
@@ -0,0 +1,121 @@
1
+ [project]
2
+ name = "opencosmo"
3
+ version = "1.0.0"
4
+ description = "OpenCosmo Python Toolkit"
5
+ authors = [
6
+ { name = "Patrick Wells", email = "pwells@anl.gov" },
7
+ { name = "Will Hicks", email = "whicks@anl.gov"},
8
+ { name = "Patricia Larsen", email = "prlarsen@anl.gov" },
9
+ { name = "Michael Buehlmann", email = "mbuehlmann@anl.gov" }
10
+
11
+ ]
12
+ readme = "README.md"
13
+ requires-python = ">=3.11,<3.15"
14
+
15
+ dependencies = [
16
+ "h5py>=3.12.1,<4.0.0",
17
+ "astropy>=7.2.0,<8.0.0",
18
+ "pydantic>=2.10.6,<3.0.0",
19
+ "hdf5plugin>=5.0.0,<6.0.0",
20
+ "healpy>=1.18.1,<2.0.0",
21
+ "healsparse==1.11.1",
22
+ "deprecated>=1.2.18,<2.0.0",
23
+ "numpy>=2.0,<2.4",
24
+ "click (>=8.2.1,<9.0.0)",
25
+ "numba>=0.62.1",
26
+ "rustworkx>=0.17.1",
27
+ ]
28
+
29
+ [dependency-groups]
30
+ dev = [
31
+ "ruff>=0.9.4,<1.0.0",
32
+ "mypy>=1.15,<2.0.0",
33
+ "types-deprecated>=1.2.15.20250304",
34
+ "pre-commit>=4.2.0,<5.0.0",
35
+ "towncrier (>=24.8.0,<25.0.0)",
36
+ "pip>=25.1.1",
37
+ "pytest>=8.3.4,<9.0.0",
38
+ "pytest-timeout>=2.4.0",
39
+ ]
40
+ docs = [
41
+ "sphinx>=9.0.0",
42
+ "sphinx-rtd-theme>=3.0.2,<4.0.0",
43
+ "autodoc-pydantic>=2.2.0,<3.0.0",
44
+ ]
45
+ mpi = [
46
+ "mpi4py>=3.1.0,<5.0.0"
47
+ ]
48
+ test = [
49
+ "pandas>=2.3.3",
50
+ "pandas-stubs>=2.3.2.250926",
51
+ "polars>=1.35.2",
52
+ "pyarrow>=21.0.0",
53
+ "pyxsim>=4.4.3",
54
+ "yt>=4.4.1",
55
+ ]
56
+ test-mpi = [
57
+ "mpi-pytest>=2025.4.0,<2026.0.0"
58
+ ]
59
+ [project.scripts]
60
+ opencosmo = "opencosmo.analysis.cli:cli"
61
+
62
+ [project.optional-dependencies]
63
+ io = [
64
+ "pyarrow>=21.0.0",
65
+ ]
66
+
67
+ [build-system]
68
+ requires = ["uv_build>=0.8.2,<0.9.0", "pip"]
69
+ build-backend = "uv_build"
70
+
71
+ [tool.uv.build-backend]
72
+ source-include = ["LICENSE.md"]
73
+
74
+
75
+ [[tool.mypy.overrides]]
76
+ module = ["h5py", "astropy.*", "healpy", "healsparse", "numba"]
77
+ ignore_missing_imports = true
78
+
79
+ [tool.towncrier]
80
+ directory = "changes"
81
+ package = "opencosmo"
82
+ filename = "docs/source/changelog.rst"
83
+
84
+ [tool.pytest.ini_options]
85
+ testpaths = ["test"]
86
+ log_cli = true
87
+ log_cli_level = "INFO"
88
+
89
+ [tool.pyrefly]
90
+ project-includes = [
91
+ "**/*.py*",
92
+ ]
93
+ replace-imports-with-any = ["astropy.units", "astropy.constants"]
94
+
95
+ [lint.pycodestyle]
96
+ max-doc-length = 90
97
+
98
+ [tool.ruff.lint]
99
+ future-annotations = true
100
+ preview = true
101
+ extend-select = ["TC"]
102
+
103
+ [tool.towncrier.fragment.improvement]
104
+ name = "Improvements"
105
+ showcontent = true
106
+
107
+ [tool.towncrier.fragment.feature]
108
+ name = "New Features"
109
+
110
+ [tool.towncrier.fragment.bugfix]
111
+ name = "Bugfixes"
112
+
113
+ [tool.towncrier.fragment.doc]
114
+ name = "Documentation"
115
+
116
+ [tool.towncrier.fragment.removal]
117
+ name = "Deprecations and Removals"
118
+
119
+ [tool.towncrier.fragment.misc]
120
+ name = "Miscellaneous"
121
+
@@ -0,0 +1,26 @@
1
+ from .collection import (
2
+ HealpixMap,
3
+ Lightcone,
4
+ SimulationCollection,
5
+ StructureCollection,
6
+ )
7
+ from .column import col
8
+ from .dataset import Dataset
9
+ from .io import open, write
10
+ from .spatial import make_box, make_cone
11
+
12
+ __version__ = "1.0.0"
13
+
14
+ __all__ = [
15
+ "write",
16
+ "col",
17
+ "open",
18
+ "Dataset",
19
+ "StructureCollection",
20
+ "SimulationCollection",
21
+ "Lightcone",
22
+ "HealpixMap",
23
+ "make_box",
24
+ "make_cone",
25
+ "__version__",
26
+ ]
@@ -0,0 +1,42 @@
1
+ # ruff: noqa
2
+ from importlib import import_module
3
+
4
+ known_yt_tools = [
5
+ "create_yt_dataset",
6
+ "ProjectionPlot",
7
+ "SlicePlot",
8
+ "ParticleProjectionPlot",
9
+ "ProfilePlot",
10
+ "PhasePlot",
11
+ "visualize_halo",
12
+ "halo_projection_array",
13
+ ]
14
+
15
+
16
+ """
17
+ Right now, we have only have two analysis modules so we can handle them directly. In the
18
+ future we will need to implement a more robust system that handles things automatically.
19
+ """
20
+
21
+
22
+ def __getattr__(name):
23
+ if name in known_yt_tools:
24
+ yt_viz = import_module(".yt_viz", package="opencosmo.analysis")
25
+ yt_utils = import_module(".yt_utils", package="opencosmo.analysis")
26
+ try:
27
+ return getattr(yt_viz, name)
28
+ except AttributeError:
29
+ pass
30
+ try:
31
+ return getattr(yt_utils, name)
32
+ except AttributError:
33
+ pass
34
+
35
+ # except ImportError as ie:
36
+ # raise ImportError(
37
+ # "You tried to import one of the OpenCosmo YT tools, but your python "
38
+ # "environment does not have the necessary dependencies. You can do install "
39
+ # "them with `pip install opencosmo[analysis]`\n"
40
+ # f"{ie}"
41
+ # )
42
+ raise ImportError(f"Cannot import name '{name}' from opencosmo.analysis")
@@ -0,0 +1,32 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, Optional
4
+
5
+ import click
6
+
7
+ from opencosmo.analysis.install import get_file_versions, install_spec
8
+
9
+ if TYPE_CHECKING:
10
+ from pathlib import Path
11
+
12
+
13
+ @click.group()
14
+ def cli():
15
+ pass
16
+
17
+
18
+ @cli.command(name="install")
19
+ @click.argument("spec_name", required=True)
20
+ @click.option("--file", type=click.Path(exists=True), required=False)
21
+ @click.option("--dev", is_flag=True)
22
+ def install(spec_name: str, file: Optional[Path] = None, dev: bool = False):
23
+ if file is not None:
24
+ versions = get_file_versions(spec_name, file)
25
+ else:
26
+ versions = {}
27
+
28
+ install_spec(spec_name, versions, dev=dev)
29
+
30
+
31
+ if __name__ == "__main__":
32
+ cli()
@@ -0,0 +1,20 @@
1
+ from __future__ import annotations
2
+
3
+ from collections import namedtuple
4
+ from typing import TYPE_CHECKING, NamedTuple, Type, TypeVar
5
+
6
+ if TYPE_CHECKING:
7
+ from opencosmo import Dataset
8
+
9
+ DIFFMAH_INPUT = namedtuple(
10
+ "DIFFMAH_INPUT", ["logm0", "logtc", "early_index", "late_index", "t_peak"]
11
+ )
12
+
13
+ T = TypeVar("T", bound=NamedTuple)
14
+
15
+
16
+ def make_named_tuple(dataset: Dataset, input_tuple: Type[T]) -> T:
17
+ required_columns = input_tuple._fields
18
+ data = dataset.select(required_columns).data
19
+ output = {c: data[c].value for c in required_columns}
20
+ return input_tuple(**output) # type: ignore
@@ -0,0 +1,5 @@
1
+ from .install import install_spec
2
+ from .specs import get_specs
3
+ from .versions import get_file_versions
4
+
5
+ __all__ = ["get_specs", "install_spec", "get_file_versions"]