Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
9c66aad
add qc scripts into new src dir
K-Meech Apr 20, 2026
25c04f2
move python png generation script into own file
K-Meech Apr 20, 2026
eac8e33
move css stylesheet into separate file
K-Meech Apr 20, 2026
3fb4e43
move javascript into separate file
K-Meech Apr 20, 2026
4ee29ff
update stylesheet name
K-Meech Apr 20, 2026
e488724
run linter over new files
K-Meech Apr 20, 2026
7ce9635
draft of installing FSL directly via conda
K-Meech Apr 21, 2026
90fe052
pin python dependencies
K-Meech Apr 21, 2026
ef2e3ea
activate and deactivate conda env for unet step
K-Meech Apr 22, 2026
7c58bc8
use original png and html generation files
K-Meech Apr 22, 2026
3767cea
convert png_generator bash script to python
K-Meech Apr 22, 2026
8a859b9
add matplotlib to conda env
K-Meech Apr 22, 2026
8983b2e
update html output paths
K-Meech Apr 23, 2026
b9d215b
pull subject ids directly from the png directory
K-Meech Apr 23, 2026
a5bd54a
integrate QC steps into analysis script
K-Meech Apr 23, 2026
1e89715
update png_generator to process a single subject and session combo
K-Meech Apr 23, 2026
7347094
run png steps as part of parallel process
K-Meech Apr 23, 2026
f651fb0
skip writing png slices if they already exist
K-Meech Apr 23, 2026
12b49b0
pass paths on command-line to MAKE_HTML.sh
K-Meech Apr 23, 2026
cae2842
add qc guide images to the correct location
K-Meech Apr 23, 2026
e949231
update overlay filename to _combined
K-Meech Apr 23, 2026
774d1b0
fix typo in png existence checks
K-Meech Apr 23, 2026
b831b81
add html prefix argument
K-Meech Apr 23, 2026
df9b7b4
force non-bids to have some output structure
K-Meech Apr 23, 2026
3216f41
remove miniforge installer after use in docker image
K-Meech Apr 23, 2026
f52eb1a
explicitly state the python version
K-Meech Apr 23, 2026
605c54d
update main readme and developer docs
K-Meech Apr 23, 2026
a7e210e
update non-bids data docs
K-Meech Apr 23, 2026
380a26e
add QC usage docs
K-Meech Apr 24, 2026
32b9e53
make sure last line of csv file is always read
K-Meech Apr 24, 2026
e5c12c6
add docs for the qc pipeline steps
K-Meech Apr 24, 2026
839e40f
link to QC workflow when discussing -h
K-Meech Apr 24, 2026
36aed05
make sure result zip and log filenames are identical across diffrent …
K-Meech Apr 24, 2026
f99a69d
fix typos in QC docs
K-Meech Apr 24, 2026
ff9cefe
merge upstream changes
K-Meech Apr 24, 2026
5d555b2
remove duplicated base_png and overlay_png lines
K-Meech Apr 24, 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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
.vscode/
data/
tmp/
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ repos:
args:
- --force-exclude
- --hidden
- --locale=en-gb
- --locale=en
- repo: https://github.com/igorshubovych/markdownlint-cli
rev: v0.41.0
hooks:
Expand Down
17 changes: 13 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
FROM cvriend/pgs:latest
WORKDIR /

