seqseg 2.1.7__tar.gz → 2.1.8__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.
- {seqseg-2.1.7 → seqseg-2.1.8}/PKG-INFO +28 -51
- seqseg-2.1.8/README.md +114 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/pyproject.toml +1 -1
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/cli.py +75 -34
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/pipeline/train.py +349 -43
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/tests/test_cli_helpers.py +58 -13
- seqseg-2.1.8/seqseg/tests/test_train_data.py +95 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/tests/test_train_pipeline.py +290 -68
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg.egg-info/PKG-INFO +28 -51
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg.egg-info/SOURCES.txt +1 -0
- seqseg-2.1.7/README.md +0 -137
- {seqseg-2.1.7 → seqseg-2.1.8}/LICENSE +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/__init__.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/api.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/citations.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/config/__init__.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/config/aorta_tutorial.yaml +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/config/global.yaml +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/config/global_aorta.yaml +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/config/global_cereb.yaml +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/config/global_coro.yaml +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/config/global_debug.yaml +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/config/global_default.yaml +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/config/global_pulm.yaml +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/config/global_seg.yaml +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/config/global_test.yaml +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/config_models.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/modules/__init__.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/modules/assembly.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/modules/capping.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/modules/centerline.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/modules/datasets.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/modules/evaluation.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/modules/initialization.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/modules/local_assembly.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/modules/nnunet.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/modules/params.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/modules/prediction.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/modules/simvascular.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/modules/simvascular_contour.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/modules/sitk_functions.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/modules/sweep.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/modules/tracing.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/modules/tracing_functions.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/modules/vmtk_functions.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/modules/vtk_functions.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/parallel/old_auto_centerline.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/parallel/parallel_auto_centerline.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/parallel/parallel_auto_centerline2.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/parallel/parallel_auto_centerline3.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/parallel/parallel_auto_centerline4.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/pipeline/__init__.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/pipeline/classic.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/pipeline/config.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/pipeline/directories.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/pipeline/plus.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/pipeline/post.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/pipeline/single_trace.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/scripts/__init__.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/scripts/prepare_casx_dataset.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/scripts/taubin_smooth.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/seqseg.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/seqseg_plus.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/tests/conftest.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/tests/test_api_entry.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/tests/test_centerline_get_end_points.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/tests/test_centerline_gradient.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/tests/test_datasets_paths.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/tests/test_nnunet2.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/tests/test_nnunet_device.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/tests/test_prepare_casx_dataset.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/tests/test_resample_spacing.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/tests/test_segmentation.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/tests/test_single_trace_staging.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/tests/test_start_seg.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/tests/test_user_paths.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/tests/test_vtk.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg/user_paths.py +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg.egg-info/dependency_links.txt +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg.egg-info/entry_points.txt +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg.egg-info/requires.txt +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/seqseg.egg-info/top_level.txt +0 -0
- {seqseg-2.1.7 → seqseg-2.1.8}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: seqseg
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.8
|
|
4
4
|
Summary: A deep learning-based medical image blood vessel tracking and segmentation tool.
|
|
5
5
|
Author-email: Numi Sveinsson Cepero <numi@berkeley.com>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -30,8 +30,8 @@ Provides-Extra: viz
|
|
|
30
30
|
Requires-Dist: matplotlib>=3.5; extra == "viz"
|
|
31
31
|
Dynamic: license-file
|
|
32
32
|
|
|
33
|
-

|
|
34
|
+

