Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

Isocenter

DOI PyPI License

De-identify a DICOM cohort without touching the source files, and hand compliance a report that names anything the run could not do.

Isocenter is a Python library for indexing, de-identifying, and exporting DICOM datasets at cohort scale. It builds a SQLite metadata index and a pixel/waveform sidecar beside a read-only source tree, applies your de-identification profile and pixel redaction rules to an in-memory object graph, grades its own output, and writes clean copies to a new directory as DICOM or PhysioNet WFDB.

You have a cohort of studies and a protocol an IRB approved. You need to hand a de-identified copy to a collaborator, a registry, or a model, and to hand your compliance reviewer a record of what was removed, what stayed because the protocol allowed it, and anything the run lost on the way. Isocenter is the library your script imports to do that. There is no command-line tool: the Python API is the whole interface.

Documentation: https://kvnlng.github.io/Isocenter/

What it refuses to do

  • Modify a source file. Ingest reads; anonymize and redact change an in-memory graph. Until export(), the session writes only the store, isocenter.log and files you ask for (a configuration, a key, a report, a manifest or a cohort table). export() writes copies to a directory you name, so a crashed or abandoned run leaves the originals as they were. The store (<name>.db and <name>_pixels.bin) holds the original identifiers and pixels, so keep it where PHI may live.
  • Grade a lossy export PASS. Every step that can lose data writes an audit row, and the compliance report reads those rows. A cohort that lost a file, a private tag, a waveform group, or a pixel frame grades REVIEW_REQUIRED and names the loss. An export that attempted instances and wrote none of them raises ExportError; a partial export returns what it wrote, with an ERROR row for each failure.
  • Pass through pixels it could not decode. If a compressed frame cannot be decompressed, because of a missing codec or a stream the decoder rejects, the export fails on that instance rather than copying bytes it never inspected.
  • Advertise a Python version it does not test. The suite runs on all four supported versions, including the free-threaded 3.14t build, at every release, and 3.12 and 3.14t must pass before anything is uploaded. The PyPI classifiers list only those.

