⚠️ Research use only. Transducin is a research pipeline for parsing proprietary OCT formats and generating standard DICOM Structured Reports. It has not received regulatory clearance or approval from any health authority (COFEPRIS, FDA, CE marking, or equivalent) for clinical use. It performs no diagnostic classification or interpretation — it reproduces, in standard DICOM form, quantitative measurements already computed by the source device's own firmware. This software must not be used for clinical diagnosis, treatment decisions, or patient management.
Multi-vendor OCT → DICOM pipeline for RetinaOS. Converts proprietary ophthalmic OCT files to standard DICOM, extracts clinical measurements (CMT, ETDRS 9-sector grid, mRNFL/pRNFL, mGCIPL, biometry), generates TID 1500 Structured Reports with full anatomic context, and sends them to an Orthanc PACS via C-STORE.
Transducin generating a TID 1500 SR from a Revo FC130 .OPT file and displaying it in OHIF Viewer:
https://github.com/oftalmos-org/transducin/raw/main/demo/Transducin_in_OHIF_example_video.mp4
- Full Revo FC130 pipeline: B-scans, SLO, ENFACE, ANGPRV, OCTA_MIP →
OphthalmicTomographyImageStorage - All Revo FC130 scan types: macular, optic_nerve, angio, hd_line, ultra_wide, wide_field, biometry, fundus (detection by chunk presence and dimensions)
- Clinical extraction: CMT, ETDRS 9-sector grid, pRNFL (peripapillary), mRNFL, mGCIPL, biometry (AL, CCT), C/D ratio
- SR TID 1500/1501 with full anatomic context (FindingSite, laterality, S/N/I/T topographic modifiers)
- Standardized PatientID protocol
- Multi-vendor hot folder watcher
- C-STORE → Orthanc PACS
- Cirrus HD-OCT
.EX.DCM: CMT/RNFL/GCL from private tags(0073,xxxx)+ SR TID 1500 - Cirrus PDF export: Macular Thickness OU, ONH+RNFL OU, Ganglion Cell OU (minimum mGCIPL)
- PTS 925Wi Optopol (perimetry): DICOM Secondary Capture (Modality OPV) with embedded PDF
- Heidelberg Spectralis
.e2e, Topcon.fds/.fda, Bioptigen.OCTvia oct-converter - Visual field SR TID 6002 (Supplement 247 — pending highdicom #406)
- OCT SR migration to DICOM Supplement 247 TID 6001–6007
input/REVO/*.opt input/CIRRUS/*.EX.DCM
│ │
revo_opt_reader ←── segmentation cirrus_extractor
(B-scans + SLO/ENFACE/ANGPRV (private tags 0073,xxxx)
+ ETDRS + mRNFL + mGCIPL │
+ biometry + SQI + TRAJ) │
│ │
opt_extractor ─┴─────────────┐
(filename + PARAMS.DAT │
+ MYOPI JSON + scan type) OCTClinicalData
│ │
└───────────────────────────────────────────┘
│
sr_builder (TID 1500: anatomic context + FindingSite + laterality)
│ groups: macular · peripapillary · biometry
hot_folder_watcher
│
C-STORE → Orthanc PACS
| Module | Function |
|---|---|
clinical_data.py |
Dataclasses: OCTClinicalData, ETDRSGrid, RNFLSectors, VisualFieldData (PTS) |
opt_extractor.py |
Revo FC130 .opt metadata: filename, PARAMS.DAT zlib, MYOPI JSON (biometry), scan type detection by chunk presence and dimensions |
revo_opt_reader.py |
.opt B-scans → OphthalmicTomographyImageStorage + SLO/ENFACE/ANGPRV/OCTA_MIP → OphthalmicPhotography8Bit + CMT/ETDRS/pRNFL/mRNFL/mGCIPL from segmentation |
sr_builder.py |
DICOM SR TID 1500 — macular, peripapillary, and biometry groups; vendor-aware (Optopol / Zeiss) |
cirrus_extractor.py |
Extracts CMT, ETDRS, RNFL, C/D from CZM private tags (0073,xxxx) in .EX.DCM files |
cirrus_pdf_extractor.py |
Cirrus PDF OCR: Macular Thickness OU, ONH+RNFL OU, Ganglion Cell OU → OCTClinicalData |
pts925_extractor.py |
PTS 925 Optopol perimetry → VisualFieldData → SOP 1.2.840.10008.5.1.4.1.1.80 |
hot_folder_watcher.py |
Multi-vendor watcher: .opt .dcm .EX.DCM .pdf .OCT .e2e .fds .fda → pipeline → C-STORE |
verify_sr.py |
Validates SR: TID 1500, PatientID, SNOMED-CT (9 codes), Orthanc REST query |
| Manufacturer | Device | Format | Status |
|---|---|---|---|
| Optopol | Revo FC130 | .opt |
B-scans + SLO/ENFACE/ANGPRV + ETDRS + mRNFL + mGCIPL + MYOPI biometry |
| Carl Zeiss Meditec | Cirrus HD-OCT | .ex.dcm |
CMT/RNFL/GCL from private tags (0073,xxxx) + SR TID 1500 |
| Bioptigen / Leica | various | .OCT |
Planned v1.2 via oct-converter |
| Topcon | DRI OCT Triton/Atlantis | .fds, .fda |
Planned v1.2 via oct-converter |
| Heidelberg Engineering | Spectralis | .e2e |
Planned v1.2 via oct-converter |
Detection based on chunks present (ANGPRV, DMARKERS, EYE) and n_bscans × n_ascans dimensions.
| Type | Dimensions (B-scans × A-scans) | Output images |
|---|---|---|
macular |
168 × 1024 (6×6 mm cube) | _OCT.dcm, _SLO.dcm, _ENFACE.dcm |
optic_nerve |
192 × 640 (6 mm ONH cube) | _OCT.dcm, _SLO.dcm |
angio |
320 × 320 (3 mm OCTA) | _OCT.dcm, _SLO.dcm, _ENFACE.dcm, _ANGPRV.dcm, _OCTA_MIP.dcm |
hd_line |
18–25 × 1024 (HD raster) | _OCT.dcm, _SLO.dcm |
ultra_wide |
1 × 10240 or 6 × 8192 (14–16 mm field) | _OCT.dcm, _SLO.dcm |
wide_field |
5 × 1536 (12 mm field) | _OCT.dcm, _SLO.dcm |
biometry |
BMETR + MYOPI JSON (zlib) | data only → biometry SR |
fundus |
Color_fundus (from filename) | skipped (no measurements) |
- Laterality: inferred from the arithmetic sign of OCTPARAMS tag 23 (foveal horizontal position in mm); validated at 100% across 18 files from two device models and three software versions.
- Calibrated PixelSpacing: derived from scan parameters in the PARAMS.DAT chunk; all
OphthalmicTomographyImageStorageinstances includePixelSpacingwith real µm/px scale. - AnatomicRegionSequence: present in all image and SR instances; encoded with SNOMED-CT SRT (T-AA610 posterior segment, T-AA700 anterior segment) per DICOM CP-1676.
Structured Reports follow TID 1500/1501 with full anatomic context. Each measurement includes FindingSite (anatomic site), SNOMED-CT laterality, and topographic modifier where applicable. AlgorithmIdentification references Transducin/<__version__> in each group.
| Measurement | SCT code | Unit | Site |
|---|---|---|---|
| CMT — Central Macular Thickness | 422453003 |
µm | Fovea centralis |
| ETDRS C (central subfield) | 422453003 |
µm | Fovea centralis |
| ETDRS S1/N1/I1/T1 (1–3 mm ring) | 422399008 |
µm | Retina + S/N/I/T mod. |
| ETDRS S2/N2/I2/T2 (3–6 mm ring) | 422399008 |
µm | Retina + S/N/I/T mod. |
| mRNFL global and S/I sectors | 422995006 |
µm | Retina |
| mGCIPL global and S/I sectors | 422455005 |
µm | Retina |
| Measurement | SCT code | Unit | Site |
|---|---|---|---|
| pRNFL global | 422995006 |
µm | Optic nerve head |
| pRNFL S/N/I/T sectors | 422995006 |
µm | Optic nerve head + mod. |
| C/D ratio | 363932005 |
— | Optic nerve head |
| Measurement | SCT code | Unit |
|---|---|---|
| Axial length (AL) | 252017007 |
mm |
| CCT — central corneal thickness | 397545004 |
mm |
| K1 — flat meridian keratometry | 252014009 |
mm |
| K2 — steep meridian keratometry | 252016006 |
mm |
This software is provided for research and technical integration purposes only. It is not a certified medical device. The implementer is responsible for any clinical validation required by their jurisdiction.
cirrus_pdf_extractor.py requires poppler for PDF rendering:
# macOS
brew install poppler
# Windows
conda install -c conda-forge poppler# Requires Python >=3.11
git clone https://github.com/oftalmos-org/transducin.git
cd transducin
python3 -m venv .venv
source .venv/bin/activate
pip install -e .# As root:
git clone https://github.com/oftalmos-org/transducin.git /opt/transducin
bash /opt/transducin/deploy/install.shThe deploy/install.sh script:
- Installs Python 3.11 via
dnf - Creates a
transducinsystem user - Creates directories
/data/input/REVO,/data/output,/var/log/transducin - Installs the package into
/opt/transducin/venv/ - Registers and starts the
transducin.servicesystemd unit
Configure Orthanc in /etc/systemd/system/transducin.service and reload:
# Edit host/port for your infrastructure
systemctl edit transducin.service
# Add under [Service]:
# ExecStart=... --orthanc-host <IP_ORTHANC> --orthanc-port 4242
systemctl daemon-reload
systemctl start transducin
journalctl -fu transducin# Production watcher
python -m transducin.hot_folder_watcher \
--watch input/REVO \
--output Output \
--orthanc-host <ORTHANC_HOST> \
--orthanc-port 4242
# Local test without C-STORE (process existing files)
python -m transducin.hot_folder_watcher \
--watch input/REVO \
--output Output \
--no-cstore \
--process-existing
# Convert Revo .opt directly to DICOM (B-scans + en-face images)
python -m transducin.revo_opt_reader input/REVO/file.opt -o Output/
# Verify generated SR
python transducin/verify_sr.py Output/sr/file_SR.dcm
# Module self-tests
python -m transducin.opt_extractor
python -m transducin.sr_builder
python -m transducin.verify_srThe watcher accepts configuration via environment variables or CLI arguments:
| Env variable | CLI argument | Default |
|---|---|---|
ORTHANC_HOST |
--orthanc-host |
<ORTHANC_HOST> |
ORTHANC_PORT |
--orthanc-port |
4242 |
ORTHANC_AET |
--orthanc-aet |
ORTHANC |
TRANSDUCIN_AET |
— | TRANSDUCIN |
| Component | Address |
|---|---|
| Orthanc PACS | <ORTHANC_HOST>:4242 (DICOM) / :8042 (REST) |
| OHIF Viewer | http://<ORTHANC_HOST>:3000 |
| Local AET | TRANSDUCIN |
| Revo input | input/REVO/ |
| Logs | logs/watcher_YYYYMMDD.log |
| Library | Version | Role |
|---|---|---|
| Python | ≥3.11 | Runtime (.venv/bin/python — Oracle Linux production) |
| pydicom | ≥3.0.1 | DICOM read/write, VR, UIDs |
| highdicom | ≥0.27.0 | SR TID 1500/1501 — ComprehensiveSR, MeasurementReport, FindingSite |
| pynetdicom | latest | C-STORE SCU to Orthanc |
| watchdog | latest | Hot folder — FileSystemEventHandler |
| numpy | latest | Pixel data arrays and OCT segmentation |
| pdfplumber | latest | Text and image extraction from Cirrus PDFs |
| pdf2image | ≥1.17.0 | PDF → PIL Image rendering (requires poppler) |
| zlib | stdlib | Revo FC130 .opt chunk decompression |
DICOM Storage Classes:
OphthalmicTomographyImageStorage1.2.840.10008.5.1.4.1.1.77.1.5.4OphthalmicPhotography8BitImageStorage1.2.840.10008.5.1.4.1.1.77.1.5.1(SLO, ENFACE, ANGPRV)- SR TID 1500/1501 Measurement Report with anatomic context
| Version | Description |
|---|---|
| 1.0.0 | First public release. Full Revo FC130 pipeline (B-scans, SLO, ENFACE, ANGPRV, OCTA_MIP). Clinical extraction: CMT, ETDRS 9-sector grid, pRNFL, mRNFL, mGCIPL, biometry, C/D ratio. SR TID 1500/1501 with anatomic context. Cirrus HD-OCT .EX.DCM private tags + vendor-aware SR. Cirrus PDF OCR. PTS 925Wi perimetry. Standardized PatientID protocol. |
Transducin/
├── transducin/ # Core RetinaOS modules
│ ├── clinical_data.py
│ ├── opt_extractor.py
│ ├── revo_opt_reader.py
│ ├── sr_builder.py
│ ├── cirrus_extractor.py
│ ├── cirrus_pdf_extractor.py
│ ├── pts925_extractor.py
│ ├── hot_folder_watcher.py
│ └── verify_sr.py
├── deploy/ # Production deployment
│ ├── transducin.service # Systemd unit (Oracle Linux 9 / RHEL 9)
│ └── install.sh # Automated install script
├── input/REVO/ # .opt input files (not versioned)
├── Output/ # Generated DICOM (not versioned)
└── logs/ # Watcher logs (not versioned)
PACS maintenance tools at the repository root (require Orthanc connection via .env):
| Script | Function |
|---|---|
backfill_cirrus_studydesc.py |
Retroactive StudyDescription fix for Cirrus studies already in Orthanc |
backfill_revo_studydesc.py |
Retroactive StudyDescription fix for Revo studies already in Orthanc |
fix_cirrus_merges.py |
Repair merged Cirrus study UIDs (split incorrectly merged studies) |
fix_cirrus_pids.py |
Repair Cirrus PatientID mismatches against the standardized protocol |
reprocess_cirrus.py |
Reprocess Cirrus .EX.DCM batch (re-extract + re-upload SR) |
reprocess_cooked_opts.py |
Reprocess already-converted .opt files (SR only, skip image re-export) |
reprocess_cirrus_transpose.py |
Fix transposed Cirrus series (B-scan orientation correction) |
retag_cirrus_studies.py |
Retag Cirrus study metadata in Orthanc |
scan_type_counter.py |
Count scan types in corpus (source data for paper Table 3) |
scripts/batch_opt_to_dicom.py |
Batch .opt → DICOM locally without C-STORE (set --input/--output) |
Apache 2.0 — Copyright (c) 2026 Jesús Noel Jaurrieta Hinojos. See LICENSE.
Multi-vendor support (Heidelberg, Topcon, Bioptigen) planned for v1.2 via oct-converter as an optional dependency.
SOCT documentation available from Optopol Technology upon request.
