Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
a65c12c
ENH: Add session-label option for analyses
mnoergaard Nov 17, 2025
923f6e5
FIX: update parser to only include PET
mnoergaard Nov 17, 2025
bfb2a1b
FIX: add test for session-label option
mnoergaard Nov 17, 2025
f447fd2
FIX: style
mnoergaard Nov 17, 2025
db25bbd
FIX: style
mnoergaard Nov 17, 2025
cf628f4
ENH: Add dynamic visualization for motion correction
mnoergaard Nov 17, 2025
e03d224
FIX: update to SVG output
mnoergaard Nov 17, 2025
e00cd10
FIX: update display time and looping
mnoergaard Nov 17, 2025
fb0b6cf
FIX: update duration for motion display
mnoergaard Nov 17, 2025
7d67e88
FIX: update duration to 0.25 s
mnoergaard Nov 17, 2025
250aacc
FIX: set duration to 0.2 seconds
mnoergaard Nov 17, 2025
8bde720
FIX: update display of frames
mnoergaard Nov 17, 2025
a8dcf4d
FIX: add click to restart animation
mnoergaard Nov 17, 2025
eb3a99a
FIX: update description
mnoergaard Nov 17, 2025
afaa474
FIX: modify playback
mnoergaard Nov 17, 2025
788c8ba
FIX: update description
mnoergaard Nov 17, 2025
5c8b871
FIX: style
mnoergaard Nov 17, 2025
06c6391
FIX: ruff
mnoergaard Nov 17, 2025
7070913
FIX: style
mnoergaard Nov 17, 2025
0dc9fc1
FIX: style
mnoergaard Nov 17, 2025
b934b44
FIX: Fix motion report for 3D data
mnoergaard Nov 17, 2025
86b5a97
FIX: style
mnoergaard Nov 17, 2025
f7837b0
ENH: add test for motion visualization
mnoergaard Nov 18, 2025
8ce30e9
FIX: style
mnoergaard Nov 18, 2025
de430d1
Add framewise displacement trace to motion report
mnoergaard Nov 18, 2025
994d408
FIX: style
mnoergaard Nov 18, 2025
f59cef7
FIX: style
mnoergaard Nov 18, 2025
cf87e03
FIX: update figure
mnoergaard Nov 18, 2025
5154716
Merge pull request #173 from nipreps/add-framewise-displacement-graph…
mnoergaard Nov 18, 2025
a584df3
FIX: syntax error
mnoergaard Nov 18, 2025
ec35969
FIX: style
mnoergaard Nov 18, 2025
4f7ce64
FIX: style
mnoergaard Nov 18, 2025
4af9edd
FIX: update tests to improve coverage
mnoergaard Nov 18, 2025
0e7c7b6
FIX: update test
mnoergaard Nov 18, 2025
d5aec99
ENH: add labels to y-axis FD lineplot
mnoergaard Nov 18, 2025
b42c733
FIX: update FD lineplot
mnoergaard Nov 18, 2025
52b8aa3
FIX: style
mnoergaard Nov 18, 2025
9fff5ba
FIX: change y-label position
mnoergaard Nov 18, 2025
b76cd74
Merge pull request #168 from nipreps/add_session_label
mnoergaard Nov 19, 2025
6a9c4f4
Merge branch 'main' into add_hmc_visual
mnoergaard Nov 19, 2025
4d69f65
ENH: Add x-axis tick labels to FD plot
mnoergaard Nov 19, 2025
d69d8f5
FIX: update x-tick labels on FD plot
mnoergaard Nov 19, 2025
217772b
FIX: update figure description
mnoergaard Nov 19, 2025
f895f87
Merge pull request #171 from nipreps/add_hmc_visual
mnoergaard Nov 19, 2025
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
27 changes: 25 additions & 2 deletions petprep/cli/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,13 @@ def _bids_filter(value, parser):
'identifier (the sub- prefix can be removed)',
)
# Re-enable when option is actually implemented
# g_bids.add_argument('-s', '--session-id', action='store', default='single_session',
# help='Select a specific session to be processed')
g_bids.add_argument(
'--session-label',
nargs='+',
type=lambda label: label.removeprefix('ses-'),
help='A space delimited list of session identifiers or a single '
'identifier (the ses- prefix can be removed)',
)
# Re-enable when option is actually implemented
# g_bids.add_argument('-r', '--run-id', action='store', default='single_run',
# help='Select a specific run to be processed')
Expand Down Expand Up @@ -749,6 +754,13 @@ def parse_args(args=None, namespace=None):
config.execution.log_level = int(max(25 - 5 * opts.verbose_count, logging.DEBUG))
config.from_dict(vars(opts), init=['nipype'])

if config.execution.session_label:
config.execution.bids_filters = config.execution.bids_filters or {}
config.execution.bids_filters['pet'] = {
**config.execution.bids_filters.get('pet', {}),
'session': config.execution.session_label,
}

