Skip to content

Commit

Permalink
Put series into subfolders when downloading a study
Browse files Browse the repository at this point in the history
  • Loading branch information
medihack committed Jan 23, 2025
1 parent fc92c0a commit 41a68b6
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 21 deletions.
30 changes: 18 additions & 12 deletions adit/core/processors.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from .utils.dicom_dataset import QueryDataset, ResultDataset
from .utils.dicom_operator import DicomOperator
from .utils.dicom_utils import write_dataset
from .utils.sanitize import sanitize_dirname
from .utils.sanitize import sanitize_filename

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -95,7 +95,7 @@ def process(self) -> ProcessingResult:

def _transfer_to_server(self) -> None:
with tempfile.TemporaryDirectory(prefix="adit_") as tmpdir:
patient_folder = self._download_dicoms(Path(tmpdir))
patient_folder = self._download_to_folder(Path(tmpdir))
assert self.dest_operator
self.dest_operator.upload_instances(patient_folder)

Expand Down Expand Up @@ -128,14 +128,14 @@ def _transfer_to_archive(self) -> None:
_add_to_archive(archive_path, archive_password, readme_path)

with tempfile.TemporaryDirectory(prefix="adit_") as tmpdir:
patient_folder = self._download_dicoms(Path(tmpdir))
patient_folder = self._download_to_folder(Path(tmpdir))
_add_to_archive(archive_path, archive_password, patient_folder)

def _transfer_to_folder(self) -> None:
assert self.transfer_task.destination.node_type == DicomNode.NodeType.FOLDER
dicom_folder = Path(self.transfer_task.destination.dicomfolder.path)
download_folder = dicom_folder / self._create_destination_name()
self._download_dicoms(download_folder)
self._download_to_folder(download_folder)

def _create_destination_name(self) -> str:
transfer_job = self.transfer_task.job
Expand All @@ -144,18 +144,18 @@ def _create_destination_name(self) -> str:
name += str(transfer_job.pk) + "_"
name += transfer_job.created.strftime("%Y%m%d") + "_"
name += transfer_job.owner.username
return sanitize_dirname(name)
return sanitize_filename(name)

def _download_dicoms(
def _download_to_folder(
self,
download_folder: Path,
) -> Path:
pseudonym = self.transfer_task.pseudonym
if pseudonym:
patient_folder = download_folder / sanitize_dirname(pseudonym)
patient_folder = download_folder / sanitize_filename(pseudonym)
else:
pseudonym = None
patient_folder = download_folder / sanitize_dirname(self.transfer_task.patient_id)
patient_folder = download_folder / sanitize_filename(self.transfer_task.patient_id)

study = self._find_study()
modalities = study.ModalitiesInStudy
Expand Down Expand Up @@ -298,10 +298,16 @@ def callback(ds: Dataset | None) -> None:

modifier(ds)

folder_path = Path(study_folder)
file_name = f"{ds.SOPInstanceUID}.dcm"
file_path = folder_path / file_name
folder_path.mkdir(parents=True, exist_ok=True)
final_folder: Path
if settings.CREATE_SERIES_SUB_FOLDERS:
series_folder_name = sanitize_filename(f"{ds.SeriesNumber}-{ds.SeriesDescription}")
final_folder = study_folder / series_folder_name
else:
final_folder = study_folder

final_folder.mkdir(parents=True, exist_ok=True)
file_name = sanitize_filename(f"{ds.SOPInstanceUID}.dcm")
file_path = final_folder / file_name
write_dataset(ds, file_path)

if series_uids:
Expand Down
15 changes: 6 additions & 9 deletions adit/core/utils/sanitize.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import re


def sanitize_dirname(dirname):
def sanitize_filename(name):
"""Windows can't handle some file and folder names so we have to sanitize them."""
dirname = dirname.strip()
dirname = re.sub(r"(\<|\>|\:|\"|\/|\\|\||\?|\*)", "", dirname)
dirname = re.sub(r"(\.+)$", "", dirname)
return dirname


def sanitize_filename(filename):
return sanitize_dirname(filename)
sanitized_name = re.sub(r'[<>:"/\\|?*\x00-\x1F]', "_", name)
sanitized_name = sanitized_name.strip()
if not sanitized_name:
sanitized_name = "default"
return sanitized_name
4 changes: 4 additions & 0 deletions adit/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,10 @@
DEFAULT_BOUNDARY = "adit-boundary"
ERROR_MESSAGE = "Processing your DicomWeb request failed."

# If enabled, series are placed into separate folders when downloading a study.
# Otherwise all images of the whole study are placed into folder.
CREATE_SERIES_SUB_FOLDERS = True

# Elements to keep during pseudonymization
SKIP_ELEMENTS_ANONYMIZATION = [
"AcquisitionDate",
Expand Down

0 comments on commit 41a68b6

Please sign in to comment.