Skip to content

Commit 42e5c61

Browse files
author
Christopher Bridge
committed
Various fixes to PIN integration example
Signed-off-by: Christopher Bridge <[email protected]>
1 parent 8e959ab commit 42e5c61

File tree

4 files changed

+61
-47
lines changed

4 files changed

+61
-47
lines changed

integrations/nuance_pin/README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ with minimal code changes.
88

99
## Prerequisites
1010

11-
Before setting up and running the example MONAI spleen segmentation app to run as a Nuance PIN App, the user will need to install/download the following libraries.
11+
Before setting up and running the example MONAI lung nodule detection app to run as a Nuance PIN App, the user will need to install/download the following libraries.
1212
It is optional to use a GPU for the example app, however, it is recommended that a GPU is used for inference as it is very computationally intensive.
1313

1414
Minimum software requirements:
@@ -30,9 +30,9 @@ cd integrations/nuance_pin
3030
In this folder you will see the following directory structure
3131
```bash
3232
nuance_pin
33-
├── app # directory with MONAI app code
34-
├── lib # directory where we will place Nuance PIN wheels
35-
├── model # directory where we will place the model used by our MONAI app
33+
├── app/ # directory with MONAI app code
34+
├── lib/ # you should create this directory where we will place Nuance PIN wheels
35+
├── model/ # directory where we will place the model used by our MONAI app
3636
├── app_wrapper.py # Nuance PIN wrapper code
3737
├── docker-compose.yml # docker compose runtime script
3838
├── Dockerfile # container image build script
@@ -48,7 +48,7 @@ To download the test data you may follow the instructions in the [Lund Nodule De
4848

4949
### Download Nuance PIN SDK
5050

51-
Place the Nuance PIN `ai_service` wheel in the `nuance_pin/lib` folder. This can be obtained in the link provided in step 3 of of the [prerequisites](#prerequisites).
51+
Place the Nuance PIN `ai_service` wheel in the `nuance_pin/lib` folder. This can be obtained in the link provided in step 4 of of the [prerequisites](#prerequisites).
5252

5353
### Running the Example App in the Container
5454

@@ -57,7 +57,7 @@ Now we are ready to build and start the container that runs our MONAI app as a N
5757
docker-compose up --build
5858
```
5959

