Skip to content

Commit a208eb6

Browse files
committed
updated documentation on when to use template anats
1 parent 3a0bf86 commit a208eb6

File tree

4 files changed

+137
-43
lines changed

4 files changed

+137
-43
lines changed

README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ options:
7171
Select only a specific session(s) to include in the defacing workflow
7272
--session_label_exclude session_label_exclude [session_label_exclude ...]
7373
Select a specific session(s) to exclude from the defacing workflow
74+
--use_template_anat Use template anatomical image when no T1w is available for PET scans.
75+
Options: 't1' (included T1w template), 'mni' (MNI template), or 'pet'
76+
(averaged PET image).
7477
--open_browser Open browser to show QA reports after completion
7578
```
7679
@@ -80,6 +83,26 @@ Working example usage:
8083
petdeface /inputfolder /outputfolder --n_procs 16 --skip_bids_validator --placement adjacent
8184
```
8285
86+
### Template Anatomical Images
87+
88+
When PET scans lack corresponding T1w anatomical images, PETdeface can use template anatomical images for registration and defacing. Three options are available:
89+
90+
- **`--use_template_anat t1`**: Uses a T1w template included with the PETdeface library
91+
- **`--use_template_anat mni`**: Uses the MNI standard brain template
92+
- **`--use_template_anat pet`**: Creates a template by averaging the PET data across time
93+
94+
**Important**: When using template anatomical images, it's crucial to validate the defacing quality. Inspect the output using the generated HTML report (with `--open_browser`) or a NIfTI viewer to ensure the defacing is valid for your data.
95+
96+
**Recommended workflow for subjects missing T1w images**:
97+
1. First, exclude subjects missing T1w using `--participant_label_exclude`
98+
2. Run defacing on subjects with T1w images
99+
3. Then run defacing separately on subjects missing T1w using `--participant_label` and test different templates (`t1`, `mni`, `pet`) to determine which works best for your data
100+
101+
Example usage with template anatomical:
102+
```bash
103+
petdeface /inputfolder /outputfolder --use_template_anat t1 --n_procs 16
104+
```
105+
83106
### Docker Usage
84107

85108
Requirements:

docs/usage.rst

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,9 @@ options:
123123
Select only a specific session(s) to include in the defacing workflow
124124
--session_label_exclude session_label_exclude [session_label_exclude ...]
125125
Select a specific session(s) to exclude from the defacing workflow
126+
--use_template_anat Use template anatomical image when no T1w is available for PET scans.
127+
Options: 't1' (included T1w template), 'mni' (MNI template), or 'pet'
128+
(averaged PET image).
126129
--open_browser Following defacing this flag will open the browser to view the defacing results
127130

128131
Docker Based
@@ -175,4 +178,31 @@ PETdeface will do it's best to locate a valid FreeSurfer license file on the hos
175178
to the container by checking `FREESURFER_HOME` and `FREESURFER_LICENSE` environment variables. If you
176179
receive an error message relating to the FreeSurfer license file, try setting and exporting the
177180
`FREESURFER_LICENSE` environment variable to the location of the FreeSurfer license file on the host
178-
machine.
181+
machine.
182+
183+
Template Anatomical Images
184+
-------------------------
185+
186+
When PET scans lack corresponding T1w anatomical images, PETdeface can use template anatomical images for
187+
registration and defacing. Three options are available:
188+
189+
- **`--use_template_anat t1`**: Uses a T1w template included with the PETdeface library
190+
- **`--use_template_anat mni`**: Uses the MNI standard brain template
191+
- **`--use_template_anat pet`**: Creates a template by averaging the PET data across time
192+
193+
**Important**: When using template anatomical images, it's crucial to validate the defacing quality.
194+
Inspect the output using the generated HTML report (with `--open_browser`) or a NIfTI viewer to ensure
195+
the defacing is valid for your data.
196+
197+
**Recommended workflow for subjects missing T1w images**:
198+
199+
1. First, exclude subjects missing T1w using `--participant_label_exclude`
200+
2. Run defacing on subjects with T1w images
201+
3. Then run defacing separately on subjects missing T1w using `--participant_label` and test
202+
different templates (`t1`, `mni`, `pet`) to determine which works best for your data
203+
204+
Example usage with template anatomical:
205+
206+
.. code-block:: bash
207+
208+
petdeface /inputfolder /outputfolder --use_template_anat t1 --n_procs 16

petdeface/petdeface.py

Lines changed: 83 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
sys.path.insert(0, str(current_dir))
3838

