Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
e972b02
v2.0 RC : major refactor, webgl in notebook (plot3d)
m-reuter Feb 16, 2026
c24b566
add logger and raise errors instead of exit
m-reuter Feb 16, 2026
870e1dc
add docstrings
m-reuter Feb 16, 2026
297e812
update testing
m-reuter Feb 16, 2026
6479bc4
bump actions to newer python
m-reuter Feb 16, 2026
0f41d59
fix input order
m-reuter Feb 16, 2026
ebd9b62
re-add ignore-world-list
m-reuter Feb 16, 2026
ee0cc3f
update doc
m-reuter Feb 16, 2026
36b859a
fix pydocstyle errors
m-reuter Feb 16, 2026
678b2ba
fix some docstrings
m-reuter Feb 16, 2026
fbadd92
explicit test path
m-reuter Feb 16, 2026
1488c0c
improve doc strings
m-reuter Feb 16, 2026
b4849ac
more sphinx fixes
m-reuter Feb 16, 2026
fe6ff60
more sphinx fixes
m-reuter Feb 16, 2026
df597a7
types toplevel, better window capture
m-reuter Feb 17, 2026
5b0a5e6
make QT6 optional for gui
m-reuter Feb 18, 2026
452f26c
remove Qt6 in docker (no gui)
m-reuter Feb 18, 2026
567a6fe
update documentation slightly
m-reuter Feb 18, 2026
2f980f5
fix typo
m-reuter Feb 18, 2026
b895807
local imports, further refactor of snap1 and snap4 to avoid code dupl…
m-reuter Feb 18, 2026
308e562
bug fixes in CLI, added whippersnap1 CLI (untested)
m-reuter Feb 18, 2026
a3e52de
add docstring parameter
m-reuter Feb 18, 2026
edff5d4
adding egl off-screen rendering capabilities
m-reuter Feb 18, 2026
a2bf6cd
egl updates
m-reuter Feb 18, 2026
e9609f5
egl updates
m-reuter Feb 18, 2026
a5bdc62
egl updates
m-reuter Feb 18, 2026
272e936
egl updates
m-reuter Feb 18, 2026
d1da6d6
egl updates
m-reuter Feb 18, 2026
de4553f
egl updates
m-reuter Feb 18, 2026
1f259e9
egl updates
m-reuter Feb 18, 2026
4e30dc8
egl updates
m-reuter Feb 18, 2026
bb99b05
egl updates
m-reuter Feb 18, 2026
44563f3
egl updates
m-reuter Feb 18, 2026
b6cb745
egl updates
m-reuter Feb 18, 2026
3435bf0
egl updates
m-reuter Feb 18, 2026
b0026a6
egl updates
m-reuter Feb 18, 2026
bc9bafe
egl updates
m-reuter Feb 18, 2026
8aa55f7
egl updates
m-reuter Feb 18, 2026
ddff059
fixes, especially fixed thresholds in snap4 for both hemis
m-reuter Feb 19, 2026
55bfdda
update build and test
m-reuter Feb 19, 2026
3d1fe01
fix ruff errors
m-reuter Feb 19, 2026
4c5b8c2
shortcut EGL without DISPLAY on linux
m-reuter Feb 19, 2026
91c34da
new feature: video of rotation
m-reuter Feb 19, 2026
7eed418
restructure CLI, keep snap4 and GUI separate
m-reuter Feb 19, 2026
c1213dd
update Dockerfile to whippersnap4 and video
m-reuter Feb 19, 2026
a194993
add DOCKER doc and update README.md and sphinx
m-reuter Feb 19, 2026
fb5c6cd
fix sphinx
m-reuter Feb 19, 2026
607bbfe
fix sphinx
m-reuter Feb 19, 2026
cb09c2c
remove sphinx-gallery
m-reuter Feb 20, 2026
2e9b8cc
renamed examples -> tutorials
m-reuter Feb 20, 2026
d7b61a4
add code for example download via pooch and github release data
m-reuter Feb 20, 2026
a0e8f96
update tutorial ipynb
m-reuter Feb 20, 2026
dd880ef
sphinx build update
m-reuter Feb 20, 2026
efb720e
fix ruff
m-reuter Feb 20, 2026
2bb7412
fix doc build and update show_window paramters
m-reuter Feb 20, 2026
cea31fe
only publish on v* releases to enable data only releases
m-reuter Feb 20, 2026
536a5a0
refactor to allow passing of arrays or files, add tests
m-reuter Feb 21, 2026
26f24f9
fix ruff
m-reuter Feb 21, 2026
ddf9a95
add import for OFF, PLY and VTK ASCII triangle meshes
m-reuter Feb 21, 2026
1b622c3
update data path
m-reuter Feb 21, 2026
2d89603
ruff fix
m-reuter Feb 21, 2026
2f73f2a
add imports to doc build for rotating gif
m-reuter Feb 21, 2026
4021352
update doc for any mesh input and also whippersnap GUI CLI
m-reuter Feb 21, 2026
1ab18bf
add support for reading multiple overlay file formats and gifti surfaces
m-reuter Feb 21, 2026
d13728a
rename read_geometry to freesurfer_io.py
m-reuter Feb 21, 2026
cfda079
fix ruff
m-reuter Feb 21, 2026
8fad5b1
minor fixes, fixing pillow min version
m-reuter Feb 21, 2026
70572ca
readme mention gifti and overlay support
m-reuter Feb 21, 2026
0b6f8a4
move redundant CLI doc in README
m-reuter Feb 21, 2026
fdcbc32
remove CLI imports in init
m-reuter Feb 21, 2026
6868634
add --mesh to whippersnap1
m-reuter Feb 21, 2026
f58f700
add --mesh to whippersnap1
m-reuter Feb 21, 2026
86d286d
fix GUI on mac
m-reuter Feb 21, 2026
ddff35e
more tests also with offscreen render
m-reuter Feb 21, 2026
7d7c3a3
reduce and adapt tests
m-reuter Feb 21, 2026
972f995
add GUI mouse navigation
m-reuter Feb 21, 2026
50d6091
GUI add s key for snapshot
m-reuter Feb 22, 2026
8548b4b
doc workflow remove comments
m-reuter Feb 22, 2026
9386743
fix sphinx
m-reuter Feb 22, 2026
3cf84e3
support for also reading LUT from command line
m-reuter Feb 22, 2026
48c8f3e
skip test if no gl context is available
m-reuter Feb 22, 2026
3b1d6e9
fix lut test
m-reuter Feb 22, 2026
e58777b
fix typo
m-reuter Feb 22, 2026
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
4 changes: 0 additions & 4 deletions .codespellignore

