Skip to content

Commit

Permalink
Merge pull request #60 from radexperts/dicognito-0.17.0
Browse files Browse the repository at this point in the history
Upgrade dicognito to v0.17.0
  • Loading branch information
medihack authored Nov 20, 2023
2 parents adb867a + 7d881d6 commit b09682e
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 46 deletions.
2 changes: 2 additions & 0 deletions KNOWLEDGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@

## DICOM

- All available DICOM tags: <https://dicom.nema.org/medical/dicom/current/output/chtml/part06/chapter_6.html>

### pydicom and datetime

- To automatically convert dates to the datetime.date class this config must be set explicitly (default is False): config.datetime_conversion = True
Expand Down
60 changes: 19 additions & 41 deletions adit/core/utils/transfer_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
from datetime import datetime
from functools import partial
from pathlib import Path
from typing import Any, Callable
from typing import Callable

from dicognito.anonymizer import Anonymizer
from dicognito.value_keeper import ValueKeeper
from django.conf import settings
from pydicom import Dataset

Expand Down Expand Up @@ -94,6 +95,15 @@ def _transfer_to_folder(self) -> None:
download_folder = dicom_folder / self._create_destination_name()
self._download_dicoms(download_folder)

def _create_destination_name(self) -> str:
transfer_job = self.transfer_task.job
name = "adit_"
name += transfer_job._meta.app_label + "_"
name += str(transfer_job.id) + "_"
name += transfer_job.created.strftime("%Y%m%d") + "_"
name += transfer_job.owner.username
return sanitize_dirname(name)

def _download_dicoms(
self,
download_folder: Path,
Expand Down Expand Up @@ -134,7 +144,8 @@ def _download_dicoms(
study_folder = patient_folder / f"{prefix}-{modalities}"
os.makedirs(study_folder, exist_ok=True)

anonymizer = Anonymizer()
anonymizer = self._setup_anonymizer()

modifier = partial(
self._modify_dataset,
anonymizer,
Expand All @@ -159,15 +170,6 @@ def _download_dicoms(

return patient_folder

def _create_destination_name(self) -> str:
transfer_job = self.transfer_task.job
name = "adit_"
name += transfer_job._meta.app_label + "_"
name += str(transfer_job.id) + "_"
name += transfer_job.created.strftime("%Y%m%d") + "_"
name += transfer_job.owner.username
return sanitize_dirname(name)

def _fetch_patient(self) -> ResultDataset:
patients = list(
self.source_operator.find_patients(
Expand Down Expand Up @@ -228,6 +230,12 @@ def _fetch_series_list(self, series_uid: str) -> list[ResultDataset]:

return results

def _setup_anonymizer(self) -> Anonymizer:
anonymizer = Anonymizer()
for element in settings.SKIP_ELEMENTS_ANONYMIZATION:
anonymizer.add_element_handler(ValueKeeper(element))
return anonymizer

def _download_study(
self,
patient_id: str,
Expand Down Expand Up @@ -262,38 +270,8 @@ def _modify_dataset(
"""Optionally pseudonymize an incoming dataset with the given pseudonym
and add the trial ID and name to the DICOM header if specified."""
if pseudonym:
# All dates get anonymized by dicognito, but we want to retain some dates.
# For that we save them here to restore them after anonymization as dicognito
# currently does not provide that functionality.
# TODO: Use dicognito for this when issue is fixed:
# https://github.com/blairconrad/dicognito/issues/155
# TODO: Make this configurable.
attributes_to_retain = [
"StudyDate",
"StudyTime",
"SeriesDate",
"SeriesTime",
"AcquisitionDate",
"AcquisitionTime",
"ImageDate",
"ImageTime",
"ContentDate",
"ContentTime",
"DateOfLastCalibration",
"TimeOfLastCalibration",
"AcquisitionDateTime",
]
saved_attributes: dict[str, Any] = {}
for attr in attributes_to_retain:
value = ds.get(attr)
if value is not None:
saved_attributes[attr] = value

anonymizer.anonymize(ds)

for attr in saved_attributes:
setattr(ds, attr, saved_attributes[attr])

ds.PatientID = pseudonym
ds.PatientName = pseudonym

Expand Down
13 changes: 13 additions & 0 deletions adit/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -422,3 +422,16 @@
# DicomWeb Settings
DEFAULT_BOUNDARY = "adit-boundary"
ERROR_MESSAGE = "Processing your DicomWeb request failed."

# Elements to keep during pseudonymization
SKIP_ELEMENTS_ANONYMIZATION = [
"AcquisitionDate",
"AcquisitionDateTime",
"AcquisitionTime",
"ContentDate",
"ContentTime",
"SeriesDate",
"SeriesTime",
"StudyDate",
"StudyTime",
]
8 changes: 4 additions & 4 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ channels = "^4.0.0"
channels-redis = "^4.0.0"
cryptography = "^41.0.1"
daphne = "^4.0.0"
dicognito = "^0.16.0"
dicognito = "^0.17.0"
dicomweb-client = "^0.59.1"
Django = "^4.0.6"
django-crispy-forms = "^2.0"
Expand Down

0 comments on commit b09682e

Please sign in to comment.