Skip to content

Commit 60b626e

Browse files
committed
Modified documentation, refactor
Signed-off-by: Gonzalo de Pedro <gonzalodepedro@ekumenlabs.com>
1 parent 6364792 commit 60b626e

9 files changed

Lines changed: 186 additions & 234 deletions

File tree

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,7 @@ log/
1717
.idea/
1818

1919
# Other
20-
*.swp
20+
*.swp
21+
22+
# Dicom samples
23+
dicom_to_ros_demo/dicom_samples

README.md

Lines changed: 52 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -44,29 +44,35 @@ This framework is designed to accelerate innovation in **robotic-assisted surger
4444

4545
```
4646
dicom_to_ros/
47-
├── dicom_interfaces/ # Custom ROS 2 message definitions
47+
├── docker/ # Core pipeline Docker setup
48+
│ ├── Dockerfile # ROS 2 pipeline image (listener + all nodes)
49+
│ └── docker-compose.yml # Runs the dicom_listener container
50+
├── dicom_interfaces/ # Custom ROS 2 message definitions
4851
│ └── msg/
49-
│ ├── Dicom.msg # Central internal message (metadata + pixel data)
50-
│ └── StudyInfo.msg # Patient and study metadata subset
51-
├── dicom_to_ros/ # Core ROS 2 package — 6 microservice nodes
52+
│ ├── Dicom.msg # Central internal message (metadata + pixel data)
53+
│ └── StudyInfo.msg # Patient and study metadata subset
54+
├── dicom_to_ros/ # Core ROS 2 package — 6 microservice nodes
5255
│ └── dicom_to_ros/
53-
│ ├── dicom_server.py # DICOM SCP listener (entry point)
54-
│ ├── dicom_2_img.py # 2D image publisher
55-
│ ├── dicom_2_video.py # 3D volume → video stream publisher
56-
│ ├── dicom_2_pcl.py # Point cloud publisher
57-
│ ├── dicom_2_tf.py # TF transform publisher
56+
│ ├── dicom_server.py # DICOM SCP listener (entry point)
57+
│ ├── dicom_2_img.py # 2D image publisher
58+
│ ├── dicom_2_video.py # 3D volume → video stream publisher
59+
│ ├── dicom_2_pcl.py # Point cloud publisher
60+
│ ├── dicom_2_tf.py # TF transform publisher
5861
│ ├── dicom_2_study_info.py # Study metadata publisher
59-
│ └── dicom_utils.py # Shared utilities
60-
├── dicom_to_ros_demo/ # Docker-based demo environment
61-
│ ├── docker/
62-
│ │ ├── docker-compose.yml
63-
│ │ ├── Dockerfile.bridge
64-
│ │ └── Dockerfile.downloader
65-
│ ├── rviz_config/ # Pre-configured RViz2 layout
62+
│ └── dicom_utils.py # Shared utilities
63+
├── dicom_to_ros_demo/ # Demo environment
64+
│ ├── dicom_samples/ # DICOM test data (auto-downloaded on first run)
65+
│ │ ├── 2D/
66+
│ │ └── 3D/
67+
│ ├── docker/ # Demo-specific Docker setup
68+
│ │ ├── Dockerfile.downloader # Sample downloader image
69+
│ │ ├── Dockerfile.rviz # RViz2 visualization image
70+
│ │ └── docker-compose.yml # Orchestrates downloader + RViz2
71+
│ ├── rviz_config/ # Pre-configured RViz2 layout
6672
│ └── test_data_utils/
67-
│ └── download_samples.py
73+
│ └── download_samples.py # Script to fetch public DICOM samples
6874
└── doc/
69-
└── dicom_to_ros.png
75+
└── workflow_dicom.png
7076
```
7177

7278
---
@@ -116,73 +122,47 @@ DICOM Client (storescu)
116122

117123
> **Synchronization:** All messages produced from a single DICOM file share the same `header.stamp`, making them compatible with `message_filters::TimeSynchronizer` for exact alignment of spatial, visual, and clinical data.
118124
119-
<!-- ### Image Normalization
125+
### Image Normalization
120126

121-
DICOM images are typically 12-bit or 16-bit integers. The pipeline normalizes them to `mono8` (uint8) for compatibility with standard ROS 2 computer vision tooling:
127+
DICOM images often come in 12-bit or 16-bit integers with varying ranges.
128+
To make them compatible with standard Computer Vision tools (OpenCV/ROS), the imaging nodes perform Min-Max normalization to cast them to `mono8` (uint8):
122129

123-
$$Pixel_{new} = \frac{(Pixel_{raw} - Pixel_{min})}{(Pixel_{max} - Pixel_{min})} \times 255$$ -->
130+
$$Pixel_{new} = \frac{(Pixel_{raw} - Pixel_{min})}{(Pixel_{max} - Pixel_{min})} \times 255$$
124131

125-
---
126-
127-
<!-- ## Quick Start (Docker)
128-
129-
### Prerequisites
132+
### Metadata and Data Flow
130133

