Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
63 changes: 44 additions & 19 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,61 +16,86 @@ env:
jobs:
checks:
name: Check Python ${{ matrix.python-version }} on ${{ matrix.os }}
env:
IGNORE_CONDA: true
runs-on: ${{ matrix.os }}
env:
UV_PYTHON: ${{ matrix.python-version }}
defaults:
run:
shell: bash
strategy:
matrix:
os: [ ubuntu-20.04, macos-latest, windows-latest ]
python-version: [ "3.9", "3.10", "3.11", "3.12" ]
fail-fast: true
os: [ ubuntu-22.04, macos-latest, windows-latest ]
python-version: [ "3.10", "3.11", "3.12" ]
fail-fast: false
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- uses: astral-sh/setup-uv@v7

- name: Install Python ${{ matrix.python-version }}
run: uv python install ${UV_PYTHON}

# Use msmpi on windows
- uses: mpi4py/setup-mpi@v1
if: ${{ contains(matrix.os, 'windows') }}
with:
mpi: msmpi

# Else, use the default for the OS and setup-mpi action
# Use mpich on linux (openmpi tends to hang in GitHub Actions runners)
- uses: mpi4py/setup-mpi@v1
if: ${{ contains(matrix.os, 'ubuntu') }}
with:
mpi: mpich

# Use the default for the OS (openmpi) on macOS
- uses: mpi4py/setup-mpi@v1
if: ${{ !contains(matrix.os, 'windows') }}
if: ${{ contains(matrix.os, 'macos') }}

# Setup openmp on macOS
- name: Install openmp if on macos
if: ${{ contains(matrix.os, 'macos') }}
run: |
brew install libomp llvm

- name: Upgrade pip
- name: Synchronize project environment
run: |
python3 -m pip install -U pip
if [[ "$RUNNER_OS" == "macOS" ]]; then
export CC=$(brew --prefix llvm)/bin/clang
export CXX=$(brew --prefix llvm)/bin/clang++
fi
# Build mpi4py from source on Linux so it links against the
# locally-installed MPI runtime; pre-built wheels cause
# "libmpi.so.12: cannot open shared object file" on Linux.
# On macOS and Windows the pre-built wheels work fine.
ARGS=(--locked --extra dev --extra matnormal --extra examples)
if [[ "$RUNNER_OS" == "Linux" ]]; then
ARGS+=(--no-binary-package mpi4py)
fi
uv sync "${ARGS[@]}"

- name: Run tests and other checks
- name: Run static analysis and tests
if: runner.os == 'Linux'
run: |
./pr-check.sh
uv run ./run-checks.sh
uv run ./run-tests.sh --sdist-mode
uv run bash -lc 'cd docs && make'

- name: Run tests and other checks
- name: Run static analysis and tests
if: runner.os == 'macOS'
run: |
export CLANG_PREFIX=$(brew --prefix llvm)
export CC=$CLANG_PREFIX/bin/clang
export CXX=$CLANG_PREFIX/bin/clang++
./pr-check.sh
uv run ./run-checks.sh
uv run ./run-tests.sh --sdist-mode
uv run bash -lc 'cd docs && make'

# On window, just install the package and run tests for now, we need to port the pr-check script to windows
# On Windows, just install the package and run tests for now, we need to port the pr-check script to windows
- name: Run tests and other checks
if: runner.os == 'Windows'
run: |
python -m pip install .[all] -v
python -m pytest -v
uv run python -m pytest -v

# - uses: codecov/codecov-action@v1
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
src/brainiak/_version.py

venv/
.venv/