|
|
35
35
|
|
|
36
36
|
<p align="center">
|
|
37
37
|
<img src="https://raw.githubusercontent.com/numisveinsson/SeqSeg/main/seqseg/assets/seqseg_logo.png" alt="SeqSeg — Sequential Vessel Segmentation" width="480"/><br/>
|
|
@@ -50,10 +50,6 @@ Dynamic: license-file
|
|
|
50
50
|
<a href="https://www.python.org"><img src="https://img.shields.io/badge/Python-3.9%2B-blue.svg" alt="Python 3.9+"/></a>
|
|
51
51
|
</p>
|
|
52
52
|
|
|
53
|
-
> **News:** SeqSeg writes a full SimVascular project in the `simvascular/` subdirectory — open it directly in SimVascular with pathlines and contours for every segmented branch.
|
|
54
|
-
|
|
55
|
-
---
|
|
56
|
-
|
|
57
53
|
## Why SeqSeg?
|
|
58
54
|
|
|
59
55
|
SeqSeg segments vessels **sequentially**, taking steps along vessel centerlines and detecting bifurcations to grow complete vascular trees from just **1–2 seed points**. By combining local deep-learning predictions (nnU-Net) with geometric tracking, it stays robust across vessel scales — from small coronaries to large aortas.
|
|
@@ -65,57 +61,38 @@ SeqSeg segments vessels **sequentially**, taking steps along vessel centerlines
|
|
|
65
61
|
- ✅ **Clinically validated** — coronary, aortic, cerebral, and pulmonary anatomies (pre-trained weights for aorta CT/MR and coronary CT)
|
|
66
62
|
- ⚡ **Fast** — on CPU, about 2–5 minutes for an aorta, 5–15 for a coronary tree, and 10–30 for a cerebral tree. GPU is faster. Details in [Benchmarks](docs/benchmarks.md).
|
|
67
63
|
|
|
64
|
+
A finished case includes a `simvascular/` project you can open directly in SimVascular, with pathlines and contours for every segmented branch.
|
|
65
|
+
|
|
68
66
|
<p align="center">
|
|
69
67
|
<img src="https://raw.githubusercontent.com/numisveinsson/SeqSeg/main/seqseg/assets/mr_model_tracing_fast_shorter.gif" alt="SeqSeg Demo"/><br/>
|
|
70
68
|
<i>Real-time demonstration: automatic segmentation of an abdominal aorta in a 3D MR scan.</i>
|
|
71
69
|
</p>
|
|
72
70
|
|
|
73
|
-
##
|
|
74
|
-
|
|
75
|
-
SeqSeg **2.0** uses subcommands. A command from 1.x that starts with a flag, such as `seqseg -data_dir ...`, still runs: it is rewritten to `seqseg run batch` automatically.
|
|
76
|
-
|
|
77
|
-
### Commands
|
|
78
|
-
|
|
79
|
-
| Command | Description |
|
|
80
|
-
| -------- | ----------- |
|
|
81
|
-
| **`seqseg run batch`** | Dataset batch tracing |
|
|
82
|
-
| **`seqseg run single`** | One volume and seeds. Stages files under `<outdir>/_seqseg_single_staging/`, then traces |
|
|
83
|
-
| **`seqseg run plus batch`** | Global nnU-Net sweep, then SeqSeg |
|
|
84
|
-
| **`seqseg init dataset`** | Create `images/`, `centerlines/`, `truths/`, and a template `seeds.json` |
|
|
85
|
-
| **`seqseg paths init` / `set` / `show`** | Save default nnU-Net, data, and output directories in `~/.seqseg/paths.yaml` |
|
|
86
|
-
| **`seqseg train prepare`** | Extract patches or whole volumes and build an nnU-Net dataset |
|
|
87
|
-
| **`seqseg train nnunet`** | Run nnU-Net planning, preprocessing, and training |
|
|
88
|
-
| **`seqseg doctor`** | Check imports (SimpleITK, vtk, nnunetv2, scipy, vascular-segment-sampler) and paths |
|
|
89
|
-
| **`seqseg config dump` / `fingerprint`** | Print a packaged YAML config, or list keys that differ from another |
|
|
90
|
-
| **`seqseg post global-centerline`** | Build global centerlines from existing segmentations |
|
|
91
|
-
| **`seqseg simvascular init`** | Create or refresh a SimVascular project under a case directory |
|
|
92
|
-
| **`seqseg --version`** | Print the installed version |
|
|
93
|
-
|
|
94
|
-
`seqseg run batch` flags use underscores (`-outdir` / `--outdir`). The data folder is `-data_dir` or `--data_directory`. `seqseg run single`, `seqseg train`, and `seqseg paths` use hyphens (`--image`, `--data-dir`).
|
|
71
|
+
## Start here
|
|
95
72
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
2. Use `seqseg run plus batch` in place of `python -m seqseg.seqseg_plus`. The nnU-Net path flags are unchanged.
|
|
100
|
-
3. Check the install with `seqseg --version` after `pip install -U seqseg`.
|
|
73
|
+
- **First segmentation** — the [tutorial](seqseg/tutorial/tutorial.md) runs a sample abdominal-aorta MR scan.
|
|
74
|
+
- **Your own images** — [Usage](docs/usage.md) describes `images/` and `seeds.json`. The command is in [Quick Start](#quick-start).
|
|
75
|
+
- **Train a model** — [Training](docs/training.md).
|
|
101
76
|
|
|
102
77
|
## Quick Start
|
|
103
78
|
|
|
104
79
|
Python 3.9 or newer. 3.11 is the version used in the tutorial and conda example.
|
|
105
80
|
|
|
81
|
+
The [tutorial](seqseg/tutorial/tutorial.md) is the sample run (abdominal-aorta MR, seed points, and Windows notes). Plan on 15–20 minutes including setup. Tracing is capped, so that part finishes in a few minutes; a real case should use the defaults.
|
|
82
|
+
|
|
83
|
+
Install SeqSeg and the aorta weights below, then run `seqseg run batch` on your own data. The folder needs `images/` and `seeds.json` ([Usage](docs/usage.md)). This example is an aorta MR case. Change `-train_dataset`, `-config_name`, and `-img_ext` to match your images and weights.
|
|
84
|
+
|
|
106
85
|
```bash
|
|
107
86
|
pip install seqseg
|
|
108
87
|
|
|
109
|
-
# Aorta and femoral weights (MR and CT)
|
|
88
|
+
# Aorta and femoral weights (MR and CT)
|
|
110
89
|
curl -L -o nnUNet_results.zip https://zenodo.org/records/15020477/files/nnUNet_results.zip
|
|
111
90
|
unzip nnUNet_results.zip
|
|
112
91
|
```
|
|
113
92
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
**First run:** follow the [step-by-step tutorial](seqseg/tutorial/tutorial.md). It includes an abdominal-aorta MR scan, seed points, and Windows notes. The tutorial caps the number of steps so the example finishes in a few minutes; a real case should use the defaults.
|
|
93
|
+
[Aorta and femoral weights](https://zenodo.org/records/15020477) (`nnUNet_results.zip`). [Coronary CT weights](https://zenodo.org/records/19547894) are a separate archive, `nnUNet_results_coronary.zip`.
|
|
117
94
|
|
|
118
|
-
|
|
95
|
+
`-nnunet_results_path` is the folder that contains `Dataset005_SEQAORTANDFEMOMR` (and the other dataset folders in that zip).
|
|
119
96
|
|
|
120
97
|
```bash
|
|
121
98
|
seqseg run batch \
|
|
@@ -133,21 +110,21 @@ seqseg run batch \
|
|
|
133
110
|
| Aorta / femoral CT | `Dataset006_SEQAORTANDFEMOCT` | `global_aorta` |
|
|
134
111
|
| Coronary CT | `Dataset010_SEQCOROASOCACT` | `global_coro` |
|
|
135
112
|
|
|
136
|
-
The tutorial uses `-config_name aorta_tutorial` for its sample scan.
|
|
113
|
+
The tutorial uses `-config_name aorta_tutorial` for its sample scan. The trainer-folder layout is in [Installation](docs/installation.md). The full command list and flag spelling are in [Usage](docs/usage.md).
|
|
137
114
|
|
|
138
115
|
## Documentation
|
|
139
116
|
|
|
140
|
-
| Guide | Description |
|
|
141
|
-
|
|
142
|
-
| [Installation](docs/installation.md) | Setup, dependencies, and pre-trained model weights |
|
|
143
|
-
| [Tutorial](seqseg/tutorial/tutorial.md) | End-to-end aorta example with sample data |
|
|
144
|
-
| [Usage](docs/usage.md) | Data layout, seeds, CLI arguments, and output files |
|
|
145
|
-
| [Configuration](docs/configuration.md) | YAML configs and tracking parameters |
|
|
146
|
-
| [
|
|
147
|
-
| [
|
|
148
|
-
| [Performance & Benchmarks](docs/benchmarks.md) | Accuracy, timing, and qualitative comparisons |
|
|
149
|
-
| [API](docs/api.md) | Call tracing from Python |
|
|
150
|
-
| [Research & Development](docs/development.md) | SimVascular, 3D Slicer, and repository layout |
|
|
117
|
+
| Job | Guide | Description |
|
|
118
|
+
|-----|-------|-------------|
|
|
119
|
+
| Run | [Installation](docs/installation.md) | Setup, dependencies, and pre-trained model weights |
|
|
120
|
+
| Run | [Tutorial](seqseg/tutorial/tutorial.md) | End-to-end aorta example with sample data |
|
|
121
|
+
| Run | [Usage](docs/usage.md) | Data layout, seeds, CLI arguments, and output files |
|
|
122
|
+
| Run | [Configuration](docs/configuration.md) | YAML configs and tracking parameters |
|
|
123
|
+
| Train | [Training](docs/training.md) | Train nnU-Net models on a new dataset |
|
|
124
|
+
| Understand | [Algorithm Overview](docs/algorithm.md) | Methodology, workflow, and training strategy |
|
|
125
|
+
| Understand | [Performance & Benchmarks](docs/benchmarks.md) | Accuracy, timing, and qualitative comparisons |
|
|
126
|
+
| Integrate | [API](docs/api.md) | Call tracing from Python |
|
|
127
|
+
| Integrate | [Research & Development](docs/development.md) | SimVascular, 3D Slicer, and repository layout |
|
|
151
128
|
|
|
152
129
|
## Citation
|
|
153
130
|
|
seqseg-2.1.8/README.md
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+

|
|
2
|
+

|
|
3
|
+
|
|
4
|
+
<p align="center">
|
|
5
|
+
<img src="https://raw.githubusercontent.com/numisveinsson/SeqSeg/main/seqseg/assets/seqseg_logo.png" alt="SeqSeg — Sequential Vessel Segmentation" width="480"/><br/>
|
|
6
|
+
<img src="https://raw.githubusercontent.com/numisveinsson/SeqSeg/main/seqseg/assets/coronary.png" alt="Example coronary segmentation (SeqSeg)" width="260"/>
|
|
7
|
+
</p>
|
|
8
|
+
|
|
9
|
+
<h1 align="center">SeqSeg: Sequential Vessel Segmentation and Tracking</h1>
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<b>Automatic tracking and segmentation of blood vessels in CT and MR images using deep learning and geometric tracking.</b>
|
|
13
|
+
</p>
|
|
14
|
+
|
|
15
|
+
<p align="center">
|
|
16
|
+
<a href="https://rdcu.be/dU0wy"><img src="https://img.shields.io/badge/Paper-Annals%20of%20BME-blue" alt="Paper"/></a>
|
|
17
|
+
<a href="https://github.com/numisveinsson/SeqSeg/blob/main/LICENSE"><img src="https://img.shields.io/badge/License-Apache%202.0-green.svg" alt="License"/></a>
|
|
18
|
+
<a href="https://www.python.org"><img src="https://img.shields.io/badge/Python-3.9%2B-blue.svg" alt="Python 3.9+"/></a>
|
|
19
|
+
</p>
|
|
20
|
+
|
|
21
|
+
## Why SeqSeg?
|
|
22
|
+
|
|
23
|
+
SeqSeg segments vessels **sequentially**, taking steps along vessel centerlines and detecting bifurcations to grow complete vascular trees from just **1–2 seed points**. By combining local deep-learning predictions (nnU-Net) with geometric tracking, it stays robust across vessel scales — from small coronaries to large aortas.
|
|
24
|
+
|
|
25
|
+
- 🌱 **Minimal supervision** — only 1–2 seed points to initialize
|
|
26
|
+
- 🌿 **Robust bifurcation detection** — automatically follows every branch
|
|
27
|
+
- 🩻 **Multi-modal** — works with CT and MR 3D medical images
|
|
28
|
+
- 📏 **Scalable** — vessels from ~1mm coronaries to ~30mm aortas
|
|
29
|
+
- ✅ **Clinically validated** — coronary, aortic, cerebral, and pulmonary anatomies (pre-trained weights for aorta CT/MR and coronary CT)
|
|
30
|
+
- ⚡ **Fast** — on CPU, about 2–5 minutes for an aorta, 5–15 for a coronary tree, and 10–30 for a cerebral tree. GPU is faster. Details in [Benchmarks](docs/benchmarks.md).
|
|
31
|
+
|
|
32
|
+
A finished case includes a `simvascular/` project you can open directly in SimVascular, with pathlines and contours for every segmented branch.
|
|
33
|
+
|
|
34
|
+
<p align="center">
|
|
35
|
+
<img src="https://raw.githubusercontent.com/numisveinsson/SeqSeg/main/seqseg/assets/mr_model_tracing_fast_shorter.gif" alt="SeqSeg Demo"/><br/>
|
|
36
|
+
<i>Real-time demonstration: automatic segmentation of an abdominal aorta in a 3D MR scan.</i>
|
|
37
|
+
</p>
|
|
38
|
+
|
|
39
|
+
## Start here
|
|
40
|
+
|
|
41
|
+
- **First segmentation** — the [tutorial](seqseg/tutorial/tutorial.md) runs a sample abdominal-aorta MR scan.
|
|
42
|
+
- **Your own images** — [Usage](docs/usage.md) describes `images/` and `seeds.json`. The command is in [Quick Start](#quick-start).
|
|
43
|
+
- **Train a model** — [Training](docs/training.md).
|
|
44
|
+
|
|
45
|
+
## Quick Start
|
|
46
|
+
|
|
47
|
+
Python 3.9 or newer. 3.11 is the version used in the tutorial and conda example.
|
|
48
|
+
|
|
49
|
+
The [tutorial](seqseg/tutorial/tutorial.md) is the sample run (abdominal-aorta MR, seed points, and Windows notes). Plan on 15–20 minutes including setup. Tracing is capped, so that part finishes in a few minutes; a real case should use the defaults.
|
|
50
|
+
|
|
51
|
+
Install SeqSeg and the aorta weights below, then run `seqseg run batch` on your own data. The folder needs `images/` and `seeds.json` ([Usage](docs/usage.md)). This example is an aorta MR case. Change `-train_dataset`, `-config_name`, and `-img_ext` to match your images and weights.
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pip install seqseg
|
|
55
|
+
|
|
56
|
+
# Aorta and femoral weights (MR and CT)
|
|
57
|
+
curl -L -o nnUNet_results.zip https://zenodo.org/records/15020477/files/nnUNet_results.zip
|
|
58
|
+
unzip nnUNet_results.zip
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
[Aorta and femoral weights](https://zenodo.org/records/15020477) (`nnUNet_results.zip`). [Coronary CT weights](https://zenodo.org/records/19547894) are a separate archive, `nnUNet_results_coronary.zip`.
|
|
62
|
+
|
|
63
|
+
`-nnunet_results_path` is the folder that contains `Dataset005_SEQAORTANDFEMOMR` (and the other dataset folders in that zip).
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
seqseg run batch \
|
|
67
|
+
-data_dir your_data/ \
|
|
68
|
+
-nnunet_results_path nnUNet_results/ \
|
|
69
|
+
-train_dataset Dataset005_SEQAORTANDFEMOMR \
|
|
70
|
+
-config_name global_aorta \
|
|
71
|
+
-img_ext .mha \
|
|
72
|
+
-outdir results/
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
| Anatomy | `-train_dataset` | `-config_name` |
|
|
76
|
+
|---------|------------------|----------------|
|
|
77
|
+
| Aorta / femoral MR | `Dataset005_SEQAORTANDFEMOMR` | `global_aorta` |
|
|
78
|
+
| Aorta / femoral CT | `Dataset006_SEQAORTANDFEMOCT` | `global_aorta` |
|
|
79
|
+
| Coronary CT | `Dataset010_SEQCOROASOCACT` | `global_coro` |
|
|
80
|
+
|
|
81
|
+
The tutorial uses `-config_name aorta_tutorial` for its sample scan. The trainer-folder layout is in [Installation](docs/installation.md). The full command list and flag spelling are in [Usage](docs/usage.md).
|
|
82
|
+
|
|
83
|
+
## Documentation
|
|
84
|
+
|
|
85
|
+
| Job | Guide | Description |
|
|
86
|
+
|-----|-------|-------------|
|
|
87
|
+
| Run | [Installation](docs/installation.md) | Setup, dependencies, and pre-trained model weights |
|
|
88
|
+
| Run | [Tutorial](seqseg/tutorial/tutorial.md) | End-to-end aorta example with sample data |
|
|
89
|
+
| Run | [Usage](docs/usage.md) | Data layout, seeds, CLI arguments, and output files |
|
|
90
|
+
| Run | [Configuration](docs/configuration.md) | YAML configs and tracking parameters |
|
|
91
|
+
| Train | [Training](docs/training.md) | Train nnU-Net models on a new dataset |
|
|
92
|
+
| Understand | [Algorithm Overview](docs/algorithm.md) | Methodology, workflow, and training strategy |
|
|
93
|
+
| Understand | [Performance & Benchmarks](docs/benchmarks.md) | Accuracy, timing, and qualitative comparisons |
|
|
94
|
+
| Integrate | [API](docs/api.md) | Call tracing from Python |
|
|
95
|
+
| Integrate | [Research & Development](docs/development.md) | SimVascular, 3D Slicer, and repository layout |
|
|
96
|
+
|
|
97
|
+
## Citation
|
|
98
|
+
|
|
99
|
+
When using SeqSeg, please cite the following [paper](https://rdcu.be/dU0wy):
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
@Article{SveinssonCepero2024,
|
|
103
|
+
author={Sveinsson Cepero, Numi
|
|
104
|
+
and Shadden, Shawn C.},
|
|
105
|
+
title={SeqSeg: Learning Local Segments for Automatic Vascular Model Construction},
|
|
106
|
+
journal={Annals of Biomedical Engineering},
|
|
107
|
+
year={2024},
|
|
108
|
+
month={Sep},
|
|
109
|
+
day={18},
|
|
110
|
+
issn={1573-9686},
|
|
111
|
+
doi={10.1007/s10439-024-03611-z},
|
|
112
|
+
url={https://doi.org/10.1007/s10439-024-03611-z},
|
|
113
|
+
}
|
|
114
|
+
```
|
|
@@ -437,7 +437,7 @@ def _cmd_init_dataset(ns: argparse.Namespace) -> None:
|
|
|
437
437
|
"-nnunet_results_path ...\n"
|
|
438
438
|
"\nNext (train a new model): also fill centerlines/ and truths/, then:\n"
|
|
439
439
|
f" seqseg paths init --data-dir {root}/ --outdir ~/seqseg_train\n"
|
|
440
|
-
" seqseg train prepare --name MYDATA --dataset-
|
|
440
|
+
" seqseg train prepare --name MYDATA --dataset-id 999 --modality CT\n"
|
|
441
441
|
)
|
|
442
442
|
|
|
443
443
|
|
|
@@ -634,6 +634,12 @@ def _cmd_paths_export(_ns: argparse.Namespace) -> None:
|
|
|
634
634
|
|
|
635
635
|
|
|
636
636
|
def _cmd_train_prepare(ns: argparse.Namespace) -> None:
|
|
637
|
+
if not ns.preprocess_only and not ns.name:
|
|
638
|
+
print(
|
|
639
|
+
"seqseg train prepare: --name is required",
|
|
640
|
+
file=sys.stderr,
|
|
641
|
+
)
|
|
642
|
+
sys.exit(2)
|
|
637
643
|
try:
|
|
638
644
|
result = prepare_training_dataset(
|
|
639
645
|
data_dir=ns.data_dir,
|
|
@@ -656,11 +662,14 @@ def _cmd_train_prepare(ns: argparse.Namespace) -> None:
|
|
|
656
662
|
skip_sample=ns.skip_sample,
|
|
657
663
|
skip_convert=ns.skip_convert,
|
|
658
664
|
also_test=ns.also_test,
|
|
659
|
-
yes=ns.yes,
|
|
660
665
|
verbose=ns.verbose,
|
|
661
666
|
img_ext=ns.img_ext,
|
|
662
667
|
global_volumes=ns.global_volumes,
|
|
663
668
|
keep_extracted=ns.keep_extracted,
|
|
669
|
+
configuration=ns.configuration,
|
|
670
|
+
plans=ns.plans,
|
|
671
|
+
np=ns.np,
|
|
672
|
+
preprocess_only=ns.preprocess_only,
|
|
664
673
|
)
|
|
665
674
|
except TrainDependencyError as e:
|
|
666
675
|
print(str(e), file=sys.stderr)
|
|
@@ -670,6 +679,9 @@ def _cmd_train_prepare(ns: argparse.Namespace) -> None:
|
|
|
670
679
|
if message.startswith("Sampler config"):
|
|
671
680
|
print(message, file=sys.stderr)
|
|
672
681
|
sys.exit(2)
|
|
682
|
+
if "seqseg train prepare" in message:
|
|
683
|
+
print(message, file=sys.stderr)
|
|
684
|
+
sys.exit(1)
|
|
673
685
|
import traceback
|
|
674
686
|
|
|
675
687
|
traceback.print_exc()
|
|
@@ -691,7 +703,11 @@ def _cmd_train_prepare(ns: argparse.Namespace) -> None:
|
|
|
691
703
|
sys.exit(1)
|
|
692
704
|
|
|
693
705
|
print("\nPrepare complete.")
|
|
694
|
-
if
|
|
706
|
+
if ns.preprocess_only:
|
|
707
|
+
print(
|
|
708
|
+
f" Preprocessed {ns.configuration} from the existing raw dataset."
|
|
709
|
+
)
|
|
710
|
+
elif result.removed_staging:
|
|
695
711
|
print(
|
|
696
712
|
" Extracted volumes were linked into nnU-Net raw and the "
|
|
697
713
|
"temporary folder was removed."
|
|
@@ -699,9 +715,17 @@ def _cmd_train_prepare(ns: argparse.Namespace) -> None:
|
|
|
699
715
|
else:
|
|
700
716
|
kind = "Whole volumes" if ns.global_volumes else "Patches"
|
|
701
717
|
print(f" {kind}: {result.extracted_dir}")
|
|
718
|
+
if not result.preprocessed:
|
|
719
|
+
print(
|
|
720
|
+
" nnU-Net preprocessing was skipped (--skip-convert). "
|
|
721
|
+
"Re-run prepare without --skip-convert before training."
|
|
722
|
+
)
|
|
702
723
|
results = resolve_path("nnunet_results")
|
|
703
724
|
if results:
|
|
704
725
|
print(f" Trained models will be written under: {results}")
|
|
726
|
+
config_flag = ""
|
|
727
|
+
if ns.configuration != "3d_fullres":
|
|
728
|
+
config_flag = f" --configuration {ns.configuration}"
|
|
705
729
|
for name, path in zip(result.dataset_names, result.dataset_dirs):
|
|
706
730
|
try:
|
|
707
731
|
ds_id = dataset_id_from_name(name)
|
|
@@ -709,11 +733,12 @@ def _cmd_train_prepare(ns: argparse.Namespace) -> None:
|
|
|
709
733
|
ds_id = "?"
|
|
710
734
|
print(f" nnU-Net dataset: {name}")
|
|
711
735
|
print(f" path: {path}")
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
736
|
+
if result.preprocessed:
|
|
737
|
+
print(
|
|
738
|
+
" next:\n"
|
|
739
|
+
f" seqseg train nnunet --dataset-id {ds_id}"
|
|
740
|
+
f"{config_flag} --fold 0"
|
|
741
|
+
)
|
|
717
742
|
|
|
718
743
|
|
|
719
744
|
def _cmd_train_nnunet(ns: argparse.Namespace) -> None:
|
|
@@ -736,12 +761,10 @@ def _cmd_train_nnunet(ns: argparse.Namespace) -> None:
|
|
|
736
761
|
dataset_id,
|
|
737
762
|
configuration=ns.configuration,
|
|
738
763
|
fold=ns.fold,
|
|
739
|
-
skip_plan=ns.skip_plan,
|
|
740
|
-
plan_only=ns.plan_only,
|
|
741
|
-
np=ns.np,
|
|
742
764
|
trainer=ns.trainer,
|
|
743
765
|
plans=ns.plans,
|
|
744
766
|
cleanup=ns.cleanup,
|
|
767
|
+
continue_training=ns.continue_training,
|
|
745
768
|
)
|
|
746
769
|
except Exception as e: # noqa: BLE001
|
|
747
770
|
print(f"seqseg train nnunet failed: {e}", file=sys.stderr)
|
|
@@ -1021,7 +1044,7 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
1021
1044
|
|
|
1022
1045
|
p_prep = train_sub.add_parser(
|
|
1023
1046
|
"prepare",
|
|
1024
|
-
help="
|
|
1047
|
+
help="Extract volumes, write an nnU-Net dataset, and plan/preprocess",
|
|
1025
1048
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
1026
1049
|
)
|
|
1027
1050
|
p_prep.add_argument(
|
|
@@ -1044,16 +1067,20 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
1044
1067
|
p_prep.add_argument(
|
|
1045
1068
|
"--name",
|
|
1046
1069
|
"-name",
|
|
1047
|
-
|
|
1070
|
+
default=None,
|
|
1048
1071
|
type=str,
|
|
1049
|
-
help="Dataset name stem (e.g. MYDATA → Dataset0XX_MYDATACT)"
|
|
1072
|
+
help="Dataset name stem (e.g. MYDATA → Dataset0XX_MYDATACT). "
|
|
1073
|
+
"Required unless --preprocess-only",
|
|
1050
1074
|
)
|
|
1051
1075
|
p_prep.add_argument(
|
|
1076
|
+
"--dataset-id",
|
|
1052
1077
|
"--dataset-number",
|
|
1053
1078
|
"-dataset_number",
|
|
1079
|
+
dest="dataset_number",
|
|
1054
1080
|
required=True,
|
|
1055
1081
|
type=int,
|
|
1056
|
-
help="nnU-Net dataset id (e.g. 999).
|
|
1082
|
+
help="nnU-Net dataset id to create (e.g. 999). "
|
|
1083
|
+
"Incremented per modality if several",
|
|
1057
1084
|
)
|
|
1058
1085
|
p_prep.add_argument(
|
|
1059
1086
|
"--modality",
|
|
@@ -1065,7 +1092,7 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
1065
1092
|
p_prep.add_argument(
|
|
1066
1093
|
"--config-name",
|
|
1067
1094
|
"-config_name",
|
|
1068
|
-
default="
|
|
1095
|
+
default="default_mm",
|
|
1069
1096
|
type=str,
|
|
1070
1097
|
help="Sampler YAML name/path (from vascular-segment-sampler)",
|
|
1071
1098
|
)
|
|
@@ -1125,18 +1152,41 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
1125
1152
|
action="store_true",
|
|
1126
1153
|
help="Also convert modality_test folders when present",
|
|
1127
1154
|
)
|
|
1128
|
-
p_prep.add_argument("--yes", action="store_true", help="Non-interactive confirms")
|
|
1129
1155
|
p_prep.add_argument("--verbose", action="store_true")
|
|
1130
1156
|
p_prep.add_argument(
|
|
1131
1157
|
"--keep-extracted",
|
|
1132
1158
|
action="store_true",
|
|
1133
1159
|
help="Keep <nnunet-root>/_seqseg_extracted after conversion into nnUNet_raw",
|
|
1134
1160
|
)
|
|
1161
|
+
p_prep.add_argument(
|
|
1162
|
+
"--configuration",
|
|
1163
|
+
default="3d_fullres",
|
|
1164
|
+
choices=["3d_fullres", "2d", "3d_lowres", "3d_cascade_fullres"],
|
|
1165
|
+
help="nnU-Net configuration to preprocess. Default 3d_fullres",
|
|
1166
|
+
)
|
|
1167
|
+
p_prep.add_argument(
|
|
1168
|
+
"--plans",
|
|
1169
|
+
default="nnUNetPlans",
|
|
1170
|
+
type=str,
|
|
1171
|
+
help="nnU-Net plans name (training -p). Default nnUNetPlans",
|
|
1172
|
+
)
|
|
1173
|
+
p_prep.add_argument(
|
|
1174
|
+
"--np",
|
|
1175
|
+
type=int,
|
|
1176
|
+
default=None,
|
|
1177
|
+
help="Processes for nnU-Net preprocessing. Default: --num-cores",
|
|
1178
|
+
)
|
|
1179
|
+
p_prep.add_argument(
|
|
1180
|
+
"--preprocess-only",
|
|
1181
|
+
action="store_true",
|
|
1182
|
+
help="Preprocess another configuration from an existing raw dataset "
|
|
1183
|
+
"and plans file. Does not extract or convert subvolumes",
|
|
1184
|
+
)
|
|
1135
1185
|
p_prep.set_defaults(_handler=_cmd_train_prepare, img_ext=None)
|
|
1136
1186
|
|
|
1137
1187
|
p_nn = train_sub.add_parser(
|
|
1138
1188
|
"nnunet",
|
|
1139
|
-
help="
|
|
1189
|
+
help="Train with nnUNetv2_train (--c continues from the latest checkpoint)",
|
|
1140
1190
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
1141
1191
|
)
|
|
1142
1192
|
p_nn.add_argument(
|
|
@@ -1149,13 +1199,13 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
1149
1199
|
"--dataset-name",
|
|
1150
1200
|
type=str,
|
|
1151
1201
|
default=None,
|
|
1152
|
-
help="Alternative to --dataset-id (e.g.
|
|
1202
|
+
help="Alternative to --dataset-id (e.g. Dataset999_MYDATACT)",
|
|
1153
1203
|
)
|
|
1154
1204
|
p_nn.add_argument(
|
|
1155
1205
|
"--configuration",
|
|
1156
1206
|
default="3d_fullres",
|
|
1157
1207
|
choices=["3d_fullres", "2d", "3d_lowres", "3d_cascade_fullres"],
|
|
1158
|
-
help="nnU-Net configuration
|
|
1208
|
+
help="nnU-Net configuration to train. Default 3d_fullres",
|
|
1159
1209
|
)
|
|
1160
1210
|
p_nn.add_argument(
|
|
1161
1211
|
"--fold",
|
|
@@ -1164,20 +1214,11 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
1164
1214
|
help="Fold to train (0-4 or all)",
|
|
1165
1215
|
)
|
|
1166
1216
|
p_nn.add_argument(
|
|
1167
|
-
"--
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
)
|
|
1171
|
-
p_nn.add_argument(
|
|
1172
|
-
"--plan-only",
|
|
1217
|
+
"--c",
|
|
1218
|
+
"--continue",
|
|
1219
|
+
dest="continue_training",
|
|
1173
1220
|
action="store_true",
|
|
1174
|
-
help="
|
|
1175
|
-
)
|
|
1176
|
-
p_nn.add_argument(
|
|
1177
|
-
"--np",
|
|
1178
|
-
type=int,
|
|
1179
|
-
default=None,
|
|
1180
|
-
help="Processes for plan_and_preprocess (-np)",
|
|
1221
|
+
help="Continue training from checkpoint_latest.pth (nnU-Net --c)",
|
|
1181
1222
|
)
|
|
1182
1223
|
p_nn.add_argument("--trainer", default="nnUNetTrainer", type=str)
|
|
1183
1224
|
p_nn.add_argument("--plans", default="nnUNetPlans", type=str)
|
|
@@ -1186,7 +1227,7 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
1186
1227
|
action="store_true",
|
|
1187
1228
|
help="After training succeeds, delete this dataset's nnUNet_raw and "
|
|
1188
1229
|
"nnUNet_preprocessed folders. Leaves nnUNet_results. "
|
|
1189
|
-
"
|
|
1230
|
+
"A later --c run needs that preprocessed data.",
|
|
1190
1231
|
)
|
|
1191
1232
|
p_nn.set_defaults(_handler=_cmd_train_nnunet)
|
|
1192
1233
|
|