What it does

  • De-identification against the DICOM PS3.15 Annex E Basic Profile table, edition 2026c. A profile decides which tags go, are emptied, are replaced, or are date-shifted; a field your protocol permits stays. Nested sequences are scanned, not only the top level. Date jitter is deterministic per patient within a project, so intervals survive. UIDs are replaced consistently, so references between exported files still resolve (a UID in a private tag is not replaced yet: #765).
  • Machine-specific pixel redaction. Redaction zones are keyed by device, because the same model burns identifiers into the same place every time. An optional OCR pass finds where the text lands, and CTP DicomPixelAnonymizer.script rules import directly.
  • Reversible anonymization, if you choose it. Original identities can be encrypted under a key into the Encrypted Attributes Sequence (0400,0500) before anonymization, and recovered later by whoever holds the key.
  • A persistent session. A Patient → Study → Series → Instance graph over a SQLite index and a pixel sidecar, so a 10,000-instance cohort reopens without rescanning and a job can be paused and resumed. Every action is written to an audit log.
  • A compliance report with a PASS or REVIEW_REQUIRED grade, every exception listed, and a signature block for the reviewer.
  • Waveforms. DICOM waveform IODs (ECG, hemodynamic) export as PhysioNet WFDB records, with an annotation bridge to Murmur Studio.

Install

Isocenter needs Python 3.12 or later on Linux or macOS. The storage layer's locks use fcntl, so it does not import on Windows; there, use WSL or a Linux container.

pip install isocenter

Release candidates: pip install --pre isocenter.

python -c "import isocenter; print(isocenter.__version__)"

The OCR and NLP extras, and what each needs, are on the installation page.

Example

Put some DICOM files in input/ and run:

from isocenter import Session

# Worker processes are started by spawn, so a script needs this guard.
if __name__ == "__main__":
    with Session("my_project.db") as session:   # the session store
        session.ingest("input")                  # reads; never writes the source
        report = session.audit()                 # findings under the default policy
        session.anonymize(report)                # in memory
        summary = session.export("export_clean")
        print(len(summary.written_uids), "files written")
        session.generate_report("compliance_report.md")

With no configuration loaded, the default policy is the Basic Profile table (646 tag rules), with Study Date jittered, Patient's Sex and Age kept, and private tags removed. export_clean/ holds one Subject_ANON_… folder per patient written. An image the default lossless JPEG 2000 cannot hold (32-bit samples, for example) is not written: its ERROR row says so and names use_compression=False. The Executive Summary of compliance_report.md opens with the grade. The Quick Start adds a configuration, redaction, reversible anonymization and a verify step, and the tutorials run each step on files bundled with pydicom.

Burned-in text

Machines burn identifiers into the pixels, and the same model tends to burn them in the same place every time. Isocenter finds that text by OCR and blanks it with redaction zones you write per device. The OCR guide covers both.

5b. Zone Discovery

discover_redaction_zones() OCRs a random sample of one machine's instances and returns a DiscoveryResult of where text was found, so you can write zones from what the data does rather than from one screenshot. The scan needs the ocr extra (pip install "isocenter[ocr]") and the tesseract binary; without either it raises OcrUnavailableError naming what is missing.

result = session.discover_redaction_zones("SN-12345", sample_size=50, min_confidence=80.0)

# Suggested zones, in the [y1, y2, x1, x2] form the redaction config takes.
for zone in result.to_zones(min_occurrence=0.25):
    print(zone["type"], zone["zone"], zone["examples"])

to_zones() clusters the candidates, and keeps only clusters seen in at least min_occurrence of the sampled instances: a name in one frame out of fifty is noise, one in forty is the overlay. Working on a DiscoveryResult needs no extra:

>>> from isocenter.discovery import DiscoveryCandidate, DiscoveryResult
>>> result = DiscoveryResult([
...     DiscoveryCandidate("SMITH^JOHN", 92.0, [10, 8, 60, 12], 0, "NAME_PATTERN"),
...     DiscoveryCandidate("MERCY GENERAL", 88.0, [200, 180, 50, 10], 1, "PROPER_NOUN"),
... ], n_sources=2)
>>> list(result.to_dataframe().columns)
['text', 'confidence', 'box', 'source_index', 'classification']
>>> result.get_density_matrix(bins=(2, 2))
[[1, 0], [0, 1]]
>>> result.to_zones(min_occurrence=0.5)
[{'zone': [8, 20, 10, 70], 'type': 'LIKELY_NAME', 'occurrence': 0.5, 'confidence': 92.0, 'examples': ['SMITH^JOHN']}, {'zone': [180, 190, 200, 250], 'type': 'PROPER_NOUN', 'occurrence': 0.5, 'confidence': 88.0, 'examples': ['MERCY GENERAL']}]

filter(), to_zones() and to_dataframe() are frozen for 1.x; get_density_matrix() is documented but internal (API stability). get_density_matrix() is not an image-space heatmap. It bins each box's centre into a grid normalised by the largest box origin among the candidates, not by the image's Rows and Columns, so two scans are not comparable to each other or to the image. Take coordinates from to_zones() or from each candidate's box.

Writing the zones

Zones go in the configuration file, under the machine they belong to:

machines:
  - serial_number: "DEV12345"
    model_name: "UltraSound Pro"
    redaction_zones:
      - [0, 50, 0, 800] # [row_start, row_end, col_start, col_end]

Documentation

Citing Isocenter

If Isocenter's de-identification is part of how a dataset was prepared, it belongs in the methods section rather than the acknowledgements. Use GitHub's Cite this repository button, which reads CITATION.cff.

Each release is archived on Zenodo. Cite the concept DOI, 10.5281/zenodo.22104298, which always resolves to the latest version, so the citation follows the work. If you need to record the exact version used, name it in the text (Isocenter v1.0.0) and leave the DOI pointing at the concept record.

Isocenter is the upstream half of a pair: it builds and de-identifies the corpus that Murmur Studio (10.5281/zenodo.21077528) reviews. Work that used both should cite both.

License

Apache-2.0. See LICENSE and NOTICE.

Releases up to and including 0.9.2 were published under the GNU Affero General Public License v3.0 or later and remain available under it; the change is not retroactive.

Contact

Bug reports and questions about documented behaviour go to GitHub Issues; they are answered there, in public, for free.

Help beyond that is available as paid consulting: configuring a de-identification profile for a protocol, integrating Isocenter into a pipeline, reviewing a run's report before it goes to a reviewer, or a feature your study needs sooner than the roadmap. Write to support@isocenter.net with what you need, and use the same address for anything that should not be public.

Release files for isocenter 1.0.0rc2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for isocenter 1.0.0rc2
File Size Uploaded
isocenter-1.0.0rc2.tar.gz 2.3 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for isocenter 1.0.0rc2
File Interpreter ABI Platform
isocenter-1.0.0rc2-py3-none-any.whl Python 3 none any Details

Total release size: 3.0 MB

Release files / isocenter-1.0.0rc2.tar.gz

Download URL isocenter-1.0.0rc2.tar.gz
Size 2.3 MB
Tags Source
SHA-256 checksum
How to use checksums
4b70f2878b8eeb31cbca2e2ee48efa6dba6206f004d088ac7a76b8568fb7eced
BLAKE2b-256 checksum
How to use checksums
03c2e1cbdc77ef3d4fd6f0808fb163014f7ab5e01206271969c1872a408394e7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release files / isocenter-1.0.0rc2-py3-none-any.whl

Download URL isocenter-1.0.0rc2-py3-none-any.whl
Size 673.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
acb6ea588478e6a76cd368704264aa59f77c5b6fcde0d7eac166ee4d8ff73267
BLAKE2b-256 checksum
How to use checksums
34308bd5773e5aec59181e2ddadc15efe73f6ad4343fa26a5469ee8e87d831d5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.0.0rc2 This release

2 release files

0.9.8

2 release files

0.9.7

2 release files

0.9.6

2 release files

0.9.5

2 release files

0.9.4

2 release files

0.9.3

2 release files

0.9.2

2 release files

0.9.1

2 release files

0.9.0

2 release files

0.8.2

2 release files

0.8.1

2 release files

0.8.0

2 release files

0.7.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page