pvc_vals = (opts.pvc_tool, opts.pvc_method, opts.pvc_psf)
if any(val is not None for val in pvc_vals) and not all(val is not None for val in pvc_vals):
parser.error('Options --pvc-tool, --pvc-method and --pvc-psf must be used together.')
Expand Down Expand Up @@ -908,5 +920,16 @@ def parse_args(args=None, namespace=None):
f'One or more participant labels were not found in the BIDS directory: {", ".join(missing_subjects)}.'
)

if config.execution.session_label:
available_sessions = set(
config.execution.layout.get_sessions(subject=list(participant_label) or None)
)
missing_sessions = set(config.execution.session_label) - available_sessions
if missing_sessions:
parser.error(
'One or more session labels were not found in the BIDS directory: '
f'{", ".join(sorted(missing_sessions))}.'
)

config.execution.participant_label = sorted(participant_label)
config.workflow.skull_strip_template = config.workflow.skull_strip_template[0]
41 changes: 41 additions & 0 deletions petprep/cli/tests/test_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@

from argparse import ArgumentError

import nibabel as nb
import numpy as np
import pytest
from packaging.version import Version

Expand Down Expand Up @@ -225,6 +227,45 @@ def test_derivatives(tmp_path):
_reset_config()


def test_session_label_only_filters_pet(tmp_path):
bids = tmp_path / 'bids'
out_dir = tmp_path / 'out'
work_dir = tmp_path / 'work'
bids.mkdir()
(bids / 'dataset_description.json').write_text('{"Name": "Test", "BIDSVersion": "1.8.0"}')

anat_path = bids / 'sub-01' / 'anat' / 'sub-01_T1w.nii.gz'
anat_path.parent.mkdir(parents=True, exist_ok=True)
nb.Nifti1Image(np.zeros((5, 5, 5)), np.eye(4)).to_filename(anat_path)

pet_path = bids / 'sub-01' / 'ses-blocked' / 'pet' / 'sub-01_ses-blocked_pet.nii.gz'
pet_path.parent.mkdir(parents=True, exist_ok=True)
nb.Nifti1Image(np.zeros((5, 5, 5, 1)), np.eye(4)).to_filename(pet_path)
(pet_path.with_suffix('').with_suffix('.json')).write_text(
'{"FrameTimesStart": [0], "FrameDuration": [1]}'
)

try:
parse_args(
args=[
str(bids),
str(out_dir),
'participant',
'--session-label',
'blocked',
'--skip-bids-validation',
'-w',
str(work_dir),
]
)

filters = config.execution.bids_filters
assert filters.get('pet', {}).get('session') == ['blocked']
assert 'session' not in filters.get('anat', {})
finally:
_reset_config()


def test_pvc_argument_handling(tmp_path, minimal_bids):
out_dir = tmp_path / 'out'
work_dir = tmp_path / 'work'
Expand Down
2 changes: 2 additions & 0 deletions petprep/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,8 @@ class execution(_Config):
"""Unique identifier of this particular run."""
participant_label = None
"""List of participant identifiers that are to be preprocessed."""
session_label = None
"""List of session identifiers that are to be preprocessed."""
task_id = None
"""Select a particular task from all available in the dataset."""
templateflow_home = _templateflow_home
Expand Down
1 change: 1 addition & 0 deletions petprep/data/reports-spec-pet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ sections:
reportlets:
- bids: {datatype: figures, desc: summary, suffix: pet}
- bids: {datatype: figures, desc: validation, suffix: pet}
- bids: {datatype: figures, desc: hmc, suffix: pet}
- bids: {datatype: figures, desc: carpetplot, suffix: pet}
- bids: {datatype: figures, desc: confoundcorr, suffix: pet}
- bids: {datatype: figures, desc: coreg, suffix: pet}
Expand Down
5 changes: 5 additions & 0 deletions petprep/data/reports-spec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,11 @@ sections:
static: false
subtitle: PET Summary and Carpet Plot

- bids: {datatype: figures, desc: hmc, suffix: pet}
caption: Animated frames before and after PET head motion correction with synchronized framewise displacement trace (keep cursor over image to restart). Below is a lineplot of the Framewise Displacement (FD) in mm per frame. Red line segments between points indicate frames where FD exceeds 3 mm, suggesting motion that may impact data quality.
static: false
subtitle: Motion correction

- bids: {datatype: figures, desc: confoundcorr, suffix: pet}
caption: |
Left: Correlation heatmap illustrating relationships among PET-derived confound variables (e.g., motion parameters, global signal).
Expand Down
2 changes: 2 additions & 0 deletions petprep/interfaces/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from niworkflows.interfaces.bids import DerivativesDataSink as _DDSink

from .cifti import GeneratePetCifti
from .motion import MotionPlot
from .tacs import ExtractRefTAC, ExtractTACs


Expand All @@ -15,4 +16,5 @@ class DerivativesDataSink(_DDSink):
'GeneratePetCifti',
'ExtractTACs',
'ExtractRefTAC',
'MotionPlot',
)
Loading