127 lines
5.2 KiB
Markdown
127 lines
5.2 KiB
Markdown
# mkiso PHP Scripts — Analysis
|
||
|
||
## File Inventory
|
||
|
||
| File | Purpose | Output |
|
||
|------|---------|--------|
|
||
| `mkiso.php` | Retrieve DICOM studies by accession number from PACS, wrap in ISO with microdicom viewer, serve as download | ISO download |
|
||
| `mkiso2.php` | Retrieve DICOM studies from PACS, then forward to another PACS (C-STORE relay) | DICOM forwarded to `172.16.0.120:104` |
|
||
| `mkiso_multiple.php` | Multi-accession variant of mkiso.php, with patient-name lookup in DB, ISO download | ISO download with patient-name filename |
|
||
|
||
---
|
||
|
||
## Shared Flow (all three scripts)
|
||
|
||
```
|
||
1. Parse accession_number from GET parameter
|
||
2. Create temp working dir: /tmp/dicomdir_<uniqid>/
|
||
3. Copy microdicom viewer files into temp dir (bootstrap DICOM viewer ISO)
|
||
4. Fetch DICOM studies from PACS via Java dcm4che2 dcmqr (C-MOVE)
|
||
5. [PACS is: ABPACS@localhost:11112, AE CDRECORD:10104 is the local receiver]
|
||
```
|
||
|
||
---
|
||
|
||
## The Java Command — Deep Dive
|
||
|
||
```bash
|
||
JAVA_HOME=/usr/lib/jvm/jdk1.8.0_144 LANG=en_US.iso-8859-1 \
|
||
/usr/local/dcm4che/dcm4che2/bin/dcmqr \
|
||
-L CDRECORD:10104 \
|
||
ABPACS@localhost:11112 \
|
||
-cmove CDRECORD \
|
||
-qAccessionNumber=${accession_number} \
|
||
-cstore ${cstore} \
|
||
-cstoredest ${dicomdir}/DICOMDIR
|
||
```
|
||
|
||
**This single Java process does FOUR things:**
|
||
|
||
| Role | Parameter | Description |
|
||
|------|-----------|-------------|
|
||
| **Storage SCP** | `-L CDRECORD:10104` | Listens as AE `CDRECORD` on port `10104` to receive incoming C-STORE from PACS |
|
||
| **Query SCU** | `-qAccessionNumber=X` | Queries PACS for studies matching the accession number |
|
||
| **C-MOVE SCU** | `-cmove CDRECORD` | Tells PACS to send matched studies to `CDRECORD` (itself) |
|
||
| **File writer** | `-cstoredest DICOMDIR` | Saves received DICOM files to the specified directory |
|
||
|
||
**The `-cstore` parameter** specifies a DICOM SOP Class to negotiate. dcm4che2 maps the two-letter modality codes to SOP Class UIDs internally:
|
||
|
||
| Code | SOP Class | UID |
|
||
|------|-----------|-----|
|
||
| CR | Computed Radiography | 1.2.840.10008.5.1.4.1.1.1 |
|
||
| CT | CT Image Storage | 1.2.840.10008.5.1.4.1.1.2 |
|
||
| MR | MR Image Storage | 1.2.840.10008.5.1.4.1.1.4 |
|
||
| US | Ultrasound Image | 1.2.840.10008.5.1.4.1.1.6.1 |
|
||
| NM | Nuclear Medicine | 1.2.840.10008.5.1.4.1.1.20 |
|
||
| PET | PET Image | 1.2.840.10008.5.1.4.1.1.128 |
|
||
| SC | Secondary Capture | 1.2.840.10008.5.1.4.1.1.7 |
|
||
| XA | X-Ray Angio | 1.2.840.10008.5.1.4.1.1.12.1 |
|
||
| XRF | X-Ray Fluoroscopy | 1.2.840.10008.5.1.4.1.1.12.2 |
|
||
| DX | Digital X-Ray | 1.2.840.10008.5.1.4.1.1.1.1 |
|
||
| MG | Mammography | 1.2.840.10008.5.1.4.1.1.1.2 |
|
||
| PR | Presentation State | 1.2.840.10008.5.1.4.1.1.11.1 |
|
||
| KO | Key Object Selection | 1.2.840.10008.5.1.4.1.1.88.59 |
|
||
| SR | Structured Report | 1.2.840.10008.5.1.4.1.1.88.11 |
|
||
|
||
**The loop iterates over ALL 14 modalities for the same accession number.** Most will return nothing — the script uses a brute-force "try everything" approach since it doesn't know which modality a given accession number uses.
|
||
|
||
---
|
||
|
||
## Per-Script Differences
|
||
|
||
### mkiso.php
|
||
```
|
||
Fetch → genisoimage → serve ISO download → cleanup
|
||
```
|
||
- ISO filename: `{accession_number}.iso`
|
||
- After PACS fetch: creates ISO with genisoimage, streams it as download, deletes temp files
|
||
|
||
### mkiso2.php
|
||
```
|
||
Fetch → dcmsend to 172.16.0.120:104 → exit
|
||
```
|
||
- **No ISO creation.** Instead forwards retrieved DICOM files to another PACS server (`172.16.0.120:104`)
|
||
- Uses `dcmsend +sd +rd 172.16.0.120 104 $dicomdir/DICOMDIR` (dcmtk `dcmsend` — a C-STORE SCU)
|
||
- ISO creation and download code is commented out
|
||
- This script acts as a **DICOM relay/proxy**: PACS A → temp dir → PACS B
|
||
|
||
### mkiso_multiple.php
|
||
```
|
||
Parse comma-separated ACC#s → DB lookup (patient name) →
|
||
for each ACC#, for each modality: fetch from PACS →
|
||
genisoimage → serve ISO download → cleanup
|
||
```
|
||
- Supports **comma-separated** accession numbers (e.g. `?accession_number=MR.001,CT.002`)
|
||
- **Database lookup** on two DBs:
|
||
- `pacsdb_his` (192.168.2.7) — finds `AccessionNumber` → `MEDRECID`, `RegID`
|
||
- `pacsdb_his` — `MEDRECID` → `Nama` (patient name)
|
||
- ISO filename: `{PATIENT_NAME}-{ACCESSION_LIST}.iso` (alphanumeric only)
|
||
- Inner loop: for each accession number, try all 14 modalities
|
||
|
||
---
|
||
|
||
## DICOM Operations Summary
|
||
|
||
| Script | C-MOVE (PACS→local) | C-STORE (local→PACS2) | ISO gen | DB lookup |
|
||
|--------|---------------------|----------------------|---------|-----------|
|
||
| mkiso.php | ✅ 14 modality loop | ❌ | ✅ | ❌ |
|
||
| mkiso2.php | ✅ 14 modality loop | ✅ (dcmsend) | ❌ | ❌ |
|
||
| mkiso_multiple.php | ✅ 14 modality × N acc# | ❌ | ✅ | ✅ (patient name) |
|
||
|
||
---
|
||
|
||
## Environment
|
||
|
||
| Component | Version/Location |
|
||
|-----------|-----------------|
|
||
| dcm4che2 (Java) | `/usr/local/dcm4che/dcm4che2/bin/dcmqr` |
|
||
| Java | JDK 1.8.0_144 (`/usr/lib/jvm/jdk1.8.0_144`) |
|
||
| genisoimage | `/usr/bin/genisoimage` |
|
||
| dcmsend | `/usr/bin/dcmsend` (dcmtk C-STORE SCU) |
|
||
| dcmtk (static) | `/data/dcmtk-bin/` (v3.6.6) — findscu, movescu, storescp, getscu |
|
||
| microdicom | `/var/www/html/microdicom/` (DICOM viewer bootstrap files) |
|
||
| PACS source | `ABPACS@localhost:11112` |
|
||
| Local AE | `CDRECORD:10104` |
|
||
| PACS dest (mkiso2) | `172.16.0.120:104` |
|
||
| DB (mkiso_multiple) | `192.168.2.7:3306` (pacsdb_his / rsabt201107) |
|