This file was deleted.

5 changes: 4 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu, macos, windows]
python-version: ["3.9", "3.10", "3.11", "3.12"]
python-version: ["3.10", "3.11", "3.12", "3.13"]
name: ${{ matrix.os }} - py${{ matrix.python-version }}
runs-on: ${{ matrix.os }}-latest
defaults:
Expand All @@ -28,6 +28,9 @@ jobs:
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
- name: Install system OpenGL/EGL libraries (Ubuntu)
if: matrix.os == 'ubuntu'
run: sudo apt-get install -y --no-install-recommends libegl1 libgl1
- name: Install dependencies
run: |
python -m pip install --progress-bar off --upgrade pip setuptools wheel
Expand Down
14 changes: 5 additions & 9 deletions .github/workflows/code-style.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Setup Python 3.10
- name: Setup Python 3.13
uses: actions/setup-python@v6
with:
python-version: '3.10'
python-version: '3.13'
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --progress-bar off --upgrade pip setuptools wheel
Expand All @@ -27,10 +28,5 @@ jobs:
run: ruff check .
- name: Run codespell
uses: codespell-project/actions-codespell@master
with:
check_filenames: true
check_hidden: true
skip: './.git,./build,./.mypy_cache,./.pytest_cache'
ignore_words_file: ./.codespellignore
# - name: Run pydocstyle
# run: pydocstyle .
- name: Run pydocstyle
run: pydocstyle .
21 changes: 13 additions & 8 deletions .github/workflows/doc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,30 +20,35 @@ jobs:
uses: actions/checkout@v6
with:
path: ./main
- name: Setup Python 3.10
- name: Setup Python 3.13
uses: actions/setup-python@v6
with:
python-version: '3.10'
- name: Install Linux dependencies
if: runner.os == 'Linux'
python-version: '3.13'
cache: pip
- name: Install system dependencies
run: |
sudo apt update
sudo apt-get update
sudo apt-get -y install libgl1 libegl1
sudo apt install libxcb-cursor0
sudo apt-get -y install libgl1 libegl1 libxcb-cursor0 pandoc
- name: Install package
run: |
python -m pip install --progress-bar off --upgrade pip setuptools wheel
python -m pip install --progress-bar off main/.[doc]
- name: Display system information
run: whippersnappy-sys_info --developer
- name: Cache WhipperSnapPy sample data
uses: actions/cache@v4
with:
path: ~/.cache/whippersnappy
key: sample-data-sub-rs-data-v1.0
- name: Build doc
run: TZ=UTC sphinx-build ./main/doc ./doc-build/dev -W --keep-going
- name: Upload documentation
uses: actions/upload-artifact@v6
with:
name: doc-dev
path: ./doc-build/dev
path: |
doc-build/dev
!doc-build/dev/.doctrees

