cs-dmri 0.1.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.
- cs_dmri-0.1.0/.github/workflows/ci.yml +116 -0
- cs_dmri-0.1.0/.github/workflows/release.yml +313 -0
- cs_dmri-0.1.0/.gitignore +36 -0
- cs_dmri-0.1.0/.readthedocs.yaml +15 -0
- cs_dmri-0.1.0/Cargo.lock +1897 -0
- cs_dmri-0.1.0/Cargo.toml +90 -0
- cs_dmri-0.1.0/LICENSE-APACHE +209 -0
- cs_dmri-0.1.0/LICENSE-DIPY +48 -0
- cs_dmri-0.1.0/LICENSE-MIT +29 -0
- cs_dmri-0.1.0/LICENSE-MRTRIX +408 -0
- cs_dmri-0.1.0/PKG-INFO +65 -0
- cs_dmri-0.1.0/README.md +75 -0
- cs_dmri-0.1.0/build.rs +62 -0
- cs_dmri-0.1.0/cs_dmri/__init__.py +58 -0
- cs_dmri-0.1.0/cs_dmri/_frame.py +34 -0
- cs_dmri-0.1.0/cs_dmri/_inputs.py +48 -0
- cs_dmri-0.1.0/cs_dmri/_spatial.py +94 -0
- cs_dmri-0.1.0/cs_dmri/dti.py +97 -0
- cs_dmri-0.1.0/cs_dmri/dwi.py +184 -0
- cs_dmri-0.1.0/cs_dmri/gradients.py +107 -0
- cs_dmri-0.1.0/cs_dmri/multitissue.py +248 -0
- cs_dmri-0.1.0/cs_dmri/qc.py +253 -0
- cs_dmri-0.1.0/cs_dmri/shore.py +258 -0
- cs_dmri-0.1.0/docs/_static/.gitkeep +0 -0
- cs_dmri-0.1.0/docs/api/python.md +77 -0
- cs_dmri-0.1.0/docs/api/rust.md +20 -0
- cs_dmri-0.1.0/docs/changes.md +16 -0
- cs_dmri-0.1.0/docs/cli/cs-dti.md +102 -0
- cs_dmri-0.1.0/docs/cli/cs-fit.md +170 -0
- cs_dmri-0.1.0/docs/cli/cs-mtnorm.md +47 -0
- cs_dmri-0.1.0/docs/cli/cs-odf.md +115 -0
- cs_dmri-0.1.0/docs/cli/cs-qc.md +26 -0
- cs_dmri-0.1.0/docs/cli/cs-response.md +141 -0
- cs_dmri-0.1.0/docs/cli/cs-ss3t-full.md +175 -0
- cs_dmri-0.1.0/docs/cli/cs-ss3t.md +131 -0
- cs_dmri-0.1.0/docs/cli/cs-synth.md +63 -0
- cs_dmri-0.1.0/docs/cli/index.md +29 -0
- cs_dmri-0.1.0/docs/conf.py +55 -0
- cs_dmri-0.1.0/docs/development.md +52 -0
- cs_dmri-0.1.0/docs/index.md +59 -0
- cs_dmri-0.1.0/docs/installation.md +58 -0
- cs_dmri-0.1.0/docs/license.md +18 -0
- cs_dmri-0.1.0/docs/quickstart.md +56 -0
- cs_dmri-0.1.0/docs/references.md +58 -0
- cs_dmri-0.1.0/docs/requirements.txt +5 -0
- cs_dmri-0.1.0/docs/tools/make_cli_pages.py +52 -0
- cs_dmri-0.1.0/docs/user/conventions.md +58 -0
- cs_dmri-0.1.0/docs/user/dti.md +40 -0
- cs_dmri-0.1.0/docs/user/export.md +81 -0
- cs_dmri-0.1.0/docs/user/multitissue.md +73 -0
- cs_dmri-0.1.0/docs/user/qc.md +137 -0
- cs_dmri-0.1.0/docs/user/shore.md +103 -0
- cs_dmri-0.1.0/pyproject.toml +49 -0
- cs_dmri-0.1.0/python/.cargo/config.toml +14 -0
- cs_dmri-0.1.0/python/Cargo.toml +27 -0
- cs_dmri-0.1.0/python/README.md +31 -0
- cs_dmri-0.1.0/python/src/lib.rs +399 -0
- cs_dmri-0.1.0/python/src/models.rs +708 -0
- cs_dmri-0.1.0/python/tests/_dipy_reference.py +45 -0
- cs_dmri-0.1.0/python/tests/conftest.py +27 -0
- cs_dmri-0.1.0/python/tests/test_cli_parity.py +83 -0
- cs_dmri-0.1.0/python/tests/test_dwi_dti.py +77 -0
- cs_dmri-0.1.0/python/tests/test_models.py +254 -0
- cs_dmri-0.1.0/python/tests/test_qc.py +101 -0
- cs_dmri-0.1.0/scripts/bench_fit_options.py +794 -0
- cs_dmri-0.1.0/scripts/bench_plots.R +191 -0
- cs_dmri-0.1.0/scripts/generate_lasso_fixtures.py +190 -0
- cs_dmri-0.1.0/scripts/gold_compare.Rmd +490 -0
- cs_dmri-0.1.0/scripts/gold_standard.sh +301 -0
- cs_dmri-0.1.0/scripts/microstructure_math.md +329 -0
- cs_dmri-0.1.0/scripts/validate_microstructure.py +532 -0
- cs_dmri-0.1.0/src/basis/mod.rs +47 -0
- cs_dmri-0.1.0/src/basis/shore.rs +274 -0
- cs_dmri-0.1.0/src/bin/cs-dti.rs +259 -0
- cs_dmri-0.1.0/src/bin/cs-fit.rs +535 -0
- cs_dmri-0.1.0/src/bin/cs-mtnorm.rs +226 -0
- cs_dmri-0.1.0/src/bin/cs-odf.rs +343 -0
- cs_dmri-0.1.0/src/bin/cs-qc.rs +178 -0
- cs_dmri-0.1.0/src/bin/cs-response.rs +321 -0
- cs_dmri-0.1.0/src/bin/cs-ss3t-full.rs +491 -0
- cs_dmri-0.1.0/src/bin/cs-ss3t.rs +346 -0
- cs_dmri-0.1.0/src/bin/cs-synth.rs +221 -0
- cs_dmri-0.1.0/src/dti.rs +579 -0
- cs_dmri-0.1.0/src/fit.rs +774 -0
- cs_dmri-0.1.0/src/graddev.rs +271 -0
- cs_dmri-0.1.0/src/io/coeffs.rs +186 -0
- cs_dmri-0.1.0/src/io/dwi.rs +377 -0
- cs_dmri-0.1.0/src/io/microstructure.rs +676 -0
- cs_dmri-0.1.0/src/io/mod.rs +282 -0
- cs_dmri-0.1.0/src/io/odx_out.rs +1743 -0
- cs_dmri-0.1.0/src/io/output.rs +538 -0
- cs_dmri-0.1.0/src/io/provenance.rs +182 -0
- cs_dmri-0.1.0/src/lib.rs +156 -0
- cs_dmri-0.1.0/src/math.rs +247 -0
- cs_dmri-0.1.0/src/multitissue/dhollander.rs +1174 -0
- cs_dmri-0.1.0/src/multitissue/forward.rs +247 -0
- cs_dmri-0.1.0/src/multitissue/mod.rs +33 -0
- cs_dmri-0.1.0/src/multitissue/mtnormalise.rs +839 -0
- cs_dmri-0.1.0/src/multitissue/pipeline.rs +141 -0
- cs_dmri-0.1.0/src/multitissue/response.rs +252 -0
- cs_dmri-0.1.0/src/multitissue/response_estimation.rs +644 -0
- cs_dmri-0.1.0/src/multitissue/sidecar.rs +71 -0
- cs_dmri-0.1.0/src/multitissue/ss3t.rs +768 -0
- cs_dmri-0.1.0/src/multitissue/volume.rs +179 -0
- cs_dmri-0.1.0/src/odf.rs +269 -0
- cs_dmri-0.1.0/src/progress.rs +181 -0
- cs_dmri-0.1.0/src/qc.rs +1106 -0
- cs_dmri-0.1.0/src/qspace.rs +369 -0
- cs_dmri-0.1.0/src/scalars/microstructure.rs +362 -0
- cs_dmri-0.1.0/src/scalars/mod.rs +8 -0
- cs_dmri-0.1.0/src/sh.rs +84 -0
- cs_dmri-0.1.0/src/solver/alpha.rs +449 -0
- cs_dmri-0.1.0/src/solver/csd.rs +274 -0
- cs_dmri-0.1.0/src/solver/fista.rs +231 -0
- cs_dmri-0.1.0/src/solver/icls.rs +738 -0
- cs_dmri-0.1.0/src/solver/mod.rs +51 -0
- cs_dmri-0.1.0/src/solver/shore_icls.rs +200 -0
- cs_dmri-0.1.0/src/solver/tikhonov.rs +106 -0
- cs_dmri-0.1.0/src/synth.rs +84 -0
- cs_dmri-0.1.0/src/voxel_loop.rs +194 -0
- cs_dmri-0.1.0/tests/alpha_selection.rs +347 -0
- cs_dmri-0.1.0/tests/common/mod.rs +254 -0
- cs_dmri-0.1.0/tests/data/lasso_fixtures/ill_conditioned.bin +0 -0
- cs_dmri-0.1.0/tests/data/lasso_fixtures/manifest.json +10 -0
- cs_dmri-0.1.0/tests/data/lasso_fixtures/medium_dense.bin +0 -0
- cs_dmri-0.1.0/tests/data/lasso_fixtures/near_alpha_max.bin +0 -0
- cs_dmri-0.1.0/tests/data/lasso_fixtures/nonneg_medium.bin +0 -0
- cs_dmri-0.1.0/tests/data/lasso_fixtures/nonneg_small.bin +0 -0
- cs_dmri-0.1.0/tests/data/lasso_fixtures/small_dense.bin +0 -0
- cs_dmri-0.1.0/tests/data/lasso_fixtures/underdetermined.bin +0 -0
- cs_dmri-0.1.0/tests/data/lasso_fixtures/very_low_alpha.bin +0 -0
- cs_dmri-0.1.0/tests/optimization_kkt.rs +235 -0
- cs_dmri-0.1.0/tests/optimization_limits.rs +157 -0
- cs_dmri-0.1.0/tests/optimization_recovery.rs +165 -0
- cs_dmri-0.1.0/tests/optimization_sklearn.rs +205 -0
- cs_dmri-0.1.0/tests/roundtrip.rs +152 -0
- cs_dmri-0.1.0/tests/scalars.rs +235 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
# Cancel in-flight runs when a new commit is pushed to the same PR/branch.
|
|
10
|
+
concurrency:
|
|
11
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
12
|
+
cancel-in-progress: true
|
|
13
|
+
|
|
14
|
+
env:
|
|
15
|
+
CARGO_TERM_COLOR: always
|
|
16
|
+
RUST_BACKTRACE: 1
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
rust-tests:
|
|
20
|
+
name: Rust tests (${{ matrix.os }})
|
|
21
|
+
runs-on: ${{ matrix.os }}
|
|
22
|
+
strategy:
|
|
23
|
+
fail-fast: false
|
|
24
|
+
matrix:
|
|
25
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
26
|
+
steps:
|
|
27
|
+
- uses: actions/checkout@v4
|
|
28
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
29
|
+
- uses: Swatinem/rust-cache@v2
|
|
30
|
+
|
|
31
|
+
# Build only the cs_dmri crate here. cs_dmri_py is a Python cdylib
|
|
32
|
+
# whose link step needs `-undefined dynamic_lookup` on macOS
|
|
33
|
+
# (configured in python/.cargo/config.toml, only visible when cargo
|
|
34
|
+
# runs from python/). The cdylib itself is built in the python-tests
|
|
35
|
+
# job via maturin; `cargo check` here still catches Rust errors.
|
|
36
|
+
- name: cargo build (cs_dmri)
|
|
37
|
+
run: cargo build -p cs_dmri --all-targets
|
|
38
|
+
|
|
39
|
+
- name: cargo check (cs_dmri_py)
|
|
40
|
+
run: cargo check -p cs_dmri_py
|
|
41
|
+
|
|
42
|
+
- name: cargo test (cs_dmri)
|
|
43
|
+
run: cargo test -p cs_dmri
|
|
44
|
+
|
|
45
|
+
python-tests:
|
|
46
|
+
name: Python tests (${{ matrix.os }} / py${{ matrix.python-version }})
|
|
47
|
+
runs-on: ${{ matrix.os }}
|
|
48
|
+
strategy:
|
|
49
|
+
fail-fast: false
|
|
50
|
+
matrix:
|
|
51
|
+
os: [ubuntu-latest, macos-latest]
|
|
52
|
+
python-version: ['3.10', '3.12']
|
|
53
|
+
steps:
|
|
54
|
+
- uses: actions/checkout@v4
|
|
55
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
56
|
+
- uses: Swatinem/rust-cache@v2
|
|
57
|
+
- uses: actions/setup-python@v5
|
|
58
|
+
with:
|
|
59
|
+
python-version: ${{ matrix.python-version }}
|
|
60
|
+
cache: pip
|
|
61
|
+
|
|
62
|
+
# `maturin develop` requires an active virtualenv (it refuses to
|
|
63
|
+
# install into the system Python). Create one inside python/ and
|
|
64
|
+
# activate it for the remainder of the job by exporting VIRTUAL_ENV
|
|
65
|
+
# and prepending its bin/ directory to PATH.
|
|
66
|
+
- name: Create + activate virtualenv
|
|
67
|
+
working-directory: python
|
|
68
|
+
run: |
|
|
69
|
+
python -m venv .venv
|
|
70
|
+
echo "VIRTUAL_ENV=$PWD/.venv" >> "$GITHUB_ENV"
|
|
71
|
+
echo "$PWD/.venv/bin" >> "$GITHUB_PATH"
|
|
72
|
+
|
|
73
|
+
- name: Install build + test deps
|
|
74
|
+
working-directory: python
|
|
75
|
+
run: |
|
|
76
|
+
python -m pip install --upgrade pip
|
|
77
|
+
python -m pip install maturin pytest numpy nibabel dipy
|
|
78
|
+
|
|
79
|
+
- name: Build + install (maturin develop)
|
|
80
|
+
working-directory: python
|
|
81
|
+
run: maturin develop --release
|
|
82
|
+
|
|
83
|
+
# tests/test_cli_parity.py skips here: it needs the qsiprep test data.
|
|
84
|
+
- name: Run Python tests
|
|
85
|
+
working-directory: python
|
|
86
|
+
run: pytest tests/ -v
|
|
87
|
+
|
|
88
|
+
docs:
|
|
89
|
+
name: Documentation
|
|
90
|
+
runs-on: ubuntu-latest
|
|
91
|
+
steps:
|
|
92
|
+
- uses: actions/checkout@v4
|
|
93
|
+
- uses: actions/setup-python@v5
|
|
94
|
+
with:
|
|
95
|
+
python-version: '3.12'
|
|
96
|
+
cache: pip
|
|
97
|
+
# Read the Docs builds without the compiled extension (autodoc mocks
|
|
98
|
+
# it), so this job does the same.
|
|
99
|
+
- name: Install documentation dependencies
|
|
100
|
+
run: python -m pip install -r docs/requirements.txt
|
|
101
|
+
- name: Build documentation
|
|
102
|
+
run: sphinx-build -W --keep-going -b html docs docs/_build/html
|
|
103
|
+
|
|
104
|
+
cli-reference:
|
|
105
|
+
name: Command-line reference is current
|
|
106
|
+
runs-on: ubuntu-latest
|
|
107
|
+
steps:
|
|
108
|
+
- uses: actions/checkout@v4
|
|
109
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
110
|
+
- uses: Swatinem/rust-cache@v2
|
|
111
|
+
- name: Build the tools
|
|
112
|
+
run: cargo build --release --bins
|
|
113
|
+
- name: Regenerate docs/cli from --help
|
|
114
|
+
run: python docs/tools/make_cli_pages.py
|
|
115
|
+
- name: Check for differences
|
|
116
|
+
run: git diff --exit-code docs/cli
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
name: Release wheels + PyPI
|
|
2
|
+
|
|
3
|
+
# Trigger on bare semver tags (e.g. 0.1.0, 0.2.0rc1) or manual dispatch.
|
|
4
|
+
on:
|
|
5
|
+
push:
|
|
6
|
+
tags:
|
|
7
|
+
- '[0-9]+.[0-9]+.[0-9]+*'
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
env:
|
|
14
|
+
CARGO_TERM_COLOR: always
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
# ─── Tag / version sanity check ────────────────────────────────────────────
|
|
18
|
+
#
|
|
19
|
+
# Refuses to build if the pushed tag (`X.Y.Z`) doesn't match the version
|
|
20
|
+
# in [workspace.package] of Cargo.toml. Catches "I tagged but forgot to
|
|
21
|
+
# bump" before we waste 4× wheel build minutes on a wrong-version release.
|
|
22
|
+
# All build jobs `needs: verify-version`, so a mismatch fails the whole
|
|
23
|
+
# workflow at the first step.
|
|
24
|
+
verify-version:
|
|
25
|
+
name: Verify tag matches Cargo.toml
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
outputs:
|
|
28
|
+
version: ${{ steps.check.outputs.version }}
|
|
29
|
+
steps:
|
|
30
|
+
- uses: actions/checkout@v4
|
|
31
|
+
- id: check
|
|
32
|
+
run: |
|
|
33
|
+
set -euo pipefail
|
|
34
|
+
# Extract the version from the [workspace.package] section.
|
|
35
|
+
PKG_VERSION=$(awk '
|
|
36
|
+
/^\[workspace\.package\]/ { in_section = 1; next }
|
|
37
|
+
/^\[/ { in_section = 0 }
|
|
38
|
+
in_section && /^version[[:space:]]*=/ {
|
|
39
|
+
gsub(/^version[[:space:]]*=[[:space:]]*"|"[[:space:]]*$/, "")
|
|
40
|
+
print
|
|
41
|
+
exit
|
|
42
|
+
}
|
|
43
|
+
' Cargo.toml)
|
|
44
|
+
echo "Cargo.toml: $PKG_VERSION"
|
|
45
|
+
echo "version=$PKG_VERSION" >> "$GITHUB_OUTPUT"
|
|
46
|
+
# Only enforce tag<->version match when triggered by a tag push.
|
|
47
|
+
# workflow_dispatch and re-runs without a tag fall through.
|
|
48
|
+
if [[ "$GITHUB_REF" != refs/tags/* ]]; then
|
|
49
|
+
echo "Not a tag push; skipping tag<->version match."
|
|
50
|
+
exit 0
|
|
51
|
+
fi
|
|
52
|
+
TAG_VERSION="${GITHUB_REF#refs/tags/}"
|
|
53
|
+
echo "Tag: $TAG_VERSION"
|
|
54
|
+
if [ "$TAG_VERSION" != "$PKG_VERSION" ]; then
|
|
55
|
+
echo "::error::Tag $TAG_VERSION does not match [workspace.package].version = \"$PKG_VERSION\". Bump Cargo.toml or retag."
|
|
56
|
+
exit 1
|
|
57
|
+
fi
|
|
58
|
+
|
|
59
|
+
# ─── Linux wheels ───────────────────────────────────────────────────────────
|
|
60
|
+
linux:
|
|
61
|
+
name: Linux ${{ matrix.target }} (${{ matrix.libc }})
|
|
62
|
+
runs-on: ubuntu-latest
|
|
63
|
+
needs: [verify-version]
|
|
64
|
+
strategy:
|
|
65
|
+
fail-fast: false
|
|
66
|
+
matrix:
|
|
67
|
+
include:
|
|
68
|
+
- target: x86_64
|
|
69
|
+
libc: manylinux
|
|
70
|
+
- target: aarch64
|
|
71
|
+
libc: manylinux
|
|
72
|
+
- target: x86_64
|
|
73
|
+
libc: musllinux
|
|
74
|
+
- target: aarch64
|
|
75
|
+
libc: musllinux
|
|
76
|
+
steps:
|
|
77
|
+
- uses: actions/checkout@v4
|
|
78
|
+
- uses: PyO3/maturin-action@v1
|
|
79
|
+
# cs_dmri itself has no C dependencies, but odx-rs builds HDF5 from
|
|
80
|
+
# source (hdf5-metno, static), which needs CMake >= 3.26. Set the
|
|
81
|
+
# CMAKE env var so the cmake-rs crate uses our pip-installed cmake;
|
|
82
|
+
# before-script-linux populates /opt/_pipcmake/bin/cmake. This block
|
|
83
|
+
# is odx-rs's, kept in step with it.
|
|
84
|
+
env:
|
|
85
|
+
CMAKE: /opt/_pipcmake/bin/cmake
|
|
86
|
+
with:
|
|
87
|
+
target: ${{ matrix.target }}
|
|
88
|
+
# abi3-py39 wheels work for all CPython >= 3.9.
|
|
89
|
+
args: --release --out dist
|
|
90
|
+
working-directory: python
|
|
91
|
+
# `2_28` (AlmaLinux 9 / glibc 2.28) instead of the older `auto`
|
|
92
|
+
# (= `2014` = manylinux_2_17, CentOS 7 / glibc 2.17). The 2014
|
|
93
|
+
# cross image ships Python 3.6, which maturin rejects (needs
|
|
94
|
+
# >=3.7) and which is below our abi3-py39 baseline. 2_28 has
|
|
95
|
+
# Python 3.9+ baked in. The compat trade-off is glibc 2.28+
|
|
96
|
+
# required at install time — i.e. RHEL/AlmaLinux 8+, Debian 10+,
|
|
97
|
+
# Ubuntu 18.10+ (essentially anything from the last ~6 years).
|
|
98
|
+
manylinux: ${{ matrix.libc == 'manylinux' && '2_28' || 'musllinux_1_2' }}
|
|
99
|
+
before-script-linux: |
|
|
100
|
+
# hdf5-metno-src builds HDF5 from source via cmake; it requires
|
|
101
|
+
# CMake >= 3.26. Both manylinux_2_17 (AlmaLinux yum cmake 3.20)
|
|
102
|
+
# and musllinux_1_2 (Alpine apk cmake 3.22) ship too-old
|
|
103
|
+
# versions, and cross-compile images from messense (used for
|
|
104
|
+
# aarch64) don't have /opt/python/ at all. Install a recent
|
|
105
|
+
# cmake via pip from whatever Python we can find, and pin its
|
|
106
|
+
# path via the CMAKE env var.
|
|
107
|
+
#
|
|
108
|
+
# `set -ex` prints every command so failures are diagnosable
|
|
109
|
+
# from the workflow log without re-running.
|
|
110
|
+
set -ex
|
|
111
|
+
|
|
112
|
+
uname -a
|
|
113
|
+
cat /etc/os-release || true
|
|
114
|
+
ls -d /opt/python 2>&1 || echo "(no /opt/python — likely a cross-compile image)"
|
|
115
|
+
|
|
116
|
+
# Install minimal build tools + a system Python if needed.
|
|
117
|
+
# The cross-compile images have package managers but often no
|
|
118
|
+
# Python preinstalled, so add it here.
|
|
119
|
+
if command -v apk >/dev/null 2>&1; then
|
|
120
|
+
apk update
|
|
121
|
+
apk add --no-cache make gcc g++ musl-dev linux-headers perl bash python3 py3-pip
|
|
122
|
+
elif command -v dnf >/dev/null 2>&1; then
|
|
123
|
+
dnf install -y make gcc gcc-c++ perl python3 python3-pip
|
|
124
|
+
elif command -v yum >/dev/null 2>&1; then
|
|
125
|
+
yum install -y make gcc gcc-c++ perl python3 python3-pip
|
|
126
|
+
elif command -v apt-get >/dev/null 2>&1; then
|
|
127
|
+
apt-get update
|
|
128
|
+
apt-get install -y make gcc g++ perl python3 python3-pip
|
|
129
|
+
fi
|
|
130
|
+
|
|
131
|
+
# Resolve a pip we can use. Prefer the PyPA-style /opt/python
|
|
132
|
+
# bundled CPython on native images; on *cross-compile* images
|
|
133
|
+
# (messense/*-cross), /opt/python contains TARGET-arch binaries
|
|
134
|
+
# that can't execute on the build host (kernel returns ENOEXEC,
|
|
135
|
+
# bash falls back to interpreting the pip script and chokes on
|
|
136
|
+
# Python syntax). Probe each candidate by running --version
|
|
137
|
+
# before committing to it.
|
|
138
|
+
PIP_CMD=""
|
|
139
|
+
PYBIN=""
|
|
140
|
+
for cand in /opt/python/cp310-cp310/bin /opt/python/cp311-cp311/bin \
|
|
141
|
+
/opt/python/cp312-cp312/bin /opt/python/cp39-cp39/bin \
|
|
142
|
+
/opt/python/cp313-cp313/bin; do
|
|
143
|
+
if [ -d "$cand" ] && "$cand/python" --version >/dev/null 2>&1; then
|
|
144
|
+
PYBIN="$cand"
|
|
145
|
+
PIP_CMD="$cand/pip"
|
|
146
|
+
break
|
|
147
|
+
fi
|
|
148
|
+
done
|
|
149
|
+
if [ -z "$PIP_CMD" ]; then
|
|
150
|
+
if command -v pip3 >/dev/null 2>&1; then
|
|
151
|
+
PIP_CMD="pip3"
|
|
152
|
+
elif command -v python3 >/dev/null 2>&1; then
|
|
153
|
+
python3 -m ensurepip --default-pip 2>/dev/null || true
|
|
154
|
+
PIP_CMD="python3 -m pip"
|
|
155
|
+
else
|
|
156
|
+
echo "::error::No Python/pip found in build container"
|
|
157
|
+
exit 1
|
|
158
|
+
fi
|
|
159
|
+
fi
|
|
160
|
+
echo "Using PIP_CMD='$PIP_CMD' (PYBIN='${PYBIN:-system}')"
|
|
161
|
+
|
|
162
|
+
# If we found a /opt/python/cp* Python, make sure it shadows
|
|
163
|
+
# any older system python3 on PATH. maturin invokes `python3`
|
|
164
|
+
# from PATH after this script runs, and we've seen older
|
|
165
|
+
# cross-compile images leave a too-old `/usr/bin/python3` in
|
|
166
|
+
# place (e.g., 3.6 on the legacy manylinux2014 cross image).
|
|
167
|
+
if [ -n "$PYBIN" ]; then
|
|
168
|
+
ln -sf "$PYBIN/python" /usr/local/bin/python3
|
|
169
|
+
ln -sf "$PYBIN/python" /usr/local/bin/python
|
|
170
|
+
fi
|
|
171
|
+
|
|
172
|
+
# Install cmake>=3.26 from PyPI. `--break-system-packages` is
|
|
173
|
+
# for PEP 668-marked Pythons (some distros); harmless on others.
|
|
174
|
+
$PIP_CMD install --no-cache-dir --upgrade --break-system-packages "cmake>=3.26" 2>/dev/null \
|
|
175
|
+
|| $PIP_CMD install --no-cache-dir --upgrade "cmake>=3.26"
|
|
176
|
+
|
|
177
|
+
# Find where the pip-installed cmake landed. With /opt/python
|
|
178
|
+
# it's in $PYBIN/cmake; with system pip it's wherever pip puts
|
|
179
|
+
# console scripts — discoverable via `command -v cmake` after
|
|
180
|
+
# install (PATH is updated by the install).
|
|
181
|
+
INSTALLED_CMAKE=""
|
|
182
|
+
if [ -n "$PYBIN" ] && [ -x "$PYBIN/cmake" ]; then
|
|
183
|
+
INSTALLED_CMAKE="$PYBIN/cmake"
|
|
184
|
+
elif command -v cmake >/dev/null 2>&1; then
|
|
185
|
+
INSTALLED_CMAKE=$(command -v cmake)
|
|
186
|
+
else
|
|
187
|
+
# Last-ditch: ask pip where it put the script.
|
|
188
|
+
INSTALLED_CMAKE=$($PIP_CMD show -f cmake 2>/dev/null | awk '/Location:/ {loc=$2} /bin\/cmake/ {print loc"/"$1}' | head -1)
|
|
189
|
+
# That gives a path relative to site-packages; resolve to abs.
|
|
190
|
+
if [ -n "$INSTALLED_CMAKE" ]; then
|
|
191
|
+
INSTALLED_CMAKE=$(realpath "$INSTALLED_CMAKE" 2>/dev/null || echo "$INSTALLED_CMAKE")
|
|
192
|
+
fi
|
|
193
|
+
fi
|
|
194
|
+
if [ -z "$INSTALLED_CMAKE" ] || [ ! -x "$INSTALLED_CMAKE" ]; then
|
|
195
|
+
echo "::error::Could not locate pip-installed cmake binary"
|
|
196
|
+
$PIP_CMD show -f cmake || true
|
|
197
|
+
exit 1
|
|
198
|
+
fi
|
|
199
|
+
echo "Pip-installed cmake at: $INSTALLED_CMAKE"
|
|
200
|
+
|
|
201
|
+
# Pin the path to match the CMAKE env var set on the step.
|
|
202
|
+
mkdir -p /opt/_pipcmake/bin
|
|
203
|
+
ln -sf "$INSTALLED_CMAKE" /opt/_pipcmake/bin/cmake
|
|
204
|
+
|
|
205
|
+
# Shadow common system locations as a PATH fallback.
|
|
206
|
+
for target in /usr/local/bin/cmake /usr/bin/cmake; do
|
|
207
|
+
parent=$(dirname "$target")
|
|
208
|
+
[ -d "$parent" ] && ln -sf "$INSTALLED_CMAKE" "$target" || true
|
|
209
|
+
done
|
|
210
|
+
|
|
211
|
+
# Diagnostic: confirm the right cmake is found via every route.
|
|
212
|
+
echo "--- cmake versions:"
|
|
213
|
+
"$INSTALLED_CMAKE" --version
|
|
214
|
+
/opt/_pipcmake/bin/cmake --version
|
|
215
|
+
cmake --version
|
|
216
|
+
- uses: actions/upload-artifact@v4
|
|
217
|
+
with:
|
|
218
|
+
name: wheels-linux-${{ matrix.target }}-${{ matrix.libc }}
|
|
219
|
+
path: python/dist
|
|
220
|
+
|
|
221
|
+
# ─── macOS wheels (x86_64 + Apple Silicon) ─────────────────────────────────
|
|
222
|
+
#
|
|
223
|
+
# Runner mapping:
|
|
224
|
+
# - aarch64 → macos-14 (Apple Silicon, free)
|
|
225
|
+
# - x86_64 → macos-15-intel (Intel x86_64 on macOS 15; GitHub's
|
|
226
|
+
# recommended migration path for x86_64
|
|
227
|
+
# builds, supported until August 2027).
|
|
228
|
+
#
|
|
229
|
+
# The older `macos-13` runner pool is queue-pressured; `macos-15-intel`
|
|
230
|
+
# is the current Intel target with much better availability. There's no
|
|
231
|
+
# `macos-15-intel-large` etc. — Intel hardware is being retired, so
|
|
232
|
+
# macos-15-intel is the long tail.
|
|
233
|
+
macos:
|
|
234
|
+
name: macOS ${{ matrix.target }}
|
|
235
|
+
runs-on: ${{ matrix.target == 'aarch64' && 'macos-14' || 'macos-15-intel' }}
|
|
236
|
+
needs: [verify-version]
|
|
237
|
+
strategy:
|
|
238
|
+
fail-fast: false
|
|
239
|
+
matrix:
|
|
240
|
+
target: [x86_64, aarch64]
|
|
241
|
+
steps:
|
|
242
|
+
- uses: actions/checkout@v4
|
|
243
|
+
- uses: PyO3/maturin-action@v1
|
|
244
|
+
with:
|
|
245
|
+
target: ${{ matrix.target }}
|
|
246
|
+
args: --release --out dist
|
|
247
|
+
working-directory: python
|
|
248
|
+
- uses: actions/upload-artifact@v4
|
|
249
|
+
with:
|
|
250
|
+
name: wheels-macos-${{ matrix.target }}
|
|
251
|
+
path: python/dist
|
|
252
|
+
|
|
253
|
+
# ─── Windows wheels ────────────────────────────────────────────────────────
|
|
254
|
+
windows:
|
|
255
|
+
name: Windows ${{ matrix.target }}
|
|
256
|
+
runs-on: windows-latest
|
|
257
|
+
needs: [verify-version]
|
|
258
|
+
strategy:
|
|
259
|
+
fail-fast: false
|
|
260
|
+
matrix:
|
|
261
|
+
target: [x64]
|
|
262
|
+
steps:
|
|
263
|
+
- uses: actions/checkout@v4
|
|
264
|
+
- uses: PyO3/maturin-action@v1
|
|
265
|
+
with:
|
|
266
|
+
target: ${{ matrix.target }}
|
|
267
|
+
args: --release --out dist
|
|
268
|
+
working-directory: python
|
|
269
|
+
- uses: actions/upload-artifact@v4
|
|
270
|
+
with:
|
|
271
|
+
name: wheels-windows-${{ matrix.target }}
|
|
272
|
+
path: python/dist
|
|
273
|
+
|
|
274
|
+
# ─── Source distribution ───────────────────────────────────────────────────
|
|
275
|
+
sdist:
|
|
276
|
+
name: sdist
|
|
277
|
+
runs-on: ubuntu-latest
|
|
278
|
+
needs: [verify-version]
|
|
279
|
+
steps:
|
|
280
|
+
- uses: actions/checkout@v4
|
|
281
|
+
- uses: PyO3/maturin-action@v1
|
|
282
|
+
with:
|
|
283
|
+
command: sdist
|
|
284
|
+
args: --out dist
|
|
285
|
+
working-directory: python
|
|
286
|
+
- uses: actions/upload-artifact@v4
|
|
287
|
+
with:
|
|
288
|
+
name: sdist
|
|
289
|
+
path: python/dist
|
|
290
|
+
|
|
291
|
+
publish:
|
|
292
|
+
name: Publish to PyPI
|
|
293
|
+
needs: [linux, macos, windows, sdist]
|
|
294
|
+
runs-on: ubuntu-latest
|
|
295
|
+
if: startsWith(github.ref, 'refs/tags/')
|
|
296
|
+
environment:
|
|
297
|
+
name: pypi
|
|
298
|
+
url: https://pypi.org/p/cs_dmri
|
|
299
|
+
permissions:
|
|
300
|
+
id-token: write
|
|
301
|
+
steps:
|
|
302
|
+
- uses: actions/download-artifact@v4
|
|
303
|
+
with:
|
|
304
|
+
path: dist
|
|
305
|
+
merge-multiple: true
|
|
306
|
+
- name: Inspect artifacts
|
|
307
|
+
run: ls -la dist/
|
|
308
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
309
|
+
with:
|
|
310
|
+
packages-dir: dist
|
|
311
|
+
# Switch to test.pypi.org for dry-runs by uncommenting:
|
|
312
|
+
# repository-url: https://test.pypi.org/legacy/
|
|
313
|
+
skip-existing: true
|
cs_dmri-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Generated by Cargo
|
|
2
|
+
# will have compiled files and executables
|
|
3
|
+
debug
|
|
4
|
+
target
|
|
5
|
+
|
|
6
|
+
# These are backup files generated by rustfmt
|
|
7
|
+
**/*.rs.bk
|
|
8
|
+
|
|
9
|
+
# MSVC Windows builds of rustc generate these, which store debugging information
|
|
10
|
+
*.pdb
|
|
11
|
+
|
|
12
|
+
# Generated by cargo mutants
|
|
13
|
+
# Contains mutation testing data
|
|
14
|
+
**/mutants.out*/
|
|
15
|
+
|
|
16
|
+
# rustc will dump stack traces when hitting an internal compiler error to PWD
|
|
17
|
+
rustc-ice-*.txt
|
|
18
|
+
.DS_Store
|
|
19
|
+
# RustRover
|
|
20
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
21
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
22
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
23
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
24
|
+
#.idea/
|
|
25
|
+
|
|
26
|
+
# Reference papers kept alongside the project. Never commit these — they are
|
|
27
|
+
# third-party copyrighted PDFs, not source.
|
|
28
|
+
literature/
|
|
29
|
+
|
|
30
|
+
# Python bindings
|
|
31
|
+
python/cs_dmri/_cs_dmri*.so
|
|
32
|
+
python/cs_dmri/_cs_dmri*.pyd
|
|
33
|
+
python/.venv/
|
|
34
|
+
__pycache__/
|
|
35
|
+
*.egg-info/
|
|
36
|
+
docs/_build/
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Read the Docs configuration: https://docs.readthedocs.io/en/stable/config-file/v2.html
|
|
2
|
+
version: 2
|
|
3
|
+
|
|
4
|
+
build:
|
|
5
|
+
os: ubuntu-24.04
|
|
6
|
+
tools:
|
|
7
|
+
python: "3.12"
|
|
8
|
+
|
|
9
|
+
sphinx:
|
|
10
|
+
configuration: docs/conf.py
|
|
11
|
+
fail_on_warning: true
|
|
12
|
+
|
|
13
|
+
python:
|
|
14
|
+
install:
|
|
15
|
+
- requirements: docs/requirements.txt
|