Metadata-Version: 2.4
Name: whippersnappy
Version: 2.0.0
Summary: A package to plot and capture FastSurfer and FreeSurfer-style surface overlays.
Author-email: Martin Reuter <martin.reuter@dzne.de>
Maintainer-email: Martin Reuter <martin.reuter@dzne.de>
License: MIT License
        
        Copyright (c) 2023 Martin Reuter, DeepMI Lab, DZNE
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Project-URL: homepage, https://github.com/Deep-MI/WhipperSnapPy
Project-URL: documentation, https://github.com/Deep-MI/WhipperSnapPy
Project-URL: source, https://github.com/Deep-MI/WhipperSnapPy
Project-URL: tracker, https://github.com/Deep-MI/WhipperSnapPy/issues
Keywords: python,FreeSurfer,Brain MRI,Cortical Surface
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: Unix
Classifier: Operating System :: MacOS
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Natural Language :: English
Classifier: License :: OSI Approved :: MIT License
Classifier: Intended Audience :: Science/Research
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: glfw
Requires-Dist: numpy>=1.21
Requires-Dist: pyrr
Requires-Dist: pillow>=9.1
Requires-Dist: pyopengl>=3.1.8
Requires-Dist: nibabel
Requires-Dist: psutil
Provides-Extra: build
Requires-Dist: build; extra == "build"
Requires-Dist: twine; extra == "build"
Provides-Extra: doc
Requires-Dist: furo!=2023.8.17; extra == "doc"
Requires-Dist: matplotlib; extra == "doc"
Requires-Dist: memory-profiler; extra == "doc"
Requires-Dist: myst-parser; extra == "doc"
Requires-Dist: numpydoc; extra == "doc"
Requires-Dist: sphinx!=7.2.*; extra == "doc"
Requires-Dist: sphinxcontrib-bibtex; extra == "doc"
Requires-Dist: sphinx-copybutton; extra == "doc"
Requires-Dist: sphinx-design; extra == "doc"
Requires-Dist: sphinx-issues; extra == "doc"
Requires-Dist: pypandoc; extra == "doc"
Requires-Dist: nbsphinx; extra == "doc"
Requires-Dist: IPython; extra == "doc"
Requires-Dist: ipykernel; extra == "doc"
Requires-Dist: pooch>=1.6; extra == "doc"
Requires-Dist: pythreejs; extra == "doc"
Requires-Dist: ipywidgets; extra == "doc"
Requires-Dist: imageio>=2.28; extra == "doc"
Provides-Extra: notebook
Requires-Dist: pythreejs; extra == "notebook"
Requires-Dist: ipywidgets; extra == "notebook"
Requires-Dist: pooch>=1.6; extra == "notebook"
Provides-Extra: gui
Requires-Dist: PyQt6; extra == "gui"
Provides-Extra: video
Requires-Dist: imageio>=2.28; extra == "video"
Requires-Dist: imageio-ffmpeg>=0.4.9; extra == "video"
Provides-Extra: style
Requires-Dist: bibclean; extra == "style"
Requires-Dist: codespell; extra == "style"
Requires-Dist: pydocstyle[toml]; extra == "style"
Requires-Dist: ruff; extra == "style"
Provides-Extra: test
Requires-Dist: pytest; extra == "test"
Requires-Dist: pytest-cov; extra == "test"
Requires-Dist: pytest-timeout; extra == "test"
Provides-Extra: all
Requires-Dist: whippersnappy[build]; extra == "all"
Requires-Dist: whippersnappy[doc]; extra == "all"
Requires-Dist: whippersnappy[style]; extra == "all"
Requires-Dist: whippersnappy[test]; extra == "all"
Requires-Dist: whippersnappy[notebook]; extra == "all"
Requires-Dist: whippersnappy[gui]; extra == "all"
Requires-Dist: whippersnappy[video]; extra == "all"
Provides-Extra: full
Requires-Dist: whippersnappy[all]; extra == "full"
Dynamic: license-file

# WhipperSnapPy

WhipperSnapPy is a Python/OpenGL tool to render triangular surface meshes
with color overlays or parcellations and generate screenshots — from the
command line, in Jupyter notebooks, or via a desktop GUI.

It works with FreeSurfer and FastSurfer brain surfaces as well as any
triangle mesh in OFF, legacy ASCII VTK PolyData, ASCII PLY, or GIfTI (.gii, .surf.gii) format, or
passed directly as a NumPy ``(vertices, faces)`` tuple.

## Installation

```bash
pip install whippersnappy
```

For rotation video support (MP4/WebM):

```bash
pip install 'whippersnappy[video]'
```

For the interactive desktop GUI:

```bash
pip install 'whippersnappy[gui]'
```

For interactive 3D in Jupyter notebooks:

```bash
pip install 'whippersnappy[notebook]'
```