60-
If the build is successful the a service will start on `localhost:5000`. We can verify the service is running
60+
If the build is successful the service will start on `localhost:5000`. We can verify the service is running
6161
by issuing a "live" request such as
6262
```bash
6363
curl -v http://localhost:5000/aiservice/2/live && echo ""

integrations/nuance_pin/app/inference.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ def pre_process(self, img_reader) -> Compose:
181181
ToTensord(
182182
keys=image_key,
183183
),
184-
ToDeviced(keys=image_key, device="cuda"),
184+
ToDeviced(keys=image_key, device=self.device),
185185
EnsureChannelFirstd(keys=image_key),
186186
Spacingd(keys=image_key, pixdim=(0.703125, 0.703125, 1.25)),
187187
Orientationd(

integrations/nuance_pin/app/post_inference_ops.py

Lines changed: 53 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,26 @@ def compute(self, op_input: InputContext, op_output: OutputContext, context: Exe
4646
series_uid = hd.UID()
4747
series_number = randint(1, 100000)
4848

49+
# One graphic layer to contain all detections
50+
layer = hd.pr.GraphicLayer(
51+
layer_name="LUNG_NODULES",
52+
order=1,
53+
description="Lung Nodule Detections",
54+
)
55+
56+
annotations = []
57+
58+
all_ref_images = [
59+
ins.get_native_sop_instance()
60+
for ins in selected_series.series.get_sop_instances()
61+
]
62+
accession = all_ref_images[0].AccessionNumber
63+
4964
for inst_num, (box_data, box_score) in enumerate(zip(detection_result.box_data, detection_result.score_data)):
5065

66+
tracking_id = f"{accession}_nodule_{inst_num}" # site-specific ID
67+
tracking_uid = hd.UID()
68+
5169
polyline = hd.pr.GraphicObject(
5270
graphic_type=hd.pr.GraphicTypeValues.POLYLINE,
5371
graphic_data=np.array(
@@ -60,8 +78,8 @@ def compute(self, op_input: InputContext, op_output: OutputContext, context: Exe
6078
]
6179
), # coordinates of polyline vertices
6280
units=hd.pr.AnnotationUnitsValues.PIXEL, # units for graphic data
63-
tracking_id="lung_nodule_MONAI", # site-specific ID
64-
tracking_uid=hd.UID(), # highdicom will generate a unique ID
81+
tracking_id=tracking_id,
82+
tracking_uid=tracking_uid,
6583
)
6684

6785
self.logger.info(f"Box: {[box_data[0], box_data[1], box_data[3], box_data[4]]}")
@@ -70,14 +88,8 @@ def compute(self, op_input: InputContext, op_output: OutputContext, context: Exe
7088
text_value=f"{box_score:.2f}",
7189
bounding_box=(box_data[0], box_data[1], box_data[3], box_data[4]), # left, top, right, bottom
7290
units=hd.pr.AnnotationUnitsValues.PIXEL, # units for bounding box
73-
tracking_id="LungNoduleMONAI", # site-specific ID
74-
tracking_uid=hd.UID(), # highdicom will generate a unique ID
75-
)
76-
77-
layer = hd.pr.GraphicLayer(
78-
layer_name="LUNG_NODULE",
79-
order=1,
80-
description="Lung Nodule Detection",
91+
tracking_id=tracking_id,
92+
tracking_uid=tracking_uid,
8193
)
8294

8395
affected_slice_idx = [
@@ -103,37 +115,39 @@ def compute(self, op_input: InputContext, op_output: OutputContext, context: Exe
103115
graphic_objects=[polyline],
104116
)
105117

106-
# Assemble the components into a GSPS object
107-
gsps = hd.pr.GrayscaleSoftcopyPresentationState(
108-
referenced_images=ref_images,
109-
series_instance_uid=series_uid,
110-
series_number=series_number,
111-
sop_instance_uid=hd.UID(),
112-
instance_number=inst_num + 1,
113-
manufacturer="MONAI",
114-
manufacturer_model_name="lung_nodule_ct_detection",
115-
software_versions="v0.2.0",
116-
device_serial_number="",
117-
content_label="ANNOTATIONS",
118-
graphic_layers=[layer],
119-
graphic_annotations=[annotation],
120-
institution_name="MONAI",
121-
institutional_department_name="Deploy",
122-
voi_lut_transformations=[
123-
hd.pr.SoftcopyVOILUTTransformation(
124-
window_center=-550.0,
125-
window_width=1350.0,
126-
)
127-
],
128-
)
118+
annotations.append(annotation)
119+
120+
# Assemble the components into a GSPS object
121+
gsps = hd.pr.GrayscaleSoftcopyPresentationState(
122+
referenced_images=all_ref_images,
123+
series_instance_uid=series_uid,
124+
series_number=series_number,
125+
sop_instance_uid=hd.UID(),
126+
instance_number=1,
127+
manufacturer="MONAI",
128+
manufacturer_model_name="lung_nodule_ct_detection",
129+
software_versions="v0.2.0",
130+
device_serial_number="",
131+
content_label="ANNOTATIONS",
132+
graphic_layers=[layer],
133+
graphic_annotations=annotations,
134+
institution_name="MONAI",
135+
institutional_department_name="Deploy",
136+
voi_lut_transformations=[
137+
hd.pr.SoftcopyVOILUTTransformation(
138+
window_center=-550.0,
139+
window_width=1350.0,
140+
)
141+
],
142+
)
129143

130-
gsps.save_as(os.path.join(output_path, f"gsps-{inst_num:04d}.dcm"))
144+
gsps.save_as(os.path.join(output_path, f"gsps.dcm"))
131145

132-
self.upload_gsps(
133-
file=os.path.join(output_path, f"gsps-{inst_num:04d}.dcm"),
134-
document_detail="MONAI Lung Nodule Detection v0.2.0",
135-
series_uid=series_uid,
136-
)
146+
self.upload_gsps(
147+
file=os.path.join(output_path, f"gsps.dcm"),
148+
document_detail="MONAI Lung Nodule Detection v0.2.0",
149+
series_uid=series_uid,
150+
)
137151

138152

139153
@md.input("original_dicom", List[StudySelectedSeries], IOType.IN_MEMORY)

integrations/nuance_pin/app_wrapper.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ def initialize_class(cls):
7373
monai_app_class_name = cls.monai_app_module.rsplit(".", 1)[1]
7474
if not cls.monai_app_module:
7575
raise ValueError(
76-
"MONAI App to be run has not been specificed in `MONAI_APP_CLASSPATH` environment variable"
76+
"MONAI App to be run has not been specified in `MONAI_APP_CLASSPATH` environment variable"
7777
)
7878

7979
monai_app_class = getattr(import_module(monai_app_class_module), monai_app_class_name)

0 commit comments

Comments
 (0)