deploy:
if: github.event_name == 'push'
Expand Down
7 changes: 5 additions & 2 deletions .github/workflows/pytest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu, macos, windows]
python-version: ["3.9", "3.10", "3.11", "3.12"]
python-version: ["3.10", "3.11", "3.12", "3.13"]
name: ${{ matrix.os }} - py${{ matrix.python-version }}
runs-on: ${{ matrix.os }}-latest
defaults:
Expand All @@ -32,14 +32,17 @@ jobs:
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
- name: Install system OpenGL/EGL libraries (Ubuntu)
if: matrix.os == 'ubuntu'
run: sudo apt-get install -y --no-install-recommends libegl1 libgl1
- name: Install package
run: |
python -m pip install --progress-bar off --upgrade pip setuptools wheel
python -m pip install --progress-bar off .[test]
- name: Display system information
run: whippersnappy-sys_info --developer
- name: Run pytest
run: pytest whippersnappy --cov=whippersnappy --cov-report=xml --cov-config=pyproject.toml
run: pytest tests --cov=whippersnappy --cov-report=xml --cov-config=pyproject.toml
- name: Upload to codecov
if: ${{ matrix.os == 'ubuntu' && matrix.python-version == '3.10' && github.repository == 'Deep-MI/WhipperSnapPy' }}
uses: codecov/codecov-action@v5
Expand Down
170 changes: 170 additions & 0 deletions DOCKER.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
# Docker Guide

The Docker image provides a fully headless rendering environment with EGL
off-screen support. No display server or `xvfb` is required.

The default entry point is `whippersnap4` (four-view batch rendering).
`whippersnap1` (single-view snapshot and rotation video) can be invoked by
overriding the entry point.

---

## Building the image

From the repository root:

```bash
docker build --rm -t whippersnappy -f Dockerfile .
```

---

## Running — four-view batch rendering (`whippersnap4`)

`whippersnap4` renders lateral and medial views of both hemispheres and writes
a single composed PNG image.

Mount your local directories into the container and pass the in-container paths
as arguments:

```bash
docker run --rm --init \
-v /path/to/subject:/subject \
-v /path/to/output:/output \
--user $(id -u):$(id -g) \
whippersnappy \
-lh /subject/surf/lh.thickness \
-rh /subject/surf/rh.thickness \
-sd /subject \
-o /output/snap4.png
```

### With an annotation file instead of an overlay

```bash
docker run --rm --init \
-v /path/to/subject:/subject \
-v /path/to/output:/output \
--user $(id -u):$(id -g) \
whippersnappy \
--lh_annot /subject/label/lh.aparc.annot \
--rh_annot /subject/label/rh.aparc.annot \
-sd /subject \
-o /output/snap4_annot.png
```

### With a caption and custom thresholds