Off-screen (headless) rendering is supported natively via EGL on Linux — no
`xvfb` required. See the <a href="DOCKER.md">Docker guide</a> for headless usage.

## Command-Line Usage

After installation the following commands are available:

### Four-view snapshot (`whippersnap4`)

Renders lateral and medial views of both hemispheres into a single composed image:

```bash
whippersnap4 -lh $LH_OVERLAY \
             -rh $RH_OVERLAY \
             -sd $SUBJECT_DIR \
             --fmax 4 --fthresh 2 \
             --caption "Cortical Thickness" \
             -o snap4.png
```

### Single-view snapshot (`whippersnap1`)

Renders one view of any triangular surface mesh:

```bash
whippersnap1 --mesh $SUBJECT_DIR/surf/lh.white \
             --overlay $LH_OVERLAY \
             --bg-map  $SUBJECT_DIR/surf/lh.curv \
             --roi     $SUBJECT_DIR/label/lh.cortex.label \
             --view left \
             -o snap1.png

# Also works with OFF / VTK / PLY
whippersnap1 --mesh mesh.off --overlay values.mgh -o snap1.png
whippersnap1 --mesh surface.surf.gii --overlay overlay.func.gii -o snap1.png
```

### Rotation video (`whippersnap1 --rotate`)

Renders a 360° animation of any triangular surface mesh:

```bash
whippersnap1 --mesh $SUBJECT_DIR/surf/lh.white \
             --overlay $LH_OVERLAY \
             --rotate \
             -o rotation.mp4
```

### Desktop GUI (`whippersnap`)

Launches an interactive Qt window with live threshold controls.

**General mode** — any triangular mesh:

```bash
pip install 'whippersnappy[gui]'
whippersnap --mesh mesh.off --overlay values.mgh
whippersnap --mesh lh.white --overlay lh.thickness --bg-map lh.curv
```

**FreeSurfer shortcut** — derive all paths from a subject directory:

```bash
whippersnap -sd $SUBJECT_DIR --hemi lh -lh $LH_OVERLAY
whippersnap -sd $SUBJECT_DIR --hemi rh --annot rh.aparc.annot
```

For all options run `whippersnap4 --help`, `whippersnap1 --help`, or `whippersnap --help`.

## Python API

```python
from whippersnappy import snap1, snap4, snap_rotate, plot3d
```

| Function | Description |
|---|---|
| `snap1` | Single-view snapshot of any triangular mesh → PIL Image |
| `snap4` | Four-view composed image (FreeSurfer subject, lateral/medial both hemispheres) |
| `snap_rotate` | 360° rotation video of any triangular surface mesh (MP4, WebM, or GIF) |
| `plot3d` | Interactive 3D WebGL viewer for Jupyter notebooks |

**Supported mesh inputs for `snap1`, `snap_rotate`, and `plot3d`:**
FreeSurfer binary surfaces (e.g. `lh.white`), OFF (`.off`), legacy ASCII VTK PolyData (`.vtk`), ASCII PLY (`.ply`), GIfTI surface (`.gii`, `.surf.gii`), or a `(vertices, faces)` NumPy array tuple.

**Supported overlay/label inputs:**
FreeSurfer morph (`.curv`, `.thickness`), MGH/MGZ, ASCII (`.txt`, `.csv`), NumPy (`.npy`, `.npz`), GIfTI functional/label (`.func.gii`, `.label.gii`, `.gii`).

### Example

```python
from whippersnappy import snap1, snap4

# FreeSurfer surface with overlay
img = snap1('lh.white',
            overlay='lh.thickness',
            bg_map='lh.curv',
            roi='lh.cortex.label')
img.save('snap1.png')

# Four-view overview (FreeSurfer subject directory)
img = snap4(sdir='/path/to/subject',
            lh_overlay='/path/to/lh.thickness',
            rh_overlay='/path/to/rh.thickness',
            colorbar=True, caption='Cortical Thickness (mm)')
img.save('snap4.png')

# OFF / VTK / PLY / GIfTI mesh
img = snap1('mesh.off', overlay='values.mgh')
img = snap1('surface.surf.gii', overlay='overlay.func.gii')

# Array inputs (e.g. from LaPy or trimesh)
import numpy as np
v = np.random.randn(1000, 3).astype(np.float32)
f = np.array([[0, 1, 2]], dtype=np.uint32)
overlay = np.random.randn(1000).astype(np.float32)
img = snap1((v, f), overlay=overlay)
```


See `tutorials/whippersnappy_tutorial.ipynb` for complete notebook examples.


## Docker

The Docker image provides a fully headless EGL rendering environment — no
display server or `xvfb` required. See <a href="DOCKER.md"><strong>DOCKER.md</strong></a> for details.

## API Documentation

https://deep-mi.org/WhipperSnapPy

## Links

Lab webpage: https://deep-mi.org
