Skip to content

Commit 75e29f1

Browse files
committed
enabled anat only, cleaned up comments
1 parent 22f3daf commit 75e29f1

File tree

2 files changed

+105
-91
lines changed

2 files changed

+105
-91
lines changed

petdeface/petdeface.py

Lines changed: 104 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@
5252
for place in places_to_look:
5353
for root, folders, files in os.walk(place):
5454
for file in files:
55-
if file.endswith("pyproject.toml") and "petdeface" in os.path.join(root, file):
55+
if file.endswith("pyproject.toml") and "petdeface" in os.path.join(
56+
root, file
57+
):
5658
toml_file = os.path.join(root, file)
5759

5860
with open(toml_file, "r") as f:
@@ -71,12 +73,12 @@
7173
# we check the version with a regex expression to see if all of the parts are there
7274
if re.match(r"\d+\.\d+\.\d+", __version__):
7375
break
74-
76+
7577
if __version__ != "unable to locate version number in pyproject.toml":
76-
# we try to load the version using import lib
77-
__version__ = importlib.metadata.version("petdeface")
78-
if re.match(r"\d+\.\d+\.\d+", __version__):
79-
break
78+
# we try to load the version using import lib
79+
__version__ = importlib.metadata.version("petdeface")
80+
if re.match(r"\d+\.\d+\.\d+", __version__):
81+
break
8082

8183