```bash
docker run --rm --init \
-v /path/to/subject:/subject \
-v /path/to/output:/output \
--user $(id -u):$(id -g) \
whippersnappy \
-lh /subject/surf/lh.thickness \
-rh /subject/surf/rh.thickness \
-sd /subject \
--fthresh 2.0 --fmax 4.0 \
--caption "Cortical thickness" \
-o /output/snap4_thickness.png
```

### All `whippersnap4` options

```
docker run --rm whippersnappy --help
```

---

## Running — single-view snapshot (`whippersnap1`)

Override the entry point with `--entrypoint whippersnap1`:

```bash
docker run --rm --init \
--entrypoint whippersnap1 \
-v /path/to/subject:/subject \
-v /path/to/output:/output \
--user $(id -u):$(id -g) \
whippersnappy \
--mesh /subject/surf/lh.white \
--overlay /subject/surf/lh.thickness \
--bg-map /subject/surf/lh.curv \
--view left \
--fthresh 2.0 --fmax 4.0 \
-o /output/snap1.png
```

### All `whippersnap1` options

```bash
docker run --rm --entrypoint whippersnap1 whippersnappy --help
```

---

## Running — 360° rotation video (`whippersnap1 --rotate`)

`whippersnap1 --rotate` renders a full 360° rotation video and writes an
`.mp4`, `.webm`, or `.gif` file. `imageio-ffmpeg` is bundled in the image —
no system ffmpeg is required.

### MP4 (H.264, recommended)

```bash
docker run --rm --init \
--entrypoint whippersnap1 \
-v /path/to/subject:/subject \
-v /path/to/output:/output \
--user $(id -u):$(id -g) \
whippersnappy \
--mesh /subject/surf/lh.white \
--overlay /subject/surf/lh.thickness \
--bg-map /subject/surf/lh.curv \
--rotate \
--rotate-frames 72 \
--rotate-fps 24 \
-o /output/rotation.mp4
```

### Animated GIF (no ffmpeg needed)

```bash
docker run --rm --init \
--entrypoint whippersnap1 \
-v /path/to/subject:/subject \
-v /path/to/output:/output \
--user $(id -u):$(id -g) \
whippersnappy \
--mesh /subject/surf/lh.white \
--overlay /subject/surf/lh.thickness \
--rotate \
--rotate-frames 36 \
--rotate-fps 12 \
-o /output/rotation.gif
```

---

## Path mapping summary

| Host path | Container path | Purpose |
|-----------|---------------|---------|
| `/path/to/subject` | `/subject` | FreeSurfer subject directory (contains `surf/`, `label/`) |
| `/path/to/output` | `/output` | Directory where output files are written |

All output files are written to the container path you pass via `-o`; mount the
parent directory to retrieve them on the host.

---

## Notes

- The `--init` flag is recommended so that signals (e.g. `Ctrl-C`) are handled
correctly inside the container.
- `--user $(id -u):$(id -g)` ensures output files are owned by your host user,
not root.
- The interactive GUI (`whippersnap`) is **not** available in the Docker image —
it requires a display server and PyQt6, which are not installed.

20 changes: 10 additions & 10 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
FROM ubuntu:20.04
FROM python:3.11-slim

# Install packages
RUN apt-get update && apt-get install -y --no-install-recommends \
python3 pip xvfb libglib2.0-0 libxkbcommon-x11-0 libgl1 libegl1 \
libfontconfig1 libdbus-1-3 && \
apt clean && \
rm -rf /var/libs/apt/lists/* /tmp/* /var/tmp/*
libegl1 \
libgl1 \
libglib2.0-0 \
libfontconfig1 \
libdbus-1-3 && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*

# Install python packages
RUN pip install --upgrade pip
RUN pip install pyopengl glfw pillow numpy pyrr PyQt6

COPY . /WhipperSnapPy
RUN pip install /WhipperSnapPy
RUN pip install /WhipperSnapPy[video]

ENTRYPOINT ["xvfb-run","whippersnap"]
ENTRYPOINT ["whippersnap4"]
CMD ["--help"]
Loading