*.iml
*.eggs
Expand Down
12 changes: 6 additions & 6 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ build-backend = "scikit_build_core.build"
[project]
name = "brainiak"
description = "Brain Imaging Analysis Kit"
requires-python = ">=3.9"
requires-python = ">=3.10"
readme = "README.rst"
license = { file = "LICENSE" }
authors = [
Expand Down Expand Up @@ -66,8 +66,8 @@ dependencies = [
"psutil",
"nibabel",
"joblib",
"wheel", # See https://github.com/astropy/astropy-helpers/issues/501
"pydicom",
"wheel>=0.46.2", # See https://github.com/astropy/astropy-helpers/issues/501
"pydicom>=3.0.2",
]

[project.optional-dependencies]
Expand Down Expand Up @@ -99,7 +99,7 @@ examples = [
"timecorr",
"seaborn",
"holoviews",
"pyOpenSSL",
"pyOpenSSL>=26.0.0",
"awscli",
"bcrypt",
"indexed_gzip",
Expand All @@ -111,13 +111,13 @@ examples = [
"nilearn",
"nodejs",
"numpy",
"pydicom",
"pydicom>=3.0.2",
"requests",
"rpyc",
"scikit-learn",
"scipy>=1.6.0",
"toml",
"tornado",
"tornado>=6.5.5",
"websocket-client",
"wsaccel",
"inotify",
Expand Down
15 changes: 8 additions & 7 deletions run-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@ set -e
# detect editable mode. Use the "--sdist-mode" flag.
sdist_mode=$1

python3 -m pip freeze | grep -qi /brainiak \
|| [ ${sdist_mode:-default} = "--sdist-mode" ] \
|| {
echo "You must install brainiak in editable mode"`
`" before calling "$(basename "$0")
exit 1
}
if [ "${sdist_mode:-default}" != "--sdist-mode" ]; then
python3 -m pip freeze | grep -qi /brainiak \
|| {
echo "You must install brainiak in editable mode"`
`" before calling "$(basename "$0")
exit 1
}
fi

coverage run -m pytest

Expand Down
15 changes: 11 additions & 4 deletions src/brainiak/funcalign/fastsrm.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,17 @@ def get_shape(path):
path: str
path to np array
"""
f = open(path, "rb")
version = np.lib.format.read_magic(f)
shape, fortran_order, dtype = np.lib.format._read_array_header(f, version)
f.close()
with open(path, "rb") as f:
version = np.lib.format.read_magic(f)
if version == (1, 0):
shape, fortran_order, dtype = (
np.lib.format.read_array_header_1_0(f))
elif version == (2, 0):
shape, fortran_order, dtype = (
np.lib.format.read_array_header_2_0(f))
else:
raise ValueError(
"Unknown numpy .npy format version: %s" % str(version))
return shape


Expand Down
14 changes: 9 additions & 5 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import multiprocessing
import sys

from mpi4py import MPI
Expand Down Expand Up @@ -50,17 +49,22 @@ def seeded_rng():
@pytest.fixture(scope="module", autouse=True)
def pool_size():
"""
Set the pool_size to 1 for MPI tests when start_method for multiprocessing
is not fork.
Set the pool_size to 1 for MPI tests to avoid forking inside MPI
processes.

This replaces the old skip_non_fork fixture. We don't need to skip these
tests completely, but we need to ensure that the pool_size is set to 1 so
they don't launch any multiprocessing pools within the MPI environment.
Forking inside an MPI process can cause hangs or crashes with certain MPI
transports (e.g., libfabric EFA on AWS-based CI runners).
On windows, it seems like intel mpi and msmpi both have issues with fork,
so we need to set the pool_size to 1 there as well.
"""
if (multiprocessing.get_start_method() != "fork" and
MPI.COMM_WORLD.Get_attr(MPI.APPNUM) is not None):
# When running inside an MPI subprocess (launched by mpiexec), avoid
# forking regardless of the multiprocessing start method. On Linux the
# default start method is "fork", but fork()-after-MPI_Init is unsafe with
# many MPI transports (libfabric EFA, OpenMPI shared-memory, …).
if MPI.COMM_WORLD.Get_attr(MPI.APPNUM) is not None:
return 1

# OpenMPI has issues with fork, so we need to set the pool_size to 1
Expand Down
Loading
Loading