8284
def locate_freesurfer_license():
@@ -101,7 +103,7 @@ def locate_freesurfer_license():
101103
else:
102104
return fs_license_env_var
103105
else:
104-
# collect freesurfer home environment variable and look there instead
106+
# collect freesurfer home environment variable and look there instead
105107
fs_home = pathlib.Path(os.environ.get("FREESURFER_HOME", ""))
106108
if not fs_home:
107109
raise ValueError(
@@ -271,7 +273,10 @@ def deface(args: Union[dict, argparse.Namespace]) -> None:
271273
for subject_id in subjects:
272274
try:
273275
single_subject_wf = init_single_subject_wf(
274-
subject_id, args.bids_dir, preview_pics=args.preview_pics
276+
subject_id,
277+
args.bids_dir,
278+
preview_pics=args.preview_pics,
279+
anat_only=args.anat_only,
275280
)
276281
except FileNotFoundError:
277282
single_subject_wf = None
@@ -294,9 +299,10 @@ def deface(args: Union[dict, argparse.Namespace]) -> None:
294299

295300
def init_single_subject_wf(
296301
subject_id: str,
297-
bids_data: [pathlib.Path, BIDSLayout],
302+
bids_data: Union[pathlib.Path, BIDSLayout],
298303
output_dir: pathlib.Path = None,
299304
preview_pics=False,
305+
anat_only=False,
300306
) -> Workflow:
301307
"""
302308
Organize the preprocessing pipeline for a single subject.
@@ -307,6 +313,10 @@ def init_single_subject_wf(
307313
:type bids_data: pathlib.Path, BIDSLayout]
308314
:param output_dir: _description_, defaults to None
309315
:type output_dir: pathlib.Path, optional
316+
:param preview_pics: _description_, defaults to False
317+
:type preview_pics: bool, optional
318+
:param anat_only: _description_, defaults to False
319+
:type anat_only: bool, optional
310320
:raises FileNotFoundError: _description_
311321
:return: _description_
312322
:rtype: Workflow
@@ -404,71 +414,80 @@ def init_single_subject_wf(
404414
t1w_workflows[t1w_file] = {"workflow": t1w_wf, "anat_string": anat_string}
405415

406416
workflow = Workflow(name=name)
407-
for pet_file, t1w_file in subject_data.items():
408-
try:
409-
ses_id = re.search("ses-[^_|\/]*", str(pet_file)).group(0)
410-
pet_string = f"sub-{subject_id}_{ses_id}"
411-
except AttributeError:
412-
ses_id = ""
413-
pet_string = f"sub-{subject_id}"
417+
if anat_only:
418+
for each in t1w_workflows.values():
419+
workflow.add_nodes([each["workflow"]])
420+
else:
421+
for pet_file, t1w_file in subject_data.items():
422+
try:
423+
ses_id = re.search("ses-[^_|\/]*", str(pet_file)).group(0)
424+
pet_string = f"sub-{subject_id}_{ses_id}"
425+
except AttributeError:
426+
ses_id = ""
427+
pet_string = f"sub-{subject_id}"
414428

415-
# collect run info from pet file
416-
try:
417-
run_id = "_" + re.search("run-[^_|\/]*", str(pet_file)).group(0)
418-
except AttributeError:
419-
run_id = ""
420-
pet_wf_name = f"pet_{pet_string}{run_id}_wf"
421-
pet_wf = Workflow(name=pet_wf_name)
422-
423-
weighted_average = Node(
424-
WeightedAverage(pet_file=pet_file), name="weighted_average"
425-
)
429+
# collect run info from pet file
430+
try:
431+
run_id = "_" + re.search("run-[^_|\/]*", str(pet_file)).group(0)
432+
except AttributeError:
433+
run_id = ""
434+
pet_wf_name = f"pet_{pet_string}{run_id}_wf"
435+
pet_wf = Workflow(name=pet_wf_name)
436+
437+
weighted_average = Node(
438+
WeightedAverage(pet_file=pet_file), name="weighted_average"
439+
)
426440

427-
# rename registration file to something more descriptive than registration.lta
428-
# we do this here to account for mulitple runs during the same session
429-
mricoreg = MRICoreg(reference_file=t1w_file)
430-
mricoreg.inputs.out_lta_file = f"{pet_string}{run_id}_desc-pet2anat_pet.lta"
441+
# rename registration file to something more descriptive than registration.lta
442+
# we do this here to account for mulitple runs during the same session
443+
mricoreg = MRICoreg(reference_file=t1w_file)
444+
mricoreg.inputs.out_lta_file = f"{pet_string}{run_id}_desc-pet2anat_pet.lta"
431445

432-
coreg_pet_to_t1w = Node(mricoreg, "coreg_pet_to_t1w")
446+
coreg_pet_to_t1w = Node(mricoreg, "coreg_pet_to_t1w")
433447

434-
deface_pet = Node(ApplyMideface(in_file=pet_file), name="deface_pet")
448+
deface_pet = Node(ApplyMideface(in_file=pet_file), name="deface_pet")
435449

436-
pet_wf.connect(
437-
[
438-
(weighted_average, coreg_pet_to_t1w, [("out_file", "source_file")]),
439-
(coreg_pet_to_t1w, deface_pet, [("out_lta_file", "lta_file")]),
440-
(
441-
coreg_pet_to_t1w,
442-
datasink,
443-
[("out_lta_file", f"{pet_string.replace('_', '.')}.pet.@{run_id}")],
444-
),
445-
(
446-
deface_pet,
447-
datasink,
448-
[
449-
(
450-
"out_file",
451-
f"{pet_string.replace('_', '.')}.pet.@defaced{run_id}",
452-
)
453-
],
454-
),
455-
]
456-
)
450+
pet_wf.connect(
451+
[
452+
(weighted_average, coreg_pet_to_t1w, [("out_file", "source_file")]),
453+
(coreg_pet_to_t1w, deface_pet, [("out_lta_file", "lta_file")]),
454+
(
455+
coreg_pet_to_t1w,
456+
datasink,
457+
[
458+
(
459+
"out_lta_file",
460+
f"{pet_string.replace('_', '.')}.pet.@{run_id}",
461+
)
462+
],
463+
),
464+
(
465+
deface_pet,
466+
datasink,
467+
[
468+
(
469+
"out_file",
470+
f"{pet_string.replace('_', '.')}.pet.@defaced{run_id}",
471+
)
472+
],
473+
),
474+
]
475+
)
457476

458-
workflow.connect(
459-
[
460-
(
461-
t1w_workflows[t1w_file]["workflow"],
462-
pet_wf,
463-
[
464-
(
465-
f"deface_t1w_{t1w_workflows[t1w_file]['anat_string']}.out_facemask",
466-
"deface_pet.facemask",
467-
)
468-
],
469-
)
470-
]
471-
)
477+
workflow.connect(
478+
[
479+
(
480+
t1w_workflows[t1w_file]["workflow"],
481+
pet_wf,
482+
[
483+
(
484+
f"deface_t1w_{t1w_workflows[t1w_file]['anat_string']}.out_facemask",
485+
"deface_pet.facemask",
486+
)
487+
],
488+
)
489+
]
490+
)
472491

473492
return workflow
474493

@@ -718,13 +737,12 @@ def __init__(
718737
self,
719738
bids_dir,
720739
output_dir=None,
721-
anat_only=False, # TODO: currently not implemented
740+
anat_only=False,
722741
subject="",
723-
session="", # TODO: currently not implemented
724742
n_procs=2,
725743
skip_bids_validator=True,
726-
remove_existing=True, # TODO: currently not implemented
727-
placement="adjacent", # TODO: currently not implemented
744+
remove_existing=True,
745+
placement="adjacent",
728746
preview_pics=True,
729747
excludeparticipant=[],
730748
):
@@ -734,7 +752,6 @@ def __init__(
734752
self.output_dir = output_dir
735753
self.anat_only = anat_only
736754
self.subject = subject
737-
self.session = session
738755
self.n_procs = n_procs
739756
self.skip_bids_validator = skip_bids_validator
740757
self.preview_pics = preview_pics
@@ -747,7 +764,9 @@ def __init__(
747764
if not self.fs_license.exists():
748765
raise ValueError("Freesurfer license is not valid")
749766
else:
750-
print(f"Using freesurfer license at {self.fs_license} found in system env at $FREESURFER_LICENSE")
767+
print(
768+
f"Using freesurfer license at {self.fs_license} found in system env at $FREESURFER_LICENSE"
769+
)
751770

752771
def run(self):
753772
"""
@@ -760,7 +779,6 @@ def run(self):
760779
"output_dir": self.output_dir,
761780
"anat_only": self.anat_only,
762781
"subject": self.subject,
763-
"session": self.session,
764782
"n_procs": self.n_procs,
765783
"skip_bids_validator": self.skip_bids_validator,
766784
"participant_label": self.subject,
@@ -795,9 +813,9 @@ def cli():
795813
default=None,
796814
)
797815
parser.add_argument(
798-
'analysis_level',
799-
nargs='?',
800-
default='participant',
816+
"analysis_level",
817+
nargs="?",
818+
default="participant",
801819
help="This BIDS app always operates at the participant level, if this argument is changed it will be ignored and run as "
802820
"a participant level analysis",
803821
)
@@ -817,14 +835,6 @@ def cli():
817835
required=False,
818836
default="",
819837
)
820-
parser.add_argument(
821-
"--session",
822-
"-ses",
823-
help="The label of the session to be processed.",
824-
type=str,
825-
required=False,
826-
default="",
827-
)
828838
parser.add_argument(
829839
"--docker",
830840
"-d",
@@ -1010,7 +1020,11 @@ def main(): # noqa: max-complexity: 12
10101020
elif args.singularity:
10111021
singularity_command = f"singularity exec -e"
10121022

1013-
if args.output_dir == "None" or args.output_dir is None or args.output_dir == "":
1023+
if (
1024+
args.output_dir == "None"
1025+
or args.output_dir is None
1026+
or args.output_dir == ""
1027+
):
10141028
args.output_dir = args.bids_dir / "derivatives" / "petdeface"
10151029

10161030
# create output directory if it doesn't exist
@@ -1051,7 +1065,9 @@ def main(): # noqa: max-complexity: 12
10511065
"Freesurfer license not found, please set FREESURFER_LICENSE environment variable or place license.txt in FREESURFER_HOME"
10521066
)
10531067

