Skip to content

Commit 4a83ed8

Browse files
Add pytests (#102)
* first pass at writing tests * add test dependencies * add test which uses cube_samples, and add MPI test * Add tests to workflow (separate for with and without mpi) * remember to install test dependencies * minimal changes to pyproject.toml to get optional dependencies to work * remove errant _mpi filename change from test * revert changes to pyproject.toml and just put dependencies in CI * use 3 mpi processes instead of 2 for "proper" mpi * use --oversubscribe
1 parent 5dcecd9 commit 4a83ed8

File tree

2 files changed

+128
-1
lines changed

2 files changed

+128
-1
lines changed

.github/workflows/CI.yml

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,45 @@ jobs:
4343
run: python run_pypolychord.py
4444

4545
- name: Test pypolychord (MPI)
46-
run: mpirun -np 2 python run_pypolychord.py
46+
run: mpirun --oversubscribe -np 3 python run_pypolychord.py
4747

4848
- name: Test pypolychord (anesthetic)
4949
if: ${{ ! contains( '3.6, 3.7', matrix.python-version ) }}
5050
run: |
5151
pip install -r requirements.txt
5252
python run_pypolychord.py
53+
54+
55+
tests:
56+
runs-on: ${{ matrix.os }}
57+
strategy:
58+
matrix:
59+
os: [ubuntu-latest]
60+
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11']
61+
include:
62+
- os: ubuntu-20.04
63+
python-version: '3.6'
64+
65+
steps:
66+
- uses: actions/checkout@v3
67+
- name: Set up Python ${{ matrix.python-version }}
68+
uses: actions/setup-python@v4
69+
with:
70+
python-version: ${{ matrix.python-version }}
71+
72+
- name: Install dependencies (Linux)
73+
run: sudo apt-get install gfortran libopenmpi-dev
74+
75+
- name: Install dependencies
76+
run: |
77+
python -m pip install --upgrade pip
78+
python -m pip install mpi4py pytest pytest-mpi fortranformat
79+
80+
- name: Install pypolychord
81+
run: pip install -v '.[test]'
82+
83+
- name: Test pypolychord (no MPI)
84+
run: python -m pytest tests
85+
86+
- name: Test pypolychord (MPI)
87+
run: mpirun --oversubscribe -np 3 python -m pytest tests --only-mpi

tests/test_run_pypolychord.py

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import pytest
2+
import numpy as np
3+
import pypolychord
4+
from pypolychord.settings import PolyChordSettings
5+
from pypolychord.priors import UniformPrior
6+
7+
8+
def gaussian_likelihood(theta):
9+
""" Simple Gaussian Likelihood"""
10+
11+
sigma = 0.1
12+
13+
nDims = len(theta)
14+
r2 = sum(theta**2)
15+
logL = -np.log(2*np.pi*sigma*sigma)*nDims/2.0
16+
logL += -r2/2/sigma/sigma
17+
18+
return logL, [r2]
19+
20+
21+
default_settings = PolyChordSettings(4, 1)
22+
default_settings.file_root = 'settings'
23+
default_settings.nlive = 200
24+
default_settings.read_resume = False
25+
default_settings.feedback = 0
26+
27+
cube_samples_settings = PolyChordSettings(4, 1)
28+
cube_samples_settings.file_root = 'cube_samples'
29+
cube_samples_settings.nlive = 200
30+
cube_samples_settings.read_resume = False
31+
cube_samples_settings.cube_samples = np.array([[0.1, 0.2, 0.3, 0.4],
32+
[0.5, 0.6, 0.7, 0.8]])
33+
cube_samples_settings.feedback = 0
34+
35+
36+
@pytest.mark.parametrize("settings, likelihood, nDims, nDerived",
37+
[(default_settings, gaussian_likelihood, 4, 1),
38+
(cube_samples_settings, gaussian_likelihood, 4, 1)])
39+
def test_run(settings, likelihood, nDims, nDerived):
40+
# Define a box uniform prior from -1 to 1
41+
def prior(hypercube):
42+
""" Uniform prior from [-1,1]^D. """
43+
return UniformPrior(-1, 1)(hypercube)
44+
45+
# Optional dumper function giving run-time read access to
46+
# the live points, dead points, weights and evidences
47+
48+
def dumper(live, dead, logweights, logZ, logZerr):
49+
print("Last dead point:", dead[-1])
50+
51+
# Run PolyChord
52+
53+
print("Running PolyChord")
54+
output = pypolychord.run_polychord(likelihood, nDims, nDerived, settings, prior, dumper)
55+
56+
# Create a paramnames file
57+
58+
paramnames = [('p%i' % i, r'\theta_%i' % i) for i in range(nDims)]
59+
paramnames += [('r*', 'r')]
60+
output.make_paramnames_files(paramnames)
61+
62+
63+
@pytest.mark.parametrize("settings, likelihood, nDims, nDerived",
64+
[(default_settings, gaussian_likelihood, 4, 1),
65+
(cube_samples_settings, gaussian_likelihood, 4, 1)])
66+
@pytest.mark.mpi
67+
def test_run_mpi(settings, likelihood, nDims, nDerived):
68+
from mpi4py import MPI
69+
70+
settings.file_root += '_mpi'
71+
72+
# Define a box uniform prior from -1 to 1
73+
def prior(hypercube):
74+
""" Uniform prior from [-1,1]^D. """
75+
return UniformPrior(-1, 1)(hypercube)
76+
77+
# Optional dumper function giving run-time read access to
78+
# the live points, dead points, weights and evidences
79+
80+
def dumper(live, dead, logweights, logZ, logZerr):
81+
print("Last dead point:", dead[-1])
82+
83+
# Run PolyChord
84+
85+
print("Running PolyChord")
86+
output = pypolychord.run_polychord(likelihood, nDims, nDerived, settings, prior, dumper)
87+
88+
# Create a paramnames file
89+
90+
paramnames = [('p%i' % i, r'\theta_%i' % i) for i in range(nDims)]
91+
paramnames += [('r*', 'r')]
92+
output.make_paramnames_files(paramnames)

0 commit comments

Comments
 (0)