Architecture¶
dicom-dre is a pure-Python DICOM de-identification engine. It filters images,
blanks burned-in pixel regions, and rewrites metadata tags. For each input file
it produces one of three outcomes by running three stages in sequence.
Overview¶
For each input DICOM file the engine runs three stages:
Filter: a device catalog decides whether to keep or reject the image.
Pixel scrub: the engine blanks the burned-in text regions the catalog identified. When it blanks a region, it sets
BurnedInAnnotation(0028,0301) toNOand records the Clean Pixel Data Option113101in the De-identification Method Code Sequence for that instance.Metadata: the engine rewrites DICOM tags: it removes PHI, re-derives UIDs, and shifts or keeps dates.
Each run returns a DeidentifyResult whose outcome
is one of three Outcome values:
Outcome |
Cause |
|---|---|
|
The file passed the filter, and the engine wrote it out. |
|
A device or exclusion rule rejected the file; the result contains the matched reason. |
|
Processing raised an exception; the result contains the error text. |
Pipeline¶
Every de-identification call enters through
dicom_dre.pipeline.deidentify_file(), which composes the three stages and
returns a DeidentifyResult.
flowchart LR
A["PHI DICOM"] --> F{"Filter<br>catalog.evaluate()"}
F -->|deny| X["FILTERED<br>(+ reason)"]
F -->|allow / scrub| S["Pixel scrub<br>blank_regions()"]
S --> M["Metadata<br>profile.apply()"]
M --> O["DEIDENTIFIED"]
F -.->|exception| Q["QUARANTINED"]
An exception raised in any stage does not propagate to the caller.
deidentify_file catches it and returns a QUARANTINED result instead.
Stages¶
Filter¶
catalog.evaluate(DicomTags.from_file(path)) returns a
CatalogDecision with an action (allow, deny, or
scrub), a human-readable reason, and a list of scrub regions. A deny action
stops the pipeline and produces a FILTERED result whose filter_reason is the
matched rule. Catalog evaluation reads tags directly with pydicom.
See Device Catalog.
Pixel scrub¶
When the decision contains scrub regions,
dicom_dre.pixel_blanker.blank_regions() blanks them. The engine edits
JPEG Baseline images directly in the compressed bitstream with no re-encoding.
For all other transfer syntaxes, it decodes with pydicom and numpy, blanks the
regions, and writes uncompressed Explicit VR Little Endian.
See JPEG DCT Scrubbing.
Metadata¶
The bound DeidProfile runs its tag rules on the
dataset with DeidProfile.apply(ds, params), where params is a
DeidParameters containing the per-patient values.
Rules are small closures defined in
dicom_dre.actions (for example remove, empty, hash_uid,
jitter_date, keep). The profile factories in dicom_dre.profiles
compose the tag sets each profile applies them to.
Each factory in actions.py closes over its build-time arguments at
profile-construction time and returns a
(Dataset, BaseTag, DeidParameters) -> None callable that reads per-patient
values from the supplied parameters. The available actions:
Action |
Effect |
|---|---|
|
Leave the element unchanged. |
|
Delete the element from the dataset. |
|
Replace the value with a zero-length value (empty list for |
|
Replace the value with a literal string, optionally creating the element when absent. |
|
Write a per-patient value read from |
|
Write a caller-supplied identifier verbatim, otherwise hash the original element value (salted with |
|
Re-derive a UID as an MD5 hash under |
|
Shift the |
|
Append |
|
Replace an |
|
Apply |
Profiles compose these actions rather than parsing a script.
Private-tag preservation¶
By default the engine removes every private data element that has no explicit
tag rule. A profile declares a reviewer-approved set of private elements to
retain verbatim through its preserved_private_specs field (a frozenset of
PrivateTagSpec), keyed on the private-creator string. At apply time,
DeidProfile.apply(ds, params) resolves each spec’s private-creator block (the
block is runtime-assigned, not fixed) and keeps both the resolved data elements
and their creator element. The engine removes all other private elements as
usual.
An offset in a spec may be wrapped in Jitter. A Jitter-flagged offset is
resolved and kept like any preserved offset, and its DA/DT value is then
shifted by the same per-study jitter applied to standard date tags. The shift
runs after the element rules and recurses into sequence items. For a
date-preserving profile the jitter is unset, so a flagged value is left
unchanged. The default profile flags PulseSequenceDate (0019,xx9D) in the
GEMS_ACQU_01 block; strict inherits the same specs.
The default profile declares the specs; lds and lds-no-dob inherit
them, and strict declares the same set. The engine stamps the
De-identification Method Code Sequence (0012,0064) on every de-identified
instance; it adds the Retain Safe Private Option item 113111 only when the
profile removes private groups (remove_private) and the instance retains at
least one preserved private element. A profile that keeps all private elements
does not emit 113111, since that is not the selective safe private option.
See Profiles.
Profiles¶
The default, lds, lds-no-dob, and strict profiles each map to a
factory function in dicom_dre.profiles. A profile name selects which
tags the engine keeps, removes, or shifts. Profiles describes the
behavior of each profile.
Regression validation¶
A regression fixture suite guards catalog and metadata behavior against known
inputs. Each fixture pins the expected filter decision, scrub decision, scrub
regions, and de-identified metadata for a representative instance, so the test
run catches a change that alters any of them. The fixtures reside in
tests/unit/test_catalog_regression_fixtures.py.
See Testing.
Extending¶
To allow or deny a new device, or to blank a new pixel region, add a
device()entry todicom_dre.default_catalog. See Extending the catalog.To change a tag rule or add a profile, compose actions in
dicom_dre.profiles, deriving from an existing profile withdataclasses.replace.
Module reference¶
Module |
Responsibility |
|---|---|
|
Orchestrator: composes the three stages into a |
|
|
|
|
|
Tag-action factories ( |
|
|
|
Catalog engine: |
|
Device and exclusion rule data |
|
|
|
DCT-domain JPEG blanking and C accelerator |