Getting started

Clone this repo, install dicomselect, then run this example in the repo.

from dicomselect import Database
from pathlib import Path

db_path = Path('tests/output/example.db')
db_path.parent.mkdir(exist_ok=True)

# initialize the Database object with a path to the to-be-created SQLite database file
db = Database(db_path)

# create the .db file, using test data as the input directory.
db.create('tests/input/ProstateX', max_workers=4)

with (db as query):
    # we only want to convert images with patient_id "ProstateX-0000" and image_direction "transverse"
    query_0000 = query.where('patient_id', '=', 'ProstateX-0000'
                             ).where('image_direction', '=', 'transverse')

    # print out a detailed extraction of our query
    print(query_0000.include('image_direction', 'rows', 'columns', 'flip_angle'))

# initialize the Plan object, with a template of DICOM headers for our conversion
# (note: dcm to dcm conversion is possible, if you only need restructuring of your data)
plan = db.plan('{patient_id}/prostateX_{series_description}_{instance_creation_time}', query_0000)

target_dir = Path('tests/output/example')
if target_dir.exists():
    import shutil
    shutil.rmtree(target_dir)

# ensure these properties are set
plan.target_dir = 'tests/output/example'
plan.extension = '.mha'
plan.max_workers = 4

# print out a detailed structure of our intended conversion
print(plan)

plan.execute()
# check out the result in 'tests/output/example'!

More samples

Create a new database

from pathlib import Path
from dicomselect.database import Database

db_path = Path("/path/to/dicomselect_archive.db")
archive_path = Path("/path/to/archive")
db_path.parent.mkdir(parents=True, exist_ok=True)
db = Database(db_path)
db.create(archive_path, max_workers=4)

Select scans

  1. Simple matching of values

from dicomselect.database import Database

mapping = {
    "t2w": {
        "SeriesDescription": [
            "t2_tse_tra_snel_bij bewogen t2 tra",
            "t2_tse_tra",
            "t2_tse_tra_prostate",
            "t2_tse_tra_snel",
            "t2_tse_tra_Grappa3"
        ]
    },
}

db_path = Path("/path/to/dicomselect_archive.db")
db = Database(db_path)
cursor = db.open()
query = cursor.where("series_description", "in", mapping["t2w"]["SeriesDescription"])
print(query)
db.close()
  1. Pattern matching and combining queries

from dicomselect.database import Database

mapping = {
    "hbv": {
        "SeriesDescription": [
            "ep2d_diff_tra%CALC_BVAL",
            "diffusie-3Scan-4bval_fsCALC_BVAL"
        ],
        "ImageType": [
            r"DERIVED\PRIMARY\DIFFUSION\CALC_BVALUE\TRACEW\DIS2D\DFC",
            r"DERIVED\PRIMARY\DIFFUSION\CALC_BVALUE\TRACEW\DIS2D",
            r"DERIVED\PRIMARY\DIFFUSION\CALC_BVALUE\TRACEW\ND\DFC",
            r"DERIVED\PRIMARY\DIFFUSION\CALC_BVALUE\TRACEW\NORM\DIS2D",
        ]
    }
}

db_path = Path("/path/to/dicomselect_archive.db")
db = Database(db_path)
cursor = db.open()
query1 = cursor.where("series_description", "LIKE", mapping["hbv"]["SeriesDescription"])
query2 = cursor.where("image_type", "LIKE", mapping["hbv"]["ImageType"])
query = query1.union(query2)
print(query)
db.close()

Show info

# print a default overview of the query result
print(query)

# for more fine-grained control of the reporting, use the Info object
# print a summary of series_description given the query
print(query.info().include("series_description"))

# print a summary of everything but series_description given the query
# note: some recommended columns are excluded, such as columns referring to some UID.
print(query.info().exclude("series_description", recommended=True))

Convert

from dicomselect.database import Database

db_path = Path("/path/to/dicomselect_archive.db")
db = Database(db_path)
plan = db.plan("{patient_id}/{series_description}_{patients_age}", query)
plan.target_dir = "/path/to/target_dir"
plan.extension = ".mha"
print(plan)
plan.execute(max_workers=4)