131-
- [Docker](https://docs.docker.com/get-docker/) and [Docker Compose](https://docs.docker.com/compose/)
132-
- A Linux host with X11 (for RViz2 visualization)
134+
The `dicom_server` node is responsible for parsing the incoming DICOM file. It extracts all necessary metadata—including patient info, study details, and geometric data—and publishes it in a single, comprehensive `dicom_interfaces/Dicom` message.
133135

134-
### Run the Demo
136+
Downstream nodes subscribe to this topic and use the pre-parsed data:
137+
* The `dicom2studyinfo` node subscribes to the `Dicom` message and republishes a subset of this information (patient demographics and study details) as a `StudyInfo` message. The fields include:
138+
* **Identifiers:** `patient_id`, `patient_name`, `sop_instance_uid`
139+
* **Demographics:** `sex`, `age`
140+
* **Scan Details:** `modality`, `study_date`, `series_description`
141+
* The imaging (`dicom2img`, `dicom2video`) and point cloud (`dicom2pcl`) nodes use the geometric data like `pixel_spacing` and `slice_thickness` directly from the `Dicom` message to generate physically accurate `CameraInfo` and `PointCloud2` messages.
135142

136-
```bash
137-
git clone https://github.com/Ekumen-OS/dicom_to_ros.git
138-
cd dicom_to_ros/dicom_to_ros_demo
139143

140-
# Allow X11 connections from Docker
141-
xhost +local:root
142-
143-
# Build and start the full pipeline (DICOM listener + RViz2)
144-
docker compose up --build -d
145-
```
146-
147-
On first run, a `sample_downloader` service automatically downloads and organizes sample DICOM files into `dicom_samples/2D/CT/`, `dicom_samples/3D/MRI/`, etc. The pipeline starts immediately after and listens for DICOM connections on port `11112`.
148-
149-
### Send a DICOM File
144+
---
150145

151-
Install `dcmtk` on your host machine:
146+
## Quick Start (Docker)
152147

153-
```bash
154-
sudo apt update && sudo apt install dcmtk -y
155-
```
156-
157-
Send any DICOM file to the running pipeline:
148+
### Prerequisites
158149

159-
```bash
160-
storescu -v 127.0.0.1 11112 -aec ROS_DICOM_AE <path_to_dicom_file>
161-
```
150+
- [Docker](https://docs.docker.com/get-docker/) and [Docker Compose](https://docs.docker.com/compose/)
151+
- A Linux host with X11 (for RViz2 visualization)
162152

163-
### Verify Output
153+
### Running the Core Pipeline
164154

165-
Exec into the container to inspect the live topics:
155+
The `docker/` directory runs the ROS 2 DICOM listener and all processing nodes. It mounts the `dicom_interfaces` and `dicom_to_ros` packages from the repo root into the container workspace.
166156

167157
```bash
168-
docker exec -it dicom_listener /bin/bash
169-
source /ros2_ws/install/setup.bash
170-
171-
# View study metadata
172-
ros2 topic echo /dicom_study_info
158+
git clone https://github.com/Ekumen-OS/dicom_to_ros.git
159+
cd dicom_to_ros
173160

174-
# View all active topics
175-
ros2 topic list
161+
export GID=$(id -g)
162+
docker compose -f docker/docker-compose.yml up --build -d
176163
```
177164

178-
View images from the host:
179-
180-
```bash
181-
ros2 run rqt_image_view rqt_image_view
182-
# Select /dicom_image or /dicom_video_frames from the dropdown
183-
```
184-
185-
3D point clouds and TF transforms are visualized automatically in the RViz2 instance launched by Docker Compose.
165+
The pipeline starts immediately and listens for DICOM C-STORE requests on port `11112`.
186166

187167
### DICOM Server Parameters
188168

@@ -193,16 +173,11 @@ ros2 run rqt_image_view rqt_image_view
193173

194174
---
195175

196-
## Test Data
197-
198-
The automated downloader fetches small, freely hosted DICOM samples sufficient for functional verification. For high-resolution clinical rendering (detailed head CTs, torso MRIs), manually place DICOM files into `dicom_samples/` from these sources:
176+
## Demo
199177

200-
- **[OsiriX DICOM Library](https://www.osirix-viewer.com/resources/dicom-image-library/)** — High-resolution 3D volumes (e.g., MANIX head CTA)
201-
- **[The Cancer Imaging Archive (TCIA)](https://www.cancerimagingarchive.net/)** — Large-scale real-world clinical datasets
202-
- **[Siemens MAGNETOM World](https://www.magnetomworld.siemens-healthineers.com/clinical-corner/protocols/dicom-images)** — Clinical-grade MRI from Siemens scanners
203-
- **[DICOM Library](https://www.dicomlibrary.com/)** — Anonymized pathological examples
178+
For a more detailed demo, please check the [dicom_to_ros_demo](dicom_to_ros_demo/README.md) folder.
204179

205-
--- -->
180+
---
206181

207182
## Contributing
208183

@@ -219,5 +194,5 @@ This project is licensed under the **Apache License 2.0**. See [LICENSE](LICENSE
219194
---
220195

221196
<div align="center">
222-
<sub>Built with care by <a href="https://ekumenlabs.com">Ekumen Labs</a></sub>
197+
<sub>by <a href="https://ekumenlabs.com">Ekumen Labs</a></sub>
223198
</div>

0 commit comments

Comments
 (0)