Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
77 changes: 44 additions & 33 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,39 +11,50 @@ jobs:
if: github.event.pull_request.merged == false
runs-on: ubuntu-latest
steps:
- name: Clone repo
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha || github.base_ref }}

- name: Setup Python environment
uses: khanlab/actions/.github/actions/action-setup_task-installPyProject@v0.3.6
uses: prefix-dev/setup-pixi@v0.8.14
with:
python-version: '3.10'
- name: yamlfix
run: poetry run poe yamlfix-check
- name: ruff
run: poetry run poe ruff-lint-check
environments: >-
dev-only
activate-environment: dev-only

- name: isort
run: isort scattr/* -c

- name: Black
run: black scattr --check

- name: snakefmt
run: poetry run poe snakefmt-check
test:
runs-on: ubuntu-latest
needs: [quality]
strategy:
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11']
steps:
- name: Setup Python environments
uses: khanlab/actions/.github/actions/[email protected]
with:
python-version: ${{ matrix.python-version }}
install-library: true
- name: Test minimum inputs
run: poetry run poe test_base
- name: Test freesurfer input
run: poetry run poe test_freesurfer
- name: Test responsemean input
run: poetry run poe test_responsemean
- name: Test dwi input
run: poetry run poe test_dwi
- name: Test custom labelmerge inputs
run: poetry run poe test_labelmerge
- name: Test using single atlas (skipping labelmerge)
run: poetry run poe test_skip_labelmerge
- name: Test sessions
run: poetry run poe test_sessions
run: snakefmt scattr --check

# test:
# runs-on: ubuntu-latest
# needs: [quality]
# strategy:
# matrix:
# python-version: ['3.11', '3.12', '3.13']
# steps:
# - name: Setup Python environments
# uses: khanlab/actions/.github/actions/[email protected]
# with:
# python-version: ${{ matrix.python-version }}
# install-library: true
# - name: Test minimum inputs
# run: poetry run poe test_base
# - name: Test freesurfer input
# run: poetry run poe test_freesurfer
# - name: Test responsemean input
# run: poetry run poe test_responsemean
# - name: Test dwi input
# run: poetry run poe test_dwi
# - name: Test custom labelmerge inputs
# run: poetry run poe test_labelmerge
# - name: Test using single atlas (skipping labelmerge)
# run: poetry run poe test_skip_labelmerge
# - name: Test sessions
# run: poetry run poe test_sessions
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@ __pycache__/

# Ruff
.ruff_cache

.pixi
2 changes: 1 addition & 1 deletion .readthedocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ formats: [pdf]
build:
os: ubuntu-20.04
tools:
python: '3.10'
python: '3.11'
python:
install:
- requirements: docs/requirements.txt
Expand Down
12 changes: 7 additions & 5 deletions docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
docutils<0.18
sphinx-argparse<0.5.0
sphinx_rtd_theme
sphinxcontrib-asciinema
myst-parser
docutils==0.17
sphinx-argparse==0.4.0
sphinx_rtd_theme>=1.0.0
snakebids>=0.4.0
myst-parser==1.0.0
sphinxcontrib.asciinema==0.3.7
pulp<2.8.0
8,560 changes: 8,560 additions & 0 deletions pixi.lock

Large diffs are not rendered by default.

3,857 changes: 0 additions & 3,857 deletions poetry.lock

This file was deleted.

182 changes: 50 additions & 132 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,145 +1,63 @@
[tool.poetry]
[project]
name = "scattr"
version = "0.3.4-pre.1"
description = "[Snakebids app] Structural connectivity between targeted regions"
authors = [
"Jason Kai <[email protected]>",
"Tristan Kuehn",
"Ali R. Khan",
"Roy A.M. Haast",
"Jonathan C. Lau",
]
readme = "README.md"
documentation = "https://scattr.readthedocs.io"
packages = [{ include = "scattr" }]

[tool.poetry.dependencies]
python = ">=3.8, <3.12"
snakebids = "^0.10.2"
labelmerge = "^0.4.7"
matplotlib = "^3.7.1"
nibabel = "^3.2.2"
nilearn = "^0.10.0"
niworkflows = "^1.7.9"
numpy = "^1.22.3"
pygments = "^2.15.1"
scipy = "^1.8.0"
# Required constraint for compatability with snakebids
pulp = "<2.8.0"

[tool.poetry.group.dev.dependencies]
pytest-console-scripts = "1.2"
pytest = "^7.0.1"
poethepoet = "^0.13.1"
pre-commit = "^2.17.0"
snakefmt = "^0.6.1"
yamlfix = "^1.1.0"
ruff = "^0.1.14"

[tool.poetry.scripts]
scattr = 'scattr.run:main'

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

[tool.poe.tasks]
license = "MIT"
authors = [{name = "Jason Kai, Tristan Kuehn, Roy A.M. Haast & Jonathan C. Lau", email = "[email protected]"}]
requires-python = ">= 3.11"
dependencies = []
scripts = { scattr = "scattr.run:app.run" }

[package.build.backend]
name = "pixi-build-python"
version = "==0.4.0"

[tool.pixi.workspace]
channels = ["conda-forge", "bioconda"]
platforms = ["linux-64"]

[tool.pixi.feature.runtime.dependencies]
snakebids = ">=0.14.0,<0.15"
appdirs = ">=1.4.4,<2.0.0"
pyvista = ">=0.44.2,<0.45.0"
conda = ">=25.5.0,<26"

[tool.pixi.feature.dev.dependencies]
flake8 = ">=4.0.1,<5.0.0"
pytest-console-scripts = ">=1.2.1,<2.0.0"
pytest = "*"
black = ">=24.0.0,<25.0.0"
pylint = ">=2.11.1,<3.0.0"
isort = ">=5.10.1,<6.0.0"
poethepoet = ">=0.10.0,<0.11.0"
snakefmt = ">=0.10.0,<0.11.0"
pygraphviz = "*"
Jinja2 = ">=3.0.3,<4.0.0"

[tool.pixi.environments.default]
features = ["runtime"]

[tool.pixi.environments.dev]
features = ["runtime", "dev"]

[tool.pixi.environments.dev-only]
features = ["dev"]

[tool.isort]
profile = "black"
multi_line_output = 3

[tool.pixi.pypi-dependencies]
scattr = { path = ".", editable = true }

[tool.pixi.tasks]
setup = "pre-commit install"
ruff-lint = "ruff check --fix scattr"
ruff-lint-check = "ruff check scattr"
ruff-format = "ruff format ."
snakefmt = "snakefmt scattr"
snakefmt-check = "snakefmt --check scattr"
quality = ["yamlfix", "ruff-lint", "ruff-format", "snakefmt"]
quality-check = ["yamlfix-check", "ruff-lint-check", "snakefmt-check"]
test = [
"test_base",
"test_freesurfer",
"test_responsemean",
"test_dwi",
"test_labelmerge",
"test_skip_labelmerge",
"test_sessions",
]

[tool.poe.tasks.test_base]
shell = """
python ./scattr/run.py ./test/data/bids ./test/data/derivatives/ participant \
--fs-license ./test/.fs_license -np --force-output
"""

[tool.poe.tasks.test_freesurfer]
shell = """
python ./scattr/run.py ./test/data/bids test/data/derivatives/ participant \
--freesurfer_dir ./test/data/derivatives/freesurfer \
--fs-license ./test/.fs_license -np --force-output
"""

[tool.poe.tasks.test_responsemean]
shell = """
python ./scattr/run.py ./test/data/bids test/data/derivatives/ participant \
--responsemean_dir ./test/data/derivatives/mrtrix/avg \
--fs-license ./test/.fs_license -np --force-output
"""

[tool.poe.tasks.test_dwi]
shell = """
python ./scattr/run.py ./test/data/bids_nodwi test/data/derivatives/ \
participant --path-dwi \
./test/data/derivatives/prepdwi/sub-{subject}/dwi/sub-{subject}_space-T1w_desc-preproc_dwi.nii.gz \
--path-mask \
./test/data/derivatives/prepdwi/sub-{subject}/dwi/sub-{subject}_space-T1w_desc-preproc_mask.nii.gz \
--fs-license ./test/.fs_license -np --force-output
"""

[tool.poe.tasks.test_snakedwi]
shell = """
python ./scattr/run.py ./test/data/bids_nodwi test/data/derivatives/ \
participant --path-dwi \
./test/data/derivatives/snakedwi/sub-{subject}/dwi/sub-{subject}_space-T1w_desc-eddy_res-orig_dwi.nii.gz \
--path-dwi-mask \
./test/data/derivatives/snakedwi/sub-{subject}/dwi/sub-{subject}_space-T1w_desc-eddy_res-orig_mask.nii.gz \
--fs-license ./test/.fs_license -np --force-output
"""

[tool.poe.tasks.test_labelmerge]
shell = """
python ./scattr/run.py ./test/data/bids test/data/derivatives/ participant \
--labelmerge_base_dir ./base_dir \
--labelmerge_overlay_dir ./overlay_dir \
--skip_brainstem --skip_thal_seg \
--fs-license ./test/.fs_license -np --force-output
"""

[tool.poe.tasks.test_skip_labelmerge]
shell = """
python ./scattr/run.py ./test/data/bids test/data/derivatives/ participant \
--skip_labelmerge --skip_brainstem --skip_thal_seg \
--fs-license ./test/.fs_license -np --force-output
"""

[tool.poe.tasks.test_sessions]
shell = """
python ./scattr/run.py ./test/data/bids_sessions \
test/data/derivatives_sessions/ participant \
--fs-license ./test.fs_license -np --force-output
"""

[tool.poe.tasks.yamlfix]
shell = """
find . -type f \\( \
-iname \\*.yaml -o -iname \\*.yml ! -iname snakemake* \
! -iname snakebids* \
\\) -exec yamlfix {} \\;
"""

[tool.poe.tasks.yamlfix-check]
shell = """
find . -type f \\( \
-iname \\*.yaml -o -iname \\*.yml ! -iname snakemake* \
! -iname snakebids* \
\\) -exec yamlfix --check {} \\;
"""

[tool.ruff]
select = ["E", "W", "N", "RUF", "I", "UP"]
Expand Down
71 changes: 71 additions & 0 deletions scattr.egg-info/PKG-INFO
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
Metadata-Version: 2.4
Name: scattr
Version: 0.3.4rc1
Summary: [Snakebids app] Structural connectivity between targeted regions
Author-email: "Jason Kai, Tristan Kuehn, Roy A.M. Haast & Jonathan C. Lau" <[email protected]>
License-Expression: MIT
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# Structural Connectivity Applied To Targeted Regions (SCATTR)
[![Documentation Status](https://readthedocs.org/projects/scattr/badge/?version=stable)](https://scattr.readthedocs.io/en/stable/?badge=stable)
![Version](https://img.shields.io/github/v/tag/khanlab/scattr?label=version)
![Python3](https://img.shields.io/badge/python-3.8_|_3.9_|_3.10_|_3.11-blue.svg)
[![Tests](https://github.com/khanlab/scattr/actions/workflows/test.yml/badge.svg?branch=main)](https://github.com/khanlab/scattr/actions/workflows/test.yml?query=branch%3Amain)
![Docker Pulls](https://img.shields.io/docker/pulls/khanlab/scattr)
[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.7636506.svg)](https://doi.org/10.5281/zenodo.7636506)

SCATTR is a BIDS App that performs a tractography processing workflow to
identify connections between targetted structures of interest (extracted from
various atlases) in the brain, using some common neuroimaging tools like
`prepdwi`, `Freesurfer`, and `Mrtrix3`.

![Example outputs](https://raw.githubusercontent.com/khanlab/scattr/main/docs/images/ex_output.png)

This is useful for:

* Analyzing structural connections of known brain circuits
* Examining specific connections of interest
* Comparison across different groups (e.g. controls vs patients)


## Example use of workflow
This workflow was used to process and analyze the data from
[`hcp_subcortical_repo`](https://github.com/kaitj/hcp_subcortical_repro)
(see Kai et al., 2022).

## Workflow
A brief summary of the workflow can be found below (see documentation for
a detailed summary):

_Note: The workflow assumes Freesurfer has already been run on the dataset, as
well as diffusion preprocessing (e.g. distortion correction)._

![Workflow example](https://raw.githubusercontent.com/khanlab/scattr/main/docs/images/workflow.png)

1. Merge the segmentations of structures in a standard template space from
various sources (if necessary) via
[labelmerge](https://zenodo.org/record/7636410) into a combined atlas, which is
used downstream to identify targeted connections.
1. Estimate and apply transformations from standard template space to
subject-specific space.
1. Further process the pre-processed diffusion data to enable tractography
(e.g. compute response functions, fibre orientation distribution,
normalization).
1. Perform whole-brain tractography from computed files, applying filtering
(e.g. SIFT2) to computed tractogram. Once filtered, connections between the
merged segmentations (from step 1) are identified, generating a connectome map.
1. Analysis can then be performed on the map to examine and explore the
connectome of interest.

### **Full documentation:** [here](https://scattr.readthedocs.io/en/stable/)

## Relevant Papers

* Kai, J., Khan, A.R., Haast, R.A.M., Lau, J.C. (2022).
Mapping the subcortical connectome using in vivo diffusion MRI: feasibility
and reliability. Terra incognita: diving into the human subcortex,
special issue of NeuroImage. doi:
[10.1016/j.neuroimage.2022.119553](https://doi.org/10.1016/j.neuroimage.2022.119553).
Loading