1054-
singularity_command += f" --bind {str(license_location)}:/opt/freesurfer/license.txt"
1068+
singularity_command += (
1069+
f" --bind {str(license_location)}:/opt/freesurfer/license.txt"
1070+
)
10551071
singularity_command += f" docker://openneuropet/petdeface:{__version__}"
10561072
singularity_command += f" petdeface"
10571073
singularity_command += args_string
@@ -1060,14 +1076,12 @@ def main(): # noqa: max-complexity: 12
10601076

10611077
subprocess.run(singularity_command, shell=True)
10621078

1063-
10641079
else:
10651080
petdeface = PetDeface(
10661081
bids_dir=args.bids_dir,
10671082
output_dir=args.output_dir,
10681083
anat_only=args.anat_only,
10691084
subject=args.participant_label,
1070-
session=args.session,
10711085
n_procs=args.n_procs,
10721086
skip_bids_validator=args.skip_bids_validator,
10731087
remove_existing=args.remove_existing,

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "petdeface"
3-
version = "0.2.0"
3+
version = "0.2.1"
44
description = "A nipype PET and MR defacing pipeline for BIDS datasets utilizing FreeSurfer's MiDeFace."
55
authors = ["Martin Nørgaard <[email protected]>", "Anthony Galassi <[email protected]>", "Murat Bilgel <[email protected]>"]
66
license = "MIT"

0 commit comments

Comments
 (0)