biomedisa 2024.5.14__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- biomedisa/__init__.py +53 -0
- biomedisa/__main__.py +18 -0
- biomedisa/biomedisa_features/DataGenerator.py +299 -0
- biomedisa/biomedisa_features/DataGeneratorCrop.py +121 -0
- biomedisa/biomedisa_features/PredictDataGenerator.py +87 -0
- biomedisa/biomedisa_features/PredictDataGeneratorCrop.py +74 -0
- biomedisa/biomedisa_features/__init__.py +0 -0
- biomedisa/biomedisa_features/active_contour.py +434 -0
- biomedisa/biomedisa_features/amira_to_np/__init__.py +0 -0
- biomedisa/biomedisa_features/amira_to_np/amira_data_stream.py +980 -0
- biomedisa/biomedisa_features/amira_to_np/amira_grammar.py +369 -0
- biomedisa/biomedisa_features/amira_to_np/amira_header.py +290 -0
- biomedisa/biomedisa_features/amira_to_np/amira_helper.py +72 -0
- biomedisa/biomedisa_features/assd.py +167 -0
- biomedisa/biomedisa_features/biomedisa_helper.py +801 -0
- biomedisa/biomedisa_features/create_slices.py +286 -0
- biomedisa/biomedisa_features/crop_helper.py +586 -0
- biomedisa/biomedisa_features/curvop_numba.py +149 -0
- biomedisa/biomedisa_features/django_env.py +172 -0
- biomedisa/biomedisa_features/keras_helper.py +1219 -0
- biomedisa/biomedisa_features/nc_reader.py +179 -0
- biomedisa/biomedisa_features/pid.py +52 -0
- biomedisa/biomedisa_features/process_image.py +253 -0
- biomedisa/biomedisa_features/pycuda_test.py +84 -0
- biomedisa/biomedisa_features/random_walk/__init__.py +0 -0
- biomedisa/biomedisa_features/random_walk/gpu_kernels.py +183 -0
- biomedisa/biomedisa_features/random_walk/pycuda_large.py +826 -0
- biomedisa/biomedisa_features/random_walk/pycuda_large_allx.py +806 -0
- biomedisa/biomedisa_features/random_walk/pycuda_small.py +414 -0
- biomedisa/biomedisa_features/random_walk/pycuda_small_allx.py +493 -0
- biomedisa/biomedisa_features/random_walk/pyopencl_large.py +760 -0
- biomedisa/biomedisa_features/random_walk/pyopencl_small.py +441 -0
- biomedisa/biomedisa_features/random_walk/rw_large.py +390 -0
- biomedisa/biomedisa_features/random_walk/rw_small.py +310 -0
- biomedisa/biomedisa_features/remove_outlier.py +399 -0
- biomedisa/biomedisa_features/split_volume.py +274 -0
- biomedisa/deeplearning.py +519 -0
- biomedisa/interpolation.py +371 -0
- biomedisa/mesh.py +406 -0
- biomedisa-2024.5.14.dist-info/LICENSE +191 -0
- biomedisa-2024.5.14.dist-info/METADATA +306 -0
- biomedisa-2024.5.14.dist-info/RECORD +44 -0
- biomedisa-2024.5.14.dist-info/WHEEL +5 -0
- biomedisa-2024.5.14.dist-info/top_level.txt +1 -0
@@ -0,0 +1,519 @@
|
|
1
|
+
#!/usr/bin/python3
|
2
|
+
##########################################################################
|
3
|
+
## ##
|
4
|
+
## Copyright (c) 2024 Philipp Lösel. All rights reserved. ##
|
5
|
+
## ##
|
6
|
+
## This file is part of the open source project biomedisa. ##
|
7
|
+
## ##
|
8
|
+
## Licensed under the European Union Public Licence (EUPL) ##
|
9
|
+
## v1.2, or - as soon as they will be approved by the ##
|
10
|
+
## European Commission - subsequent versions of the EUPL; ##
|
11
|
+
## ##
|
12
|
+
## You may redistribute it and/or modify it under the terms ##
|
13
|
+
## of the EUPL v1.2. You may not use this work except in ##
|
14
|
+
## compliance with this Licence. ##
|
15
|
+
## ##
|
16
|
+
## You can obtain a copy of the Licence at: ##
|
17
|
+
## ##
|
18
|
+
## https://joinup.ec.europa.eu/page/eupl-text-11-12 ##
|
19
|
+
## ##
|
20
|
+
## Unless required by applicable law or agreed to in ##
|
21
|
+
## writing, software distributed under the Licence is ##
|
22
|
+
## distributed on an "AS IS" basis, WITHOUT WARRANTIES ##
|
23
|
+
## OR CONDITIONS OF ANY KIND, either express or implied. ##
|
24
|
+
## ##
|
25
|
+
## See the Licence for the specific language governing ##
|
26
|
+
## permissions and limitations under the Licence. ##
|
27
|
+
## ##
|
28
|
+
##########################################################################
|
29
|
+
|
30
|
+
import sys, os
|
31
|
+
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
32
|
+
sys.path.append(BASE_DIR)
|
33
|
+
import biomedisa
|
34
|
+
import biomedisa_features.crop_helper as ch
|
35
|
+
from biomedisa_features.keras_helper import *
|
36
|
+
from biomedisa_features.biomedisa_helper import _error_
|
37
|
+
from tensorflow.python.framework.errors_impl import ResourceExhaustedError
|
38
|
+
import tensorflow as tf
|
39
|
+
import numpy as np
|
40
|
+
import traceback
|
41
|
+
import argparse
|
42
|
+
import h5py
|
43
|
+
import time
|
44
|
+
import subprocess
|
45
|
+
import glob
|
46
|
+
|
47
|
+
class Biomedisa(object):
|
48
|
+
pass
|
49
|
+
|
50
|
+
def get_gpu_memory():
|
51
|
+
try:
|
52
|
+
result = subprocess.check_output(['nvidia-smi', '--query-gpu=memory.free', '--format=csv,nounits,noheader'], encoding='utf-8')
|
53
|
+
# Convert lines to list
|
54
|
+
gpu_memory = [int(x) for x in result.strip().split('\n')]
|
55
|
+
return gpu_memory
|
56
|
+
except:
|
57
|
+
return None
|
58
|
+
|
59
|
+
def deep_learning(img_data, label_data=None, val_img_data=None, val_label_data=None,
|
60
|
+
path_to_images=None, path_to_labels=None, val_images=None, val_labels=None,
|
61
|
+
path_to_model=None, predict=False, train=False, header_file=None,
|
62
|
+
balance=False, crop_data=False, flip_x=False, flip_y=False, flip_z=False,
|
63
|
+
swapaxes=False, train_dice=False, val_dice=True, no_compression=False, ignore='none', only='all',
|
64
|
+
network_filters='32-64-128-256-512', resnet=False, debug_cropping=False,
|
65
|
+
save_cropped=False, epochs=100, no_normalization=False, rotate=0.0, validation_split=0.0,
|
66
|
+
learning_rate=0.01, stride_size=32, validation_stride_size=32, validation_freq=1,
|
67
|
+
batch_size=None, x_scale=256, y_scale=256, z_scale=256, no_scaling=False, early_stopping=0,
|
68
|
+
pretrained_model=None, fine_tune=False, workers=1, cropping_epochs=50,
|
69
|
+
x_range=None, y_range=None, z_range=None, header=None, extension='.tif',
|
70
|
+
img_header=None, img_extension='.tif', average_dice=False, django_env=False,
|
71
|
+
path=None, success=True, return_probs=False, patch_normalization=False,
|
72
|
+
z_patch=64, y_patch=64, x_patch=64, path_to_logfile=None, img_id=None, label_id=None,
|
73
|
+
remote=False, queue=0, username=None, shortfilename=None, dice_loss=False,
|
74
|
+
acwe=False, acwe_alpha=1.0, acwe_smooth=1, acwe_steps=3, clean=None, fill=None):
|
75
|
+
|
76
|
+
# create biomedisa
|
77
|
+
bm = Biomedisa()
|
78
|
+
bm.process = 'deep_learning'
|
79
|
+
results = None
|
80
|
+
|
81
|
+
# time
|
82
|
+
TIC = time.time()
|
83
|
+
|
84
|
+
# transfer arguments
|
85
|
+
key_copy = tuple(locals().keys())
|
86
|
+
for arg in key_copy:
|
87
|
+
bm.__dict__[arg] = locals()[arg]
|
88
|
+
|
89
|
+
# compression
|
90
|
+
if bm.no_compression:
|
91
|
+
bm.compression = False
|
92
|
+
else:
|
93
|
+
bm.compression = True
|
94
|
+
|
95
|
+
# normalization
|
96
|
+
if bm.no_normalization:
|
97
|
+
bm.normalize = 0
|
98
|
+
else:
|
99
|
+
bm.normalize = 1
|
100
|
+
|
101
|
+
# django environment
|
102
|
+
if bm.django_env:
|
103
|
+
from biomedisa_app.views import unique_file_path
|
104
|
+
from biomedisa_features.django_env import create_pid_object
|
105
|
+
|
106
|
+
# path to image data
|
107
|
+
if bm.train:
|
108
|
+
|
109
|
+
# training files
|
110
|
+
bm.path_to_images = bm.path_to_images.split(',')[:-1]
|
111
|
+
bm.path_to_labels = bm.path_to_labels.split(',')[:-1]
|
112
|
+
|
113
|
+
# validation files
|
114
|
+
if bm.val_images is not None:
|
115
|
+
bm.val_images = bm.val_images.split(',')[:-1]
|
116
|
+
bm.val_labels = bm.val_labels.split(',')[:-1]
|
117
|
+
else:
|
118
|
+
bm.val_images = [None]
|
119
|
+
bm.val_labels = [None]
|
120
|
+
|
121
|
+
# project name
|
122
|
+
project = os.path.splitext(bm.shortfilename)[0]
|
123
|
+
|
124
|
+
# path to model
|
125
|
+
bm.path_to_model = BASE_DIR + f'/private_storage/images/{bm.username}/{project}.h5'
|
126
|
+
if not bm.remote:
|
127
|
+
bm.path_to_model = unique_file_path(bm.path_to_model)
|
128
|
+
|
129
|
+
if bm.predict:
|
130
|
+
project = os.path.splitext(os.path.basename(bm.path_to_model))[0]
|
131
|
+
|
132
|
+
# create pid object
|
133
|
+
create_pid_object(os.getpid(), bm.remote, bm.queue, bm.img_id, (bm.path_to_model if bm.train else ''))
|
134
|
+
|
135
|
+
# write in log file
|
136
|
+
with open(bm.path_to_logfile, 'a') as logfile:
|
137
|
+
print('%s %s %s %s' %(time.ctime(), bm.username, bm.shortfilename, 'Process was started.'), file=logfile)
|
138
|
+
print(f'PROJECT:{project} PREDICT:{bm.predict} IMG:{bm.shortfilename}', file=logfile)
|
139
|
+
if bm.train:
|
140
|
+
print(f'IMG_LIST:{bm.path_to_images} LABEL_LIST:{bm.path_to_labels} VAL_IMG_LIST:{bm.val_images} VAL_LABEL_LIST:{bm.val_labels}', file=logfile)
|
141
|
+
|
142
|
+
# path to model
|
143
|
+
if bm.train and not bm.path_to_model:
|
144
|
+
current_time = time.strftime("%d-%m-%Y_%H-%M-%S", time.localtime())
|
145
|
+
bm.path_to_model = os.getcwd() + f'/biomedisa_{current_time}.h5'
|
146
|
+
if bm.predict and not bm.path_to_model:
|
147
|
+
raise Exception("'path_to_model' must be specified")
|
148
|
+
|
149
|
+
# disable file saving when called as a function
|
150
|
+
if img_data is not None:
|
151
|
+
bm.path_to_images = None
|
152
|
+
bm.path_to_cropped_image = None
|
153
|
+
|
154
|
+
# adapt scaling to stride size and patch size
|
155
|
+
bm.stride_size = max(1, min(bm.stride_size, 64))
|
156
|
+
bm.x_scale = bm.x_scale - (bm.x_scale - bm.x_patch) % bm.stride_size
|
157
|
+
bm.y_scale = bm.y_scale - (bm.y_scale - bm.y_patch) % bm.stride_size
|
158
|
+
bm.z_scale = bm.z_scale - (bm.z_scale - bm.z_patch) % bm.stride_size
|
159
|
+
|
160
|
+
# adapt batch size to available gpu memory
|
161
|
+
if bm.batch_size is None:
|
162
|
+
bm.batch_size = 6
|
163
|
+
gpu_memory = get_gpu_memory()
|
164
|
+
if gpu_memory:
|
165
|
+
if bm.predict:
|
166
|
+
gpu_memory = gpu_memory[:1]
|
167
|
+
if 14000 < np.sum(gpu_memory) < 28000:
|
168
|
+
bm.batch_size = 12
|
169
|
+
elif 28000 <= np.sum(gpu_memory):
|
170
|
+
bm.batch_size = 24
|
171
|
+
|
172
|
+
if bm.train:
|
173
|
+
|
174
|
+
# path to results
|
175
|
+
bm.path_to_final = None
|
176
|
+
bm.path_to_cropped_image = None
|
177
|
+
|
178
|
+
# get number of GPUs
|
179
|
+
strategy = tf.distribute.MirroredStrategy()
|
180
|
+
ngpus = int(strategy.num_replicas_in_sync)
|
181
|
+
|
182
|
+
# batch size must be divisible by the number of GPUs and two
|
183
|
+
rest = bm.batch_size % (2*ngpus)
|
184
|
+
if 2*ngpus - rest < rest:
|
185
|
+
bm.batch_size = bm.batch_size + 2*ngpus - rest
|
186
|
+
else:
|
187
|
+
bm.batch_size = bm.batch_size - rest
|
188
|
+
|
189
|
+
if not bm.django_env:
|
190
|
+
bm.path_to_images, bm.path_to_labels = [bm.path_to_images], [bm.path_to_labels]
|
191
|
+
bm.val_images, bm.val_labels = [bm.val_images], [bm.val_labels]
|
192
|
+
|
193
|
+
# train automatic cropping
|
194
|
+
bm.cropping_weights, bm.cropping_config, bm.cropping_norm = None, None, None
|
195
|
+
if bm.crop_data:
|
196
|
+
bm.cropping_weights, bm.cropping_config, bm.cropping_norm = ch.load_and_train(
|
197
|
+
bm.normalize, bm.path_to_images, bm.path_to_labels, bm.path_to_model,
|
198
|
+
bm.cropping_epochs, bm.batch_size, bm.validation_split,
|
199
|
+
bm.flip_x, bm.flip_y, bm.flip_z, bm.rotate, bm.only, bm.ignore,
|
200
|
+
bm.val_images, bm.val_labels, img_data, label_data,
|
201
|
+
val_img_data, val_label_data)
|
202
|
+
|
203
|
+
# train automatic segmentation
|
204
|
+
train_semantic_segmentation(bm, bm.path_to_images, bm.path_to_labels,
|
205
|
+
bm.val_images, bm.val_labels,
|
206
|
+
img_data, label_data,
|
207
|
+
val_img_data, val_label_data,
|
208
|
+
header, extension)
|
209
|
+
|
210
|
+
if bm.predict:
|
211
|
+
|
212
|
+
# get meta data
|
213
|
+
hf = h5py.File(bm.path_to_model, 'r')
|
214
|
+
meta = hf.get('meta')
|
215
|
+
configuration = meta.get('configuration')
|
216
|
+
channels, bm.x_scale, bm.y_scale, bm.z_scale, normalize, mu, sig = np.array(configuration)[:]
|
217
|
+
channels, bm.x_scale, bm.y_scale, bm.z_scale, normalize, mu, sig = int(channels), int(bm.x_scale), \
|
218
|
+
int(bm.y_scale), int(bm.z_scale), int(normalize), float(mu), float(sig)
|
219
|
+
if '/meta/normalization' in hf:
|
220
|
+
normalization_parameters = np.array(meta.get('normalization'), dtype=float)
|
221
|
+
else:
|
222
|
+
normalization_parameters = np.array([[mu],[sig]])
|
223
|
+
allLabels = np.array(meta.get('labels'))
|
224
|
+
# check if amira header is available in the network
|
225
|
+
if header is None and meta.get('header') is not None:
|
226
|
+
header = [np.array(meta.get('header'))]
|
227
|
+
extension = '.am'
|
228
|
+
crop_data = True if 'cropping_weights' in hf else False
|
229
|
+
hf.close()
|
230
|
+
|
231
|
+
# extract image files
|
232
|
+
bm.tmp_dir = None
|
233
|
+
if bm.path_to_images is not None and (os.path.splitext(bm.path_to_images)[1]=='.tar' or bm.path_to_images[-7:]=='.tar.gz'):
|
234
|
+
path_to_dir = os.path.dirname(bm.path_to_images) + '/final.'+os.path.basename(bm.path_to_images)
|
235
|
+
if path_to_dir[-3:]=='.gz':
|
236
|
+
path_to_dir = path_to_dir[:-3]
|
237
|
+
if bm.django_env and not bm.remote:
|
238
|
+
path_to_dir = unique_file_path(path_to_dir)
|
239
|
+
bm.tmp_dir = BASE_DIR + '/tmp/' + id_generator(40)
|
240
|
+
tar = tarfile.open(bm.path_to_images)
|
241
|
+
tar.extractall(path=bm.tmp_dir)
|
242
|
+
tar.close()
|
243
|
+
bm.path_to_images = bm.tmp_dir
|
244
|
+
bm.save_cropped, bm.acwe = False, False
|
245
|
+
bm.clean, bm.fill = None, None
|
246
|
+
|
247
|
+
# list of images
|
248
|
+
path_to_finals = []
|
249
|
+
if bm.path_to_images is not None and os.path.isdir(bm.path_to_images):
|
250
|
+
files = glob.glob(bm.path_to_images+'/**/*', recursive=True)
|
251
|
+
bm.path_to_images = [f for f in files if os.path.isfile(f)]
|
252
|
+
else:
|
253
|
+
bm.path_to_images = [bm.path_to_images]
|
254
|
+
|
255
|
+
# loop over all images
|
256
|
+
for bm.path_to_image in bm.path_to_images:
|
257
|
+
|
258
|
+
# create path_to_final
|
259
|
+
if bm.path_to_image:
|
260
|
+
filename = os.path.basename(bm.path_to_image)
|
261
|
+
filename = os.path.splitext(filename)[0]
|
262
|
+
if filename[-4:] == '.nii':
|
263
|
+
filename = filename[:-4]
|
264
|
+
bm.path_to_cropped_image = os.path.dirname(bm.path_to_image) + '/' + filename + '.cropped.tif'
|
265
|
+
if bm.django_env and not bm.remote and not bm.tmp_dir:
|
266
|
+
bm.path_to_cropped_image = unique_file_path(bm.path_to_cropped_image)
|
267
|
+
filename = 'final.' + filename
|
268
|
+
bm.path_to_final = os.path.dirname(bm.path_to_image) + '/' + filename + extension
|
269
|
+
if bm.django_env and not bm.remote and not bm.tmp_dir:
|
270
|
+
bm.path_to_final = unique_file_path(bm.path_to_final)
|
271
|
+
|
272
|
+
# crop data
|
273
|
+
region_of_interest, cropped_volume = None, None
|
274
|
+
if crop_data:
|
275
|
+
region_of_interest, cropped_volume = ch.crop_data(bm.path_to_image, bm.path_to_model, bm.path_to_cropped_image,
|
276
|
+
bm.batch_size, bm.debug_cropping, bm.save_cropped, img_data, bm.x_range, bm.y_range, bm.z_range)
|
277
|
+
|
278
|
+
# load prediction data
|
279
|
+
img, img_header, z_shape, y_shape, x_shape, region_of_interest, img_data = load_prediction_data(bm.path_to_image,
|
280
|
+
channels, bm.x_scale, bm.y_scale, bm.z_scale, bm.no_scaling, normalize, normalization_parameters,
|
281
|
+
region_of_interest, img_data, img_header)
|
282
|
+
|
283
|
+
# make prediction
|
284
|
+
results, bm = predict_semantic_segmentation(bm, img, bm.path_to_model,
|
285
|
+
bm.z_patch, bm.y_patch, bm.x_patch, z_shape, y_shape, x_shape, bm.compression, header,
|
286
|
+
img_header, bm.stride_size, allLabels, bm.batch_size, region_of_interest,
|
287
|
+
bm.no_scaling, extension, img_data)
|
288
|
+
|
289
|
+
# results
|
290
|
+
if cropped_volume is not None:
|
291
|
+
results['cropped_volume'] = cropped_volume
|
292
|
+
|
293
|
+
# path to results
|
294
|
+
if bm.path_to_image:
|
295
|
+
path_to_finals.append(bm.path_to_final)
|
296
|
+
|
297
|
+
# write tar file and delete extracted image files
|
298
|
+
if bm.tmp_dir is not None and os.path.exists(bm.tmp_dir):
|
299
|
+
with tarfile.open(path_to_dir, 'w') as tar:
|
300
|
+
for file_path in path_to_finals:
|
301
|
+
file_name = os.path.basename(file_path)
|
302
|
+
tar.add(file_path, arcname=file_name)
|
303
|
+
shutil.rmtree(bm.tmp_dir)
|
304
|
+
bm.path_to_final = path_to_dir
|
305
|
+
bm.path_to_cropped_image = None
|
306
|
+
|
307
|
+
# computation time
|
308
|
+
t = int(time.time() - TIC)
|
309
|
+
if t < 60:
|
310
|
+
time_str = str(t) + " sec"
|
311
|
+
elif 60 <= t < 3600:
|
312
|
+
time_str = str(t // 60) + " min " + str(t % 60) + " sec"
|
313
|
+
elif 3600 < t:
|
314
|
+
time_str = str(t // 3600) + " h " + str((t % 3600) // 60) + " min " + str(t % 60) + " sec"
|
315
|
+
print('Total calculation time:', time_str)
|
316
|
+
|
317
|
+
# django environment
|
318
|
+
if bm.django_env:
|
319
|
+
from biomedisa_app.config import config
|
320
|
+
from biomedisa_features.django_env import post_processing
|
321
|
+
validation=True if bm.validation_split or (bm.val_images is not None and bm.val_images[0] is not None) else False
|
322
|
+
post_processing(bm.path_to_final, time_str, config['SERVER_ALIAS'], bm.remote, bm.queue,
|
323
|
+
img_id=bm.img_id, label_id=bm.label_id, path_to_model=bm.path_to_model,
|
324
|
+
path_to_cropped_image=(bm.path_to_cropped_image if crop_data else None),
|
325
|
+
train=bm.train, predict=bm.predict, validation=validation)
|
326
|
+
|
327
|
+
# write in log file
|
328
|
+
path_to_time = BASE_DIR + '/log/time.txt'
|
329
|
+
with open(path_to_time, 'a') as timefile:
|
330
|
+
if predict:
|
331
|
+
message = 'Successfully segmented ' + bm.shortfilename
|
332
|
+
else:
|
333
|
+
message = 'Successfully trained ' + project
|
334
|
+
print('%s %s %s %s on %s' %(time.ctime(), bm.username, message, time_str, config['SERVER_ALIAS']), file=timefile)
|
335
|
+
|
336
|
+
return results
|
337
|
+
|
338
|
+
if __name__ == '__main__':
|
339
|
+
|
340
|
+
# initialize arguments
|
341
|
+
parser = argparse.ArgumentParser(description='Biomedisa deeplearning.',
|
342
|
+
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
343
|
+
|
344
|
+
# mutually exclusive group
|
345
|
+
g = parser.add_mutually_exclusive_group()
|
346
|
+
|
347
|
+
# required arguments
|
348
|
+
parser.add_argument('path_to_images', type=str, metavar='PATH_TO_IMAGES',
|
349
|
+
help='Location of image data (tarball, directory, or file)')
|
350
|
+
parser.add_argument('path', type=str, metavar='PATH',
|
351
|
+
help='Location of label data during training (tarball, directory, or file) or model for prediction (h5)')
|
352
|
+
|
353
|
+
# optional arguments
|
354
|
+
g.add_argument('-p','--predict', action='store_true', default=False,
|
355
|
+
help='Automatic/predict segmentation')
|
356
|
+
g.add_argument('-t','--train', action='store_true', default=False,
|
357
|
+
help='Train neural network')
|
358
|
+
parser.add_argument('-v', '--version', action='version', version=f'{biomedisa.__version__}',
|
359
|
+
help='Biomedisa version')
|
360
|
+
parser.add_argument('-b','--balance', action='store_true', default=False,
|
361
|
+
help='Balance foreground and background training patches')
|
362
|
+
parser.add_argument('-cd','--crop_data', action='store_true', default=False,
|
363
|
+
help='Crop data automatically to region of interest')
|
364
|
+
parser.add_argument('--acwe', action='store_true', default=False,
|
365
|
+
help='Post-processing with active contour')
|
366
|
+
parser.add_argument('--acwe_alpha', metavar='ALPHA', type=float, default=1.0,
|
367
|
+
help='Pushing force of active contour')
|
368
|
+
parser.add_argument('--acwe_smooth', metavar='SMOOTH', type=int, default=1,
|
369
|
+
help='Smoothing steps of active contour')
|
370
|
+
parser.add_argument('--acwe_steps', metavar='STEPS', type=int, default=3,
|
371
|
+
help='Iterations of active contour')
|
372
|
+
parser.add_argument('-c','--clean', nargs='?', type=float, const=0.1, default=None,
|
373
|
+
help='Remove outliers, e.g. 0.5 means that objects smaller than 50 percent of the size of the largest object will be removed')
|
374
|
+
parser.add_argument('-f','--fill', nargs='?', type=float, const=0.9, default=None,
|
375
|
+
help='Fill holes, e.g. 0.5 means that all holes smaller than 50 percent of the entire label will be filled')
|
376
|
+
parser.add_argument('--flip_x', action='store_true', default=False,
|
377
|
+
help='Randomly flip x-axis during training')
|
378
|
+
parser.add_argument('--flip_y', action='store_true', default=False,
|
379
|
+
help='Randomly flip y-axis during training')
|
380
|
+
parser.add_argument('--flip_z', action='store_true', default=False,
|
381
|
+
help='Randomly flip z-axis during training')
|
382
|
+
parser.add_argument('-sa','--swapaxes', action='store_true', default=False,
|
383
|
+
help='Randomly swap two axes during training')
|
384
|
+
parser.add_argument('-td','--train_dice', action='store_true', default=False,
|
385
|
+
help='Monitor Dice score on training data')
|
386
|
+
parser.add_argument('-nvd','--no-val_dice', dest='val_dice', action='store_false',
|
387
|
+
help='Disable monitoring of Dice score on validation data')
|
388
|
+
parser.add_argument('-dl','--dice_loss', action='store_true', default=False,
|
389
|
+
help='Dice loss function')
|
390
|
+
parser.add_argument('-ad','--average_dice', action='store_true', default=False,
|
391
|
+
help='Use averaged dice score of each label')
|
392
|
+
parser.add_argument('-nc', '--no_compression', action='store_true', default=False,
|
393
|
+
help='Disable compression of segmentation results')
|
394
|
+
parser.add_argument('-i', '--ignore', type=str, default='none',
|
395
|
+
help='Ignore specific label(s), e.g. 2,5,6')
|
396
|
+
parser.add_argument('-o', '--only', type=str, default='all',
|
397
|
+
help='Segment only specific label(s), e.g. 1,3,5')
|
398
|
+
parser.add_argument('-nf', '--network_filters', type=str, default='32-64-128-256-512',
|
399
|
+
help='Number of filters per layer up to the deepest, e.g. 32-64-128-256-512')
|
400
|
+
parser.add_argument('-rn','--resnet', action='store_true', default=False,
|
401
|
+
help='Use U-resnet instead of standard U-net')
|
402
|
+
parser.add_argument('-dc','--debug_cropping', action='store_true', default=False,
|
403
|
+
help='Debug cropping')
|
404
|
+
parser.add_argument('-sc','--save_cropped', action='store_true', default=False,
|
405
|
+
help='Save automatically cropped image')
|
406
|
+
parser.add_argument('-e','--epochs', type=int, default=100,
|
407
|
+
help='Epochs the network is trained')
|
408
|
+
parser.add_argument('-ce','--cropping_epochs', type=int, default=50,
|
409
|
+
help='Epochs the network for auto-cropping is trained')
|
410
|
+
parser.add_argument('-nn','--no_normalization', action='store_true', default=False,
|
411
|
+
help='Disable image normalization')
|
412
|
+
parser.add_argument('-r','--rotate', type=float, default=0.0,
|
413
|
+
help='Randomly rotate during training')
|
414
|
+
parser.add_argument('-vs','--validation_split', type=float, default=0.0,
|
415
|
+
help='Percentage of data used for validation')
|
416
|
+
parser.add_argument('-lr','--learning_rate', type=float, default=0.01,
|
417
|
+
help='Learning rate')
|
418
|
+
parser.add_argument('-ss','--stride_size', metavar="[1-64]", type=int, choices=range(1,65), default=32,
|
419
|
+
help='Stride size for patches')
|
420
|
+
parser.add_argument('-vss','--validation_stride_size', metavar="[1-64]", type=int, choices=range(1,65), default=32,
|
421
|
+
help='Stride size for validation patches')
|
422
|
+
parser.add_argument('-vf','--validation_freq', type=int, default=1,
|
423
|
+
help='Epochs performed before validation')
|
424
|
+
parser.add_argument('-bs','--batch_size', type=int, default=None,
|
425
|
+
help='Number of samples processed in a batch')
|
426
|
+
parser.add_argument('-vi','--val_images', type=str, metavar='PATH', default=None,
|
427
|
+
help='Location of validation image data (tarball, directory, or file)')
|
428
|
+
parser.add_argument('-vl','--val_labels', type=str, metavar='PATH', default=None,
|
429
|
+
help='Location of validation label data (tarball, directory, or file)')
|
430
|
+
parser.add_argument('-xs','--x_scale', type=int, default=256,
|
431
|
+
help='Images and labels are scaled at x-axis to this size before training')
|
432
|
+
parser.add_argument('-ys','--y_scale', type=int, default=256,
|
433
|
+
help='Images and labels are scaled at y-axis to this size before training')
|
434
|
+
parser.add_argument('-zs','--z_scale', type=int, default=256,
|
435
|
+
help='Images and labels are scaled at z-axis to this size before training')
|
436
|
+
parser.add_argument('-ns','--no_scaling', action='store_true', default=False,
|
437
|
+
help='Do not resize image and label data')
|
438
|
+
parser.add_argument('-es','--early_stopping', type=int, default=0,
|
439
|
+
help='Training is terminated when the accuracy has not increased in the epochs defined by this')
|
440
|
+
parser.add_argument('-pm','--pretrained_model', type=str, metavar='PATH', default=None,
|
441
|
+
help='Location of pretrained model (only encoder will be trained if specified)')
|
442
|
+
parser.add_argument('-ft','--fine_tune', action='store_true', default=False,
|
443
|
+
help='Fine-tune the entire pretrained model. Choose a smaller learning rate, e.g. 0.0001')
|
444
|
+
parser.add_argument('-w','--workers', type=int, default=1,
|
445
|
+
help='Parallel workers for batch processing')
|
446
|
+
parser.add_argument('-xr','--x_range', nargs="+", type=int, default=None,
|
447
|
+
help='Manually crop x-axis of image data for prediction, e.g. -xr 100 200')
|
448
|
+
parser.add_argument('-yr','--y_range', nargs="+", type=int, default=None,
|
449
|
+
help='Manually crop y-axis of image data for prediction, e.g. -xr 100 200')
|
450
|
+
parser.add_argument('-zr','--z_range', nargs="+", type=int, default=None,
|
451
|
+
help='Manually crop z-axis of image data for prediction, e.g. -xr 100 200')
|
452
|
+
parser.add_argument('-rp','--return_probs', action='store_true', default=False,
|
453
|
+
help='Return prediction probabilities for each label')
|
454
|
+
parser.add_argument('-pn','--patch_normalization', action='store_true', default=False,
|
455
|
+
help='Scale each patch to mean zero and standard deviation')
|
456
|
+
parser.add_argument('-xp','--x_patch', type=int, default=64,
|
457
|
+
help='X-dimension of patch')
|
458
|
+
parser.add_argument('-yp','--y_patch', type=int, default=64,
|
459
|
+
help='Y-dimension of patch')
|
460
|
+
parser.add_argument('-zp','--z_patch', type=int, default=64,
|
461
|
+
help='Z-dimension of patch')
|
462
|
+
parser.add_argument('-iid','--img_id', type=str, default=None,
|
463
|
+
help='Image ID within django environment/browser version')
|
464
|
+
parser.add_argument('-lid','--label_id', type=str, default=None,
|
465
|
+
help='Label ID within django environment/browser version')
|
466
|
+
parser.add_argument('-re','--remote', action='store_true', default=False,
|
467
|
+
help='The interpolation is carried out on a remote server. Must be set up in config.py')
|
468
|
+
parser.add_argument('-q','--queue', type=int, default=0,
|
469
|
+
help='Processing queue when using a remote server')
|
470
|
+
parser.add_argument('-hf','--header_file', type=str, metavar='PATH', default=None,
|
471
|
+
help='Location of header file')
|
472
|
+
bm = parser.parse_args()
|
473
|
+
|
474
|
+
bm.success = True
|
475
|
+
if bm.predict:
|
476
|
+
bm.path_to_labels = None
|
477
|
+
bm.path_to_model = bm.path
|
478
|
+
if bm.train:
|
479
|
+
bm.path_to_labels = bm.path
|
480
|
+
bm.path_to_model = bm.path_to_images + '.h5'
|
481
|
+
|
482
|
+
# django environment
|
483
|
+
if bm.img_id is not None:
|
484
|
+
bm.django_env = True
|
485
|
+
if bm.train:
|
486
|
+
reference_image_path = bm.path_to_images.split(',')[:-1][-1]
|
487
|
+
else:
|
488
|
+
reference_image_path = bm.path_to_images
|
489
|
+
bm.username = os.path.basename(os.path.dirname(reference_image_path))
|
490
|
+
bm.shortfilename = os.path.basename(reference_image_path)
|
491
|
+
bm.path_to_logfile = BASE_DIR + '/log/logfile.txt'
|
492
|
+
else:
|
493
|
+
bm.django_env = False
|
494
|
+
|
495
|
+
kwargs = vars(bm)
|
496
|
+
|
497
|
+
# train or predict segmentation
|
498
|
+
try:
|
499
|
+
deep_learning(None, **kwargs)
|
500
|
+
except InputError:
|
501
|
+
if any(InputError.img_names):
|
502
|
+
remove_extracted_data(InputError.img_names, InputError.label_names)
|
503
|
+
print(traceback.format_exc())
|
504
|
+
bm = _error_(bm, f'{InputError.message}')
|
505
|
+
except ch.InputError:
|
506
|
+
if any(ch.InputError.img_names):
|
507
|
+
remove_extracted_data(ch.InputError.img_names, ch.InputError.label_names)
|
508
|
+
print(traceback.format_exc())
|
509
|
+
bm = _error_(bm, f'{ch.InputError.message}')
|
510
|
+
except MemoryError:
|
511
|
+
print(traceback.format_exc())
|
512
|
+
bm = _error_(bm, 'MemoryError')
|
513
|
+
except ResourceExhaustedError:
|
514
|
+
print(traceback.format_exc())
|
515
|
+
bm = _error_(bm, 'GPU out of memory. Reduce your batch size')
|
516
|
+
except Exception as e:
|
517
|
+
print(traceback.format_exc())
|
518
|
+
bm = _error_(bm, e)
|
519
|
+
|