# Need fslinstaller.py
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && \
apt-get install -y --no-install-recommends \
Expand All @@ -13,12 +12,22 @@ RUN apt-get update && \
zip && \
rm -rf /var/lib/apt/lists/*

RUN wget https://fsl.fmrib.ox.ac.uk/fsldownloads/fslconda/releases/fslinstaller.py && python fslinstaller.py -d /usr/local/fsl/ -V 6.0.7.13
# Install miniforge
RUN wget -O Miniforge3.sh "https://github.com/conda-forge/miniforge/releases/download/26.1.1-3/Miniforge3-26.1.1-3-Linux-x86_64.sh" && \
bash Miniforge3.sh -b -p "/conda" && \
rm Miniforge3.sh
ENV PATH="$PATH:/conda/bin"

RUN echo '\n # FSL Setup \nFSLDIR=/usr/local/fsl \nPATH=${FSLDIR}/share/fsl/bin:${PATH} \nexport FSLDIR PATH \n. ${FSLDIR}/etc/fslconf/fsl.sh' >> /root/.bashrc
# Install python dependencies including FSL
COPY environment.yml .
RUN conda env create --file environment.yml

COPY analysis_script.sh .
# Set FSL environment variables
ENV FSLENV=enigma_pd_wml_env
ENV FSLDIR=/conda/envs/${FSLENV}
ENV PATH=${FSLDIR}/share/fsl/bin:${PATH}

COPY src .
RUN mkdir /data

RUN chmod +x analysis_script.sh
Expand Down
22 changes: 18 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ the same scanning session. The analysis steps (including pre- and post- processi

- [FSL (FMRIB Software Library)](https://fsl.fmrib.ox.ac.uk/fsl/docs/) : a library of analysis tools for FMRI, MRI and
diffusion brain imaging data.
We are using version 6.0.7.13 of FSL.

- [UNet-pgs](https://www.sciencedirect.com/science/article/pii/S1053811921004171?via%3Dihub) : A segmentation pipeline
for white matter hyperintensities (WMHs) using U-Net.
Expand Down Expand Up @@ -174,6 +173,12 @@ Note, this requires either:
- `-l` : path to CSV file containing list of subjects to include in the analysis. This should only be used if you would
like to [run the pipeline on non-BIDS data](./docs/non-bids-data.md). This path must be relative to your data directory.

- `-h`: The prefix to use for HTML files generated as part of the [QC workflow](./docs/qc_usage.md).

E.g. a prefix of 'dataset_a' would result in html files named like: dataset_a_ENIGMA_WML_QC_Linear_01.html. If you are
running the enigma-pd-wml pipeline multiple times with different datasets, you must set this prefix to a different
value each time - otherwise, they may overwrite each other's QC progress.

> [!NOTE]
> If `-f`, `-s`, and `-l` are omitted, the pipeline will be run on all subjects and assume data is in BIDS format.
<!-- markdownlint-disable MD028/no-blanks-blockquote -->
Expand All @@ -191,6 +196,13 @@ data
├── enigma-pd-wml.log
├── derivatives
│ └── enigma-pd-wml
│ │
│ ├── QC
│ │ ├── PNGS/
│ │ ├── QC_guide_examples/
│ │ ├── dataset_1_ENIGMA_WML_QC_Linear_01.html
│ │ └── dataset_1_ENIGMA_WML_QC_Nonlinear_01.html
│ │
│ └── sub-1
│ ├── ses-1
│ │ ├── input/
Expand Down Expand Up @@ -266,16 +278,18 @@ and `derivatives/enigma-pd-wml/<subject>/<session>/output` folders.

Pipeline logs can be found at:

- `enigma-pd-wml.log`: contains minimal information about the initial pipeline setup.
- `enigma-pd-wml.log`: contains minimal information about the initial pipeline setup, as well as the QC html
generation step.

- `derivatives/enigma-pd-wml/<subject>/<session>/<subject>_<session>.log`: one log per session; contains information about
the various processing steps.

## Quality control

See notes on [quality control](docs/qc.md) for the WML pipeline.
The pipeline produces QC files under `derivatives/enigma-pd-wml/QC` that allow interactive browsing and assessment
of the output images.

New interactive QC feature soon to be added.
See the [quality control docs](docs/qc_usage.md) for more information on how to use this feature.

## Periventricular and deep WML clustering

Expand Down
4 changes: 2 additions & 2 deletions _typos.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[default.extend-words]
# Don't correct -thr option
thr = "thr"
center = "center"
maximization = "maximization"
# Don't correct PNGs
PN = "PN"
21 changes: 16 additions & 5 deletions docs/developer.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,19 @@ There are two main components to the Dockerfile:

All requirements for the UNets-pgs workflow come from the
[base pgs image](https://hub.docker.com/r/cvriend/pgs/tags), including the bash script and packages like tensorflow.

FSL is installed as detailed in their [installation docs](https://fsl.fmrib.ox.ac.uk/fsl/docs/#/install/container)
and [configuration docs](https://fsl.fmrib.ox.ac.uk/fsl/docs/#/install/configuration). We're using the `-V` option at
the end of the `fslinstaller` command to [fix it to a specific FSL version
](https://fsl.fmrib.ox.ac.uk/fsl/docs/#/install/index?id=installing-older-versions-of-fsl).
Note: this uses quite old versions of python (2.7) and other packages.

FSL is installed via conda, as [specified in the FSL docs](https://fsl.fmrib.ox.ac.uk/fsl/docs/install/conda.html). We
install Miniforge as our conda distribution, then install the specific `fsl` packages used by the enigma-pd-wml workflow
as listed in the `environment.yml` file. This file also contains some additional python dependencies required by the
`png_generator.py` script for the QC workflow.

By installing FSL in this way, we reduce the overall size of the docker image - as we only install the pieces of FSL we
need to use. Alternate installation methods (e.g.
[via fslinstaller.py](https://fsl.fmrib.ox.ac.uk/fsl/docs/install/container.html)) require installation of the entirety
of FSL, giving less flexibility.

If you want to find out which FSL conda package versions correspond to a particular FSL release, see the
[FSL release docs](https://fsl.fmrib.ox.ac.uk/fsl/docs/development/management/fsl_releases.html) and specifically their
[manifest repo](https://git.fmrib.ox.ac.uk/fsl/conda/manifest/). The manifest repo has tags for all main FSL releases,
with the `yml` files stating corresponding conda package versions.
Binary file removed docs/images/poorly-segmented.png
Binary file not shown.
Binary file added docs/images/qc_interface.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed docs/images/well-segmented.png
Binary file not shown.
89 changes: 55 additions & 34 deletions docs/non-bids-data.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,48 +11,49 @@ can still run the pipeline by following these steps:

You will need to create an CSV file that describes the directory structure of your data.

The CSV file must contain one row for each subject you want to analysis. It must contain the following columns:
The CSV file must contain one row for each subject you want to analyse. It must contain the following columns:

- `flair`: path to the FLAIR MRI image for a subject
- `t1`: path to the T1-weighted MRI image for a subject
- `output`: basename of output files for a subject. The filename must not have an extension.
- `subject`: the id of the subject these images belong to
- `session`: the id of the session these images belong to

For example, if you have the following directory structure:

```bash
data
├───subject-1
├───subject-1-session-1
│ ├───flair.nii.gz
│ └───t1.nii.gz
├───subject-2
├───subject-1-session-2
│ ├───flair.nii.gz
│ └───t1.nii.gz
├───subject-2-session-1
│ ├───flair.nii.gz
│ └───t1.nii.gz
```

you would create the following CSV file:

```csv
flair,t1,output
subject-1/flair.nii.gz,subject-1/t1.nii.gz,enigma-pd-wml/subject-1/subject-1
subject-2/flair.nii.gz,subject-2/t1.nii.gz,enigma-pd-wml/subject-2/subject-2
flair,t1,subject,session
subject-1-session-1/flair.nii.gz,subject-1-session-1/t1.nii.gz,1,1
subject-1-session-2/flair.nii.gz,subject-1-session-2/t1.nii.gz,1,2
subject-2-session-1/flair.nii.gz,subject-2-session-1/t1.nii.gz,2,1
```

> [!NOTE]
> All filename must be relative to the data directory from which you run the Docker or Apptainer image. For example,
> with the above directory structure you would run the Docker (or Apptainer) run command
> from the `data/` directory, and the paths in the CSV file must be relative to this
> directory.
<!-- markdownlint-disable MD028/no-blanks-blockquote -->
> [!WARNING]
> The output files must be stored in separate directories for each subject. For example, setting the above outputs files
> to instead be `enigma-pd-wml/subject-1` and `enigma-pd-wml/subject-2` would fail, because outputs for both subjects
> would be written to the `enigma-pd-wml` directory.

## Run the pipeline

To run the pipeline, follow the [instructions for running the container](../README.md#3-run-the-container), and pass to
`-l` flag to the run command, specifying the relative. For example, to run with Docker:
To run the pipeline, follow the [instructions for running the container](../README.md#3-run-the-container), and pass the
`-l` flag to the run command, specifying the relative path to your csv file. For example, to run with Docker:

```bash
docker run -v "${PWD}":/data hamiedaharoon24/enigma-pd-wml:<tag> -l input.csv
Expand All @@ -62,40 +63,60 @@ assuming you have saved the CSV file as `input.csv` in the `data/` directory.

## Output data

After running the pipeline, you would have the following directory structure:
The pipeline will create a `derivatives` directory inside `data/` containing the results.
Your entire directory structure will look like this:

```bash
data
├── input.csv
├── enigma-pd-wml.log
├── subject-1
├── subject-1-session-1
│ ├── flair.nii.gz
│ └── t1.nii.gz
├── subject-1-session-2
│ ├── flair.nii.gz
│ └── t1.nii.gz
├── subject-2
├── subject-2-session-1
│ ├── flair.nii.gz
│ └── t1.nii.gz
├── enigma-pd-wml
│ ├── subject-1
│ │ ├── subject-1.zip
│ │ ├── subject-1.log
│ │ ├── input/
│ │ └── output/
│ └── subject-2
│ ├── subject-2.zip
│ ├── subject-2.log
│ ├── input/
│ └── output/
├── derivatives
│ └── enigma-pd-wml
│ ├── QC
│ │ ├── PNGS/
│ │ ├── QC_guide_examples/
│ │ ├── dataset_1_ENIGMA_WML_QC_Linear_01.html
│ │ └── dataset_1_ENIGMA_WML_QC_Nonlinear_01.html
│ │
│ ├── sub-1
│ │ ├── ses-1
│ │ │ ├── input/
│ │ │ ├── output/
│ │ │ ├── sub-1_ses-1.log
│ │ │ └── sub-1_ses-1_results.zip
│ │ └── ses-2
│ │ ├── input/
│ │ ├── output/
│ │ ├── sub-1_ses-2.log
│ │ └── sub-1_ses-2_results.zip
│ └── sub-2
│ └──ses-1
│ ├── input/
│ ├── output/
│ ├── sub-2_ses-1.log
│ └── sub-2_ses-1_results.zip
```

The [session-level zip files](../README.md#session-level-zip-files) are stored in
`data/enigma-pd-wml/subject-1/subject-1/subject-1.zip` and `data/enigma-pd-wml/subject-1/subject-2/subject-2.zip`. These
are the files you will need to send to the ENIGMA-PD Vasc team.
`data/derivatives/enigma-pd-wml/sub-1/ses-1/sub-1_ses-1_results.zip`, and so on for the other subject / session ids.
These are the files you will need to send to the ENIGMA-PD Vasc team.

The [intermediate files](../README.md#intermediate-files) are stored in the
`data/enigma-pd-wml/subject-1/subject-1/input/` and `data/enigma-pd-wml/subject-1/subject-1/output/` directories for
`subject-1` (and the corresponding directories for `subject-2`).
`data/derivatives/enigma-pd-wml/sub-1/ses-1/input/` and `data/derivatives/enigma-pd-wml/sub-1/ses-1/output/` directories
for subject and session 1 (and the corresponding directories for other sessions and subjects).

The top-level [log file](../README.md#output-logs) is stored in `data/enigma-pd-wml.log`, and the are stored in
`data/enigma-pd-wml/subject-1/subject-1/subject-1.zip` and `data/enigma-pd-wml/subject-1/subject-2/subject-2.zip`.
The top-level [log file](../README.md#output-logs) is stored in `data/enigma-pd-wml.log`, and the session-level log
files are stored in `data/derivatives/enigma-pd-wml/sub-1/ses-1/sub-1_ses-1.log` (and corresponding files for each
subject / session combination).
8 changes: 4 additions & 4 deletions docs/pipeline.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ flowchart TD
unet --> process_output
```

After processing, the pipeline also generates some QC output. [See the QC docs](./qc_pipeline.md) for more information
on those steps.

## fsl_anat

First, FSL's `fsl_anat` tool is run on the input T1 image and its output saved to
Expand Down Expand Up @@ -92,7 +95,4 @@ This includes steps to:
The pipeline will generate multiple `.zip` files - one per session, stored within the corresponding session
sub-folder, e.g. `derivatives/enigma-pd-wml/sub-1/ses-1/sub-1_ses-1_results.zip`.

A top-level zip file will also be created (`derivatives/enigma-pd-wml/enigma-pd-wml-results.zip`). This will contain all
zip files for each session.

**Please send this top-level zip file to the ENIGMA-PD Vasc team.**
**Please send these zip files to the ENIGMA-PD Vasc team.**
28 changes: 0 additions & 28 deletions docs/qc.md

This file was deleted.

Loading