3939
# Import using absolute imports (script mode)
40-
from mideface import ApplyMideface, Mideface
40+
from mideface import ApplyMideface, Mideface, TemplateFacemask
4141
from pet import WeightedAverage
4242
from qa import run_qa
4343
from utils import run_validator
@@ -436,39 +436,84 @@ def init_single_subject_wf(
436436
if determine_in_docker():
437437
preview_pics = False
438438

439-
deface_t1w = Node(
440-
Mideface(
441-
in_file=pathlib.Path(t1w_file),
442-
pics=preview_pics,
443-
odir=".",
444-
code=f"{anat_string}",
445-
),
446-
name=f"deface_t1w_{anat_string}",
439+
# Check if this is a template anatomical image created from PET averaging
440+
is_template_from_pet = use_template_anat == "pet" and "desc-totallyat1w" in str(
441+
t1w_file
447442
)
448-
t1w_wf.connect(
449-
[
450-
(
451-
deface_t1w,
452-
datasink,
453-
[
454-
("out_file", f"{anat_string.replace('_', '.')}.anat"),
455-
(
456-
"out_facemask",
457-
f"{anat_string.replace('_', '.')}.anat.@defacemask",
458-
),
459-
(
460-
"out_before_pic",
461-
f"{anat_string.replace('_', '.')}.anat.@before",
462-
),
463-
(
464-
"out_after_pic",
465-
f"{anat_string.replace('_', '.')}.anat.@after",
466-
),
467-
],
443+
444+
if is_template_from_pet:
445+
# For PET-averaged templates, we need to create a facemask without defacing the template
446+
# We'll use TemplateFacemask to generate the facemask without defacing the template
447+
from mideface import TemplateFacemask
448+
449+
# Create a node that generates facemask but doesn't deface the template
450+
template_facemask = Node(
451+
TemplateFacemask(
452+
in_file=pathlib.Path(t1w_file),
453+
no_pics=True, # No preview pics for templates
454+
no_post=True, # No post-processing for templates
455+
odir=".",
456+
code=f"{anat_string}_template",
468457
),
469-
]
470-
)
471-
t1w_workflows[t1w_file] = {"workflow": t1w_wf, "anat_string": anat_string}
458+
name=f"deface_t1w_{anat_string}",
459+
)
460+
461+
# Only connect the facemask output, not the defaced template
462+
# This way we get the facemask for PET defacing but don't deface the template itself
463+
t1w_wf.connect(
464+
[
465+
(
466+
template_facemask,
467+
datasink,
468+
[
469+
(
470+
"out_facemask",
471+
f"{anat_string.replace('_', '.')}.anat.@defacemask",
472+
),
473+
],
474+
),
475+
]
476+
)
477+
else:
478+
# Normal defacing for real anatomical images
479+
deface_t1w = Node(
480+
Mideface(
481+
in_file=pathlib.Path(t1w_file),
482+
pics=preview_pics,
483+
odir=".",
484+
code=f"{anat_string}",
485+
),
486+
name=f"deface_t1w_{anat_string}",
487+
)
488+
t1w_wf.connect(
489+
[
490+
(
491+
deface_t1w,
492+
datasink,
493+
[
494+
("out_file", f"{anat_string.replace('_', '.')}.anat"),
495+
(
496+
"out_facemask",
497+
f"{anat_string.replace('_', '.')}.anat.@defacemask",
498+
),
499+
(
500+
"out_before_pic",
501+
f"{anat_string.replace('_', '.')}.anat.@before",
502+
),
503+
(
504+
"out_after_pic",
505+
f"{anat_string.replace('_', '.')}.anat.@after",
506+
),
507+
],
508+
),
509+
]
510+
)
511+
512+
t1w_workflows[t1w_file] = {
513+
"workflow": t1w_wf,
514+
"anat_string": anat_string,
515+
"is_template_from_pet": is_template_from_pet,
516+
}
472517

473518
workflow = Workflow(name=name)
474519
if anat_only:
@@ -1111,7 +1156,7 @@ def cli():
11111156
)
11121157
parser.add_argument(
11131158
"--use_template_anat",
1114-
help="Use template anatomical image when no T1w is available for PET scans. Options: 't1', 'mni', or 'pet'",
1159+
help="Use template anatomical image when no T1w is available for PET scans. Options: 't1' (included T1w template), 'mni' (MNI template), or 'pet' (averaged PET image).",
11151160
type=str,
11161161
required=False,
11171162
default=False,
@@ -1354,29 +1399,29 @@ def main(): # noqa: max-complexity: 12
13541399

13551400
def collect_subject_files(file_list: list) -> dict:
13561401
"""Collect files that share the same subject ID into a dictionary.
1357-
1402+
13581403
Parameters
13591404
----------
13601405
file_list : list
13611406
List of file paths to process
1362-
1407+
13631408
Returns
13641409
-------
13651410
dict
13661411
Dictionary mapping subject IDs to lists of their files
13671412
Format: {"sub-*": ["file1", "file2", ...]}
13681413
"""
13691414
subject_files = {}
1370-
1415+
13711416
for file_path in file_list:
13721417
# Extract subject ID using regex - matches 'sub-' followed by alphanumeric chars until underscore
1373-
match = re.search(r'sub-[a-zA-Z0-9]+(?=_)', str(file_path))
1418+
match = re.search(r"sub-[a-zA-Z0-9]+(?=_)", str(file_path))
13741419
if match:
13751420
sub_id = match.group(0)
13761421
if sub_id not in subject_files:
13771422
subject_files[sub_id] = []
13781423
subject_files[sub_id].append(str(file_path))
1379-
1424+
13801425
return subject_files
13811426

13821427

pyproject.toml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,23 +23,19 @@ python = ">=3.10, <4.0"
2323
setuptools = "^68.1.2"
2424
petutils = "^0.0.1"
2525
niworkflows = "^1.11.0"
26-
<<<<<<< HEAD
2726
matplotlib = "^3.10.1"
28-
=======
2927
niftifixer = {git = "https://github.com/openneuropet/nifti_fixer.git"}
3028
bids-validator-deno = "^2.0.5"
3129
nipreps = "^1.0"
3230
nireports = "^25.2.0"
3331
nibabel = "^5.3.2"
3432
nilearn = "^0.10.4"
35-
matplotlib = "^3.9.2"
3633
numpy = "^2.1.3"
3734
scipy = "^1.14.1"
3835
seaborn = "^0.13.2"
3936
pillow = "^11.0.0"
4037
imageio = "^2.36.0"
4138

42-
>>>>>>> 3d1900349781365c748e8581f6dc6b975a675da9
4339

4440
[tool.poetry.group.dev.dependencies]
4541
black = "^23.7.0"

0 commit comments

Comments
 (0)