[ab8281]: / brats_toolkit / preprocessor.py

Download this file

258 lines (224 with data), 8.3 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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
import os
import sys
import tempfile
from pathlib import Path
import socketio
from brats_toolkit.util.citation_reminder import (
citation_reminder,
deprecated_preprocessor,
)
from brats_toolkit.util.docker_functions import start_docker, stop_docker, update_docker
from brats_toolkit.util.prep_utils import tempFiler
class Preprocessor:
"""
Class for preprocessing medical imaging data.
"""
@citation_reminder
@deprecated_preprocessor
def __init__(self, noDocker: bool = False):
"""
Initialize the Preprocessor instance.
Parameters:
- noDocker (bool): Flag indicating whether Docker is used.
"""
# settings
self.clientVersion: str = "0.0.1"
self.confirmationRequired: bool = True
self.mode: str = "cpu"
self.gpuid: str = "0"
# init sio client
self.sio: socketio.Client = socketio.Client()
# set docker usage
self.noDocker: bool = noDocker
@self.sio.event
def connect() -> None:
"""
Event handler for successful connection.
"""
print("connection established! sid:", self.sio.sid)
self.sio.emit(
"clientidentification",
{"brats_cli": self.clientVersion, "proc_mode": self.mode},
)
@self.sio.event
def connect_error() -> None:
"""
Event handler for connection error.
"""
print("The connection failed!")
@self.sio.event
def disconnect() -> None:
"""
Event handler for disconnection.
"""
print("disconnected from server")
@self.sio.on("message")
def message(data: dict) -> None:
"""
Event handler for incoming message.
"""
print("message", data)
@self.sio.on("status")
def on_status(data: dict) -> None:
"""
Event handler for status update.
"""
print("status received: ", data)
if data["message"] == "client ID json generation finished!":
self._inspect_input()
elif data["message"] == "input inspection finished!":
if "data" in data:
print("input inspection found the following exams: ", data["data"])
if self.confirmationRequired:
confirmation = input(
'press "y" to continue or "n" to scan the input folder again.'
).lower()
else:
confirmation = "y"
if confirmation == "n":
self._inspect_input()
if confirmation == "y":
self._process_start()
elif data["message"] == "image processing successfully completed.":
self.sio.disconnect()
stop_docker()
sys.exit(0)
@self.sio.on("client_outdated")
def outdated(data: dict) -> None:
"""
Event handler for outdated client version.
"""
print(
"Your client version",
self.clientVersion,
"is outdated. Please download version",
data,
"from:",
)
print("https://neuronflow.github.io/brats-preprocessor/")
self.sio.disconnect()
stop_docker()
sys.exit(0)
@self.sio.on("ipstatus")
def on_ipstatus(data: dict) -> None:
"""
Event handler for image processing status.
"""
print("image processing status received:")
print(data["examid"], ": ", data["ipstatus"])
def single_preprocess(
self,
t1File: str,
t1cFile: str,
t2File: str,
flaFile: str,
outputFolder: str,
mode: str,
confirm: bool = False,
skipUpdate: bool = False,
gpuid: str = "0",
) -> None:
"""
Process a single set of input files.
Parameters:
- t1File (str): Path to T1 file.
- t1cFile (str): Path to T1c file.
- t2File (str): Path to T2 file.
- flaFile (str): Path to FLAIR file.
- outputFolder (str): Output folder path.
- mode (str): Processing mode (e.g., "cpu", "gpu").
- confirm (bool): Whether confirmation is required.
- skipUpdate (bool): Whether to skip Docker update.
- gpuid (str): GPU ID.
Returns:
- None
"""
# assign name to file
print("basename:", os.path.basename(outputFolder))
outputPath: Path = Path(outputFolder)
dockerOutputFolder: str = os.path.abspath(outputPath.parent)
# create temp dir
storage: tempfile.TemporaryDirectory = tempfile.TemporaryDirectory()
# TODO this is a potential security hazzard as all users can access the files now, but currently it seems the only way to deal with bad configured docker installations
os.chmod(storage.name, 0o777)
dockerFolder: str = os.path.abspath(storage.name)
tempFolder: str = os.path.join(dockerFolder, os.path.basename(outputFolder))
os.makedirs(tempFolder, exist_ok=True)
print("tempFold:", tempFolder)
# create temp Files
tempFiler(t1File, "t1", tempFolder)
tempFiler(t1cFile, "t1c", tempFolder)
tempFiler(t2File, "t2", tempFolder)
tempFiler(flaFile, "fla", tempFolder)
self.batch_preprocess(
exam_import_folder=dockerFolder,
exam_export_folder=dockerOutputFolder,
mode=mode,
confirm=confirm,
skipUpdate=skipUpdate,
gpuid=gpuid,
)
def batch_preprocess(
self,
exam_import_folder: str,
exam_export_folder: str,
dicom_import_folder: str = None,
nifti_export_folder: str = None,
mode: str = "cpu",
confirm: bool = True,
skipUpdate: bool = False,
gpuid: str = "0",
) -> None:
"""
Process multiple sets of input files, potentially using Docker.
Parameters:
- exam_import_folder (str): Import folder path.
- exam_export_folder (str): Export folder path.
- dicom_import_folder (Optional[str]): DICOM import folder path.
- nifti_export_folder (Optional[str]): NIfTI export folder path.
- mode (str): Processing mode (e.g., "cpu", "gpu").
- confirm (bool): Whether confirmation is required.
- skipUpdate (bool): Whether to skip Docker update.
- gpuid (str): GPU ID.
Returns:
- None
"""
if confirm != True:
self.confirmationRequired = False
self.mode = mode
self.gpuid = gpuid
if self.noDocker != True:
stop_docker()
if skipUpdate != True:
update_docker()
start_docker(
exam_import_folder=exam_import_folder,
exam_export_folder=exam_export_folder,
dicom_import_folder=dicom_import_folder,
nifti_export_folder=nifti_export_folder,
mode=self.mode,
gpuid=self.gpuid,
)
# setup connection
# TODO do this in a more elegant way and somehow check whether docker is up and running before connect
self.sio.sleep(8) # wait 8 secs for docker to start
self._connect_client()
self.sio.wait()
def _connect_client(self) -> None:
"""
Connect to the server using SocketIO.
"""
self.sio.connect("http://localhost:5000")
print("sid:", self.sio.sid)
def _inspect_input(self) -> None:
"""
Send input inspection request to the server.
"""
print("sending input inspection request!")
self.sio.emit("input_inspection", {"hurray": "yes"})
def _process_start(self) -> None:
"""
Send processing request to the server.
"""
print("sending processing request!")
self.sio.emit("brats_processing", {"hurray": "yes"})