Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

From mesh #2

Open
wants to merge 22 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
2f8d294
A first approach at a minimal python wrapper. Still depends on config…
dforero0896 Jul 21, 2022
50cb5d4
Exposing the interface to python
dforero0896 Jul 21, 2022
5e68985
Output structure changed to dictionary to store relevant metadata
dforero0896 Jul 21, 2022
7bc5719
Added functionality to compute cross spectra on boxes
dforero0896 Jul 22, 2022
fe86566
Bugs in light cone cross spectra, otherwise working ok
dforero0896 Jul 22, 2022
52bf8fe
Cross correlation of non-periodic data working now for no apparent re…
dforero0896 Jul 23, 2022
ace0b8a
Update README.md
dforero0896 Jul 25, 2022
1bd0e93
Added support for simulation boxes with randoms
dforero0896 Aug 12, 2022
d8c2258
Merge branch 'master' of https://github.com/dforero0896/powspec
dforero0896 Aug 12, 2022
c59f148
Update README.md
dforero0896 Aug 12, 2022
52b3ed9
Further checks on the performance of the wrapper's extra functionalit…
dforero0896 Aug 24, 2022
8e59112
Modifications to avoid excessive data copies and functions should now…
dforero0896 Oct 30, 2022
c696475
Merge pull request #1 from dforero0896/optim
dforero0896 Oct 30, 2022
5b00637
Exception rasing from NULL pypower returns
dforero0896 Oct 30, 2022
5c8460a
gitignore libraries
dforero0896 Oct 30, 2022
7eda1d6
Merge pull request #2 from dforero0896/optim
dforero0896 Oct 30, 2022
0069ceb
Update README.md
dforero0896 Oct 30, 2022
78c1b77
Return NULL when error saving
dforero0896 Nov 12, 2022
81e24fc
Fixes paths for perlmutter
dforero0896 Nov 20, 2022
ab4e4d4
Removed shot noise from randoms when using boxes
dforero0896 Nov 20, 2022
4047b61
Switch to dev
dforero0896 Jan 9, 2023
2562847
Added implementation to compute power spectrum from numpy array meshes
dforero0896 Sep 29, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.powspec
*.so
28 changes: 2 additions & 26 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,28 +1,4 @@
CC = gcc
CFLAGS = -std=c99 -O3 -Wall
LIBS = -lm -lfftw3
INCL = -Isrc -Iio -Ilib -Imath

# Settings for FFTW
FFTW_DIR =
ifneq ($(FFTW_DIR),)
LIBS += -L$(FFTW_DIR)/lib
INCL += -I$(FFTW_DIR)/include
endif

# Setting for single precision density fields and FFT
#LIBS += -DSINGLE_PREC

# Settings for OpenMP (comment the following line to disable OpenMP)
LIBS += -DOMP -fopenmp -lfftw3_omp

# Settings for CFITSIO (not implemented yet)

