qradiomics 0.9.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.
- qradiomics-0.9.0/LICENSE +21 -0
- qradiomics-0.9.0/PKG-INFO +585 -0
- qradiomics-0.9.0/README.md +532 -0
- qradiomics-0.9.0/pyproject.toml +83 -0
- qradiomics-0.9.0/qradiomics/__init__.py +13 -0
- qradiomics-0.9.0/qradiomics/atomic/__init__.py +34 -0
- qradiomics-0.9.0/qradiomics/atomic/features.py +80 -0
- qradiomics-0.9.0/qradiomics/atomic/hu_correct.py +64 -0
- qradiomics-0.9.0/qradiomics/atomic/io.py +77 -0
- qradiomics-0.9.0/qradiomics/atomic/preprocess.py +118 -0
- qradiomics-0.9.0/qradiomics/atomic/registration.py +159 -0
- qradiomics-0.9.0/qradiomics/cli/__init__.py +5 -0
- qradiomics-0.9.0/qradiomics/cli/commands/__init__.py +22 -0
- qradiomics-0.9.0/qradiomics/cli/commands/analyze.py +387 -0
- qradiomics-0.9.0/qradiomics/cli/commands/anonymize.py +220 -0
- qradiomics-0.9.0/qradiomics/cli/commands/config_cmd.py +73 -0
- qradiomics-0.9.0/qradiomics/cli/commands/convert.py +374 -0
- qradiomics-0.9.0/qradiomics/cli/commands/delta.py +100 -0
- qradiomics-0.9.0/qradiomics/cli/commands/extract.py +213 -0
- qradiomics-0.9.0/qradiomics/cli/commands/hu_correct.py +48 -0
- qradiomics-0.9.0/qradiomics/cli/commands/lidc.py +117 -0
- qradiomics-0.9.0/qradiomics/cli/commands/ml.py +411 -0
- qradiomics-0.9.0/qradiomics/cli/commands/pacs.py +606 -0
- qradiomics-0.9.0/qradiomics/cli/commands/preprocess.py +149 -0
- qradiomics-0.9.0/qradiomics/cli/commands/register.py +79 -0
- qradiomics-0.9.0/qradiomics/cli/commands/results.py +109 -0
- qradiomics-0.9.0/qradiomics/cli/commands/shape.py +119 -0
- qradiomics-0.9.0/qradiomics/cli/commands/tcia.py +363 -0
- qradiomics-0.9.0/qradiomics/cli/commands/workflow.py +188 -0
- qradiomics-0.9.0/qradiomics/cli/config_io.py +49 -0
- qradiomics-0.9.0/qradiomics/cli/main.py +92 -0
- qradiomics-0.9.0/qradiomics/cli/pattern/__init__.py +6 -0
- qradiomics-0.9.0/qradiomics/cli/pattern/list.py +28 -0
- qradiomics-0.9.0/qradiomics/cli/pattern/match.py +39 -0
- qradiomics-0.9.0/qradiomics/data/pyradiomics/ct_default.yaml +26 -0
- qradiomics-0.9.0/qradiomics/data/pyradiomics/ct_original_only.yaml +12 -0
- qradiomics-0.9.0/qradiomics/data/pyradiomics/nsclc_ct.yaml +36 -0
- qradiomics-0.9.0/qradiomics/data/pyradiomics/pet_default.yaml +15 -0
- qradiomics-0.9.0/qradiomics/data/schema/pattern_schema.yaml +394 -0
- qradiomics-0.9.0/qradiomics/data/templates/ct_default.yaml +93 -0
- qradiomics-0.9.0/qradiomics/data/templates/nsclc_survival.yaml +192 -0
- qradiomics-0.9.0/qradiomics/data/templates/standard_radiomics.yaml +227 -0
- qradiomics-0.9.0/qradiomics/data/templates/survival_analysis.yaml +247 -0
- qradiomics-0.9.0/qradiomics/data_model/__init__.py +37 -0
- qradiomics-0.9.0/qradiomics/data_model/core.py +174 -0
- qradiomics-0.9.0/qradiomics/data_model/enums.py +39 -0
- qradiomics-0.9.0/qradiomics/data_model/io.py +180 -0
- qradiomics-0.9.0/qradiomics/delta/__init__.py +21 -0
- qradiomics-0.9.0/qradiomics/delta/compute.py +158 -0
- qradiomics-0.9.0/qradiomics/extractor.py +172 -0
- qradiomics-0.9.0/qradiomics/io/__init__.py +5 -0
- qradiomics-0.9.0/qradiomics/io/dicom/__init__.py +28 -0
- qradiomics-0.9.0/qradiomics/io/dicom/pet_suv.py +229 -0
- qradiomics-0.9.0/qradiomics/io/dicom/preamble.py +40 -0
- qradiomics-0.9.0/qradiomics/io/dicom/rtstruct.py +194 -0
- qradiomics-0.9.0/qradiomics/io/dicom/segmentations.py +134 -0
- qradiomics-0.9.0/qradiomics/io/dicom/series.py +77 -0
- qradiomics-0.9.0/qradiomics/io/lidc/__init__.py +47 -0
- qradiomics-0.9.0/qradiomics/io/lidc/extract.py +283 -0
- qradiomics-0.9.0/qradiomics/io/lidc/parse_xml.py +230 -0
- qradiomics-0.9.0/qradiomics/io/lidc/staple.py +91 -0
- qradiomics-0.9.0/qradiomics/io/pacs/__init__.py +36 -0
- qradiomics-0.9.0/qradiomics/io/pacs/base.py +157 -0
- qradiomics-0.9.0/qradiomics/io/pacs/config.py +142 -0
- qradiomics-0.9.0/qradiomics/io/pacs/dicomweb.py +304 -0
- qradiomics-0.9.0/qradiomics/io/pacs/dimse.py +375 -0
- qradiomics-0.9.0/qradiomics/io/pacs/factory.py +58 -0
- qradiomics-0.9.0/qradiomics/io/pacs/orthanc.py +361 -0
- qradiomics-0.9.0/qradiomics/manifest/__init__.py +20 -0
- qradiomics-0.9.0/qradiomics/manifest/io.py +159 -0
- qradiomics-0.9.0/qradiomics/pattern_loader.py +869 -0
- qradiomics-0.9.0/qradiomics/shape/__init__.py +62 -0
- qradiomics-0.9.0/qradiomics/shape/ahsn.py +112 -0
- qradiomics-0.9.0/qradiomics/shape/detection.py +110 -0
- qradiomics-0.9.0/qradiomics/shape/hessian.py +101 -0
- qradiomics-0.9.0/qradiomics/shape/mesh_utils.py +133 -0
- qradiomics-0.9.0/qradiomics/shape/phantoms.py +568 -0
- qradiomics-0.9.0/qradiomics/shape/spiculation.py +390 -0
- qradiomics-0.9.0/qradiomics/shape/wall_elim.py +62 -0
- qradiomics-0.9.0/qradiomics/verification/__init__.py +59 -0
- qradiomics-0.9.0/qradiomics/verification/harness.py +192 -0
- qradiomics-0.9.0/qradiomics/verification/image_parity.py +111 -0
- qradiomics-0.9.0/qradiomics/workflow.py +768 -0
- qradiomics-0.9.0/qradiomics.egg-info/PKG-INFO +585 -0
- qradiomics-0.9.0/qradiomics.egg-info/SOURCES.txt +102 -0
- qradiomics-0.9.0/qradiomics.egg-info/dependency_links.txt +1 -0
- qradiomics-0.9.0/qradiomics.egg-info/entry_points.txt +4 -0
- qradiomics-0.9.0/qradiomics.egg-info/requires.txt +30 -0
- qradiomics-0.9.0/qradiomics.egg-info/top_level.txt +1 -0
- qradiomics-0.9.0/setup.cfg +4 -0
- qradiomics-0.9.0/tests/test_analyze_classify.py +136 -0
- qradiomics-0.9.0/tests/test_analyze_importance.py +217 -0
- qradiomics-0.9.0/tests/test_analyze_survival.py +97 -0
- qradiomics-0.9.0/tests/test_atomic.py +204 -0
- qradiomics-0.9.0/tests/test_data_model.py +171 -0
- qradiomics-0.9.0/tests/test_delta.py +99 -0
- qradiomics-0.9.0/tests/test_image_parity.py +132 -0
- qradiomics-0.9.0/tests/test_lidc.py +249 -0
- qradiomics-0.9.0/tests/test_pacs.py +442 -0
- qradiomics-0.9.0/tests/test_parity_golden.py +70 -0
- qradiomics-0.9.0/tests/test_pet_suv.py +104 -0
- qradiomics-0.9.0/tests/test_preamble.py +82 -0
- qradiomics-0.9.0/tests/test_results_merge.py +137 -0
- qradiomics-0.9.0/tests/test_verification_harness.py +87 -0
qradiomics-0.9.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Choi Lab, Thomas Jefferson University
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,585 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: qradiomics
|
|
3
|
+
Version: 0.9.0
|
|
4
|
+
Summary: Radiomics research CLI — extract, merge, analyze in one Unix-style pipeline.
|
|
5
|
+
Author: Pradeep Bhetwal
|
|
6
|
+
Author-email: Wookjin Choi <wookjin.choi@jefferson.edu>
|
|
7
|
+
License: MIT
|
|
8
|
+
Project-URL: Homepage, https://qradiomics.com/
|
|
9
|
+
Project-URL: Repository, https://github.com/choilab-jefferson/qradiomics
|
|
10
|
+
Project-URL: Documentation, https://qradiomics.com/
|
|
11
|
+
Project-URL: Bug Tracker, https://github.com/choilab-jefferson/qradiomics/issues
|
|
12
|
+
Keywords: radiomics,pyradiomics,cli,tcia,lung-cancer,medical-imaging
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Environment :: Console
|
|
15
|
+
Classifier: Intended Audience :: Healthcare Industry
|
|
16
|
+
Classifier: Intended Audience :: Science/Research
|
|
17
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
18
|
+
Classifier: Operating System :: OS Independent
|
|
19
|
+
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
|
|
23
|
+
Requires-Python: >=3.11
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: click>=8.0.0
|
|
27
|
+
Requires-Dist: httpx>=0.24.0
|
|
28
|
+
Requires-Dist: pyyaml>=6.0
|
|
29
|
+
Requires-Dist: pydantic>=2.0.0
|
|
30
|
+
Requires-Dist: rich>=13.0.0
|
|
31
|
+
Requires-Dist: pyradiomics>=3.1.0
|
|
32
|
+
Requires-Dist: pydicom>=2.4
|
|
33
|
+
Requires-Dist: SimpleITK>=2.2.0
|
|
34
|
+
Requires-Dist: numpy>=1.24.0
|
|
35
|
+
Requires-Dist: pandas>=1.5.0
|
|
36
|
+
Requires-Dist: scikit-learn>=1.2.0
|
|
37
|
+
Requires-Dist: scikit-image>=0.21.0
|
|
38
|
+
Requires-Dist: lifelines>=0.27.0
|
|
39
|
+
Requires-Dist: statsmodels>=0.14.0
|
|
40
|
+
Requires-Dist: scipy>=1.10.0
|
|
41
|
+
Provides-Extra: shap
|
|
42
|
+
Requires-Dist: shap>=0.41.0; extra == "shap"
|
|
43
|
+
Provides-Extra: rtstruct
|
|
44
|
+
Requires-Dist: rt-utils>=1.2.7; extra == "rtstruct"
|
|
45
|
+
Provides-Extra: prefect
|
|
46
|
+
Requires-Dist: prefect>=2.10; extra == "prefect"
|
|
47
|
+
Provides-Extra: dev
|
|
48
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
49
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
50
|
+
Requires-Dist: black>=23.0.0; extra == "dev"
|
|
51
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
52
|
+
Dynamic: license-file
|
|
53
|
+
|
|
54
|
+
# qradiomics
|
|
55
|
+
|
|
56
|
+
[](LICENSE)
|
|
57
|
+
[](https://www.python.org/downloads/)
|
|
58
|
+
[](https://github.com/choilab-jefferson/qradiomics/releases)
|
|
59
|
+
|
|
60
|
+
## Kick-off
|
|
61
|
+
|
|
62
|
+
Single backend (`scripts/kickoff.sh`) for both flows. It clones the
|
|
63
|
+
repo (if not already), creates a `.venv`, `pip install -e .`, runs
|
|
64
|
+
`qr info`, and runs the smoke tests.
|
|
65
|
+
|
|
66
|
+
**For users — one-liner:**
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
curl -sSL https://raw.githubusercontent.com/choilab-jefferson/qradiomics/main/scripts/kickoff.sh | bash
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**For AI coding agents — drop-in prompt:**
|
|
73
|
+
|
|
74
|
+
> You are working on qradiomics, a lung-radiomics CLI toolkit at
|
|
75
|
+
> `github.com/choilab-jefferson/qradiomics`. Do this:
|
|
76
|
+
>
|
|
77
|
+
> 1. Run the kick-off (clones, installs, verifies):
|
|
78
|
+
> ```
|
|
79
|
+
> curl -sSL https://raw.githubusercontent.com/choilab-jefferson/qradiomics/main/scripts/kickoff.sh | bash
|
|
80
|
+
> ```
|
|
81
|
+
> 2. `cd qradiomics` and read `AGENTS.md` for operations (conventions,
|
|
82
|
+
> layout, don'ts, citations). Do **not** log PHI, do **not** push
|
|
83
|
+
> to remotes, do **not** invent new public dataset URLs — use only
|
|
84
|
+
> the ones documented in AGENTS.md.
|
|
85
|
+
> 3. Ask the user what they want to build.
|
|
86
|
+
|
|
87
|
+
Env knobs accepted by the script: `QR_REPO_URL`, `QR_REPO_DIR`,
|
|
88
|
+
`QR_BRANCH`, `QR_PYTHON`, `QR_VENV` (set to `-` to skip the venv),
|
|
89
|
+
`QR_SKIP_SMOKE=1` to skip pytest.
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
> **Active successor for three earlier Choi Lab radiomics codebases.** The
|
|
94
|
+
> C++/MATLAB pipelines in
|
|
95
|
+
> [taznux/radiomics-tools](https://github.com/taznux/radiomics-tools),
|
|
96
|
+
> [taznux/lung-image-analysis](https://github.com/taznux/lung-image-analysis), and
|
|
97
|
+
> [choilab-jefferson/LungCancerScreeningRadiomics](https://github.com/choilab-jefferson/LungCancerScreeningRadiomics)
|
|
98
|
+
> are **superseded** by this repo. The feature extractors are now in
|
|
99
|
+
> `qradiomics.feature.rtools` (Python ITK port, numerically exact to the
|
|
100
|
+
> C++ binary). New work should land here.
|
|
101
|
+
|
|
102
|
+
**Radiomics research CLI.** `qr` does two things equally well:
|
|
103
|
+
|
|
104
|
+
1. **Atomic tasks** — convert DICOM, extract features, merge clinical, fit
|
|
105
|
+
a model. Each is a single command, files in / files out.
|
|
106
|
+
2. **Workflow assembly** — generate, mutate, scaffold, and run multi-step
|
|
107
|
+
pipelines from those atomic tasks. Default executor is **Nextflow**
|
|
108
|
+
(per-patient parallel + cache + HPC); **Prefect** is the secondary
|
|
109
|
+
executor; `inline` is the small-cohort fallback.
|
|
110
|
+
|
|
111
|
+
The canonical radiomics data flow has four stages — `data → image →
|
|
112
|
+
features → modeling` — and one `qr workflow plan` call instantiates the
|
|
113
|
+
whole chain:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
# Atomic tasks
|
|
117
|
+
qr convert dicom-series / rtstruct / manifest-from-dir
|
|
118
|
+
qr extract -m manifest.csv -p <pattern> -o features.csv
|
|
119
|
+
qr results merge -f features.csv -c clinical.csv -o analysis_ready.csv
|
|
120
|
+
qr analyze {survival,classify,importance} -i analysis_ready.csv ...
|
|
121
|
+
qr ml {train,predict,evaluate} ...
|
|
122
|
+
|
|
123
|
+
# Workflow assembly
|
|
124
|
+
qr workflow plan -t dicom_to_ml -d <cohort> -c <clinical> -o plan.json
|
|
125
|
+
qr workflow scaffold -p plan.json -e nextflow -o pipeline.nf
|
|
126
|
+
qr workflow run plan.json --executor nextflow # default
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Background — three earlier projects, unified
|
|
130
|
+
|
|
131
|
+
`qradiomics` is the modern Python successor of three earlier Choi Lab
|
|
132
|
+
radiomics codebases. The MATLAB pipelines, the ITK / Ruffus C++ tools,
|
|
133
|
+
and the Docker-based screening workflow are distilled here into a single
|
|
134
|
+
Click CLI built on PyRadiomics, scikit-learn, and lifelines:
|
|
135
|
+
|
|
136
|
+
| Earlier project | Stack | Role | This repo |
|
|
137
|
+
|---|---|---|---|
|
|
138
|
+
| [taznux/lung-image-analysis](https://github.com/taznux/lung-image-analysis) | MATLAB · MIT | LIDC-IDRI nodule detection / segmentation / characterization | superseded |
|
|
139
|
+
| [taznux/radiomics-tools](https://github.com/taznux/radiomics-tools) | C++/Python (ITK, Ruffus) · MIT | DICOM tools, GrowCut segmentation, feature extraction pipeline | superseded |
|
|
140
|
+
| [choilab-jefferson/LungCancerScreeningRadiomics](https://github.com/choilab-jefferson/LungCancerScreeningRadiomics) | MATLAB / Python · GPL-3.0 | LIDC + LUNGx end-to-end screening workflow with AutoML | superseded (this repo re-implements the open subset under MIT using PyRadiomics) |
|
|
141
|
+
|
|
142
|
+
The AHSN shape descriptor pipeline (CMPB 2014) and the spiculation
|
|
143
|
+
quantification pipeline (CMPB 2021, companion to
|
|
144
|
+
[choilab-jefferson/CIR](https://github.com/choilab-jefferson/CIR))
|
|
145
|
+
are re-integrated in `qradiomics.shape` (see Shape Analysis below).
|
|
146
|
+
The longitudinal CBCT / delta-radiomics workflows (ASTRO / AAPM 2026)
|
|
147
|
+
will be released here after publication.
|
|
148
|
+
|
|
149
|
+
## Install
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
pip install -e . # core CLI + library
|
|
153
|
+
pip install -e .[rtstruct] # plus rt-utils for `qr convert rtstruct`
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Python 3.11 or newer is required. PyRadiomics, SimpleITK, lifelines,
|
|
157
|
+
scikit-learn, statsmodels, scipy, and pandas are pulled in as
|
|
158
|
+
dependencies.
|
|
159
|
+
|
|
160
|
+
After install, `qr`, `qradiomics`, and `qrdx` are available on `$PATH`
|
|
161
|
+
and point at `qradiomics.cli.main:cli`.
|
|
162
|
+
|
|
163
|
+
## DICOM Conversion
|
|
164
|
+
|
|
165
|
+
Many TCIA cohorts ship as DICOM (CT/PET/MR series + RTSTRUCT). Two
|
|
166
|
+
helpers convert into the NRRD form the rest of the pipeline consumes:
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
# 1. CT/PET/MR DICOM series → single NRRD volume
|
|
170
|
+
qr convert dicom-series \
|
|
171
|
+
-i <dataset_root>/<patient>/<study>/CT/ \
|
|
172
|
+
-o <out>/<patient>_CT.nrrd
|
|
173
|
+
|
|
174
|
+
# 2. RTSTRUCT contour → binary label NRRD (same geometry as the reference CT)
|
|
175
|
+
qr convert rtstruct \
|
|
176
|
+
-d <dataset_root>/<patient>/<study>/CT/ \
|
|
177
|
+
-r <dataset_root>/<patient>/<study>/RTSeries/RS.<uid>.dcm \
|
|
178
|
+
--roi GTV \
|
|
179
|
+
-o <out>/<patient>_GTV-label.nrrd
|
|
180
|
+
|
|
181
|
+
# 3. (Optional) build a manifest by globbing image/mask pairs in a tree
|
|
182
|
+
qr convert manifest-from-dir \
|
|
183
|
+
-d <out>/ \
|
|
184
|
+
--image-glob '*_CT.nrrd' \
|
|
185
|
+
--mask-glob '*-label.nrrd' \
|
|
186
|
+
-o manifest.csv
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
RTSTRUCT conversion uses `rt-utils` (install via
|
|
190
|
+
`pip install qradiomics[rtstruct]`). ROI lookup is case-insensitive (a
|
|
191
|
+
`--roi Heart` request matches a structure set with `heart`). The mask
|
|
192
|
+
is auto-reshaped to the CT geometry, with a ±1-slice z-axis trim/pad
|
|
193
|
+
when the structure set references slices outside the series.
|
|
194
|
+
|
|
195
|
+
## End-to-end Example — TCIA NSCLC-Radiomics (Lung1) from scratch
|
|
196
|
+
|
|
197
|
+
Starts from nothing — pulls DICOM straight from TCIA, converts, extracts,
|
|
198
|
+
joins clinical, and reports the Cox PH ranking. The same chain runs for
|
|
199
|
+
any TCIA collection by swapping the first argument.
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
# 0. One-time: install + workspace
|
|
203
|
+
pip install -e .[rtstruct]
|
|
204
|
+
export USER_DATA=/data/$USER # ≥ 30 GB free for Lung1 (~422 patients)
|
|
205
|
+
mkdir -p $USER_DATA/{Lung1,Lung1-out}
|
|
206
|
+
|
|
207
|
+
# 1. DICOM pull from TCIA (CT + RTSTRUCT for the same series instance UIDs)
|
|
208
|
+
qr tcia download \
|
|
209
|
+
--collection NSCLC-Radiomics --modality CT \
|
|
210
|
+
-o $USER_DATA/Lung1 -j 16
|
|
211
|
+
qr tcia download \
|
|
212
|
+
--collection NSCLC-Radiomics --modality RTSTRUCT \
|
|
213
|
+
-o $USER_DATA/Lung1 -j 16
|
|
214
|
+
|
|
215
|
+
# 2. DICOM → NRRD per patient: CT volume + GTV-1 binary mask
|
|
216
|
+
for pat in $USER_DATA/Lung1/*/; do
|
|
217
|
+
pid=$(basename "$pat")
|
|
218
|
+
qr convert dicom-series \
|
|
219
|
+
-i "$pat"*/CT \
|
|
220
|
+
-o "$USER_DATA/Lung1-out/${pid}_CT.nrrd"
|
|
221
|
+
qr convert rtstruct \
|
|
222
|
+
-d "$pat"*/CT \
|
|
223
|
+
-r "$pat"*/RTSeries/*.dcm \
|
|
224
|
+
--roi GTV-1 \
|
|
225
|
+
-o "$USER_DATA/Lung1-out/${pid}_GTV-label.nrrd"
|
|
226
|
+
done
|
|
227
|
+
|
|
228
|
+
# 3. Manifest from the converted tree
|
|
229
|
+
qr convert manifest-from-dir \
|
|
230
|
+
-d "$USER_DATA/Lung1-out" \
|
|
231
|
+
--image-glob '*_CT.nrrd' \
|
|
232
|
+
--mask-glob '*_GTV-label.nrrd' \
|
|
233
|
+
-o "$USER_DATA/Lung1-out/manifest.csv"
|
|
234
|
+
|
|
235
|
+
# 4. PyRadiomics extraction under the nsclc-survival pattern
|
|
236
|
+
# (Original + LoG + Wavelet + Square + SquareRoot + Logarithm ×
|
|
237
|
+
# {firstorder, shape, glcm, glrlm, glszm, gldm, ngtdm} ≈ 1130 features)
|
|
238
|
+
qr extract \
|
|
239
|
+
-m "$USER_DATA/Lung1-out/manifest.csv" \
|
|
240
|
+
-p nsclc-survival \
|
|
241
|
+
-o "$USER_DATA/Lung1-out/features.csv"
|
|
242
|
+
|
|
243
|
+
# 5. Join with the published clinical table (download once)
|
|
244
|
+
# Header has Survival.time + deadstatus → results merge auto-renames.
|
|
245
|
+
curl -sLo "$USER_DATA/Lung1-out/clinical.csv" \
|
|
246
|
+
"https://www.cancerimagingarchive.net/wp-content/uploads/NSCLC-Radiomics-Lung1.clinical-version3-Oct-2019.csv"
|
|
247
|
+
qr results merge \
|
|
248
|
+
-f "$USER_DATA/Lung1-out/features.csv" \
|
|
249
|
+
-c "$USER_DATA/Lung1-out/clinical.csv" \
|
|
250
|
+
--clinical-id-col PatientID \
|
|
251
|
+
--time-col Survival.time --event-col deadstatus.event \
|
|
252
|
+
-o "$USER_DATA/Lung1-out/analysis_ready.csv"
|
|
253
|
+
|
|
254
|
+
# 6. Univariate Cox PH on every radiomic feature → ranked CSV
|
|
255
|
+
qr analyze survival \
|
|
256
|
+
-i "$USER_DATA/Lung1-out/analysis_ready.csv" \
|
|
257
|
+
--outcome OS_months --event OS_event \
|
|
258
|
+
-o "$USER_DATA/Lung1-out/cox_results.csv"
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
Expected outcome on Lung1 (≈ 420 patients): `original_ngtdm_Busyness`
|
|
262
|
+
ranks at the top (HR ≈ 1.23, p < 1e-4) — replicating the headline
|
|
263
|
+
finding from the Aerts 2014 *Nature Communications* radiomics paper.
|
|
264
|
+
|
|
265
|
+
A 422-patient run takes ≈ 1 h on a 16-core workstation (≈ 30 min
|
|
266
|
+
download, 20 min DICOM→NRRD, 15 min extraction, seconds for the rest).
|
|
267
|
+
For a 5-patient smoke run on the same chain, see
|
|
268
|
+
`scripts/smoke.py` (synthetic NRRD; no TCIA download required).
|
|
269
|
+
|
|
270
|
+
The exact same sequence is bundled per cohort under `pipelines/lung1/`,
|
|
271
|
+
`pipelines/lidc_idri/`, `pipelines/nsclc_cetuximab/`, and
|
|
272
|
+
`pipelines/acrin_heart/` with Nextflow / Prefect / inline executors —
|
|
273
|
+
see the **Deployable Pipelines** section below.
|
|
274
|
+
|
|
275
|
+
### Alternative starting point — manifest you already have
|
|
276
|
+
|
|
277
|
+
If your data is already in NRRD form with a manifest CSV (canonical
|
|
278
|
+
lowercase columns: `patient_id, modality, image_path, mask_path`), skip
|
|
279
|
+
steps 0-3 and start at step 4 above.
|
|
280
|
+
|
|
281
|
+
Browse the bundled patterns with `qr pattern list` and `qr pattern search <kw>`.
|
|
282
|
+
|
|
283
|
+
## Deployable Pipelines
|
|
284
|
+
|
|
285
|
+
For each TCIA-public cohort, [`pipelines/`](pipelines/) ships a ready-
|
|
286
|
+
to-run bundle: `plan.json` + `main.nf` + `prefect_flow.py` +
|
|
287
|
+
`nextflow.config` + `deploy.sh`. Run any cohort end-to-end with:
|
|
288
|
+
|
|
289
|
+
```bash
|
|
290
|
+
cd pipelines/lung1/
|
|
291
|
+
cp /path/to/your/clinical.csv clinical/clinical.csv
|
|
292
|
+
./deploy.sh # nextflow (per-patient parallel, default)
|
|
293
|
+
EXECUTOR=prefect ./deploy.sh # via Prefect 2.x
|
|
294
|
+
EXECUTOR=inline ./deploy.sh # sequential subprocess (smoke tests)
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
Available bundles: `lung1/`, `nsclc_cetuximab/`, `lidc_idri/`, `acrin_heart/`.
|
|
298
|
+
|
|
299
|
+
## Workflow Assembly — agents compose, qr executes
|
|
300
|
+
|
|
301
|
+
The canonical four-stage data flow is encoded in the **template
|
|
302
|
+
library** that `qr workflow plan` draws from:
|
|
303
|
+
|
|
304
|
+
| Template | Stages covered | When to use |
|
|
305
|
+
|---|---|---|
|
|
306
|
+
| `nrrd_survival` | data → features → modeling | cohort already in NRRD form |
|
|
307
|
+
| `dicom_survival` | data → image → features → modeling | cohort ships as DICOM + RTSTRUCT |
|
|
308
|
+
| `dicom_to_ml` | data → image → features → modeling (ML) | full end-to-end DICOM → trained model + CV metrics + held-out evaluation |
|
|
309
|
+
|
|
310
|
+
```bash
|
|
311
|
+
# 1. Generate a plan
|
|
312
|
+
qr workflow plan -t dicom_to_ml \
|
|
313
|
+
-d /data/cohort -c clinical.csv \
|
|
314
|
+
--roi GTV --pattern nsclc-survival \
|
|
315
|
+
-o plan.json
|
|
316
|
+
|
|
317
|
+
# 2. (Optional) scaffold a Nextflow file for inspection / editing
|
|
318
|
+
qr workflow scaffold -p plan.json -e nextflow -o pipeline.nf
|
|
319
|
+
|
|
320
|
+
# 3. Run — default executor is Nextflow (per-patient parallel + cache)
|
|
321
|
+
qr workflow run plan.json
|
|
322
|
+
qr workflow run plan.json --executor inline # small interactive
|
|
323
|
+
qr workflow run plan.json --executor prefect # Prefect-orchestrated
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
The plan is plain JSON/YAML — agents can read, mutate (add a stage,
|
|
327
|
+
swap a pattern, change the executor), and re-run without re-templating.
|
|
328
|
+
Per-patient steps are marked in the plan and fanned out automatically
|
|
329
|
+
by the Nextflow / Prefect scaffolders.
|
|
330
|
+
|
|
331
|
+
## Validated Cohorts
|
|
332
|
+
|
|
333
|
+
The pipeline has been validated end-to-end on three TCIA public cohorts:
|
|
334
|
+
|
|
335
|
+
| Cohort | Format on TCIA | Conversion path |
|
|
336
|
+
|---|---|---|
|
|
337
|
+
| [NSCLC-Radiomics (LUNG1)](https://www.cancerimagingarchive.net/collection/nsclc-radiomics/) | DICOM CT + RTSTRUCT (or pre-converted NRRD via the published companion pack) | `qr convert dicom-series` + `qr convert rtstruct --roi GTV-1`, or feed NRRD directly |
|
|
338
|
+
| [NSCLC-Cetuximab](https://www.cancerimagingarchive.net/collection/nsclc-cetuximab/) | DICOM CT + RTSTRUCT | `qr convert dicom-series` + `qr convert rtstruct --roi PTV` |
|
|
339
|
+
| [ACRIN-NSCLC-FDG-PET](https://www.cancerimagingarchive.net/collection/acrin-nsclc-fdg-pet/) | DICOM CT/PET + RTSTRUCT | `qr convert dicom-series` + `qr convert rtstruct --roi Heart` (case-insensitive) |
|
|
340
|
+
|
|
341
|
+
All three flow cleanly through `convert → extract → results merge → analyze`.
|
|
342
|
+
Ready-to-run shell scripts for each cohort (plus LIDC-IDRI and the IBSI
|
|
343
|
+
phantom) live in [`examples/`](examples/README.md).
|
|
344
|
+
|
|
345
|
+
## Verified End-to-End Pipelines
|
|
346
|
+
|
|
347
|
+
Each row is a published study whose protocol has been reproduced end-to-end
|
|
348
|
+
in this repo. Pick the row matching your study, run the listed command, and
|
|
349
|
+
the result will be within reported tolerance of the paper.
|
|
350
|
+
|
|
351
|
+
| Pipeline | Paper anchor | Entry point | Verified outcome |
|
|
352
|
+
|---|---|---|---|
|
|
353
|
+
| **LIDC AHSN nodule detection** | Choi & Choi, *Comput Methods Programs Biomed* 2014;113(1):37–54 ([doi](https://doi.org/10.1016/j.cmpb.2013.08.015)) | `pipelines/lidc_idri/ahsn_proxy.py` · `pipelines/lidc_idri/ahsn_hardneg.py` | 180-D AHSN descriptor on LIDC nodule vs non-nodule |
|
|
354
|
+
| **LIDC + LUNGx malignancy radiomics (RM)** | Choi et al., *Med Phys* 2018;45(4):1537–1549 ([doi](https://doi.org/10.1002/mp.12820)) | `pipelines/lidc_idri/reproduce_papers.py` · `pipelines/lidc_idri/methods_compare.py` | LIDC RM AUC ≈ 0.816 ± 0.006 · LUNGx ext+cal ≈ 0.756 (paper: 0.80–0.85 / 0.76) |
|
|
355
|
+
| **LUNGx interpretable spiculation (PM, RM+spic)** | Choi et al., *Comput Methods Programs Biomed* 2021;200:105839 ([doi](https://doi.org/10.1016/j.cmpb.2020.105839)) | `pipelines/lidc_idri/methods_compare.py` (PM) · `qradiomics.shape.spiculation_from_voxel` | radiomics+spic PM ≈ 0.868 ± 0.039 (paper: 0.85) |
|
|
356
|
+
| **HeartToxicity FDG uptake 3-class (TJU prePT → ACRIN/HeartCB postPT)** | Choi et al., *JCO Clin Cancer Inform* 2024 Appendix C ([doi](https://doi.org/10.1200/CCI.23.00241)) | qradiomics-dev `pipelines/heart_local/` (private cohort extension; protocol reproduced with `qradiomics.feature.rtools` postPT-auto + pyradiomics two-source concat) | TJU prePT → ACRIN/HeartCB postPT external acc ≈ 0.80 / 0.78 (Step 1) — matches paper anchor |
|
|
357
|
+
|
|
358
|
+
Each entry point writes a JSON/CSV report next to the script; no manual
|
|
359
|
+
gluing required.
|
|
360
|
+
|
|
361
|
+
## Command Reference
|
|
362
|
+
|
|
363
|
+
| Command | Stage | Purpose |
|
|
364
|
+
|-----------------------------|------------|---------------------------------------------------------------|
|
|
365
|
+
| `qr tcia download` | data | Bulk-download a TCIA collection (multi-process + progress) |
|
|
366
|
+
| `qr anonymize` | data | Strip PHI from a DICOM tree (DICOM PS3.15 Annex E) |
|
|
367
|
+
| `qr convert dicom-series` | data/image | DICOM CT/MR → NRRD; PT auto-routes through SUV conversion |
|
|
368
|
+
| `qr convert rtstruct` | data/image | DICOM RTSTRUCT contour → label NRRD (case-insensitive ROI) |
|
|
369
|
+
| `qr convert manifest-from-dir` | data | Glob image+mask pairs into a manifest CSV |
|
|
370
|
+
| `qr preprocess` | image | bbox crop + isotropic resample per (image, mask) row |
|
|
371
|
+
| `qr register` | image | Rigid Mattes-MI/LBFGSB moving→fixed (Scenario C mask transfer)|
|
|
372
|
+
| `qr hu-correct` | image | Histogram-match CBCT to a reference CT |
|
|
373
|
+
| `qr extract` | features | PyRadiomics → features.csv (manifest + pattern) |
|
|
374
|
+
| `qr shape extract` | features | AHSN + spiculation shape descriptors |
|
|
375
|
+
| `qr delta` | features | DeltaPair (A - B) + trend slope per patient across timepoints |
|
|
376
|
+
| `qr results merge` | features | features.csv + clinical.csv → analysis_ready.csv |
|
|
377
|
+
| `qr analyze survival` | modeling | Univariate Cox proportional hazards |
|
|
378
|
+
| `qr analyze classify` | modeling | Univariate logistic regression |
|
|
379
|
+
| `qr analyze importance` | modeling | Random-forest + permutation (+ optional SHAP) |
|
|
380
|
+
| `qr ml train` | modeling | CV Cox / logistic + leakage-safe corr/univariate selection |
|
|
381
|
+
| `qr ml predict` | modeling | Apply a trained model to new features |
|
|
382
|
+
| `qr ml evaluate` | modeling | Hold-out evaluation report (c-index / AUC) |
|
|
383
|
+
| `qr workflow plan` | assembly | Generate a multi-step plan from a template |
|
|
384
|
+
| `qr workflow show` | assembly | Inspect a plan's steps and variables |
|
|
385
|
+
| `qr workflow scaffold` | assembly | Render a plan as shell / nextflow / prefect |
|
|
386
|
+
| `qr workflow run` | assembly | Execute a plan (default executor: nextflow) |
|
|
387
|
+
| `qr pattern list / search` | meta | Browse bundled pattern templates |
|
|
388
|
+
| `qr config get / set` | meta | User preferences in `~/.qradiomics/config.yaml` |
|
|
389
|
+
|
|
390
|
+
## Python API — atomic core
|
|
391
|
+
|
|
392
|
+
Every CLI command is a thin wrapper around a re-usable Python API.
|
|
393
|
+
External libraries (e.g. longitudinal CBCT orchestrators) consume the
|
|
394
|
+
atomic layer directly instead of shelling out.
|
|
395
|
+
|
|
396
|
+
```python
|
|
397
|
+
from qradiomics.atomic import (
|
|
398
|
+
load_image_and_mask, preprocess_pair,
|
|
399
|
+
build_extractor, run_extractor, extract_features,
|
|
400
|
+
register_pair, resample_to_fixed, histogram_match_hu,
|
|
401
|
+
)
|
|
402
|
+
from qradiomics.data_model import (
|
|
403
|
+
Cohort, Patient, TreatmentCourse, Study,
|
|
404
|
+
ImageSeries, RTStructureSet, ROI,
|
|
405
|
+
AtomicUnit, Modality, StudyType,
|
|
406
|
+
save_cohort, load_cohort,
|
|
407
|
+
)
|
|
408
|
+
from qradiomics.manifest import flatten_cohort, read_manifest, write_manifest
|
|
409
|
+
from qradiomics.delta import DeltaPair, compute_delta, compute_trend
|
|
410
|
+
from qradiomics.io.dicom import read_pet_suv
|
|
411
|
+
|
|
412
|
+
# Single atomic unit: one image, one mask → ≈1409 features
|
|
413
|
+
image, mask = load_image_and_mask("planCT.nrrd", "Heart-label.nrrd")
|
|
414
|
+
cropped_img, cropped_msk = preprocess_pair(image, mask, pad_mm=20, resample_mm=1.0)
|
|
415
|
+
extractor = build_extractor(image_types=["Original", "LoG", "Wavelet"])
|
|
416
|
+
features = run_extractor(extractor, cropped_img, cropped_msk)
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
### Hierarchical cohort model
|
|
420
|
+
|
|
421
|
+
`qradiomics.data_model` mirrors the canonical 5–6 level hierarchy used
|
|
422
|
+
across the Choi-Lab ecosystem:
|
|
423
|
+
|
|
424
|
+
```
|
|
425
|
+
Cohort → Patient → TreatmentCourse → Study → ImageSeries / RTStructureSet → ROI
|
|
426
|
+
(optional)
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
Diagnostic-only cohorts omit `TreatmentCourse` and attach `Study`
|
|
430
|
+
directly to `Patient`. `flatten_cohort()` walks the tree and produces a
|
|
431
|
+
list of `AtomicUnit`s — one per (image, mask) pair — which becomes the
|
|
432
|
+
manifest CSV consumed by `qr extract`.
|
|
433
|
+
|
|
434
|
+
```python
|
|
435
|
+
cohort = Cohort(cohort_id="lng-cbct")
|
|
436
|
+
patient = Patient(patient_id="P001")
|
|
437
|
+
course = TreatmentCourse(course_id="rt1", fractions=30, prescription_dose_gy=60.0)
|
|
438
|
+
study = Study(study_id="S-week4", timepoint="week4", relative_day=28)
|
|
439
|
+
study.series["CBCT"] = ImageSeries(series_id="CBCT-w4",
|
|
440
|
+
image_path="/data/CBCT_w4.nrrd", modality=Modality.CBCT, image_tag="CBCT-w4")
|
|
441
|
+
rs = RTStructureSet(rtstruct_id="rs", referenced_series_uid="...")
|
|
442
|
+
rs.rois["GTV"] = ROI(roi_id="GTV", mask_path="/data/GTV-label.nrrd",
|
|
443
|
+
mask_tag="manual", mask_image_tag="CBCT-w4")
|
|
444
|
+
study.structure_sets["rs"] = rs
|
|
445
|
+
course.studies[study.study_id] = study
|
|
446
|
+
patient.treatment_courses[course.course_id] = course
|
|
447
|
+
cohort.patients[patient.patient_id] = patient
|
|
448
|
+
|
|
449
|
+
units = flatten_cohort(cohort) # list[AtomicUnit]
|
|
450
|
+
write_manifest(units, "manifest.csv") # canonical 10-column schema
|
|
451
|
+
save_cohort(cohort, "cohort.yaml") # full graph persistence
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
The manifest is the bridge: anyone (the CLI, Nextflow, JeffLungRadiomics,
|
|
455
|
+
external scripts) can consume it without needing the Python model.
|
|
456
|
+
|
|
457
|
+
## Shape Analysis — `qradiomics.shape`
|
|
458
|
+
|
|
459
|
+
Python re-implementations of two published Choi-Lab pipelines, used as
|
|
460
|
+
a library (no CLI yet — call as functions):
|
|
461
|
+
|
|
462
|
+
**2014 CMPB — AHSN pulmonary nodule detection**
|
|
463
|
+
|
|
464
|
+
```python
|
|
465
|
+
from qradiomics.shape import (
|
|
466
|
+
surface_elements, # Hessian eigendecomp + per-voxel normals (§2.2.1)
|
|
467
|
+
detect_candidates, # Multi-scale Sato/Li dot enhancement (§2.2.2)
|
|
468
|
+
ahsn, AHSNConfig, # Angular Histogram of Surface Normals (§2.3.1)
|
|
469
|
+
wall_eliminate, # Iterative wall detection / elimination (§2.3.2)
|
|
470
|
+
make, make_all, # Synthetic 3D lung phantoms for testing
|
|
471
|
+
)
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
**2021 CMPB — Spiculation quantification** (companion to
|
|
475
|
+
[CIR](https://github.com/choilab-jefferson/CIR))
|
|
476
|
+
|
|
477
|
+
```python
|
|
478
|
+
from qradiomics.shape import (
|
|
479
|
+
voxel_to_mesh, # marching cubes → triangular mesh
|
|
480
|
+
spherical_parameterization, # cotangent-Laplacian → unit sphere
|
|
481
|
+
area_distortion, # per-vertex log-area distortion
|
|
482
|
+
detect_peaks, # negative-distortion peaks = spike candidates
|
|
483
|
+
spiculation_features, # Na / Nl / Na_att / s1 / s2 features
|
|
484
|
+
spiculation_from_voxel, # one-shot mask → SpiculationFeatures
|
|
485
|
+
)
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
See `tests/shape/` for end-to-end usage on analytic shapes
|
|
489
|
+
(sphere / spiked-sphere / phantoms).
|
|
490
|
+
|
|
491
|
+
## Repository Layout
|
|
492
|
+
|
|
493
|
+
```
|
|
494
|
+
qradiomics/
|
|
495
|
+
├── __init__.py # exposes PatternLoader, RadiomicsExtractor, __version__
|
|
496
|
+
├── cli/ # Click CLI (qr / qradiomics / qrdx)
|
|
497
|
+
│ ├── main.py
|
|
498
|
+
│ ├── config_io.py
|
|
499
|
+
│ ├── commands/ # extract, results, analyze, config_cmd
|
|
500
|
+
│ └── pattern/ # list, match
|
|
501
|
+
├── pattern_loader.py # YAML pattern templates → Pydantic models
|
|
502
|
+
├── extractor.py # PyRadiomics wrapper
|
|
503
|
+
├── shape/ # Published shape pipelines (re-implementation)
|
|
504
|
+
│ ├── hessian.py # 2014 §2.2.1 — Hessian + surface elements
|
|
505
|
+
│ ├── detection.py # 2014 §2.2.2 — multi-scale Sato/Li dot filter
|
|
506
|
+
│ ├── ahsn.py # 2014 §2.3.1 — AHSN descriptor
|
|
507
|
+
│ ├── wall_elim.py # 2014 §2.3.2 — iterative wall elimination
|
|
508
|
+
│ ├── mesh_utils.py # 2021 — voxel → mesh + geometry primitives
|
|
509
|
+
│ ├── spiculation.py # 2021 — spherical param + Na/Nl/Na_att/s1/s2
|
|
510
|
+
│ └── phantoms.py # Synthetic 3D lung phantoms for testing
|
|
511
|
+
└── data/
|
|
512
|
+
├── templates/ # pattern YAMLs (ct_default, nsclc_survival, ...)
|
|
513
|
+
├── pyradiomics/ # per-pattern PyRadiomics extractor configs
|
|
514
|
+
└── schema/ # pattern-template JSON schema
|
|
515
|
+
|
|
516
|
+
tests/ # pytest: analyze + results.merge (19 tests)
|
|
517
|
+
LICENSE # MIT
|
|
518
|
+
pyproject.toml
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
## Bundled Pattern Templates
|
|
522
|
+
|
|
523
|
+
| `pattern_id` | Description |
|
|
524
|
+
|----------------------|-------------------------------------------------------|
|
|
525
|
+
| `ct-default` | Plain CT, single timepoint, multi image-type baseline |
|
|
526
|
+
| `standard-radiomics` | Multi-modality generic radiomics |
|
|
527
|
+
| `survival-analysis` | Cox + RSF + KM, time-to-event task |
|
|
528
|
+
| `nsclc-survival` | NSCLC CT GTV, LoG+Wavelet+Square/Sqrt/Log image types |
|
|
529
|
+
|
|
530
|
+
Drop a new `*.yaml` into `qradiomics/data/templates/` to add a study;
|
|
531
|
+
`qr pattern list` picks it up automatically.
|
|
532
|
+
|
|
533
|
+
## Citing
|
|
534
|
+
|
|
535
|
+
If you use this CLI in published work, please cite the relevant
|
|
536
|
+
upstream papers. PyRadiomics and the NSCLC-Radiomics cohort are the
|
|
537
|
+
two essential citations for any qradiomics-derived feature analysis:
|
|
538
|
+
|
|
539
|
+
- **PyRadiomics** — van Griethuysen JJM, Fedorov A, Parmar C, et al.
|
|
540
|
+
*Computational Radiomics System to Decode the Radiographic
|
|
541
|
+
Phenotype.* Cancer Research 2017; 77(21):e104-e107.
|
|
542
|
+
doi:[10.1158/0008-5472.CAN-17-0339](https://doi.org/10.1158/0008-5472.CAN-17-0339)
|
|
543
|
+
- **NSCLC-Radiomics (TCIA LUNG1)** — Aerts HJWL, Velazquez ER, Leijenaar
|
|
544
|
+
RTH, et al. *Decoding tumour phenotype by noninvasive imaging using a
|
|
545
|
+
quantitative radiomics approach.* Nature Communications 2014; 5:4006.
|
|
546
|
+
doi:[10.1038/ncomms5006](https://doi.org/10.1038/ncomms5006)
|
|
547
|
+
|
|
548
|
+
If you build on the lung-screening lineage that this CLI grew out of,
|
|
549
|
+
please additionally cite:
|
|
550
|
+
|
|
551
|
+
- Choi W, Oh JH, Riyahi S, Liu C-J, Jiang F, Chen W, White C, Rimner A,
|
|
552
|
+
Mechalakos JG, Deasy JO, Lu W. *Radiomics analysis of pulmonary
|
|
553
|
+
nodules in low-dose CT for early detection of lung cancer.* Medical
|
|
554
|
+
Physics 2018; 45(4):1537-1549.
|
|
555
|
+
doi:[10.1002/mp.12820](https://doi.org/10.1002/mp.12820)
|
|
556
|
+
- Choi W, Nadeem S, Riyahi S, Deasy JO, Tannenbaum A, Lu W.
|
|
557
|
+
*Reproducible and Interpretable Spiculation Quantification for Lung
|
|
558
|
+
Cancer Screening.* Computer Methods and Programs in Biomedicine 2021;
|
|
559
|
+
200:105839.
|
|
560
|
+
doi:[10.1016/j.cmpb.2020.105839](https://doi.org/10.1016/j.cmpb.2020.105839)
|
|
561
|
+
- Choi WJ, Choi TS. *Automated pulmonary nodule detection based on
|
|
562
|
+
three-dimensional shape-based feature descriptor.* Computer Methods
|
|
563
|
+
and Programs in Biomedicine 2014; 113(1):37-54.
|
|
564
|
+
doi:[10.1016/j.cmpb.2013.08.015](https://doi.org/10.1016/j.cmpb.2013.08.015)
|
|
565
|
+
- Choi W, Werner-Wasik M, Siglin J, et al. *Heart Radiomics for the
|
|
566
|
+
Early Detection of Cardiac Toxicity in Non–Small-Cell Lung Cancer.*
|
|
567
|
+
JCO Clinical Cancer Informatics 2024; 8:e2300241.
|
|
568
|
+
doi:[10.1200/CCI.23.00241](https://doi.org/10.1200/CCI.23.00241)
|
|
569
|
+
— Appendix C 3-class FDG uptake-pattern protocol (TJU prePT →
|
|
570
|
+
ACRIN/HeartCB postPT external validation) is reproduced in the
|
|
571
|
+
qradiomics-dev private extension on top of the public
|
|
572
|
+
`qradiomics.feature.rtools` postPT-auto extractor.
|
|
573
|
+
|
|
574
|
+
## Authors and Acknowledgements
|
|
575
|
+
|
|
576
|
+
- [**Wookjin Choi**](https://github.com/taznux) — overall architecture,
|
|
577
|
+
CLI design, pattern templates
|
|
578
|
+
- [**Pradeep Bhetwal**](https://github.com/Pradeepbhetwal) — survival
|
|
579
|
+
analysis on the LUNG1 cohort
|
|
580
|
+
- Choi Lab, Department of Radiation Oncology, Sidney Kimmel Medical
|
|
581
|
+
College at Thomas Jefferson University
|
|
582
|
+
|
|
583
|
+
## License
|
|
584
|
+
|
|
585
|
+
MIT — see [LICENSE](LICENSE).
|