Skip to content

Commit

Permalink
debugging deidentification
Browse files Browse the repository at this point in the history
  • Loading branch information
tclose committed Sep 27, 2024
1 parent a185f42 commit 64071c1
Show file tree
Hide file tree
Showing 9 changed files with 58 additions and 9 deletions.
1 change: 1 addition & 0 deletions extras/fileformats/extras/medimage/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
from . import diffusion
from . import nifti
from . import raw
from . import base
11 changes: 8 additions & 3 deletions extras/fileformats/extras/medimage/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@


@extra_implementation(MedicalImage.deidentify)
def dicom_deidentify(
def no_deidentification_necessary(
image: MedicalImage,
out_dir: ty.Optional[Path] = None,
new_stem: ty.Optional[str] = None,
Expand All @@ -15,8 +15,13 @@ def dicom_deidentify(
"""Assume that no deidentification is needed for medical images by default. We make a
copy of the image in the output directory for consistency with the behavior of other
deidentification formats"""
if image.contains_phi:
raise NotImplementedError(

Check warning on line 19 in extras/fileformats/extras/medimage/base.py

View check run for this annotation

Codecov / codecov/patch

extras/fileformats/extras/medimage/base.py#L18-L19

Added lines #L18 - L19 were not covered by tests
f"{type(image)} images contain Protected Health Information (PHI) and needs a "
"specific deidentification method"
)
if out_dir is None:
out_dir = Path(tempfile.mkdtemp())
out_dir.mkdir(exist_ok=True, parents=True)
image.copy(out_dir, new_stem=new_stem, mode=copy_mode)
return image
cpy = image.copy(out_dir, new_stem=new_stem, mode=copy_mode)
return cpy

Check warning on line 27 in extras/fileformats/extras/medimage/base.py

View check run for this annotation

Codecov / codecov/patch

extras/fileformats/extras/medimage/base.py#L23-L27

Added lines #L23 - L27 were not covered by tests
5 changes: 3 additions & 2 deletions extras/fileformats/extras/medimage/dicom.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ def dicom_deidentify(
out_dir = Path(tempfile.mkdtemp())
out_dir.mkdir(parents=True, exist_ok=True)
dcm = dicom.load()
dcm.PatientBirthDate = "" # dcm.PatientBirthDate[:4] + "0101"
dcm.PatientBirthDate = dcm.PatientBirthDate[:4] + "0101"
dcm.PatientName = "Anonymous^Anonymous"
for field in FIELDS_TO_DEIDENTIFY:
try:
elem = dcm[field]
Expand Down Expand Up @@ -155,7 +156,7 @@ def dicom_collection_deidentify(
("0008", "009C"), # Consulting Physician's Name
("0008", "1070"), # Operators' Name
("0010", "4000"), # Patient Comments
("0010", "0010"), # Patient's Name
# ("0010", "0010"), # Patient's Name
("0010", "0021"), # Issuer of Patient ID
("0010", "0032"), # Patient's Birth Time
("0010", "0050"), # Patient's Insurance Plan Code SQ
Expand Down
6 changes: 5 additions & 1 deletion fileformats/medimage/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import typing as ty
from pathlib import Path
import logging
from typing_extensions import Self
from fileformats.core import extra, FileSet, mtime_cached_property
from fileformats.core.mixin import WithClassifiers
from .contents import ContentsClassifier
Expand All @@ -16,6 +15,10 @@
from typing import TypeAlias
else:
from typing_extensions import TypeAlias
if sys.version_info >= (3, 12):
from typing import Self
else:
from typing_extensions import Self

Check warning on line 21 in fileformats/medimage/base.py

View check run for this annotation

Codecov / codecov/patch

fileformats/medimage/base.py#L21

Added line #L21 was not covered by tests

if ty.TYPE_CHECKING:
import numpy.typing # noqa: F401
Expand All @@ -39,6 +42,7 @@ class MedicalImage(WithClassifiers, FileSet):
image_contents = ()
allowed_classifiers = (ContentsClassifier,)
exclusive_classifiers = (ImagingModality, AnatomicalEntity, Derivative)
contains_phi: bool = True

@extra
def read_array(self) -> DataArrayType:
Expand Down
11 changes: 10 additions & 1 deletion fileformats/medimage/dicom.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
import sys
import typing as ty
from collections import defaultdict, Counter
from pathlib import Path
from typing_extensions import Self, TypeAlias
from fileformats.core.decorators import mtime_cached_property
from fileformats.core import extra, FileSet, extra_implementation
from fileformats.core.collection import TypedCollection
from fileformats.generic import TypedDirectory, TypedSet
from fileformats.application import Dicom
from .base import MedicalImage

if sys.version_info >= (3, 9):
from typing import TypeAlias
else:
from typing_extensions import TypeAlias

Check warning on line 15 in fileformats/medimage/dicom.py

View check run for this annotation

Codecov / codecov/patch

fileformats/medimage/dicom.py#L15

Added line #L15 was not covered by tests
if sys.version_info >= (3, 12):
from typing import Self
else:
from typing_extensions import Self

Check warning on line 19 in fileformats/medimage/dicom.py

View check run for this annotation

Codecov / codecov/patch

fileformats/medimage/dicom.py#L19

Added line #L19 was not covered by tests

if ty.TYPE_CHECKING:
import pydicom.tag

Expand Down
1 change: 1 addition & 0 deletions fileformats/medimage/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
class AnalyzeHeader(BinaryFile):

ext = ".hdr"
contains_phi = False


class Analyze(WithSeparateHeader, MedicalImage, BinaryFile):
Expand Down
1 change: 1 addition & 0 deletions fileformats/medimage/nifti.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
class Nifti(MedicalImage, BinaryFile):

ext: str = ".nii"
contains_phi = False


class WithBids(WithSideCars):
Expand Down
20 changes: 20 additions & 0 deletions fileformats/medimage/raw/pet/base.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,29 @@
import sys
import typing as ty
from pathlib import Path
from fileformats.core import FileSet, extra
from fileformats.generic import BinaryFile

if sys.version_info >= (3, 12):
from typing import Self
else:
from typing_extensions import Self

Check warning on line 10 in fileformats/medimage/raw/pet/base.py

View check run for this annotation

Codecov / codecov/patch

fileformats/medimage/raw/pet/base.py#L10

Added line #L10 was not covered by tests


class PetRawData(BinaryFile):
"""Base class for raw PET data files"""

@extra
def deidentify(
self,
out_dir: ty.Optional[Path] = None,
new_stem: ty.Optional[str] = None,
copy_mode: FileSet.CopyMode = FileSet.CopyMode.copy,
) -> Self:
"""Returns a new copy of the data with any subject-identifying information
stripped from the from the data header"""
raise NotImplementedError

Check warning on line 25 in fileformats/medimage/raw/pet/base.py

View check run for this annotation

Codecov / codecov/patch

fileformats/medimage/raw/pet/base.py#L25

Added line #L25 was not covered by tests


class PetListMode(PetRawData):
"raw projection data"
Expand Down
11 changes: 9 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ name = "fileformats-medimage"
description = "Classes for representing various medical imaging file formats in Python classes for use in type hinting in data workflows"
readme = "README.rst"
requires-python = ">=3.8"
dependencies = ["fileformats >=0.7.1"]
dependencies = ["fileformats >=0.14.1"]
license = { file = "LICENSE" }
authors = [{ name = "Thomas G. Close", email = "[email protected]" }]
maintainers = [{ name = "Thomas G. Close", email = "[email protected]" }]
Expand All @@ -29,7 +29,14 @@ classifiers = [
dynamic = ["version"]

[project.optional-dependencies]
dev = ["black", "pre-commit", "codespell", "flake8", "flake8-pyproject"]
dev = [
"black",
"pre-commit",
"codespell",
"flake8",
"flake8-pyproject",
"typing_extensions >= 4.6",
]
test = [
"pytest >=6.2.5",
"pytest-env>=0.6.2",
Expand Down

0 comments on commit 64071c1

Please sign in to comment.