-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathexample_classifier.py
More file actions
117 lines (97 loc) · 4.54 KB
/
Copy pathexample_classifier.py
File metadata and controls
117 lines (97 loc) · 4.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
"""This is an example operator to implement an image classifier"""
import monai.deploy.core as md
import numpy as np
from monai.deploy.core.domain.dicom_series_selection import StudySelectedSeries
from typing import List, Optional
from collections import UserDict
from monai.deploy.core import (
ExecutionContext,
InputContext,
IOType,
Operator,
OutputContext,
DataPath,
)
from monai.data import DataLoader, Dataset
from monai.transforms import Compose
from transforms import load_and_norm, crop_and_output
import torch
import datetime
@md.input("study_selected_series_list", List[StudySelectedSeries], IOType.IN_MEMORY)
@md.input("bbox_array", np.ndarray, IOType.DISK)
@md.output("output_udict", UserDict, IOType.DISK)
@md.env(pip_packages=["monai"])
class ClassifierOperator(Operator):
"""Classifies the given image and returns the class name."""
def __init__(self, classifier_model: Optional[str] = "", *args, **kwargs):
super().__init__(*args, **kwargs)
self.classifier_model = classifier_model
def compute(
self,
op_input: InputContext,
op_output: OutputContext,
context: ExecutionContext,
):
# get image from list
study_selected_series_list = op_input.get("study_selected_series_list")
if not study_selected_series_list or len(study_selected_series_list) < 1:
raise ValueError("Missing expected input 'study_selected_series_list'")
selected_series = study_selected_series_list[0].selected_series[0].series
dicom_list = [sop._sop.filename for sop in selected_series._sop_instances]
transforms = Compose(load_and_norm() + crop_and_output())
bbox_array = op_input.get("bbox_array").tolist()[0]
if bbox_array[-1] < 0.9:
# Update as appropriate to given project
output_dict = {
"result": "Indeterminate result",
"error_message": "Unable to identify the scaphoid bone",
"advice": "ScaphX is unable to provide a reliable assessment for this case. Please proceed with standard clinical evaluation, including X-ray interpretation and additional imaging as needed.",
"start_time": f"{begin}",
"end_time": f"{end}",
"bounding_box": bbox_array,
}
else:
dataset = Dataset(
data=[{"image": dicom_list, "label": -1, "roi": bbox_array}],
transform=transforms,
)
dataloader = DataLoader(dataset, batch_size=1, shuffle=False)
model = torch.jit.load(self.classifier_model)
model.eval()
begin = str(datetime.datetime.now())
with torch.inference_mode():
for d in dataloader:
pred = model(d["image"].to("cpu"))
confidence = torch.nn.functional.softmax(pred, dim=1)
result = confidence[0].detach().numpy()[0]
end = str(datetime.datetime.now())
# Update as appropriate to specific project
if result >= 0.9:
output_dict = {
"result": "Scaphoid Fracture Detected",
"error_message": "None",
"advice": "Apply a below elbow POP backslab and refer the patient to fracture clinic as per scaphoid pathway.",
"start_time": f"{begin}",
"end_time": f"{end}",
"bounding_box": bbox_array,
}
elif result >= 0.9: # and result < 0.8:
output_dict = {
"result": "Indeterminate result",
"error_message": "Unable to classify image",
"advice": "ScaphX is unable to provide a reliable assessment for this case. Please proceed with standard clinical evaluation, including X-ray interpretation and additional imaging as needed.",
"start_time": f"{begin}",
"end_time": f"{end}",
"bounding_box": bbox_array,
}
else:
output_dict = {
"result": "No Scaphoid Fracture Detected",
"error_message": "None",
"advice": "Provide patient with Futura splint and refer the patient as per scaphoid pathway.",
"start_time": f"{begin}",
"end_time": f"{end}",
"bounding_box": bbox_array,
}
output_udict = UserDict(output_dict)
op_output.set(output_udict, "output_udict")