Skip to content

Commit ef594e6

Browse files
committed
added qa to run at end of petdeface
1 parent 4d69a07 commit ef594e6

File tree

2 files changed

+104
-9
lines changed

2 files changed

+104
-9
lines changed

petdeface/petdeface.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1057,6 +1057,18 @@ def cli():
10571057
required=False,
10581058
default=[],
10591059
)
1060+
parser.add_argument(
1061+
"--qa",
1062+
action="store_true",
1063+
default=False,
1064+
help="Generate QA reports after defacing is complete",
1065+
)
1066+
parser.add_argument(
1067+
"--open-browser",
1068+
action="store_true",
1069+
default=False,
1070+
help="Open browser automatically after QA report generation (requires --qa)",
1071+
)
10601072

10611073
arguments = parser.parse_args()
10621074
return arguments
@@ -1257,6 +1269,65 @@ def main(): # noqa: max-complexity: 12
12571269
)
12581270
petdeface.run()
12591271

1272+
# Generate QA reports if requested
1273+
if args.qa:
1274+
print("\n" + "=" * 60)
1275+
print("Generating QA reports...")
1276+
print("=" * 60)
1277+
1278+
try:
1279+
# Import qa module
1280+
import qa
1281+
import sys
1282+
1283+
# Determine the defaced directory based on placement
1284+
if args.placement == "adjacent":
1285+
defaced_dir = args.bids_dir.parent / f"{args.bids_dir.name}_defaced"
1286+
elif args.placement == "inplace":
1287+
defaced_dir = args.bids_dir
1288+
elif args.placement == "derivatives":
1289+
defaced_dir = args.bids_dir / "derivatives" / "petdeface"
1290+
else:
1291+
defaced_dir = (
1292+
args.output_dir
1293+
if args.output_dir
1294+
else args.bids_dir / "derivatives" / "petdeface"
1295+
)
1296+
1297+
# Build QA arguments as sys.argv style
1298+
qa_argv = [
1299+
"qa.py", # Script name
1300+
"--faced-dir",
1301+
str(args.bids_dir),
1302+
"--defaced-dir",
1303+
str(defaced_dir),
1304+
]
1305+
1306+
if args.open_browser:
1307+
qa_argv.append("--open-browser")
1308+
1309+
if args.participant_label:
1310+
qa_argv.extend(["--subject", " ".join(args.participant_label)])
1311+
1312+
# Temporarily replace sys.argv and run QA
1313+
original_argv = sys.argv
1314+
sys.argv = qa_argv
1315+
1316+
try:
1317+
qa.main()
1318+
finally:
1319+
sys.argv = original_argv
1320+
1321+
print("\n" + "=" * 60)
1322+
print("QA reports generated successfully!")
1323+
print("=" * 60)
1324+
1325+
except Exception as e:
1326+
print(f"\nError generating QA reports: {e}")
1327+
print(
1328+
"QA report generation failed, but defacing completed successfully."
1329+
)
1330+
12601331

12611332
if __name__ == "__main__":
12621333
main()

petdeface/qa.py

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,24 @@ def preprocess_single_subject(s, output_dir):
2626
"""Preprocess a single subject's images (for parallel processing)."""
2727
temp_dir = os.path.join(output_dir, "temp_3d_images")
2828

29+
# Extract BIDS suffix from original path to preserve meaningful naming
30+
orig_basename = os.path.basename(s["orig_path"])
31+
defaced_basename = os.path.basename(s["defaced_path"])
32+
33+
# Extract the meaningful part (e.g., "sub-01_ses-baseline_T1w" or "sub-01_ses-baseline_pet")
34+
def extract_bids_name(basename):
35+
# Remove .nii.gz extension
36+
name = basename.replace(".nii.gz", "").replace(".nii", "")
37+
return name
38+
39+
orig_bids_name = extract_bids_name(orig_basename)
40+
defaced_bids_name = extract_bids_name(defaced_basename)
41+
2942
# Preprocess original image
3043
orig_result = load_and_preprocess_image(s["orig_path"])
3144
if isinstance(orig_result, nib.Nifti1Image):
32-
# Need to save the averaged image
33-
orig_3d_path = os.path.join(temp_dir, f"orig_{s['id']}.nii.gz")
45+
# Need to save the averaged image with meaningful name
46+
orig_3d_path = os.path.join(temp_dir, f"orig_{orig_bids_name}.nii.gz")
3447
nib.save(orig_result, orig_3d_path)
3548
orig_img = orig_result
3649
else:
@@ -41,8 +54,8 @@ def preprocess_single_subject(s, output_dir):
4154
# Preprocess defaced image
4255
defaced_result = load_and_preprocess_image(s["defaced_path"])
4356
if isinstance(defaced_result, nib.Nifti1Image):
44-
# Need to save the averaged image
45-
defaced_3d_path = os.path.join(temp_dir, f"defaced_{s['id']}.nii.gz")
57+
# Need to save the averaged image with meaningful name
58+
defaced_3d_path = os.path.join(temp_dir, f"defaced_{defaced_bids_name}.nii.gz")
4659
nib.save(defaced_result, defaced_3d_path)
4760
defaced_img = defaced_result
4861
else:
@@ -451,12 +464,19 @@ def create_comparison_html(
451464
output_dir,
452465
display_mode="side-by-side",
453466
size="compact",
467+
orig_path=None,
468+
defaced_path=None,
454469
):
455470
"""Create HTML comparison page for a subject using nilearn ortho views."""
456471

457-
# Get basenames for display
458-
orig_basename = f"orig_{subject_id}.nii.gz"
459-
defaced_basename = f"defaced_{subject_id}.nii.gz"
472+
# Get basenames for display - use actual filenames with BIDS suffixes if available
473+
if orig_path and defaced_path:
474+
orig_basename = os.path.basename(orig_path)
475+
defaced_basename = os.path.basename(defaced_path)
476+
else:
477+
# Fallback to generic names if paths not provided
478+
orig_basename = f"orig_{subject_id}.nii.gz"
479+
defaced_basename = f"defaced_{subject_id}.nii.gz"
460480

461481
# Generate images and get their filenames
462482
image_files = []
@@ -744,6 +764,8 @@ def process_subject(subject, output_dir, size="compact"):
744764
output_dir,
745765
"side-by-side", # Always generate side-by-side for individual pages
746766
size,
767+
subject["orig_path"],
768+
subject["defaced_path"],
747769
)
748770
print(f" Completed: {subject['id']}")
749771
return comparison_file
@@ -832,8 +854,10 @@ def create_side_by_side_index_html(subjects, output_dir, size="compact"):
832854
comparisons_html = ""
833855
for subject in subjects:
834856
subject_id = subject["id"]
835-
orig_basename = f"orig_{subject_id}.nii.gz"
836-
defaced_basename = f"defaced_{subject_id}.nii.gz"
857+
858+
# Use actual filenames with BIDS suffixes instead of generic names
859+
orig_basename = os.path.basename(subject["orig_path"])
860+
defaced_basename = os.path.basename(subject["defaced_path"])
837861

838862
# Check if the PNG files exist
839863
orig_png = f"images/original_{subject_id}.png"

0 commit comments

Comments
 (0)