Skip to content

[doc] update citation message #16

[doc] update citation message

[doc] update citation message #16

Workflow file for this run

name: ci
on:
push:
branches: [main]
pull_request:
defaults:
run:
shell: bash
jobs:
cpp-build:
name: build (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-22.04
binary: build/siamize
deps_check: |
echo "--- ldd ---"
ldd build/siamize
echo "--- direct (NEEDED) deps ---"
readelf -d build/siamize | grep NEEDED
- os: macos-latest
binary: build/siamize
deps_check: |
echo "--- otool -L (linked dylibs) ---"
otool -L build/siamize
- os: windows-latest
# MSVC multi-config generator drops the binary under Release/.
binary: build/Release/siamize.exe
deps_check: |
ls -la build/Release/
steps:
- uses: actions/checkout@v4
- name: Install OpenMP (macOS)
if: runner.os == 'macOS'
run: |
brew install libomp
echo "OpenMP_ROOT=$(brew --prefix libomp)" >> "$GITHUB_ENV"
- name: Fetch C++ deps
run: scripts/fetch_deps.sh
- name: Configure
# -DSIAMIZE_STATIC_LINK=ON is the default but we pin it for clarity:
# statically links libstdc++/libgcc/libgomp (Linux), libomp (macOS),
# /MT static CRT (Windows). Only libonnxruntime remains dynamic.
run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DSIAMIZE_STATIC_LINK=ON
- name: Build
run: cmake --build build --config Release --parallel
- name: Inspect runtime deps
run: ${{ matrix.deps_check }}
- name: Smoke-run --help
run: ${{ matrix.binary }} --help
- name: Package
shell: bash
run: |
case "${{ runner.os }}" in
Linux) PLAT=linux-x86_64 ;;
macOS) PLAT=macos ;;
Windows) PLAT=windows-x64 ;;
esac
scripts/package.sh cpu "siamize-${PLAT}-cpu"
echo "BUNDLE=siamize-${PLAT}-cpu" >> "$GITHUB_ENV"
- name: Upload bundle
uses: actions/upload-artifact@v4
with:
name: ${{ env.BUNDLE }}
path: ${{ env.BUNDLE }}.zip
if-no-files-found: error
retention-days: 14
cpp-build-cuda:
# Builds siamize with the CUDA Execution Provider enabled, then runs a
# single-fold inference on the bundled sample. GitHub-hosted runners
# have no NVIDIA GPU, so we expect siamize to register CUDA at startup,
# fail to dlopen the CUDA runtime libraries, and silently fall back to
# the CPU EP. This validates the build path AND the runtime fallback.
#
# The fp16 ONNX weight file (~270 MB raw, ~87 MB 7z-compressed) is too
# big for git, so CI grabs it from a public URL configured in the
# repository's GitHub Actions variables: Settings -> Secrets and
# variables -> Actions -> Variables -> SIAMIZE_WEIGHTS_URL is the
# FULL URL of the fold_0 weight. The URL may end in .gz (preferred,
# we decompress with gunzip), .onnx (used raw), or .7z (legacy --
# the script extracts with 7z if available). The job is skipped if
# the variable is not configured.
name: build+run cuda (${{ matrix.os }})
if: vars.SIAMIZE_WEIGHTS_URL != ''
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-22.04
binary: build/siamize
- os: windows-latest
binary: build/Release/siamize.exe
steps:
- uses: actions/checkout@v4
- name: Fetch C++ deps (GPU ORT prebuilt)
env:
ORT_BUILD: gpu
run: scripts/fetch_deps.sh
- name: Cache fold_0 weight
id: cache-fold0
uses: actions/cache@v4
with:
path: models/fold_0_fp16.onnx
key: siam-fold0-fp16-v2
- name: Fetch + extract fold_0 weight (cache miss)
if: steps.cache-fold0.outputs.cache-hit != 'true'
env:
URL: ${{ vars.SIAMIZE_WEIGHTS_URL }}
run: |
mkdir -p models
echo "Downloading $URL"
# Dispatch by the actual URL extension so the repo variable can
# point at .gz (preferred), .onnx (uncompressed), or .7z (legacy)
# without us guessing.
case "$URL" in
*.gz)
curl -fsSL "$URL" -o models/fold_0_fp16.onnx.gz
gunzip -f models/fold_0_fp16.onnx.gz
;;
*.7z)
if ! command -v 7z >/dev/null; then
sudo apt-get update -qq
sudo apt-get install -y --no-install-recommends p7zip-full
fi
curl -fsSL "$URL" -o models/fold_0_fp16.onnx.7z
7z e -y -omodels models/fold_0_fp16.onnx.7z >/dev/null
rm -f models/fold_0_fp16.onnx.7z
;;
*.onnx)
curl -fsSL "$URL" -o models/fold_0_fp16.onnx
;;
*)
echo "unsupported extension for SIAMIZE_WEIGHTS_URL: $URL"
echo "expected one of: .gz, .onnx, .7z"
exit 1
;;
esac
ls -la models/
- name: Configure (CUDA EP)
run: |
cmake -S . -B build \
-DCMAKE_BUILD_TYPE=Release \
-DSIAMIZE_STATIC_LINK=ON \
-DSIAMIZE_GPU=cuda
- name: Build
run: cmake --build build --config Release --parallel
- name: Run single-fold inference (expect CPU fallback on GPU-less runner)
run: |
set -e
${{ matrix.binary }} \
-i tests/sub-01_T1w.nii.gz \
-o pred_ci.nii.gz \
--models models/fold_0_fp16.onnx \
--device auto \
-v 2>&1 | tee siamize.log
- name: Verify CPU fallback happened
run: |
if grep -q "CUDA EP unavailable" siamize.log; then
echo "OK: CUDA EP correctly fell back to CPU."
else
echo "FAIL: expected 'CUDA EP unavailable' fallback message; got:"
cat siamize.log
exit 1
fi
- name: Verify output produced
run: |
test -s pred_ci.nii.gz || { echo "FAIL: empty/missing output"; exit 1; }
ls -lh pred_ci.nii.gz
- name: Package
shell: bash
run: |
case "${{ runner.os }}" in
Linux) PLAT=linux-x86_64 ;;
Windows) PLAT=windows-x64 ;;
esac
scripts/package.sh cuda "siamize-${PLAT}-cuda"
echo "BUNDLE=siamize-${PLAT}-cuda" >> "$GITHUB_ENV"
- name: Upload bundle
uses: actions/upload-artifact@v4
with:
name: ${{ env.BUNDLE }}
path: ${{ env.BUNDLE }}.zip
if-no-files-found: error
retention-days: 14
mex-build:
# Build siamize's MATLAB/Octave MEX wrapper and verify it loads. Heavy
# full-inference test is left to cpp-build-cuda; this job's job is just
# to catch MEX build regressions on each supported host.
name: mex (${{ matrix.label }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- label: linux-octave
os: ubuntu-22.04
kind: octave
cmake_flag: -DSIAMIZE_BUILD_OCTAVE_MEX=ON
mex_file: build/siamex.mex
- label: linux-matlab
os: ubuntu-22.04
kind: matlab
cmake_flag: -DSIAMIZE_BUILD_MATLAB_MEX=ON
mex_file: build/siamex.mexa64
- label: windows-matlab
os: windows-latest
kind: matlab
cmake_flag: -DSIAMIZE_BUILD_MATLAB_MEX=ON
mex_file: build/Release/siamex.mexw64
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Install Octave (Linux)
if: matrix.kind == 'octave' && runner.os == 'Linux'
run: |
sudo apt-get update -qq
sudo apt-get install -y --no-install-recommends octave liboctave-dev
- name: Set up MATLAB
if: matrix.kind == 'matlab'
uses: matlab-actions/setup-matlab@v2
with:
release: R2024a
- name: Install GCC 10 (Linux MATLAB)
# MATLAB R2024a on Linux bundles a libstdc++.so.6 that supports
# GLIBCXX <=3.4.28 (GCC 9 / 10). The ubuntu-22.04 runner ships
# GCC 11 as the default, whose libstdc++ headers reference
# GLIBCXX_3.4.29 symbols and produce a MEX MATLAB can't load.
# GCC 10 is MathWorks' officially supported MEX compiler for
# R2024a on Linux.
if: matrix.kind == 'matlab' && runner.os == 'Linux'
run: |
sudo apt-get update -qq
sudo apt-get install -y --no-install-recommends g++-10 gcc-10
- name: Fetch C++ deps (CPU ORT)
run: scripts/fetch_deps.sh
- name: Configure
env:
# Pin to GCC 10 for the MATLAB-on-Linux leg so the MEX only
# references GLIBCXX symbols MATLAB's bundled libstdc++ has.
CC: ${{ (matrix.kind == 'matlab' && runner.os == 'Linux') && 'gcc-10' || '' }}
CXX: ${{ (matrix.kind == 'matlab' && runner.os == 'Linux') && 'g++-10' || '' }}
run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release ${{ matrix.cmake_flag }}
- name: Build
run: cmake --build build --config Release --parallel
- name: Verify MEX exists
run: |
ls -la "${{ matrix.mex_file }}"
test -s "${{ matrix.mex_file }}"
- name: Smoke-load MEX (Octave)
if: matrix.kind == 'octave' && runner.os == 'Linux'
run: |
# Call siamex (the low-level MEX) with zero args to trigger the
# C++ "Usage:" error. Proves the .mex loaded + reached mexFunction.
octave-cli --no-gui --eval "addpath('build'); \
try; siamex(); catch err; \
if isempty(strfind(err.message, 'Usage:')); error('unexpected: %s', err.message); end; \
fprintf('MEX loaded and reached argument check\\n'); \
end" 2>&1 | tee mex.log
grep -q "MEX loaded" mex.log
- name: Run siamize.m unit tests (Octave)
if: matrix.kind == 'octave' && runner.os == 'Linux'
run: |
# Pure-MATLAB dispatcher tests. Stubs siamex internally so it
# doesn't depend on ORT or weight files; needs the jsonlab
# submodule (pulled via submodules: recursive above).
octave-cli --no-gui --eval "cd matlab/tests; run_tests('--exit')"
- name: Smoke-load MEX (MATLAB)
if: matrix.kind == 'matlab'
uses: matlab-actions/run-command@v2
with:
command: |
addpath(fullfile(pwd, 'build'));
% cd into build/Release on Windows so the MEX picks up neighboring
% onnxruntime.dll via the EXE search rule.
if ispc; cd(fullfile('build', 'Release')); end
try
siamex();
error('siamex() with no args should have thrown');
catch err
if isempty(strfind(err.message, 'Usage:'))
error('unexpected: %s', err.message);
end
fprintf('MEX loaded and reached argument check\n');
end
- name: Run siamize.m unit tests (MATLAB)
if: matrix.kind == 'matlab'
uses: matlab-actions/run-command@v2
with:
command: |
cd(fullfile('matlab', 'tests'));
[~, nfail] = run_tests();
assert(nfail == 0, 'siamize.m unit tests failed (%d)', nfail);
- name: Package
shell: bash
run: scripts/package.sh mex "siamex-${{ matrix.label }}"
- name: Upload bundle
uses: actions/upload-artifact@v4
with:
name: siamex-${{ matrix.label }}
path: siamex-${{ matrix.label }}.zip
if-no-files-found: error
retention-days: 14
python-smoke:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.10'
- name: Install Python deps
run: |
pip install --upgrade pip
pip install numpy nibabel scipy scikit-image torch \
dynamic_network_architectures onnxruntime
- name: Import smoke test
run: |
python -c "import sys; sys.path.insert(0, 'py'); import siam_ref; print(siam_ref.build_network.__name__)"
python tools/onnx_export/compare.py --help || true