SRCS = $(wildcard src/*.c lib/*.c io/*.c math/*.c)
EXEC = POWSPEC

all:
$(CC) $(CFLAGS) -o $(EXEC) $(SRCS) $(LIBS) $(INCL)

python setup.py build_ext --inplace
clean:
rm $(EXEC)
rm *.so src/pypowspec.c
28 changes: 28 additions & 0 deletions Makefile.powspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
CC = gcc
CFLAGS = -std=c99 -O3 -Wall
LIBS = -lm -lfftw3
INCL = -Isrc -Iio -Ilib -Imath

# Settings for FFTW
FFTW_DIR =
ifneq ($(FFTW_DIR),)
LIBS += -L$(FFTW_DIR)/lib
INCL += -I$(FFTW_DIR)/include
endif

# Setting for single precision density fields and FFT
#LIBS += -DSINGLE_PREC

# Settings for OpenMP (comment the following line to disable OpenMP)
LIBS += -DOMP -fopenmp -lfftw3_omp

# Settings for CFITSIO (not implemented yet)

SRCS = $(wildcard src/*.c lib/*.c io/*.c math/*.c)
EXEC = POWSPEC

all:
$(CC) $(CFLAGS) -o $(EXEC) $(SRCS) $(LIBS) $(INCL)

clean:
rm $(EXEC)
175 changes: 175 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,180 @@
# powspec

This repository contains a small Cython wrapper to the original [code](https://github.com/cheng-zhao/powspec) by Cheng Zhao.
In the current iteration, this wrapper allows to lauch (auto and cross) power spectrum computation from in-memory data in the form of numpy arrays for periodic and non-periodic (survey-like) data. Furthermore, it expands on the original code's capability by allowing the use of randoms for simulation boxes too. This is useful when computing post-BAO reconstruction power spectra where shifted randoms are required.

I have not done many tests but the ones performed show equivalent results to those obtained by directly invoking the C code. Using randoms with boxes was tested with uniform randoms 10x the size of the catalog and show agreement with the C code's periodic box data for the most part (small scales are slightly biased).

## Use of the Python wrapper

The current implementation still requires the configuration file to be provided. Though this may be changed in the future (either by bypassing the configuration file reader or creating configuration files on-the-fly) the current configuration file reader in this wrapper will not check for `DATA`/`RANDOM` catalogs or associated configuration options (such as formatting) since these are provided to the functions as numpy arrays.

First, compilation of the wrappes should be as easy as the original code. Once the `include` and `lib` dirs have been set in the `setup.py` script, just type `make` and the library will be compiled for your python version.

Once the library is compiled, add the directory containing it to your `PATH`. Here is an example

### Auto power spectrum of simulation boxes
```python
import numpy as np
import sys
sys.path.append("/global/u1/d/dforero/codes/powspec_py/powspec/")
from pypowspec import compute_auto_box, compute_cross_box


seed = 42
np.random.seed(seed)
nobj = int(1e4)
data = 1000. * np.random.random((nobj, 3)).astype(np.double)
w = np.ones(nobj)
pk = compute_auto_box(data[:,0], data[:,1], data[:,2], w,
powspec_conf_file = "test/powspec_auto.conf",
output_file = "test/box_auto_test.powspec")
```
Providing an `output_file` triggers saving of the results in text format (results are still returned in `pk`). Otherwise the user can save `pk` as they please (i.e. binary format). Here `pk` is a dictionary containing the results. The most relevant values are `k`, and `multipoles` the latter of which is a numpy array of shape `(<number_k_bins>, <number_multipoles>)`. Some important metadata is also stored provided such as the `normalisation` and `shot_ noise`.

### Cross power spectrum of simulation boxes
```python
import numpy as np
import sys
sys.path.append("/global/u1/d/dforero/codes/powspec_py/powspec/")
from pypowspec import compute_auto_box, compute_cross_box


seed = 42
np.random.seed(seed)
nobj = int(1e4)
data = 1000. * np.random.random((nobj, 3)).astype(np.double)
w = np.ones(nobj)
# Compute the cross correlation of two catalogs (here using the same catalog)
pk = compute_cross_box(data[:,0], data[:,1], data[:,2], w,
data[:,0], data[:,1], data[:,2], w,
powspec_conf_file = "test/powspec_cross.conf",
output_auto = ["test/box_auto_test_1.powspec", "test/box_auto_test_2.powspec"],
output_cross = "test/box_cross_test.powspec")
```
Note that here you should be able to avoid computing the auto power spectrum by passing `output_auto = ["", ""]`. Passing the argument `output_auto` triggers the text-file saving of the results of the C code. If it is `None`, the function call will not automatically save the results.
Here `pk` is a dictionary containing the results. The most relevant values are `k`, `auto_multipoles` and `cross_multipoles` the latter of which are numpy arrays of shape `(<number_k_bins>, <number_multipoles>)`.

### Auto power spectrum of survey data

For non periodic data it is necessary to provide extra columns. The code expects `RA, DEC, z, W_COMP, W_FKP, NZ` for both data and randoms. All columns must be provided but if your data lacks weights, a column of ones (i.e. `w_comp = w_fkp = np.ones_like(ra)`) can be provided. The radial number density `NZ` must be provided (so normalisation works) but can be a constant array (i.e. `nz = 1e-4 * np.ones_like(ra)`).

Data selection is expected to be none by the user in python. This wrapper bypasses the on-disk data reading and AST parsing of the original C code. Any data transformation should be quick-enough in python against the FFT and mode-counting parts so it is not expected to be a bottleneck.

```python
import numpy as np
import sys
sys.path.append("/global/u1/d/dforero/codes/powspec_py/powspec/")
from pypowspec import compute_auto_lc, compute_cross_lc

import pandas as pd
dat_fname = "/global/project/projectdirs/desi/mocks/UNIT/HOD_Shadab/multiple_snapshot_lightcone/UNIT_lightcone_multibox_ELG_footprint_nz_NGC.dat"
ran_fname = "/global/project/projectdirs/desi/mocks/UNIT/HOD_Shadab/multiple_snapshot_lightcone/UNIT_lightcone_multibox_ELG_footprint_nz_1xdata_5.ran_NGC.dat"
data = pd.read_csv(dat_fname, usecols = (0,1,3,4), engine='c', delim_whitespace=True, names = ['ra', 'dec', 'zrsd', 'nz']).values
rand = pd.read_csv(ran_fname, usecols = (0,1,3,4), engine='c', delim_whitespace=True, names = ['ra', 'dec', 'zrsd', 'nz']).values
# Data selection (redshift range in this case)
data = data[(data[:,2] > 0.7) & (data[:,2] < 1.)]
rand = rand[(rand[:,2] > 0.7) & (rand[:,2] < 1.)]
# FKP weight from NZ
fkp_data = 1. / (1 + 5000 * data[:,3])
fkp_rand = 1. / (1 + 5000 * rand[:,3])
nobj = data.shape[0]
# Uniform completeness weights
wdata = np.ones(nobj)
wrand = np.ones(rand.shape[0])

pk = compute_auto_lc(data[:,0], data[:,1], data[:,2], wdata, fkp_data, data[:,3],
rand[:,0], rand[:,1], rand[:,2], wrand, fkp_rand, rand[:,3],
powspec_conf_file = "test/powspec_lc.conf",
output_file = "test/lc_auto_test.powspec")
```
Similar to the box functions, `output_file != None` triggers text result saving.

### Cross power spectrum of survey data

Here we use the same catalog as an example.
```python


import numpy as np
import sys
sys.path.append("/global/u1/d/dforero/codes/powspec_py/powspec/")
from pypowspec import compute_auto_lc, compute_cross_lc

import pandas as pd
dat_fname = "/global/project/projectdirs/desi/mocks/UNIT/HOD_Shadab/multiple_snapshot_lightcone/UNIT_lightcone_multibox_ELG_footprint_nz_NGC.dat"
ran_fname = "/global/project/projectdirs/desi/mocks/UNIT/HOD_Shadab/multiple_snapshot_lightcone/UNIT_lightcone_multibox_ELG_footprint_nz_1xdata_5.ran_NGC.dat"
data = pd.read_csv(dat_fname, usecols = (0,1,3,4), engine='c', delim_whitespace=True, names = ['ra', 'dec', 'zrsd', 'nz']).values
rand = pd.read_csv(ran_fname, usecols = (0,1,3,4), engine='c', delim_whitespace=True, names = ['ra', 'dec', 'zrsd', 'nz']).values
# Data selection (redshift range in this case)
data = data[(data[:,2] > 0.7) & (data[:,2] < 1.)]
rand = rand[(rand[:,2] > 0.7) & (rand[:,2] < 1.)]
# FKP weight from NZ
fkp_data = 1. / (1 + 5000 * data[:,3])
fkp_rand = 1. / (1 + 5000 * rand[:,3])
nobj = data.shape[0]
# Uniform completeness weights
wdata = np.ones(nobj)
wrand = np.ones(rand.shape[0])

pk = compute_cross_lc(data[:,0], data[:,1], data[:,2], wdata, fkp_data, data[:,3],
rand[:,0], rand[:,1], rand[:,2], wrand, fkp_rand, rand[:,3],
data[:,0], data[:,1], data[:,2], wdata, fkp_data, data[:,3],
rand[:,0], rand[:,1], rand[:,2], wrand, fkp_rand, rand[:,3],
powspec_conf_file = "test/powspec_lc_cross.conf",
output_auto = ["test/lc_auto_test_1.powspec","test/lc_auto_test_1.powspec"],
output_cross = "test/lc_cross_test.powspec")
```

### Auto power spectrum of reconstructed boxes

```python
import numpy as np
import sys
sys.path.append("/global/u1/d/dforero/codes/powspec_py/powspec/")
from pypowspec import compute_auto_box_rand, compute_cross_box_rand
import pandas as pd
test_fname = "/global/project/projectdirs/desi/mocks/UNIT/HOD_Shadab/HOD_boxes/redshift0.9873/UNIT_DESI_Shadab_HOD_snap97_ELG_v0.txt"
data = pd.read_csv(test_fname, usecols = (0,1,3), engine='c', delim_whitespace=True, names = ['x', 'y', 'zrsd']).values
nobj = data.shape[0]
rand = (data.max() - data.min()) * np.random.random((10 * nobj, 3)).astype(np.double)
wdata = np.ones(data.shape[0])
wrand = np.ones(rand.shape[0])
pk = compute_auto_box_rand(data[:,0], data[:,1], data[:,2], wdata,
rand[:,0], rand[:,1], rand[:,2], wrand,
powspec_conf_file = "test/powspec_auto.conf",
output_file = "test/box_auto_test_rand.powspec")

```
### Cross power spectrum of reconstructed boxes

```python
import numpy as np
import sys
sys.path.append("/global/u1/d/dforero/codes/powspec_py/powspec/")
from pypowspec import compute_auto_box_rand, compute_cross_box_rand
import pandas as pd
test_fname = "/global/project/projectdirs/desi/mocks/UNIT/HOD_Shadab/HOD_boxes/redshift0.9873/UNIT_DESI_Shadab_HOD_snap97_ELG_v0.txt"
data = pd.read_csv(test_fname, usecols = (0,1,3), engine='c', delim_whitespace=True, names = ['x', 'y', 'zrsd']).values
nobj = data.shape[0]
rand = (data.max() - data.min()) * np.random.random((10 * nobj, 3)).astype(np.double)
wdata = np.ones(data.shape[0])
wrand = np.ones(rand.shape[0])

pk = compute_cross_box_rand(data[:,0], data[:,1], data[:,2], wdata,
rand[:,0], rand[:,1], rand[:,2], wrand,
data[:,0], data[:,1], data[:,2], wdata,
rand[:,0], rand[:,1], rand[:,2], wrand,
powspec_conf_file = "test/powspec_cross.conf",
output_auto = ["test/box_auto_test_rand_1.powspec", "test/box_auto_test_rand_2.powspec"],
output_cross = "test/box_cross_test_rand.powspec")

```

Please do not hesitate to contact me if you find any bugs. Below, you may find the documentation to the original C code.

# powspec

![Codacy grade](https://img.shields.io/codacy/grade/5a6835fc4cee49d4993380ad1a45ad69.svg)

## Table of Contents
Expand Down
Binary file not shown.
Binary file added build/temp.linux-x86_64-3.7/io/ascii_fmtr.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-3.7/io/read_ascii.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-3.7/io/read_file.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-3.7/io/write_ascii.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-3.7/lib/libast.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-3.7/lib/libcfg.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-3.7/math/cspline.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-3.7/math/legauss.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-3.7/src/cnvt_coord.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-3.7/src/genr_mesh.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-3.7/src/load_conf.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-3.7/src/mp_template.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-3.7/src/multipole.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-3.7/src/powspec.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-3.7/src/pypowspec.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-3.7/src/read_cata.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-3.7/src/save_res.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-3.8/io/ascii_fmtr.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-3.8/io/read_ascii.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-3.8/io/read_file.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-3.8/io/write_ascii.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-3.8/lib/libast.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-3.8/lib/libcfg.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-3.8/math/cspline.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-3.8/math/legauss.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-3.8/src/cnvt_coord.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-3.8/src/genr_mesh.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-3.8/src/load_conf.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-3.8/src/mp_template.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-3.8/src/multipole.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-3.8/src/powspec.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-3.8/src/pypowspec.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-3.8/src/read_cata.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-3.8/src/save_res.o
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added build/temp.linux-x86_64-cpython-311/lib/libast.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-cpython-311/lib/libcfg.o
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added build/temp.linux-x86_64-cpython-39/io/read_file.o
Binary file not shown.
Binary file not shown.
Binary file added build/temp.linux-x86_64-cpython-39/lib/libast.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-cpython-39/lib/libcfg.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-cpython-39/math/cspline.o
Binary file not shown.
Binary file added build/temp.linux-x86_64-cpython-39/math/legauss.o
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added build/temp.linux-x86_64-cpython-39/src/mp_template.o
Binary file not shown.
Binary file not shown.
Binary file added build/temp.linux-x86_64-cpython-39/src/powspec.o
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added build/temp.linux-x86_64-cpython-39/src/save_res.o
Binary file not shown.
Loading