Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Iterating over multiple pairs of PET and T1w files #13

Merged
merged 7 commits into from
Aug 31, 2023
Merged
Show file tree
Hide file tree
Changes from 4 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
9 changes: 9 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[flake8]
select = B,B9,C,D,DAR,E,F,N,RST,S,W
ignore = E203,E501,RST201,RST203,RST301,W503
max-line-length = 80
max-complexity = 10
docstring-convention = google
per-file-ignores = tests/*:S101
rst-roles = class,const,func,meth,mod,ref
rst-directives = deprecated
30 changes: 30 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: check-yaml
- id: check-toml
- id: check-added-large-files
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: local
hooks:
- id: black
name: black
entry: black
language: system
types: [python]
require_serial: true
- id: flake8
name: flake8
entry: flake8
language: system
types: [python]
require_serial: true
- id: isort
name: isort
entry: isort
require_serial: true
language: system
types_or: [cython, pyi, python]
args: ["--filter-files"]
40 changes: 20 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
# petdeface
A nipype implementation of an anatomical MR and PET defacing pipeline for BIDS datasets. This is a working prototype,
in active development denoted by the 0.x.x version number. However, it is functional and can be used to deface PET and
MR data as well as co-register the two modalities. Use is encouraged and feedback via Github issues or email to
[email protected] is more than welcome. As is often the case, this medical research software is constrained
MR data as well as co-register the two modalities. Use is encouraged and feedback via Github issues or email to
[email protected] is more than welcome. As is often the case, this medical research software is constrained
to testing on data that its developers have access to.

This software can be installed via source or via pip from PyPi with `pip install petdeface`
This software can be installed via source or via pip from PyPi with `pip install petdeface`

## Requirements

### Non-Python Dependencies

- FreeSurfer and MiDeFAce >= 7.3.2
- https://surfer.nmr.mgh.harvard.edu/
- https://surfer.nmr.mgh.harvard.edu/
- https://surfer.nmr.mgh.harvard.edu/fswiki/MiDeFace

### Python Dependencies
Expand All @@ -25,9 +25,9 @@ This software can be installed via source or via pip from PyPi with `pip install

## Usage
```bash
usage: petdeface.py [-h] [--output_dir OUTPUT_DIR] [--anat_only]
[--subject SUBJECT] [--session SESSION] [--docker]
[--n_procs N_PROCS] [--skip_bids_validator] [--version]
usage: petdeface.py [-h] [--output_dir OUTPUT_DIR] [--anat_only]
[--subject SUBJECT] [--session SESSION] [--docker]
[--n_procs N_PROCS] [--skip_bids_validator] [--version]
[--placement PLACEMENT] [--remove_existing] input_dir

PetDeface
Expand All @@ -49,9 +49,9 @@ options:
--skip_bids_validator
--version, -v show program's version number and exit
--placement PLACEMENT, -p PLACEMENT
Where to place the defaced images. Options are
Where to place the defaced images. Options are
'adjacent': next to the input_dir (default) in a folder appended with _defaced
'inplace': defaces the dataset in place, e.g. replaces faced PET and T1w images
'inplace': defaces the dataset in place, e.g. replaces faced PET and T1w images
w/ defaced at input_dir
'derivatives': does all of the defacing within the derivatives folder in input_dir.
--remove_existing, -r Remove existing output files in output_dir.
Expand All @@ -76,24 +76,24 @@ pip install petdeface-<X.X.X>-py3-none-any.whl # where X.X.X is the version numb

## Citations

1. Dale A, Fischl B, Sereno MI. Cortical Surface-Based Analysis: I. Segmentation and Surface Reconstruction.
1. Dale A, Fischl B, Sereno MI. Cortical Surface-Based Analysis: I. Segmentation and Surface Reconstruction.
Neuroimage. 1999;9(2):179–94. doi:10.1006/nimg.1998.0395.
2. Fischl B. FreeSurfer. Neuroimage. 2012 Aug 15;62(2):774-81. doi: 10.1016/j.neuroimage.2012.01.021.
Epub 2012 Jan 10. PMID: 22248573; PMCID: PMC3685476.
3. Stefano Cerri, Douglas N. Greve, Andrew Hoopes, Henrik Lundell, Hartwig R. Siebner, Mark Mühlau, Koen Van Leemput,
An open-source tool for longitudinal whole-brain and white matter lesion segmentation,
NeuroImage: Clinical, Volume 38, 2023, 103354, ISSN 2213-1582, https://doi.org/10.1016/j.nicl.2023.103354.
(https://www.sciencedirect.com/science/article/pii/S2213158223000438)
4. Gorgolewski, Krzysztof J. ; Esteban, Oscar ; Burns, Christopher ; Ziegler, Erik ; Pinsard, Basile ; Madison, Cindee ;
Waskom, Michael ; Ellis, David Gage ; Clark, Dav ; Dayan, Michael ; Manhães-Savio, Alexandre ;
Notter, Michael Philipp ; Johnson, Hans ; Dewey, Blake E ; Halchenko, Yaroslav O. ; Hamalainen, Carlo ;
4. Gorgolewski, Krzysztof J. ; Esteban, Oscar ; Burns, Christopher ; Ziegler, Erik ; Pinsard, Basile ; Madison, Cindee ;
Waskom, Michael ; Ellis, David Gage ; Clark, Dav ; Dayan, Michael ; Manhães-Savio, Alexandre ;
Notter, Michael Philipp ; Johnson, Hans ; Dewey, Blake E ; Halchenko, Yaroslav O. ; Hamalainen, Carlo ;
Keshavan, Anisha ; Clark, Daniel ; Huntenburg, Julia M. ; Hanke, Michael ; Nichols, B. Nolan ; Wassermann , Demian ;
Eshaghi, Arman ; Markiewicz, Christopher ; Varoquaux, Gael ; Acland, Benjamin ; Forbes, Jessica ; Rokem, Ariel ;
Kong, Xiang-Zhen ; Gramfort, Alexandre ; Kleesiek, Jens ; Schaefer, Alexander ; Sikka, Sharad ;
Perez-Guevara, Martin Felipe ; Glatard, Tristan ; Iqbal, Shariq ; Liu, Siqi ; Welch, David ; Sharp, Paul ;
Eshaghi, Arman ; Markiewicz, Christopher ; Varoquaux, Gael ; Acland, Benjamin ; Forbes, Jessica ; Rokem, Ariel ;
Kong, Xiang-Zhen ; Gramfort, Alexandre ; Kleesiek, Jens ; Schaefer, Alexander ; Sikka, Sharad ;
Perez-Guevara, Martin Felipe ; Glatard, Tristan ; Iqbal, Shariq ; Liu, Siqi ; Welch, David ; Sharp, Paul ;
Warner, Joshua ; Kastman, Erik ; Lampe, Leonie ; Perkins, L. Nathan ; Craddock, R. Cameron ; Küttner, René ;
Bielievtsov, Dmytro ; Geisler, Daniel ; Gerhard, Stephan ; Liem, Franziskus ; Linkersdörfer, Janosch ;
Margulies, Daniel S. ; Andberg, Sami Kristian ; Stadler, Jörg ; Steele, Christopher John ; Broderick, William ;
Cooper, Gavin ; Floren, Andrew ; Huang, Lijie ; Gonzalez, Ivan ; McNamee, Daniel ; Papadopoulos Orfanos, Dimitri ;
Pellman, John ; Triplett, William ; Ghosh, Satrajit (2016). Nipype: a flexible, lightweight and extensible
Bielievtsov, Dmytro ; Geisler, Daniel ; Gerhard, Stephan ; Liem, Franziskus ; Linkersdörfer, Janosch ;
Margulies, Daniel S. ; Andberg, Sami Kristian ; Stadler, Jörg ; Steele, Christopher John ; Broderick, William ;
Cooper, Gavin ; Floren, Andrew ; Huang, Lijie ; Gonzalez, Ivan ; McNamee, Daniel ; Papadopoulos Orfanos, Dimitri ;
Pellman, John ; Triplett, William ; Ghosh, Satrajit (2016). Nipype: a flexible, lightweight and extensible
neuroimaging data processing framework in Python. 0.12.0-rc1. Zenodo. 10.5281/zenodo.50186
28 changes: 15 additions & 13 deletions petdeface/mideface.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import os
from bids import BIDSLayout
from nipype.interfaces.base import (
TraitedSpec,
CommandLineInputSpec,
CommandLine,
File,
Directory,
traits,
)

from nipype.interfaces.base import CommandLine
from nipype.interfaces.base import CommandLineInputSpec
from nipype.interfaces.base import Directory
from nipype.interfaces.base import File
from nipype.interfaces.base import TraitedSpec
from nipype.interfaces.base import traits


class MidefaceInputSpec(CommandLineInputSpec):
in_file = File(
Expand Down Expand Up @@ -62,7 +61,8 @@ class MidefaceInputSpec(CommandLineInputSpec):
argstr="--xmask-synthseg %d",
)
fill_const = traits.Tuple(
traits.Float, traits.Float,
traits.Float,
traits.Float,
desc="Fill constants",
argstr="--fill-const %f %f",
)
Expand Down Expand Up @@ -138,19 +138,22 @@ class MidefaceInputSpec(CommandLineInputSpec):
argstr="--display %d",
)
apply = traits.Str(
desc="Apply midface output to a second volume",
desc="Apply mideface output to a second volume",
argstr="--apply %s",
)
check = traits.Tuple(
File, File,
File,
File,
desc="Check whether a volume has been defaced",
argstr="--check %s %s",
)


class MidefaceOutputSpec(TraitedSpec):
out_file = File(desc="Defaced input")
out_facemask = File(desc="Facemask")


class Mideface(CommandLine):
_cmd = "mideface"
input_spec = MidefaceInputSpec
Expand All @@ -161,4 +164,3 @@ def _list_outputs(self):
outputs["out_file"] = os.path.abspath(self.inputs.out_file)
outputs["out_facemask"] = os.path.abspath(self.inputs.out_facemask)
return outputs

51 changes: 24 additions & 27 deletions petdeface/pet.py
Original file line number Diff line number Diff line change
@@ -1,42 +1,39 @@
def create_weighted_average_pet(pet_file, bids_dir):
def create_weighted_average_pet(pet_file: str, bids_dir: str) -> str:
import os
from pathlib import Path

import json
from niworkflows.interfaces.bids import ReadSidecarJSON
import nibabel as nib
import numpy as np
import os
from pathlib import Path
from niworkflows.interfaces.bids import ReadSidecarJSON

"""
Create a time-weighted average of dynamic PET data using mid-frames

Arguments
---------
pet_file: string
path to input dynamic PET volume
bids_dir: string
path to BIDS directory containing the PET file
"""

img = nib.load(pet_file)
data = img.get_fdata()

meta = ReadSidecarJSON(in_file = pet_file,
bids_dir = bids_dir,
bids_validate = False).run()
Args:
pet_file: path to input dynamic PET volume
bids_dir: path to BIDS directory containing the PET file

Returns:
path to time-weighted average of dynamic PET
"""

img = nib.load(pet_file)
data = img.get_fdata()

frames_start = np.array(meta.outputs.out_dict['FrameTimesStart'])
frames_duration = np.array(meta.outputs.out_dict['FrameDuration'])
meta = ReadSidecarJSON(
in_file=pet_file, bids_dir=bids_dir, bids_validate=False
).run()

frames = range(data.shape[-1])
frames_start = np.array(meta.outputs.out_dict["FrameTimesStart"])
frames_duration = np.array(meta.outputs.out_dict["FrameDuration"])

new_pth = os.getcwd()

mid_frames = frames_start + frames_duration/2
wavg = np.trapz(data[..., frames], dx=np.diff(mid_frames[frames]), axis=3)/np.sum(mid_frames)
mid_frames = frames_start + frames_duration / 2
wavg = np.trapz(data, x=mid_frames) / (mid_frames[-1] - mid_frames[0])
bendhouseart marked this conversation as resolved.
Show resolved Hide resolved

out_name = Path(pet_file.replace('_pet.', '_desc-wavg_pet.')).name
out_file = os.path.join(new_pth, out_name)
out_name = Path(pet_file.replace("_pet.", "_desc-wavg_pet.")).name
out_file = os.path.join(new_pth, out_name)
nib.save(nib.Nifti1Image(wavg, img.affine), out_file)

return out_file
return out_file
Loading