spacr 0.0.1__py3-none-any.whl → 0.0.2__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.
- spacr/__init__.py +4 -0
- spacr/alpha.py +18 -0
- spacr/cli.py +25 -187
- spacr/core.py +267 -56
- spacr/graph_learning.py +276 -0
- spacr/graph_learning_lap.py +84 -0
- spacr/gui_classify_app.py +197 -0
- spacr/gui_mask_app.py +58 -106
- spacr/gui_measure_app.py +14 -28
- spacr/gui_sim_app.py +0 -0
- spacr/gui_utils.py +311 -115
- spacr/io.py +260 -112
- spacr/measure.py +11 -17
- spacr/old_code.py +187 -1
- spacr/plot.py +92 -85
- spacr/sim.py +8 -1
- spacr/timelapse.py +213 -52
- spacr/train.py +7 -1
- spacr/utils.py +220 -119
- spacr-0.0.2.dist-info/METADATA +130 -0
- spacr-0.0.2.dist-info/RECORD +31 -0
- {spacr-0.0.1.dist-info → spacr-0.0.2.dist-info}/entry_points.txt +2 -0
- spacr-0.0.1.dist-info/METADATA +0 -64
- spacr-0.0.1.dist-info/RECORD +0 -26
- {spacr-0.0.1.dist-info → spacr-0.0.2.dist-info}/LICENSE +0 -0
- {spacr-0.0.1.dist-info → spacr-0.0.2.dist-info}/WHEEL +0 -0
- {spacr-0.0.1.dist-info → spacr-0.0.2.dist-info}/top_level.txt +0 -0
spacr/gui_utils.py
CHANGED
@@ -1,16 +1,11 @@
|
|
1
|
+
import spacr, inspect, traceback, io, sys, ast, ctypes, matplotlib, re, csv
|
2
|
+
import matplotlib.pyplot as plt
|
3
|
+
matplotlib.use('Agg')
|
4
|
+
import numpy as np
|
1
5
|
import tkinter as tk
|
2
6
|
from tkinter import ttk, messagebox
|
3
7
|
from tkinter.font import nametofont
|
4
|
-
import
|
5
|
-
#matplotlib.use('TkAgg')
|
6
|
-
matplotlib.use('Agg')
|
7
|
-
import ctypes
|
8
|
-
import ast
|
9
|
-
import matplotlib.pyplot as plt
|
10
|
-
import sys
|
11
|
-
import io
|
12
|
-
import traceback
|
13
|
-
import spacr
|
8
|
+
from torchvision import models
|
14
9
|
|
15
10
|
try:
|
16
11
|
ctypes.windll.shcore.SetProcessDpiAwareness(True)
|
@@ -19,6 +14,26 @@ except AttributeError:
|
|
19
14
|
|
20
15
|
from .logger import log_function_call
|
21
16
|
|
17
|
+
def read_settings_from_csv(csv_file_path):
|
18
|
+
settings = {}
|
19
|
+
with open(csv_file_path, newline='') as csvfile:
|
20
|
+
reader = csv.DictReader(csvfile)
|
21
|
+
for row in reader:
|
22
|
+
key = row['Key']
|
23
|
+
value = row['Value']
|
24
|
+
settings[key] = value
|
25
|
+
return settings
|
26
|
+
|
27
|
+
def update_settings_from_csv(variables, csv_settings):
|
28
|
+
new_settings = variables.copy() # Start with a copy of the original settings
|
29
|
+
for key, value in csv_settings.items():
|
30
|
+
if key in new_settings:
|
31
|
+
# Get the variable type and options from the original settings
|
32
|
+
var_type, options, _ = new_settings[key]
|
33
|
+
# Update the default value with the CSV value, keeping the type and options unchanged
|
34
|
+
new_settings[key] = (var_type, options, value)
|
35
|
+
return new_settings
|
36
|
+
|
22
37
|
def safe_literal_eval(value):
|
23
38
|
try:
|
24
39
|
# First, try to evaluate as a literal
|
@@ -105,114 +120,132 @@ def check_mask_gui_settings(vars_dict):
|
|
105
120
|
settings[key] = value
|
106
121
|
return settings
|
107
122
|
|
108
|
-
def
|
123
|
+
def check_measure_gui_settings(vars_dict):
|
109
124
|
settings = {}
|
110
125
|
for key, var in vars_dict.items():
|
111
|
-
value = var.get() #
|
126
|
+
value = var.get() # Retrieves the string representation for entries or the actual value for checkboxes and combos.
|
112
127
|
|
113
128
|
try:
|
114
|
-
|
115
|
-
|
116
|
-
settings[key] = [int(chan) for chan in eval(value)] if value else []
|
129
|
+
if key in ['channels', 'png_dims']:
|
130
|
+
settings[key] = [int(chan) for chan in ast.literal_eval(value)] if value else []
|
117
131
|
|
118
|
-
elif key == 'png_size':
|
119
|
-
temp_val = ast.literal_eval(value) if value else []
|
120
|
-
settings[key] = [list(map(int, dim)) for dim in temp_val] if temp_val else None
|
121
|
-
|
122
132
|
elif key in ['cell_loc', 'pathogen_loc', 'treatment_loc']:
|
123
|
-
|
133
|
+
# Convert to a list of lists of strings, ensuring all structures are lists.
|
134
|
+
settings[key] = [list(map(str, sublist)) for sublist in ast.literal_eval(value)] if value else []
|
124
135
|
|
125
136
|
elif key == 'dialate_png_ratios':
|
126
|
-
settings[key] = [float(num) for num in
|
137
|
+
settings[key] = [float(num) for num in ast.literal_eval(value)] if value else []
|
127
138
|
|
128
|
-
elif key
|
129
|
-
settings[key] =
|
139
|
+
elif key == 'normalize':
|
140
|
+
settings[key] = [int(num) for num in ast.literal_eval(value)] if value else []
|
130
141
|
|
131
|
-
|
132
|
-
|
133
|
-
settings[key] =
|
142
|
+
# Directly assign string values for these specific keys
|
143
|
+
elif key in ['normalize_by', 'experiment', 'measurement', 'input_folder']:
|
144
|
+
settings[key] = value
|
134
145
|
|
135
|
-
|
136
|
-
|
137
|
-
|
146
|
+
elif key == 'png_size':
|
147
|
+
settings[key] = [list(map(int, dim)) for dim in ast.literal_eval(value)] if value else []
|
148
|
+
|
149
|
+
# Ensure these are lists of strings, converting from tuples if necessary
|
150
|
+
elif key in ['timelapse_objects', 'crop_mode', 'cells', 'pathogens', 'treatments']:
|
151
|
+
eval_value = ast.literal_eval(value) if value else []
|
152
|
+
settings[key] = list(map(str, eval_value)) if isinstance(eval_value, (list, tuple)) else [str(eval_value)]
|
138
153
|
|
139
|
-
# Handling for single values
|
154
|
+
# Handling for single non-string values (int, float, bool)
|
140
155
|
elif key in ['cell_mask_dim', 'cell_min_size', 'nucleus_mask_dim', 'nucleus_min_size', 'pathogen_mask_dim', 'pathogen_min_size', 'cytoplasm_min_size', 'max_workers', 'channel_of_interest', 'nr_imgs']:
|
141
156
|
settings[key] = int(value) if value else None
|
142
157
|
|
143
158
|
elif key == 'um_per_pixel':
|
144
159
|
settings[key] = float(value) if value else None
|
145
160
|
|
146
|
-
#
|
161
|
+
# Handling boolean values based on checkboxes
|
147
162
|
elif key in ['save_png', 'use_bounding_box', 'save_measurements', 'plot', 'plot_filtration', 'include_uninfected', 'dialate_pngs', 'timelapse', 'representative_images']:
|
148
|
-
settings[key] =
|
149
|
-
|
150
|
-
else:
|
151
|
-
settings[key] = value
|
163
|
+
settings[key] = var.get()
|
152
164
|
|
153
165
|
except SyntaxError as e:
|
154
|
-
|
166
|
+
print(f"Syntax error processing {key}: {str(e)}")
|
167
|
+
#messagebox.showerror("Error", f"Syntax error processing {key}: {str(e)}")
|
155
168
|
return None
|
156
169
|
except Exception as e:
|
157
|
-
|
170
|
+
print(f"Error processing {key}: {str(e)}")
|
171
|
+
#messagebox.showerror("Error", f"Error processing {key}: {str(e)}")
|
158
172
|
return None
|
159
173
|
|
160
174
|
return settings
|
161
175
|
|
162
|
-
def
|
176
|
+
def check_classify_gui_settings(vars_dict):
|
163
177
|
settings = {}
|
164
178
|
for key, var in vars_dict.items():
|
165
179
|
value = var.get() # This retrieves the string representation for entries or the actual value for checkboxes and combos
|
166
180
|
|
167
181
|
try:
|
168
|
-
if key
|
169
|
-
#
|
170
|
-
settings[key] =
|
171
|
-
|
172
|
-
|
173
|
-
settings[key] =
|
174
|
-
|
175
|
-
|
176
|
-
settings[key] =
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
elif key == 'normalize_by':
|
183
|
-
# 'normalize_by' is a string, so directly assign the value
|
182
|
+
if key in ['src', 'measurement']:
|
183
|
+
# Directly assign string values
|
184
|
+
settings[key] = str(value)
|
185
|
+
elif key in ['cell_mask_dim', 'image_size', 'batch_size', 'epochs', 'gradient_accumulation_steps', 'num_workers']:
|
186
|
+
# Convert to integer
|
187
|
+
settings[key] = int(value)
|
188
|
+
elif key in ['val_split', 'learning_rate', 'weight_decay', 'dropout_rate']:
|
189
|
+
# Convert to float
|
190
|
+
settings[key] = float(value)
|
191
|
+
elif key == 'classes':
|
192
|
+
# Evaluate as list
|
193
|
+
settings[key] = ast.literal_eval(value)
|
194
|
+
|
195
|
+
elif key in ['model_type','optimizer_type','schedule','loss_type','train_mode']:
|
184
196
|
settings[key] = value
|
185
197
|
|
186
|
-
elif key
|
187
|
-
|
188
|
-
temp_val = ast.literal_eval(value) if value else []
|
189
|
-
settings[key] = [list(map(int, dim)) for dim in temp_val] if temp_val else None
|
190
|
-
|
191
|
-
# Handling for other keys as in your original function...
|
192
|
-
|
193
|
-
elif key in ['pathogens', 'treatments', 'cells', 'crop_mode', 'timelapse_objects']:
|
194
|
-
# Ensuring these are evaluated correctly as lists or other structures
|
195
|
-
settings[key] = ast.literal_eval(value) if value else None
|
196
|
-
|
197
|
-
elif key == 'timelapse_objects':
|
198
|
-
# Ensure it's a list of strings
|
199
|
-
settings[key] = eval(value) if value else []
|
198
|
+
elif key in ['gradient_accumulation','normalize','save','plot', 'init_weights','amsgrad','use_checkpoint','intermedeate_save','pin_memory', 'num_workers','verbose']:
|
199
|
+
settings[key] = bool(value)
|
200
200
|
|
201
|
-
|
202
|
-
|
203
|
-
|
201
|
+
except SyntaxError as e:
|
202
|
+
messagebox.showerror("Error", f"Syntax error processing {key}: {str(e)}")
|
203
|
+
return None
|
204
|
+
except Exception as e:
|
205
|
+
messagebox.showerror("Error", f"Error processing {key}: {str(e)}")
|
206
|
+
return None
|
204
207
|
|
205
|
-
|
206
|
-
elif key in ['cell_mask_dim', 'cell_min_size', 'nucleus_mask_dim', 'nucleus_min_size', 'pathogen_mask_dim', 'pathogen_min_size', 'cytoplasm_min_size', 'max_workers', 'channel_of_interest', 'nr_imgs']:
|
207
|
-
settings[key] = int(value) if value else None
|
208
|
+
return settings
|
208
209
|
|
209
|
-
|
210
|
-
|
210
|
+
def check_sim_gui_settings(vars_dict):
|
211
|
+
settings = {}
|
212
|
+
for key, var in vars_dict.items():
|
213
|
+
value = var.get() # This retrieves the string representation for entries or the actual value for checkboxes and combos
|
211
214
|
|
212
|
-
|
213
|
-
|
215
|
+
try:
|
216
|
+
if key in ['src', 'name', 'variable']:
|
217
|
+
# Directly assign string values
|
218
|
+
settings[key] = str(value)
|
219
|
+
|
220
|
+
elif key in ['nr_plates', 'number_of_genes','number_of_active_genes','avg_genes_per_well','avg_cells_per_well','avg_reads_per_gene']:
|
221
|
+
#generate list of integers from list
|
222
|
+
ls = [int(num) for num in ast.literal_eval(value)]
|
223
|
+
if len(ls) == 3 and ls[2] > 0:
|
224
|
+
list_of_integers = list(range(ls[0], ls[1], ls[2]))
|
225
|
+
list_of_integers = [num + 1 if num == 0 else num for num in list_of_integers]
|
226
|
+
else:
|
227
|
+
list_of_integers = [ls[0]]
|
228
|
+
settings[key] = list_of_integers
|
229
|
+
|
230
|
+
elif key in ['sequencing_error','well_ineq_coeff','gene_ineq_coeff', 'positive_mean']:
|
231
|
+
#generate list of floats from list
|
232
|
+
ls = [float(num) for num in ast.literal_eval(value)]
|
233
|
+
if len(ls) == 3 and ls[2] > 0:
|
234
|
+
list_of_floats = np.linspace(ls[0], ls[1], ls[2])
|
235
|
+
list_of_floats.tolist()
|
236
|
+
list_of_floats = [x if x != 0.0 else x + 0.01 for x in list_of_floats]
|
237
|
+
else:
|
238
|
+
list_of_floats = [ls[0]]
|
239
|
+
settings[key] = list_of_floats
|
240
|
+
|
241
|
+
elif key in ['plot', 'random_seed']:
|
242
|
+
# Evaluate as bool
|
214
243
|
settings[key] = bool(value)
|
215
|
-
|
244
|
+
|
245
|
+
elif key in ['number_of_control_genes', 'replicates', 'max_workers']:
|
246
|
+
# Convert to integer
|
247
|
+
settings[key] = int(value)
|
248
|
+
|
216
249
|
except SyntaxError as e:
|
217
250
|
messagebox.showerror("Error", f"Syntax error processing {key}: {str(e)}")
|
218
251
|
return None
|
@@ -222,17 +255,44 @@ def check_measure_gui_settings(vars_dict):
|
|
222
255
|
|
223
256
|
return settings
|
224
257
|
|
258
|
+
def sim_variables():
|
259
|
+
variables = {
|
260
|
+
'name':('entry', None, 'plates_2_4_8'),
|
261
|
+
'variable':('entry', None, 'all'),
|
262
|
+
'src':('entry', None, '/home/olafsson/Desktop/simulations'),
|
263
|
+
'number_of_control_genes':('entry', None, 30),
|
264
|
+
'replicates':('entry', None, 4),
|
265
|
+
'max_workers':('entry', None, 1),
|
266
|
+
'plot':('check', None, True),
|
267
|
+
'random_seed':('check', None, True),
|
268
|
+
'nr_plates': ('entry', None, '[8,8,0]'),# '[2,2,8]'
|
269
|
+
'number_of_genes': ('entry', None, '[100, 100, 0]'), #[1384, 1384, 0]
|
270
|
+
'number_of_active_genes': ('entry', None, '[10,10,0]'),
|
271
|
+
'avg_genes_per_well': ('entry', None, '[2, 10, 2]'),
|
272
|
+
'avg_cells_per_well': ('entry', None, '[100, 100, 0]'),
|
273
|
+
'positive_mean': ('entry', None, '[0.8, 0.8, 0]'),
|
274
|
+
'avg_reads_per_gene': ('entry', None, '[1000,1000, 0]'),
|
275
|
+
'sequencing_error': ('entry', None, '[0.01, 0.01, 0]'),
|
276
|
+
'well_ineq_coeff': ('entry', None, '[0.3,0.3,0]'),
|
277
|
+
'gene_ineq_coeff': ('entry', None, '[0.8,0.8,0]'),
|
278
|
+
}
|
279
|
+
return variables
|
280
|
+
|
281
|
+
def add_measure_gui_defaults(settings):
|
282
|
+
settings['compartments'] = ['pathogen', 'cytoplasm']
|
283
|
+
return settings
|
284
|
+
|
225
285
|
def measure_variables():
|
226
286
|
variables = {
|
227
287
|
'input_folder':('entry', None, '/mnt/data/CellVoyager/40x/einar/mitotrackerHeLaToxoDsRed_20240224_123156/test_gui/merged'),
|
228
288
|
'channels': ('combo', ['[0,1,2,3]','[0,1,2]','[0,1]','[0]'], '[0,1,2,3]'),
|
229
289
|
'cell_mask_dim':('entry', None, 4),
|
230
290
|
'cell_min_size':('entry', None, 0),
|
291
|
+
'cytoplasm_min_size':('entry', None, 0),
|
231
292
|
'nucleus_mask_dim':('entry', None, 5),
|
232
293
|
'nucleus_min_size':('entry', None, 0),
|
233
294
|
'pathogen_mask_dim':('entry', None, 6),
|
234
295
|
'pathogen_min_size':('entry', None, 0),
|
235
|
-
'cytoplasm_min_size':('entry', None, 0),
|
236
296
|
'save_png':('check', None, True),
|
237
297
|
'crop_mode':('entry', None, '["cell"]'),
|
238
298
|
'use_bounding_box':('check', None, True),
|
@@ -258,14 +318,56 @@ def measure_variables():
|
|
258
318
|
'treatments': ('entry', None, '["cm","lovastatin_20uM"]'),
|
259
319
|
'treatment_loc': ('entry', None, '[["c1","c2"], ["c3","c4"]]'),
|
260
320
|
'channel_of_interest':('entry', None, 3),
|
321
|
+
'compartments':('entry', None, '["pathogen","cytoplasm"]'),
|
261
322
|
'measurement':('entry', None, 'mean_intensity'),
|
262
323
|
'nr_imgs':('entry', None, 32),
|
263
324
|
'um_per_pixel':('entry', None, 0.1)
|
264
325
|
}
|
265
326
|
return variables
|
327
|
+
|
328
|
+
def classify_variables():
|
329
|
+
|
330
|
+
def get_torchvision_models():
|
331
|
+
# Fetch all public callable attributes from torchvision.models that are functions
|
332
|
+
model_names = [name for name, obj in inspect.getmembers(models)
|
333
|
+
if inspect.isfunction(obj) and not name.startswith("__")]
|
334
|
+
return model_names
|
335
|
+
|
336
|
+
model_names = get_torchvision_models()
|
337
|
+
variables = {
|
338
|
+
'src':('entry', None, '/mnt/data/CellVoyager/40x/einar/mitotrackerHeLaToxoDsRed_20240224_123156/test_gui/merged'),
|
339
|
+
'cell_mask_dim':('entry', None, 4),
|
340
|
+
'classes':('entry', None, '["nc","pc"]'),
|
341
|
+
'measurement':('entry', None, 'mean_intensity'),
|
342
|
+
'model_type': ('combo', model_names, 'resnet50'),
|
343
|
+
'optimizer_type': ('combo', ['adamw','adam'], 'adamw'),
|
344
|
+
'schedule': ('combo', ['reduce_lr_on_plateau','step_lr'], 'reduce_lr_on_plateau'),
|
345
|
+
'loss_type': ('combo', ['focal_loss', 'binary_cross_entropy_with_logits'], 'focal_loss'),
|
346
|
+
'image_size': ('entry', None, 224),
|
347
|
+
'batch_size': ('entry', None, 12),
|
348
|
+
'epochs': ('entry', None, 2),
|
349
|
+
'val_split': ('entry', None, 0.1),
|
350
|
+
'train_mode': ('combo', ['erm', 'irm'], 'erm'),
|
351
|
+
'learning_rate': ('entry', None, 0.0001),
|
352
|
+
'weight_decay': ('entry', None, 0.00001),
|
353
|
+
'dropout_rate': ('entry', None, 0.1),
|
354
|
+
'gradient_accumulation': ('check', None, True),
|
355
|
+
'gradient_accumulation_steps': ('entry', None, 4),
|
356
|
+
'normalize': ('check', None, True),
|
357
|
+
'save': ('check', None, True),
|
358
|
+
'plot': ('check', None, True),
|
359
|
+
'init_weights': ('check', None, True),
|
360
|
+
'amsgrad': ('check', None, True),
|
361
|
+
'use_checkpoint': ('check', None, True),
|
362
|
+
'intermedeate_save': ('check', None, True),
|
363
|
+
'pin_memory': ('check', None, True),
|
364
|
+
'num_workers': ('entry', None, 30),
|
365
|
+
'verbose': ('check', None, True),
|
366
|
+
}
|
367
|
+
return variables
|
266
368
|
|
267
369
|
|
268
|
-
|
370
|
+
#@log_function_call
|
269
371
|
def create_input_field(frame, label_text, row, var_type='entry', options=None, default_value=None):
|
270
372
|
label = ttk.Label(frame, text=label_text, style='TLabel') # Assuming you have a dark mode style for labels too
|
271
373
|
label.grid(column=0, row=row, sticky=tk.W, padx=5, pady=5)
|
@@ -289,10 +391,6 @@ def create_input_field(frame, label_text, row, var_type='entry', options=None, d
|
|
289
391
|
var = None # Placeholder in case of an undefined var_type
|
290
392
|
|
291
393
|
return var
|
292
|
-
|
293
|
-
def add_measure_gui_defaults(settings):
|
294
|
-
settings['compartments'] = ['pathogen', 'cytoplasm']
|
295
|
-
return settings
|
296
394
|
|
297
395
|
def mask_variables():
|
298
396
|
variables = {
|
@@ -314,10 +412,10 @@ def mask_variables():
|
|
314
412
|
'pathogen_background': ('entry', None, 100),
|
315
413
|
'pathogen_Signal_to_noise': ('entry', None, 3),
|
316
414
|
'pathogen_CP_prob': ('entry', None, 0),
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
415
|
+
'preprocess': ('check', None, True),
|
416
|
+
'masks': ('check', None, True),
|
417
|
+
'examples_to_plot': ('entry', None, 1),
|
418
|
+
'randomize': ('check', None, True),
|
321
419
|
'batch_size': ('entry', None, 50),
|
322
420
|
'timelapse': ('check', None, False),
|
323
421
|
'timelapse_displacement': ('entry', None, None),
|
@@ -326,14 +424,14 @@ def mask_variables():
|
|
326
424
|
'timelapse_remove_transient': ('check', None, True),
|
327
425
|
'timelapse_mode': ('combo', ['trackpy', 'btrack'], 'trackpy'),
|
328
426
|
'timelapse_objects': ('combo', ['cell','nucleus','pathogen','cytoplasm', None], None),
|
329
|
-
|
330
|
-
|
427
|
+
'fps': ('entry', None, 2),
|
428
|
+
'remove_background': ('check', None, True),
|
331
429
|
'lower_quantile': ('entry', None, 0.01),
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
430
|
+
'merge': ('check', None, False),
|
431
|
+
'normalize_plots': ('check', None, True),
|
432
|
+
'all_to_mip': ('check', None, False),
|
433
|
+
'pick_slice': ('check', None, False),
|
434
|
+
'skip_mode': ('entry', None, None),
|
337
435
|
'save': ('check', None, True),
|
338
436
|
'plot': ('check', None, True),
|
339
437
|
'workers': ('entry', None, 30),
|
@@ -401,29 +499,34 @@ def set_dark_style(style):
|
|
401
499
|
style.configure('TEntry', background='#333333', foreground='white')
|
402
500
|
style.configure('TCheckbutton', background='#333333', foreground='white')
|
403
501
|
|
404
|
-
|
405
|
-
|
406
|
-
@log_function_call
|
502
|
+
#@log_function_call
|
407
503
|
def main_thread_update_function(root, q, fig_queue, canvas_widget, progress_label):
|
408
504
|
try:
|
505
|
+
ansi_escape_pattern = re.compile(r'\x1B\[[0-?]*[ -/]*[@-~]')
|
409
506
|
while not q.empty():
|
410
507
|
message = q.get_nowait()
|
411
|
-
|
412
|
-
|
413
|
-
|
508
|
+
clean_message = ansi_escape_pattern.sub('', message)
|
509
|
+
if clean_message.startswith("Progress"):
|
510
|
+
progress_label.config(text=clean_message)
|
511
|
+
if clean_message.startswith("\rProgress"):
|
512
|
+
progress_label.config(text=clean_message)
|
513
|
+
elif clean_message.startswith("Successfully"):
|
514
|
+
progress_label.config(text=clean_message)
|
515
|
+
elif clean_message.startswith("Processing"):
|
516
|
+
progress_label.config(text=clean_message)
|
517
|
+
elif clean_message.startswith("scale"):
|
518
|
+
pass
|
519
|
+
elif clean_message.startswith("plot_cropped_arrays"):
|
520
|
+
pass
|
521
|
+
elif clean_message == "" or clean_message == "\r" or clean_message.strip() == "":
|
414
522
|
pass
|
415
523
|
else:
|
416
|
-
print(
|
417
|
-
# For non-progress messages, you can still print them to the console or handle them as needed.
|
418
|
-
|
419
|
-
while not fig_queue.empty():
|
420
|
-
fig = fig_queue.get_nowait()
|
421
|
-
clear_canvas(canvas_widget)
|
524
|
+
print(clean_message)
|
422
525
|
except Exception as e:
|
423
|
-
print(f"Error updating GUI: {e}")
|
526
|
+
print(f"Error updating GUI canvas: {e}")
|
424
527
|
finally:
|
425
528
|
root.after(100, lambda: main_thread_update_function(root, q, fig_queue, canvas_widget, progress_label))
|
426
|
-
|
529
|
+
|
427
530
|
def process_stdout_stderr(q):
|
428
531
|
"""
|
429
532
|
Redirect stdout and stderr to the queue q.
|
@@ -453,7 +556,6 @@ def clear_canvas(canvas):
|
|
453
556
|
# Redraw the now empty canvas without changing its size
|
454
557
|
canvas.draw_idle()
|
455
558
|
|
456
|
-
@log_function_call
|
457
559
|
def measure_crop_wrapper(settings, q, fig_queue):
|
458
560
|
"""
|
459
561
|
Wraps the measure_crop function to integrate with GUI processes.
|
@@ -463,7 +565,7 @@ def measure_crop_wrapper(settings, q, fig_queue):
|
|
463
565
|
- q: multiprocessing.Queue, Queue for logging messages to the GUI.
|
464
566
|
- fig_queue: multiprocessing.Queue, Queue for sending figures to the GUI.
|
465
567
|
"""
|
466
|
-
|
568
|
+
|
467
569
|
def my_show():
|
468
570
|
"""
|
469
571
|
Replacement for plt.show() that queues figures instead of displaying them.
|
@@ -477,12 +579,106 @@ def measure_crop_wrapper(settings, q, fig_queue):
|
|
477
579
|
plt.show = my_show
|
478
580
|
|
479
581
|
try:
|
480
|
-
|
481
|
-
# Pass settings as a named argument, along with any other needed arguments
|
582
|
+
print('start')
|
482
583
|
spacr.measure.measure_crop(settings=settings, annotation_settings={}, advanced_settings={})
|
483
584
|
except Exception as e:
|
484
585
|
errorMessage = f"Error during processing: {e}"
|
485
586
|
q.put(errorMessage) # Send the error message to the GUI via the queue
|
486
587
|
traceback.print_exc()
|
487
588
|
finally:
|
488
|
-
plt.show = original_show # Restore the original plt.show function
|
589
|
+
plt.show = original_show # Restore the original plt.show function
|
590
|
+
|
591
|
+
@log_function_call
|
592
|
+
def preprocess_generate_masks_wrapper(settings, q, fig_queue):
|
593
|
+
"""
|
594
|
+
Wraps the measure_crop function to integrate with GUI processes.
|
595
|
+
|
596
|
+
Parameters:
|
597
|
+
- settings: dict, The settings for the measure_crop function.
|
598
|
+
- q: multiprocessing.Queue, Queue for logging messages to the GUI.
|
599
|
+
- fig_queue: multiprocessing.Queue, Queue for sending figures to the GUI.
|
600
|
+
"""
|
601
|
+
|
602
|
+
def my_show():
|
603
|
+
"""
|
604
|
+
Replacement for plt.show() that queues figures instead of displaying them.
|
605
|
+
"""
|
606
|
+
fig = plt.gcf()
|
607
|
+
fig_queue.put(fig) # Queue the figure for GUI display
|
608
|
+
plt.close(fig) # Prevent the figure from being shown by plt.show()
|
609
|
+
|
610
|
+
# Temporarily override plt.show
|
611
|
+
original_show = plt.show
|
612
|
+
plt.show = my_show
|
613
|
+
|
614
|
+
try:
|
615
|
+
spacr.core.preprocess_generate_masks(settings['src'], settings=settings)
|
616
|
+
except Exception as e:
|
617
|
+
errorMessage = f"Error during processing: {e}"
|
618
|
+
q.put(errorMessage) # Send the error message to the GUI via the queue
|
619
|
+
traceback.print_exc()
|
620
|
+
finally:
|
621
|
+
plt.show = original_show # Restore the original plt.show function
|
622
|
+
|
623
|
+
def train_test_model_wrapper(settings, q, fig_queue):
|
624
|
+
"""
|
625
|
+
Wraps the measure_crop function to integrate with GUI processes.
|
626
|
+
|
627
|
+
Parameters:
|
628
|
+
- settings: dict, The settings for the measure_crop function.
|
629
|
+
- q: multiprocessing.Queue, Queue for logging messages to the GUI.
|
630
|
+
- fig_queue: multiprocessing.Queue, Queue for sending figures to the GUI.
|
631
|
+
"""
|
632
|
+
|
633
|
+
def my_show():
|
634
|
+
"""
|
635
|
+
Replacement for plt.show() that queues figures instead of displaying them.
|
636
|
+
"""
|
637
|
+
fig = plt.gcf()
|
638
|
+
fig_queue.put(fig) # Queue the figure for GUI display
|
639
|
+
plt.close(fig) # Prevent the figure from being shown by plt.show()
|
640
|
+
|
641
|
+
# Temporarily override plt.show
|
642
|
+
original_show = plt.show
|
643
|
+
plt.show = my_show
|
644
|
+
|
645
|
+
try:
|
646
|
+
spacr.core.train_test_model(settings['src'], settings=settings)
|
647
|
+
except Exception as e:
|
648
|
+
errorMessage = f"Error during processing: {e}"
|
649
|
+
q.put(errorMessage) # Send the error message to the GUI via the queue
|
650
|
+
traceback.print_exc()
|
651
|
+
finally:
|
652
|
+
plt.show = original_show # Restore the original plt.show function
|
653
|
+
|
654
|
+
|
655
|
+
def run_multiple_simulations_wrapper(settings, q, fig_queue):
|
656
|
+
"""
|
657
|
+
Wraps the run_multiple_simulations function to integrate with GUI processes.
|
658
|
+
|
659
|
+
Parameters:
|
660
|
+
- settings: dict, The settings for the run_multiple_simulations function.
|
661
|
+
- q: multiprocessing.Queue, Queue for logging messages to the GUI.
|
662
|
+
- fig_queue: multiprocessing.Queue, Queue for sending figures to the GUI.
|
663
|
+
"""
|
664
|
+
|
665
|
+
def my_show():
|
666
|
+
"""
|
667
|
+
Replacement for plt.show() that queues figures instead of displaying them.
|
668
|
+
"""
|
669
|
+
fig = plt.gcf()
|
670
|
+
fig_queue.put(fig) # Queue the figure for GUI display
|
671
|
+
plt.close(fig) # Prevent the figure from being shown by plt.show()
|
672
|
+
|
673
|
+
# Temporarily override plt.show
|
674
|
+
original_show = plt.show
|
675
|
+
plt.show = my_show
|
676
|
+
|
677
|
+
try:
|
678
|
+
spacr.sim.run_multiple_simulations(settings=settings)
|
679
|
+
except Exception as e:
|
680
|
+
errorMessage = f"Error during processing: {e}"
|
681
|
+
q.put(errorMessage) # Send the error message to the GUI via the queue
|
682
|
+
traceback.print_exc()
|
683
|
+
finally:
|
684
|
+
plt.show = original_show # Restore the original plt.show function
|