98 lines
3.2 KiB
Python
Executable file
98 lines
3.2 KiB
Python
Executable file
# /// script
|
|
# requires-python = ">=3.12"
|
|
# dependencies = [
|
|
# "pydicom",
|
|
# "trr379-rdmtools @ git+https://hub.trr379.de/q02/rdmtools@main",
|
|
# ]
|
|
# ///
|
|
from pathlib import Path
|
|
import rich_click as click
|
|
from rich.progress import track
|
|
|
|
from trr379_rdmtools.dicom_archive import make_dicom_archive
|
|
|
|
|
|
def get_archive_path(
|
|
output_dir: Path, sub_id: str, ses_id: str) -> Path:
|
|
return output_dir / f'{sub_id}-{ses_id}.tar'
|
|
|
|
|
|
@click.command()
|
|
@click.argument(
|
|
'input_dir',
|
|
metavar='<input-dir>',
|
|
help="Directory with the files to place into the visit archive. "
|
|
"The input base directory itself is not put into the archive "
|
|
"(i.e., its own name is irrelevant). Instead, a top-level "
|
|
"directory with the name '<study-id>_<visit_id>' is used "
|
|
"to place all archive content in.",
|
|
type=click.Path(
|
|
exists=True, file_okay=False, dir_okay=True,
|
|
readable=True, path_type=Path,
|
|
),
|
|
)
|
|
@click.argument(
|
|
'sub_id',
|
|
metavar='<subject-id>',
|
|
help="The study and visit identifiers, used to name and "
|
|
"locate the generated archive in the storage organization. "
|
|
"The study identifier must be globally unique in the storage "
|
|
"system, and the visit identifier must be unique within the "
|
|
"collection of visits in the given study",
|
|
)
|
|
@click.argument(
|
|
'ses_id',
|
|
metavar='<session-id>',
|
|
help="The study and visit identifiers, used to name and "
|
|
"locate the generated archive in the storage organization. "
|
|
"The study identifier must be globally unique in the storage "
|
|
"system, and the visit identifier must be unique within the "
|
|
"collection of visits in the given study",
|
|
)
|
|
@click.option(
|
|
"-o", "--output-dir",
|
|
metavar='PATH',
|
|
default=Path.cwd(),
|
|
help="Directory to place the archive in.",
|
|
show_default=True,
|
|
type=click.Path(
|
|
exists=True, file_okay=False, dir_okay=True,
|
|
readable=True, path_type=Path,
|
|
),
|
|
)
|
|
def cli(
|
|
input_dir: str,
|
|
sub_id: str,
|
|
ses_id: str,
|
|
output_dir: str,
|
|
):
|
|
"""Reproducible (DICOM) archive builder.
|
|
|
|
This utility generates a TAR archive from a directory containing DICOM
|
|
files.
|
|
|
|
The input directory can have any number of files, with any organization or
|
|
naming. However, the DICOM files are assumed to come from a single "visit"
|
|
(i.e., the time between a person or sample entering and then leaving a
|
|
scanner). The input directory's content is copied into a TAR archive
|
|
verbatim, with no changes to filenames or organization.
|
|
|
|
In order to generate reproducible TAR archives, the file order, recorded
|
|
permissions and ownership, and modification times are standardized. All
|
|
files in the TAR archive are declared to be owned by root/root (uid/gid:
|
|
0/0) with 0644 permissions. The modification time of any DICOM file is
|
|
determined by its contained DICOM `StudyDate/StudyTime` timestamps. The
|
|
modification time for any non-DICOM file is set to the latest timestamp
|
|
across all DICOM files.
|
|
"""
|
|
# get and check archive path
|
|
archive_path = get_archive_path(
|
|
output_dir,
|
|
sub_id,
|
|
ses_id,
|
|
)
|
|
make_dicom_archive(input_dir, archive_path, track)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
cli()
|