spacr 0.4.12__py3-none-any.whl → 0.4.15__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/core.py +4 -1
- spacr/gui_core.py +19 -41
- spacr/gui_utils.py +11 -9
- spacr/io.py +14 -7
- spacr/measure.py +11 -12
- spacr/settings.py +105 -46
- spacr/submodules.py +1 -1
- spacr/utils.py +91 -10
- {spacr-0.4.12.dist-info → spacr-0.4.15.dist-info}/METADATA +1 -1
- {spacr-0.4.12.dist-info → spacr-0.4.15.dist-info}/RECORD +14 -14
- {spacr-0.4.12.dist-info → spacr-0.4.15.dist-info}/LICENSE +0 -0
- {spacr-0.4.12.dist-info → spacr-0.4.15.dist-info}/WHEEL +0 -0
- {spacr-0.4.12.dist-info → spacr-0.4.15.dist-info}/entry_points.txt +0 -0
- {spacr-0.4.12.dist-info → spacr-0.4.15.dist-info}/top_level.txt +0 -0
spacr/core.py
CHANGED
@@ -11,7 +11,7 @@ def preprocess_generate_masks(settings):
|
|
11
11
|
|
12
12
|
from .io import preprocess_img_data, _load_and_concatenate_arrays
|
13
13
|
from .plot import plot_image_mask_overlay, plot_arrays
|
14
|
-
from .utils import _pivot_counts_table, check_mask_folder, adjust_cell_masks, print_progress, save_settings, delete_intermedeate_files
|
14
|
+
from .utils import _pivot_counts_table, check_mask_folder, adjust_cell_masks, print_progress, save_settings, delete_intermedeate_files, format_path_for_system, normalize_src_path
|
15
15
|
from .settings import set_default_settings_preprocess_generate_masks
|
16
16
|
|
17
17
|
|
@@ -23,6 +23,8 @@ def preprocess_generate_masks(settings):
|
|
23
23
|
ValueError(f'src is a required parameter')
|
24
24
|
return
|
25
25
|
|
26
|
+
settings['src'] = normalize_src_path(settings['src'])
|
27
|
+
|
26
28
|
if isinstance(settings['src'], str):
|
27
29
|
settings['src'] = [settings['src']]
|
28
30
|
|
@@ -30,6 +32,7 @@ def preprocess_generate_masks(settings):
|
|
30
32
|
source_folders = settings['src']
|
31
33
|
for source_folder in source_folders:
|
32
34
|
print(f'Processing folder: {source_folder}')
|
35
|
+
source_folder = format_path_for_system(source_folder)
|
33
36
|
settings['src'] = source_folder
|
34
37
|
src = source_folder
|
35
38
|
settings = set_default_settings_preprocess_generate_masks(settings)
|
spacr/gui_core.py
CHANGED
@@ -170,49 +170,22 @@ def display_figure(fig):
|
|
170
170
|
#flash_feedback("right")
|
171
171
|
show_next_figure()
|
172
172
|
|
173
|
-
def zoom_v1(event):
|
174
|
-
nonlocal scale_factor
|
175
|
-
|
176
|
-
zoom_speed = 0.1 # Adjust the zoom speed for smoother experience
|
177
|
-
|
178
|
-
# Determine the zoom direction based on the scroll event
|
179
|
-
if event.num == 4 or event.delta > 0: # Scroll up (zoom in)
|
180
|
-
scale_factor /= (1 + zoom_speed) # Divide to zoom in
|
181
|
-
elif event.num == 5 or event.delta < 0: # Scroll down (zoom out)
|
182
|
-
scale_factor *= (1 + zoom_speed) # Multiply to zoom out
|
183
|
-
|
184
|
-
# Adjust the axes limits based on the new scale factor
|
185
|
-
for ax in canvas.figure.get_axes():
|
186
|
-
xlim = ax.get_xlim()
|
187
|
-
ylim = ax.get_ylim()
|
188
|
-
|
189
|
-
x_center = (xlim[1] + xlim[0]) / 2
|
190
|
-
y_center = (ylim[1] + ylim[0]) / 2
|
191
|
-
|
192
|
-
x_range = (xlim[1] - xlim[0]) * scale_factor
|
193
|
-
y_range = (ylim[1] - ylim[0]) * scale_factor
|
194
|
-
|
195
|
-
# Set the new limits
|
196
|
-
ax.set_xlim([x_center - x_range / 2, x_center + x_range / 2])
|
197
|
-
ax.set_ylim([y_center - y_range / 2, y_center + y_range / 2])
|
198
|
-
|
199
|
-
# Redraw the figure efficiently
|
200
|
-
canvas.draw_idle()
|
201
|
-
|
202
173
|
def zoom_test(event):
|
203
174
|
if event.num == 4: # Scroll up
|
204
175
|
print("zoom in")
|
205
176
|
elif event.num == 5: # Scroll down
|
206
177
|
print("zoom out")
|
207
|
-
|
208
|
-
def
|
209
|
-
|
178
|
+
|
179
|
+
def zoom_v1(event):
|
180
|
+
# Fixed zoom factors (adjust these if you want faster or slower zoom)
|
181
|
+
zoom_in_factor = 0.9 # When zooming in, ranges shrink by 10%
|
182
|
+
zoom_out_factor = 1.1 # When zooming out, ranges increase by 10%
|
210
183
|
|
211
184
|
# Determine the zoom direction based on the scroll event
|
212
185
|
if event.num == 4 or (hasattr(event, 'delta') and event.delta > 0): # Scroll up = zoom in
|
213
|
-
factor =
|
186
|
+
factor = zoom_in_factor
|
214
187
|
elif event.num == 5 or (hasattr(event, 'delta') and event.delta < 0): # Scroll down = zoom out
|
215
|
-
factor =
|
188
|
+
factor = zoom_out_factor
|
216
189
|
else:
|
217
190
|
return # No recognized scroll direction
|
218
191
|
|
@@ -247,23 +220,28 @@ def display_figure(fig):
|
|
247
220
|
return # No recognized scroll direction
|
248
221
|
|
249
222
|
for ax in canvas.figure.get_axes():
|
223
|
+
# Get the current mouse position in pixel coordinates
|
224
|
+
mouse_x, mouse_y = event.x, event.y
|
225
|
+
|
226
|
+
# Convert pixel coordinates to data coordinates
|
227
|
+
inv = ax.transData.inverted()
|
228
|
+
data_x, data_y = inv.transform((mouse_x, mouse_y))
|
229
|
+
|
230
|
+
# Get the current axis limits
|
250
231
|
xlim = ax.get_xlim()
|
251
232
|
ylim = ax.get_ylim()
|
252
233
|
|
253
|
-
|
254
|
-
y_center = (ylim[1] + ylim[0]) / 2
|
255
|
-
|
234
|
+
# Calculate the zooming range around the cursor position
|
256
235
|
x_range = (xlim[1] - xlim[0]) * factor
|
257
236
|
y_range = (ylim[1] - ylim[0]) * factor
|
258
237
|
|
259
|
-
#
|
260
|
-
ax.set_xlim([
|
261
|
-
ax.set_ylim([
|
238
|
+
# Adjust the limits while keeping the mouse position fixed
|
239
|
+
ax.set_xlim([data_x - (data_x - xlim[0]) * factor, data_x + (xlim[1] - data_x) * factor])
|
240
|
+
ax.set_ylim([data_y - (data_y - ylim[0]) * factor, data_y + (ylim[1] - data_y) * factor])
|
262
241
|
|
263
242
|
# Redraw the figure efficiently
|
264
243
|
canvas.draw_idle()
|
265
244
|
|
266
|
-
|
267
245
|
# Bind events for hover, click interactions, and zoom
|
268
246
|
canvas_widget.bind("<Motion>", on_hover)
|
269
247
|
canvas_widget.bind("<Leave>", on_leave)
|
spacr/gui_utils.py
CHANGED
@@ -106,7 +106,6 @@ def parse_list(value):
|
|
106
106
|
except (ValueError, SyntaxError) as e:
|
107
107
|
raise ValueError(f"Invalid format for list: {value}. Error: {e}")
|
108
108
|
|
109
|
-
# Usage example in your create_input_field function
|
110
109
|
def create_input_field(frame, label_text, row, var_type='entry', options=None, default_value=None):
|
111
110
|
"""
|
112
111
|
Create an input field in the specified frame.
|
@@ -365,13 +364,16 @@ def convert_settings_dict_for_gui(settings):
|
|
365
364
|
from torchvision import models as torch_models
|
366
365
|
torchvision_models = [name for name, obj in torch_models.__dict__.items() if callable(obj)]
|
367
366
|
chans = ['0', '1', '2', '3', '4', '5', '6', '7', '8', None]
|
367
|
+
chan_list = ['[0,1,2,3,4,5,6,7,8]','[0,1,2,3,4,5,6,7]','[0,1,2,3,4,5,6]','[0,1,2,3,4,5]','[0,1,2,3,4]','[0,1,2,3]', '[0,1,2]', '[0,1]', '[0]', '[0,0]']
|
368
368
|
chans_v2 = [0, 1, 2, 3, None]
|
369
|
+
chans_v3 = list(range(0, 21, 1)) + [None]
|
370
|
+
chans_v4 = [0, 1, 2, 3, None]
|
369
371
|
variables = {}
|
370
372
|
special_cases = {
|
371
373
|
'metadata_type': ('combo', ['cellvoyager', 'cq1', 'nikon', 'zeis', 'custom'], 'cellvoyager'),
|
372
|
-
'channels': ('combo',
|
374
|
+
'channels': ('combo', chan_list, '[0,1,2,3]'),
|
373
375
|
'train_channels': ('combo', ["['r','g','b']", "['r','g']", "['r','b']", "['g','b']", "['r']", "['g']", "['b']"], "['r','g','b']"),
|
374
|
-
'channel_dims': ('combo',
|
376
|
+
'channel_dims': ('combo', chan_list, '[0,1,2,3]'),
|
375
377
|
'dataset_mode': ('combo', ['annotation', 'metadata', 'recruitment'], 'metadata'),
|
376
378
|
'cov_type': ('combo', ['HC0', 'HC1', 'HC2', 'HC3', None], None),
|
377
379
|
'cell_mask_dim': ('combo', chans, None),
|
@@ -380,12 +382,12 @@ def convert_settings_dict_for_gui(settings):
|
|
380
382
|
'nucleus_chann_dim': ('combo', chans, None),
|
381
383
|
'pathogen_mask_dim': ('combo', chans, None),
|
382
384
|
'pathogen_chann_dim': ('combo', chans, None),
|
383
|
-
'crop_mode': ('combo', [['cell'], ['nucleus'], ['pathogen'], ['cell', 'nucleus'], ['cell', 'pathogen'], ['nucleus', 'pathogen'], ['cell', 'nucleus', 'pathogen']], ['cell']),
|
384
|
-
|
385
|
-
'nucleus_channel': ('combo',
|
386
|
-
'cell_channel': ('combo',
|
387
|
-
'channel_of_interest': ('combo',
|
388
|
-
'pathogen_channel': ('combo',
|
385
|
+
'crop_mode': ('combo', ["['cell']", "['nucleus']", "['pathogen']", "['cell', 'nucleus']", "['cell', 'pathogen']", "['nucleus', 'pathogen']", "['cell', 'nucleus', 'pathogen']"], "['cell']"),
|
386
|
+
#'magnification': ('combo', [20, 40, 60], 20),
|
387
|
+
'nucleus_channel': ('combo', chans_v3, None),
|
388
|
+
'cell_channel': ('combo', chans_v3, None),
|
389
|
+
'channel_of_interest': ('combo', chans_v3, None),
|
390
|
+
'pathogen_channel': ('combo', chans_v3, None),
|
389
391
|
'timelapse_mode': ('combo', ['trackpy', 'btrack'], 'trackpy'),
|
390
392
|
'train_mode': ('combo', ['erm', 'irm'], 'erm'),
|
391
393
|
'clustering': ('combo', ['dbscan', 'kmean'], 'dbscan'),
|
spacr/io.py
CHANGED
@@ -891,11 +891,16 @@ def _merge_channels(src, plot=False):
|
|
891
891
|
from .utils import print_progress
|
892
892
|
|
893
893
|
stack_dir = os.path.join(src, 'stack')
|
894
|
-
allowed_names = ['01', '02', '03', '04', '00', '1', '2', '3', '4', '0']
|
894
|
+
#allowed_names = ['01', '02', '03', '04', '00', '1', '2', '3', '4', '0']
|
895
|
+
|
896
|
+
string_list = [str(i) for i in range(101)]+[f"{i:02d}" for i in range(10)]
|
897
|
+
allowed_names = sorted(string_list, key=lambda x: int(x))
|
895
898
|
|
896
899
|
# List directories that match the allowed names
|
897
900
|
chan_dirs = [d for d in os.listdir(src) if os.path.isdir(os.path.join(src, d)) and d in allowed_names]
|
898
901
|
chan_dirs.sort()
|
902
|
+
|
903
|
+
num_matching_folders = len(chan_dirs)
|
899
904
|
|
900
905
|
print(f'List of folders in src: {chan_dirs}. Single channel folders.')
|
901
906
|
|
@@ -925,7 +930,7 @@ def _merge_channels(src, plot=False):
|
|
925
930
|
if plot:
|
926
931
|
plot_arrays(os.path.join(src, 'stack'))
|
927
932
|
|
928
|
-
return
|
933
|
+
return num_matching_folders
|
929
934
|
|
930
935
|
def _mip_all(src, include_first_chan=True):
|
931
936
|
|
@@ -1584,10 +1589,6 @@ def preprocess_img_data(settings):
|
|
1584
1589
|
else:
|
1585
1590
|
print(f'Could not find any {valid_ext} files in {src} only found {extension_counts[0]}')
|
1586
1591
|
|
1587
|
-
|
1588
|
-
|
1589
|
-
|
1590
|
-
|
1591
1592
|
if os.path.exists(os.path.join(src,'stack')):
|
1592
1593
|
print('Found existing stack folder.')
|
1593
1594
|
if os.path.exists(os.path.join(src,'channel_stack')):
|
@@ -1644,7 +1645,13 @@ def preprocess_img_data(settings):
|
|
1644
1645
|
print(f"all images: {all_imgs}, full batch: {full_batches}, last batch: {last_batch_size}")
|
1645
1646
|
raise ValueError("Last batch of size 1 detected. Adjust the batch size.")
|
1646
1647
|
|
1647
|
-
_merge_channels(src, plot=False)
|
1648
|
+
nr_channel_folders = _merge_channels(src, plot=False)
|
1649
|
+
|
1650
|
+
if len(settings['channels']) != nr_channel_folders:
|
1651
|
+
print(f"Number of channels does not match number of channel folders. channels: {settings['channels']} channel folders: {nr_channel_folders}")
|
1652
|
+
new_channels = list(range(nr_channel_folders))
|
1653
|
+
print(f"Setting channels to {new_channels}")
|
1654
|
+
settings['channels'] = new_channels
|
1648
1655
|
|
1649
1656
|
if timelapse:
|
1650
1657
|
_create_movies_from_npy_per_channel(stack_path, fps=2)
|
spacr/measure.py
CHANGED
@@ -945,20 +945,25 @@ def measure_crop(settings):
|
|
945
945
|
|
946
946
|
from .io import _save_settings_to_db
|
947
947
|
from .timelapse import _timelapse_masks_to_gif
|
948
|
-
from .utils import measure_test_mode, print_progress, delete_intermedeate_files, save_settings
|
948
|
+
from .utils import measure_test_mode, print_progress, delete_intermedeate_files, save_settings, format_path_for_system, normalize_src_path
|
949
949
|
from .settings import get_measure_crop_settings
|
950
950
|
|
951
951
|
if not isinstance(settings['src'], (str, list)):
|
952
952
|
ValueError(f'src must be a string or a list of strings')
|
953
953
|
return
|
954
954
|
|
955
|
+
settings['src'] = normalize_src_path(settings['src'])
|
956
|
+
|
955
957
|
if isinstance(settings['src'], str):
|
956
958
|
settings['src'] = [settings['src']]
|
957
959
|
|
958
960
|
if isinstance(settings['src'], list):
|
959
961
|
source_folders = settings['src']
|
962
|
+
|
960
963
|
for source_folder in source_folders:
|
961
964
|
print(f'Processing folder: {source_folder}')
|
965
|
+
|
966
|
+
source_folder = format_path_for_system(source_folder)
|
962
967
|
settings['src'] = source_folder
|
963
968
|
src = source_folder
|
964
969
|
|
@@ -966,15 +971,12 @@ def measure_crop(settings):
|
|
966
971
|
settings = measure_test_mode(settings)
|
967
972
|
|
968
973
|
src_fldr = settings['src']
|
974
|
+
|
969
975
|
if not os.path.basename(src_fldr).endswith('merged'):
|
970
976
|
print(f"WARNING: Source folder, settings: src: {src_fldr} should end with '/merged'")
|
971
977
|
src_fldr = os.path.join(src_fldr, 'merged')
|
978
|
+
settings['src'] = src_fldr
|
972
979
|
print(f"Changed source folder to: {src_fldr}")
|
973
|
-
|
974
|
-
#if settings['save_measurements']:
|
975
|
-
#source_folder = os.path.dirname(settings['src'])
|
976
|
-
#os.makedirs(source_folder+'/measurements', exist_ok=True)
|
977
|
-
#_create_database(source_folder+'/measurements/measurements.db')
|
978
980
|
|
979
981
|
if settings['cell_mask_dim'] is None:
|
980
982
|
settings['uninfected'] = True
|
@@ -995,12 +997,9 @@ def measure_crop(settings):
|
|
995
997
|
print(f'Warning reserving 6 CPU cores for other processes, setting n_jobs to {spacr_cores}')
|
996
998
|
settings['n_jobs'] = spacr_cores
|
997
999
|
|
998
|
-
|
999
|
-
|
1000
|
-
|
1001
|
-
#os.makedirs(os.path.join(dirname,'settings'), exist_ok=True)
|
1002
|
-
#settings_df.to_csv(settings_csv, index=False)
|
1003
|
-
save_settings(settings, name='measure_crop_settings', show=True)
|
1000
|
+
settings_save = settings.copy()
|
1001
|
+
settings_save['src'] = os.path.dirname(settings['src'])
|
1002
|
+
save_settings(settings_save, name='measure_crop_settings', show=True)
|
1004
1003
|
|
1005
1004
|
if settings['timelapse_objects'] == 'nucleus':
|
1006
1005
|
if not settings['cell_mask_dim'] is None:
|
spacr/settings.py
CHANGED
@@ -86,7 +86,7 @@ def set_default_settings_preprocess_generate_masks(settings={}):
|
|
86
86
|
settings.setdefault('fps', 2)
|
87
87
|
settings.setdefault('timelapse_displacement', None)
|
88
88
|
settings.setdefault('timelapse_memory', 3)
|
89
|
-
settings.setdefault('timelapse_frame_limits',
|
89
|
+
settings.setdefault('timelapse_frame_limits', [5,60])
|
90
90
|
settings.setdefault('timelapse_remove_transient', False)
|
91
91
|
settings.setdefault('timelapse_mode', 'trackpy')
|
92
92
|
settings.setdefault('timelapse_objects', None)
|
@@ -256,7 +256,13 @@ def get_measure_crop_settings(settings={}):
|
|
256
256
|
settings.setdefault('homogeneity', True)
|
257
257
|
settings.setdefault('homogeneity_distances', [8,16,32])
|
258
258
|
|
259
|
-
# Cropping settings
|
259
|
+
# Cropping settings # Cropping settings
|
260
|
+
settings.setdefault('save_arrays', False)
|
261
|
+
settings.setdefault('save_png',True)
|
262
|
+
settings.setdefault('use_bounding_box',False)
|
263
|
+
settings.setdefault('png_size',[224,224])
|
264
|
+
settings.setdefault('png_dims',[0,1,2])
|
265
|
+
settings.setdefault('normalize',False) # Cropping settings
|
260
266
|
settings.setdefault('save_arrays', False)
|
261
267
|
settings.setdefault('save_png',True)
|
262
268
|
settings.setdefault('use_bounding_box',False)
|
@@ -277,9 +283,79 @@ def get_measure_crop_settings(settings={}):
|
|
277
283
|
settings.setdefault('n_jobs', os.cpu_count()-2)
|
278
284
|
|
279
285
|
# Object settings
|
280
|
-
settings.setdefault('cell_mask_dim',
|
281
|
-
settings.setdefault('nucleus_mask_dim',
|
282
|
-
settings.setdefault('pathogen_mask_dim',
|
286
|
+
settings.setdefault('cell_mask_dim',4)
|
287
|
+
settings.setdefault('nucleus_mask_dim',5)
|
288
|
+
settings.setdefault('pathogen_mask_dim',6)
|
289
|
+
settings.setdefault('cytoplasm',False)
|
290
|
+
settings.setdefault('uninfected',True)
|
291
|
+
settings.setdefault('cell_min_size',0)
|
292
|
+
settings.setdefault('nucleus_min_size',0)
|
293
|
+
settings.setdefault('pathogen_min_size',0)
|
294
|
+
settings.setdefault('cytoplasm_min_size',0)
|
295
|
+
settings.setdefault('merge_edge_pathogen_cells', True)
|
296
|
+
|
297
|
+
if settings['test_mode']:
|
298
|
+
settings['verbose'] = True
|
299
|
+
settings['plot'] = True
|
300
|
+
test_imgs = settings['test_nr']
|
301
|
+
print(f'Test mode enabled with {test_imgs} images, plotting set to True')
|
302
|
+
|
303
|
+
return settings
|
304
|
+
settings.setdefault('normalize_by','png')
|
305
|
+
settings.setdefault('crop_mode',['cell'])
|
306
|
+
settings.setdefault('dialate_pngs', False)
|
307
|
+
settings.setdefault('dialate_png_ratios', [0.2])
|
308
|
+
|
309
|
+
# Timelapsed settings
|
310
|
+
settings.setdefault('timelapse', False)
|
311
|
+
settings.setdefault('timelapse_objects', 'cell')
|
312
|
+
|
313
|
+
# Operational settings
|
314
|
+
settings.setdefault('plot',False)
|
315
|
+
settings.setdefault('n_jobs', os.cpu_count()-2)
|
316
|
+
|
317
|
+
# Object settings
|
318
|
+
settings.setdefault('cell_mask_dim',4)
|
319
|
+
settings.setdefault('nucleus_mask_dim',5)
|
320
|
+
settings.setdefault('pathogen_mask_dim',6)
|
321
|
+
settings.setdefault('cytoplasm',False)
|
322
|
+
settings.setdefault('uninfected',True)
|
323
|
+
settings.setdefault('cell_min_size',0)
|
324
|
+
settings.setdefault('nucleus_min_size',0)
|
325
|
+
settings.setdefault('pathogen_min_size',0)
|
326
|
+
settings.setdefault('cytoplasm_min_size',0)
|
327
|
+
settings.setdefault('merge_edge_pathogen_cells', True)
|
328
|
+
|
329
|
+
if settings['test_mode']:
|
330
|
+
settings['verbose'] = True
|
331
|
+
settings['plot'] = True
|
332
|
+
test_imgs = settings['test_nr']
|
333
|
+
print(f'Test mode enabled with {test_imgs} images, plotting set to True')
|
334
|
+
|
335
|
+
return settings
|
336
|
+
settings.setdefault('save_arrays', False)
|
337
|
+
settings.setdefault('save_png',True)
|
338
|
+
settings.setdefault('use_bounding_box',False)
|
339
|
+
settings.setdefault('png_size',[224,224])
|
340
|
+
settings.setdefault('png_dims',[0,1,2])
|
341
|
+
settings.setdefault('normalize',False)
|
342
|
+
settings.setdefault('normalize_by','png')
|
343
|
+
settings.setdefault('crop_mode',['cell'])
|
344
|
+
settings.setdefault('dialate_pngs', False)
|
345
|
+
settings.setdefault('dialate_png_ratios', [0.2])
|
346
|
+
|
347
|
+
# Timelapsed settings
|
348
|
+
settings.setdefault('timelapse', False)
|
349
|
+
settings.setdefault('timelapse_objects', 'cell')
|
350
|
+
|
351
|
+
# Operational settings
|
352
|
+
settings.setdefault('plot',False)
|
353
|
+
settings.setdefault('n_jobs', os.cpu_count()-2)
|
354
|
+
|
355
|
+
# Object settings
|
356
|
+
settings.setdefault('cell_mask_dim',4)
|
357
|
+
settings.setdefault('nucleus_mask_dim',5)
|
358
|
+
settings.setdefault('pathogen_mask_dim',6)
|
283
359
|
settings.setdefault('cytoplasm',False)
|
284
360
|
settings.setdefault('uninfected',True)
|
285
361
|
settings.setdefault('cell_min_size',0)
|
@@ -473,7 +549,7 @@ def get_train_test_model_settings(settings):
|
|
473
549
|
return settings
|
474
550
|
|
475
551
|
def get_analyze_recruitment_default_settings(settings):
|
476
|
-
settings.setdefault('src','path')
|
552
|
+
settings.setdefault('src', 'path')
|
477
553
|
settings.setdefault('target','protein')
|
478
554
|
settings.setdefault('cell_types',['HeLa'])
|
479
555
|
settings.setdefault('cell_plate_metadata',None)
|
@@ -672,6 +748,7 @@ expected_types = {
|
|
672
748
|
"timelapse_displacement": int,
|
673
749
|
"timelapse_memory": int,
|
674
750
|
"timelapse_frame_limits": (list, type(None)), # This can be a list of lists
|
751
|
+
#"timelapse_frame_limits": (list, type(None)), # This can be a list of lists
|
675
752
|
"timelapse_remove_transient": bool,
|
676
753
|
"timelapse_mode": str,
|
677
754
|
"timelapse_objects": list,
|
@@ -944,13 +1021,13 @@ expected_types = {
|
|
944
1021
|
}
|
945
1022
|
|
946
1023
|
categories = {"Paths":[ "src", "grna", "barcodes", "custom_model_path", "dataset","model_path","grna_csv","row_csv","column_csv", "metadata_files", "score_data","count_data"],
|
947
|
-
"General": ["metadata_type", "custom_regex", "experiment", "channels", "magnification", "channel_dims", "apply_model_to_dataset", "generate_training_dataset", "train_DL_model", "segmentation_mode", "delete_intermediate"],
|
1024
|
+
"General": ["cell_mask_dim", "cytoplasm", "cell_chann_dim", "cell_channel", "nucleus_chann_dim", "nucleus_channel", "nucleus_mask_dim", "pathogen_mask_dim", "pathogen_chann_dim", "pathogen_channel", "test_mode", "plot", "metadata_type", "custom_regex", "experiment", "channels", "magnification", "channel_dims", "apply_model_to_dataset", "generate_training_dataset", "train_DL_model", "segmentation_mode", "delete_intermediate", "uninfected", ],
|
948
1025
|
"Cellpose":["fill_in","from_scratch", "n_epochs", "width_height", "model_name", "custom_model", "resample", "rescale", "CP_prob", "flow_threshold", "percentiles", "invert", "diameter", "grayscale", "Signal_to_noise", "resize", "target_height", "target_width"],
|
949
|
-
"Cell": ["cell_diamiter","cell_intensity_range", "cell_size_range", "
|
950
|
-
"Nucleus": ["nucleus_diamiter","nucleus_intensity_range", "nucleus_size_range", "
|
951
|
-
"Pathogen": ["pathogen_diamiter","pathogen_intensity_range", "pathogen_size_range", "
|
1026
|
+
"Cell": ["cell_diamiter","cell_intensity_range", "cell_size_range", "cell_background", "cell_Signal_to_noise", "cell_CP_prob", "cell_FT", "remove_background_cell", "cell_min_size", "cytoplasm_min_size", "adjust_cells", "cells", "cell_loc"],
|
1027
|
+
"Nucleus": ["nucleus_diamiter","nucleus_intensity_range", "nucleus_size_range", "nucleus_background", "nucleus_Signal_to_noise", "nucleus_CP_prob", "nucleus_FT", "remove_background_nucleus", "nucleus_min_size", "nucleus_loc"],
|
1028
|
+
"Pathogen": ["pathogen_diamiter","pathogen_intensity_range", "pathogen_size_range", "pathogen_background", "pathogen_Signal_to_noise", "pathogen_CP_prob", "pathogen_FT", "pathogen_model", "remove_background_pathogen", "pathogen_min_size", "pathogens", "pathogen_loc", "pathogen_types", "pathogen_plate_metadata", ],
|
952
1029
|
"Measurements": ["remove_image_canvas", "remove_highly_correlated", "homogeneity", "homogeneity_distances", "radial_dist", "calculate_correlation", "manders_thresholds", "save_measurements", "tables", "image_nr", "dot_size", "filter_by", "remove_highly_correlated_features", "remove_low_variance_features", "channel_of_interest"],
|
953
|
-
"Object Image": ["save_png", "dialate_pngs", "dialate_png_ratios", "png_size", "png_dims", "save_arrays", "normalize_by", "crop_mode", "
|
1030
|
+
"Object Image": ["save_png", "dialate_pngs", "dialate_png_ratios", "png_size", "png_dims", "save_arrays", "normalize_by", "crop_mode", "use_bounding_box"],
|
954
1031
|
"Sequencing": ["outlier_detection","offset_start","chunk_size","single_direction", "signal_direction","mode","comp_level","comp_type","save_h5","expected_end","offset","target_sequence","regex", "highlight"],
|
955
1032
|
"Generate Dataset":["save_to_db","file_metadata","class_metadata", "annotation_column","annotated_classes", "dataset_mode", "metadata_type_by","custom_measurement", "sample", "size"],
|
956
1033
|
"Hyperparamiters (Training)": ["png_type", "score_threshold","file_type", "train_channels", "epochs", "loss_type", "optimizer_type","image_size","val_split","learning_rate","weight_decay","dropout_rate", "init_weights", "train", "classes", "augment", "amsgrad","use_checkpoint","gradient_accumulation","gradient_accumulation_steps","intermedeate_save","pin_memory"],
|
@@ -959,11 +1036,10 @@ categories = {"Paths":[ "src", "grna", "barcodes", "custom_model_path", "dataset
|
|
959
1036
|
"Hyperparamiters (Regression)":["cross_validation","prune_features","reg_lambda","reg_alpha","cov_type", "class_1_threshold", "plate", "other", "fraction_threshold", "alpha", "random_row_column_effects", "regression_type", "min_cell_count", "agg_type", "transform", "dependent_variable"],
|
960
1037
|
"Hyperparamiters (Activation)":["cam_type", "overlay", "correlation", "target_layer", "normalize_input"],
|
961
1038
|
"Annotation": ["filter_column", "filter_value","volcano", "toxo", "controls", "nc_loc", "pc_loc", "nc", "pc", "cell_plate_metadata","treatment_plate_metadata", "metadata_types", "cell_types", "target","positive_control","negative_control", "location_column", "treatment_loc", "channel_of_interest", "measurement", "treatments", "um_per_pixel", "nr_imgs", "exclude", "exclude_conditions", "mix", "pos", "neg"],
|
962
|
-
"Plot": ["
|
963
|
-
"Test": ["test_mode", "test_images", "random_test", "test_nr", "test", "test_split"],
|
1039
|
+
"Plot": ["split_axis_lims", "x_lim","log_x","log_y", "plot_control", "plot_nr", "examples_to_plot", "normalize_plots", "cmap", "figuresize", "plot_cluster_grids", "img_zoom", "row_limit", "color_by", "plot_images", "smooth_lines", "plot_points", "plot_outlines", "black_background", "plot_by_cluster", "heatmap_feature","grouping","min_max","cmap","save_figure"],
|
964
1040
|
"Timelapse": ["timelapse", "fps", "timelapse_displacement", "timelapse_memory", "timelapse_frame_limits", "timelapse_remove_transient", "timelapse_mode", "timelapse_objects", "compartments"],
|
965
|
-
"Advanced": ["target_unique_count","threshold_multiplier", "threshold_method", "min_n","shuffle", "target_intensity_min", "cells_per_well", "nuclei_limit", "pathogen_limit", "background", "backgrounds", "schedule", "test_size","exclude","n_repeats","top_features", "model_type_ml", "model_type","minimum_cell_count","n_estimators","preprocess", "remove_background", "normalize", "lower_percentile", "merge_pathogens", "batch_size", "filter", "save", "masks", "verbose", "randomize", "n_jobs"],
|
966
|
-
"
|
1041
|
+
"Advanced": ["merge_edge_pathogen_cells", "test_images", "random_test", "test_nr", "test", "test_split", "normalize", "target_unique_count","threshold_multiplier", "threshold_method", "min_n","shuffle", "target_intensity_min", "cells_per_well", "nuclei_limit", "pathogen_limit", "background", "backgrounds", "schedule", "test_size","exclude","n_repeats","top_features", "model_type_ml", "model_type","minimum_cell_count","n_estimators","preprocess", "remove_background", "normalize", "lower_percentile", "merge_pathogens", "batch_size", "filter", "save", "masks", "verbose", "randomize", "n_jobs"],
|
1042
|
+
"Beta": ["all_to_mip", "pick_slice", "skip_mode", "upscale", "upscale_factor"]
|
967
1043
|
}
|
968
1044
|
|
969
1045
|
|
@@ -984,22 +1060,28 @@ def check_settings(vars_dict, expected_types, q=None):
|
|
984
1060
|
q.put(f"Key {key} not found in expected types.")
|
985
1061
|
continue
|
986
1062
|
|
987
|
-
value = var.get()
|
988
|
-
if value
|
1063
|
+
value = var.get()
|
1064
|
+
if value in ['None', '']:
|
989
1065
|
value = None
|
990
1066
|
|
991
1067
|
expected_type = expected_types.get(key, str)
|
992
1068
|
|
993
1069
|
try:
|
994
|
-
if key in ["cell_plate_metadata", "timelapse_frame_limits", "png_size", "pathogen_loc", "treatment_loc", "pathogen_plate_metadata", "treatment_plate_metadata", "barcode_coordinates", "class_metadata"]:
|
995
|
-
|
1070
|
+
#if key in ["cell_plate_metadata", "timelapse_frame_limits", "png_size", "pathogen_loc", "treatment_loc", "pathogen_plate_metadata", "treatment_plate_metadata", "barcode_coordinates", "class_metadata"]:
|
1071
|
+
if key in ["cell_plate_metadata", "timelapse_frame_limits", "png_size", "png_dims", "pathogen_plate_metadata", "treatment_plate_metadata", "class_metadata", "crop_mode"]:
|
1072
|
+
|
1073
|
+
if value is None:
|
1074
|
+
parsed_value = None
|
1075
|
+
else:
|
1076
|
+
parsed_value = ast.literal_eval(value) if isinstance(value, str) and value.strip() else None
|
1077
|
+
|
1078
|
+
#parsed_value = ast.literal_eval(value) if value else None
|
1079
|
+
|
996
1080
|
if isinstance(parsed_value, list):
|
997
1081
|
if all(isinstance(i, list) for i in parsed_value) or all(not isinstance(i, list) for i in parsed_value):
|
998
1082
|
settings[key] = parsed_value
|
999
1083
|
else:
|
1000
1084
|
raise ValueError("Invalid format: Mixed list and list of lists")
|
1001
|
-
#elif parsed_value == None:
|
1002
|
-
# settings[key] = None
|
1003
1085
|
else:
|
1004
1086
|
raise ValueError("Invalid format for list or list of lists")
|
1005
1087
|
|
@@ -1180,30 +1262,7 @@ def generate_fields(variables, scrollable_frame):
|
|
1180
1262
|
"n_epochs": "(int) - Number of epochs for training the Cellpose model.",
|
1181
1263
|
"n_jobs": "(int) - The number of n_jobs to use for processing the images. This will determine how many images are processed in parallel. Increase to speed up processing.",
|
1182
1264
|
"n_neighbors": "(int) - Number of neighbors for UMAP.",
|
1183
|
-
"n_repeats": "(int) - Number of repeats for
|
1184
|
-
"normalize": "(list) - The percentiles to use for normalizing the images. This will be used to determine the range of intensities to normalize images to. If None, no normalization is done.",
|
1185
|
-
"normalize_by": "(str) - Whether to normalize the images by field of view (fov) or by PNG image (png).",
|
1186
|
-
"normalize_plots": "(bool) - Whether to normalize the plots.",
|
1187
|
-
"nr_imgs": "(int) - The number of images to plot.",
|
1188
|
-
"nucleus_CP_prob": "(float) - The cellpose probability threshold for the nucleus channel. This will be used to segment the nucleus.",
|
1189
|
-
"nucleus_FT": "(float) - The flow threshold for nucleus objects. This will be used in nucleus segmentation.",
|
1190
|
-
"nucleus_background": "(float) - The background intensity for the nucleus channel. This will be used to remove background noise.",
|
1191
|
-
"nucleus_chann_dim": "(int) - Dimension of the channel to use for nucleus segmentation.",
|
1192
|
-
"nucleus_channel": "(int) - The channel to use for the nucleus. If None, the nucleus will not be segmented.",
|
1193
|
-
"nucleus_intensity_range": "(list) - Intensity range for nucleus segmentation.",
|
1194
|
-
"nucleus_loc": "(str) - Location of the nucleus in the images.",
|
1195
|
-
"nucleus_mask_dim": "(int) - The dimension of the array the nucleus mask is saved in.",
|
1196
|
-
"nucleus_min_size": "(int) - The minimum size of nucleus objects in pixels^2.",
|
1197
|
-
"nucleus_Signal_to_noise": "(float) - The signal-to-noise ratio for the nucleus channel. This will be used to determine the range of intensities to normalize images to for nucleus segmentation.",
|
1198
|
-
"nucleus_size_range": "(list) - Size range for nucleus segmentation.",
|
1199
|
-
"optimizer_type": "(str) - Type of optimizer to use.",
|
1200
|
-
"other": "(dict) - Additional parameters for the regression analysis.",
|
1201
|
-
"pathogen_CP_prob": "(float) - The cellpose probability threshold for the pathogen channel. This will be used to segment the pathogen.",
|
1202
|
-
"pathogen_FT": "(float) - The flow threshold for pathogen objects. This will be used in pathogen segmentation.",
|
1203
|
-
"pathogen_background": "(float) - The background intensity for the pathogen channel. This will be used to remove background noise.",
|
1204
|
-
"pathogen_chann_dim": "(int) - Dimension of the channel to use for pathogen segmentation.",
|
1205
|
-
"pathogen_channel": "(int) - The channel to use for the pathogen. If None, the pathogen will not be segmented.",
|
1206
|
-
"pathogen_intensity_range": "(str) - Metadata for the pathogen plate.",
|
1265
|
+
"n_repeats": "(int) - Number of repeats for the pathogen plate.",
|
1207
1266
|
"pathogen_Signal_to_noise": "(float) - The signal-to-noise ratio for the pathogen channel. This will be used to determine the range of intensities to normalize images to for pathogen segmentation.",
|
1208
1267
|
"pathogen_size_range": "(list) - Size range for pathogen segmentation.",
|
1209
1268
|
"pathogen_types": "(list) - Types of pathogens to include in the analysis.",
|
@@ -1222,7 +1281,7 @@ def generate_fields(variables, scrollable_frame):
|
|
1222
1281
|
"plot_nr": "(int) - Number of plots to generate.",
|
1223
1282
|
"plot_outlines": "(bool) - Whether to plot outlines of segmented objects.",
|
1224
1283
|
"png_dims": "(list) - The dimensions of the PNG images to save. This will determine the dimensions of the saved images. Maximum of 3 dimensions e.g. [1,2,3].",
|
1225
|
-
"png_size": "(
|
1284
|
+
"png_size": "(list) - The size of the PNG images to save. This will determine the size of the saved images.",
|
1226
1285
|
"positive_control": "(str) - Identifier for the positive control.",
|
1227
1286
|
"preprocess": "(bool) - Whether to preprocess the images before segmentation. This includes background removal and normalization. Set to False only if this step has already been done.",
|
1228
1287
|
"radial_dist": "(list) - Radial distances for measuring features.",
|
spacr/submodules.py
CHANGED
@@ -21,7 +21,7 @@ from sklearn.metrics import mean_absolute_error
|
|
21
21
|
import matplotlib.pyplot as plt
|
22
22
|
from natsort import natsorted
|
23
23
|
|
24
|
-
def analyze_recruitment(settings
|
24
|
+
def analyze_recruitment(settings):
|
25
25
|
"""
|
26
26
|
Analyze recruitment data by grouping the DataFrame by well coordinates and plotting controls and recruitment data.
|
27
27
|
|
spacr/utils.py
CHANGED
@@ -328,14 +328,13 @@ def save_settings(settings, name='settings', show=False):
|
|
328
328
|
|
329
329
|
if isinstance(settings['src'], list):
|
330
330
|
src = settings['src'][0]
|
331
|
-
#if os.path.exists(src):
|
332
|
-
|
333
331
|
name = f"{name}_list"
|
334
332
|
else:
|
335
333
|
src = settings['src']
|
336
334
|
|
337
335
|
settings_csv = os.path.join(src,'settings',f'{name}.csv')
|
338
336
|
os.makedirs(os.path.join(src,'settings'), exist_ok=True)
|
337
|
+
print(f"Saving settings to {settings_csv}")
|
339
338
|
settings_df.to_csv(settings_csv, index=False)
|
340
339
|
|
341
340
|
def print_progress(files_processed, files_to_process, n_jobs, time_ls=None, batch_size=None, operation_type=""):
|
@@ -1145,7 +1144,7 @@ def _masks_to_masks_stack(masks):
|
|
1145
1144
|
mask_stack.append(mask)
|
1146
1145
|
return mask_stack
|
1147
1146
|
|
1148
|
-
def
|
1147
|
+
def _get_diam_v1(mag, obj):
|
1149
1148
|
|
1150
1149
|
if mag == 20:
|
1151
1150
|
if obj == 'cell':
|
@@ -1176,11 +1175,28 @@ def _get_diam(mag, obj):
|
|
1176
1175
|
diamiter = 60
|
1177
1176
|
else:
|
1178
1177
|
raise ValueError("Invalid magnification: Use 20, 40 or 60")
|
1178
|
+
|
1179
1179
|
else:
|
1180
1180
|
raise ValueError("Invalid magnification: Use 20, 40 or 60")
|
1181
1181
|
|
1182
1182
|
return diamiter
|
1183
1183
|
|
1184
|
+
def _get_diam(mag, obj):
|
1185
|
+
|
1186
|
+
if obj == 'cell':
|
1187
|
+
diamiter = 2 * mag + 80
|
1188
|
+
|
1189
|
+
if obj == 'cell_large':
|
1190
|
+
diamiter = 2 * mag + 120
|
1191
|
+
|
1192
|
+
if obj == 'nucleus':
|
1193
|
+
diamiter = 0.75 * mag + 45
|
1194
|
+
|
1195
|
+
if obj == 'pathogen':
|
1196
|
+
diamiter = mag
|
1197
|
+
|
1198
|
+
return int(diamiter)
|
1199
|
+
|
1184
1200
|
def _get_object_settings(object_type, settings):
|
1185
1201
|
object_settings = {}
|
1186
1202
|
|
@@ -1333,20 +1349,25 @@ def annotate_conditions(df, cells=None, cell_loc=None, pathogens=None, pathogen_
|
|
1333
1349
|
def _map_or_default(column_name, values, loc, df):
|
1334
1350
|
"""
|
1335
1351
|
Consolidates the logic for mapping values or assigning defaults when loc is None.
|
1336
|
-
|
1352
|
+
|
1337
1353
|
Args:
|
1338
1354
|
column_name (str): The column in the DataFrame to annotate.
|
1339
1355
|
values (list/str): The list of values or a single string to annotate.
|
1340
1356
|
loc (list of lists): Location mapping for the values, or None if not used.
|
1341
1357
|
df (pandas.DataFrame): The DataFrame to modify.
|
1342
1358
|
"""
|
1343
|
-
if isinstance(values, str)
|
1344
|
-
#
|
1345
|
-
df[column_name] = values
|
1359
|
+
if isinstance(values, str) and loc is None:
|
1360
|
+
# If a single string is provided and loc is None, assign the value to all rows
|
1361
|
+
df[column_name] = values
|
1362
|
+
|
1363
|
+
elif isinstance(values, list) and loc is None:
|
1364
|
+
# If a list of values is provided but no loc, assign the first value to all rows
|
1365
|
+
df[column_name] = values[0]
|
1366
|
+
|
1346
1367
|
elif values is not None and loc is not None:
|
1347
|
-
# Perform
|
1368
|
+
# Perform location-based mapping
|
1348
1369
|
value_dict = {val: key for key, loc_list in zip(values, loc) for val in loc_list}
|
1349
|
-
df[column_name] = np.nan
|
1370
|
+
df[column_name] = np.nan # Start with NaN
|
1350
1371
|
for val, key in value_dict.items():
|
1351
1372
|
loc_type = _get_type(val)
|
1352
1373
|
if loc_type:
|
@@ -4945,7 +4966,7 @@ def download_models(repo_id="einarolafsson/models", retries=5, delay=5):
|
|
4945
4966
|
if not os.path.exists(local_dir):
|
4946
4967
|
os.makedirs(local_dir)
|
4947
4968
|
elif len(os.listdir(local_dir)) > 0:
|
4948
|
-
print(f"Models already downloaded to: {local_dir}")
|
4969
|
+
#print(f"Models already downloaded to: {local_dir}")
|
4949
4970
|
return local_dir
|
4950
4971
|
|
4951
4972
|
attempt = 0
|
@@ -5337,3 +5358,63 @@ def calculate_shortest_distance(df, object1, object2):
|
|
5337
5358
|
df[f'{object1}_{object2}_shortest_distance'] = np.maximum(shortest_distance, 0)
|
5338
5359
|
|
5339
5360
|
return df
|
5361
|
+
|
5362
|
+
def format_path_for_system(path):
|
5363
|
+
"""
|
5364
|
+
Takes a file path and reformats it to be compatible with the current operating system.
|
5365
|
+
|
5366
|
+
Args:
|
5367
|
+
path (str): The file path to be formatted.
|
5368
|
+
|
5369
|
+
Returns:
|
5370
|
+
str: The formatted path for the current operating system.
|
5371
|
+
"""
|
5372
|
+
system = platform.system()
|
5373
|
+
|
5374
|
+
# Convert Windows-style paths to Unix-style (Linux/macOS)
|
5375
|
+
if system in ["Linux", "Darwin"]: # Darwin is macOS
|
5376
|
+
formatted_path = path.replace("\\", "/")
|
5377
|
+
|
5378
|
+
# Convert Unix-style paths to Windows-style
|
5379
|
+
elif system == "Windows":
|
5380
|
+
formatted_path = path.replace("/", "\\")
|
5381
|
+
|
5382
|
+
else:
|
5383
|
+
raise ValueError(f"Unsupported OS: {system}")
|
5384
|
+
|
5385
|
+
# Normalize path to ensure consistency
|
5386
|
+
new_path = os.path.normpath(formatted_path)
|
5387
|
+
if os.path.exists(new_path):
|
5388
|
+
print(f"Found path: {new_path}")
|
5389
|
+
else:
|
5390
|
+
print(f"Path not found: {new_path}")
|
5391
|
+
|
5392
|
+
return new_path
|
5393
|
+
|
5394
|
+
|
5395
|
+
def normalize_src_path(src):
|
5396
|
+
"""
|
5397
|
+
Ensures that the 'src' value is properly formatted as either a list of strings or a single string.
|
5398
|
+
|
5399
|
+
Args:
|
5400
|
+
src (str or list): The input source path(s).
|
5401
|
+
|
5402
|
+
Returns:
|
5403
|
+
list or str: A correctly formatted list if the input was a list (or string representation of a list),
|
5404
|
+
otherwise a single string.
|
5405
|
+
"""
|
5406
|
+
if isinstance(src, list):
|
5407
|
+
return src # Already a list, return as-is
|
5408
|
+
|
5409
|
+
if isinstance(src, str):
|
5410
|
+
try:
|
5411
|
+
# Check if it is a string representation of a list
|
5412
|
+
evaluated_src = ast.literal_eval(src)
|
5413
|
+
if isinstance(evaluated_src, list) and all(isinstance(item, str) for item in evaluated_src):
|
5414
|
+
return evaluated_src # Convert to real list
|
5415
|
+
except (SyntaxError, ValueError):
|
5416
|
+
pass # Not a valid list, treat as a string
|
5417
|
+
|
5418
|
+
return src # Return as a string if not a list
|
5419
|
+
|
5420
|
+
raise ValueError(f"Invalid type for 'src': {type(src).__name__}, expected str or list")
|
@@ -9,28 +9,28 @@ spacr/app_sequencing.py,sha256=DjG26jy4cpddnV8WOOAIiExtOe9MleVMY4MFa5uTo5w,157
|
|
9
9
|
spacr/app_umap.py,sha256=ZWAmf_OsIKbYvolYuWPMYhdlVe-n2CADoJulAizMiEo,153
|
10
10
|
spacr/cellpose.py,sha256=RBHMs2vwXcfkj0xqAULpALyzJYXddSRycgZSzmwI7v0,14755
|
11
11
|
spacr/chat_bot.py,sha256=n3Fhqg3qofVXHmh3H9sUcmfYy9MmgRnr48663MVdY9E,1244
|
12
|
-
spacr/core.py,sha256=
|
12
|
+
spacr/core.py,sha256=JfeXuLa-IR0Qn5SfNPj2NCyxRkVXE3MDy0ywPFLIFVY,49014
|
13
13
|
spacr/deep_spacr.py,sha256=WN64EaQqF87JZg3Uan46t5Y28xsAGD2KMjr2ht6CyDs,54563
|
14
14
|
spacr/gui.py,sha256=ARyn9Q_g8HoP-cXh1nzMLVFCKqthY4v2u9yORyaQqQE,8230
|
15
|
-
spacr/gui_core.py,sha256=
|
15
|
+
spacr/gui_core.py,sha256=DFzYiauhLJF7koEeKSXZAoUeUHd74LRgdt6Xktqi254,46892
|
16
16
|
spacr/gui_elements.py,sha256=HmITDncklKwtdFhxLhtYXOwndsRfgwWIPVi83VlXHB4,146419
|
17
|
-
spacr/gui_utils.py,sha256=
|
18
|
-
spacr/io.py,sha256=
|
17
|
+
spacr/gui_utils.py,sha256=ZiRMYSBj1w5jIjoTBw9_kf9RbAZD9D0DYCNHUmxNrh8,41342
|
18
|
+
spacr/io.py,sha256=BtmxZcA_fr8jFsuwisnG95E5DS14JGA9isqiI-iYdII,138923
|
19
19
|
spacr/logger.py,sha256=lJhTqt-_wfAunCPl93xE65Wr9Y1oIHJWaZMjunHUeIw,1538
|
20
|
-
spacr/measure.py,sha256=
|
20
|
+
spacr/measure.py,sha256=Z3u4BU5RzcY82IZuboQ0OsxuXaPVwOlH65Rw6FrL5z4,55045
|
21
21
|
spacr/mediar.py,sha256=FwLvbLQW5LQzPgvJZG8Lw7GniA2vbZx6Jv6vIKu7I5c,14743
|
22
22
|
spacr/ml.py,sha256=MrIAtUUxMOibWVL1SjCUnYlizawCp3l3SeY4Y9yEsPw,97251
|
23
23
|
spacr/openai.py,sha256=5vBZ3Jl2llYcW3oaTEXgdyCB2aJujMUIO5K038z7w_A,1246
|
24
24
|
spacr/plot.py,sha256=Q5TbsR2NUWhA7z4HyF_2_FAEBFSNMU-G3UNDbRzW6mM,169485
|
25
25
|
spacr/sequencing.py,sha256=ClUfwPPK6rNUbUuiEkzcwakzVyDKKUMv9ricrxT8qQY,25227
|
26
|
-
spacr/settings.py,sha256=
|
26
|
+
spacr/settings.py,sha256=7NAW69yE9FNzsQlLE2lTnDFNL4042AI4c-y20ikPlxc,84793
|
27
27
|
spacr/sim.py,sha256=1xKhXimNU3ukzIw-3l9cF3Znc_brW8h20yv8fSTzvss,71173
|
28
28
|
spacr/sp_stats.py,sha256=mbhwsyIqt5upsSD346qGjdCw7CFBa0tIS7zHU9e0jNI,9536
|
29
29
|
spacr/stats.py,sha256=mbhwsyIqt5upsSD346qGjdCw7CFBa0tIS7zHU9e0jNI,9536
|
30
|
-
spacr/submodules.py,sha256=
|
30
|
+
spacr/submodules.py,sha256=jFlJeVNuIEf63TtCOpTlOZ4iiSLr238kRBiGAAAgKE4,67626
|
31
31
|
spacr/timelapse.py,sha256=KGfG4L4-QnFfgbF7L6C5wL_3gd_rqr05Foje6RsoTBg,39603
|
32
32
|
spacr/toxo.py,sha256=TmuhejSIPLBvsgeblsUgSvBFCR1gOkApyTKidooJ5Us,26044
|
33
|
-
spacr/utils.py,sha256=
|
33
|
+
spacr/utils.py,sha256=Cyy0pS-dwvMbH8cn6gu8OG1C-Kg6yUOAEacng-vkDgk,228837
|
34
34
|
spacr/version.py,sha256=axH5tnGwtgSnJHb5IDhiu4Zjk5GhLyAEDRe-rnaoFOA,409
|
35
35
|
spacr/resources/MEDIAR/.gitignore,sha256=Ff1q9Nme14JUd-4Q3jZ65aeQ5X4uttptssVDgBVHYo8,152
|
36
36
|
spacr/resources/MEDIAR/LICENSE,sha256=yEj_TRDLUfDpHDNM0StALXIt6mLqSgaV2hcCwa6_TcY,1065
|
@@ -153,9 +153,9 @@ spacr/resources/icons/umap.png,sha256=dOLF3DeLYy9k0nkUybiZMe1wzHQwLJFRmgccppw-8b
|
|
153
153
|
spacr/resources/images/plate1_E01_T0001F001L01A01Z01C02.tif,sha256=Tl0ZUfZ_AYAbu0up_nO0tPRtF1BxXhWQ3T3pURBCCRo,7958528
|
154
154
|
spacr/resources/images/plate1_E01_T0001F001L01A02Z01C01.tif,sha256=m8N-V71rA1TT4dFlENNg8s0Q0YEXXs8slIn7yObmZJQ,7958528
|
155
155
|
spacr/resources/images/plate1_E01_T0001F001L01A03Z01C03.tif,sha256=Pbhk7xn-KUP6RSIhJsxQcrHFImBm3GEpLkzx7WOc-5M,7958528
|
156
|
-
spacr-0.4.
|
157
|
-
spacr-0.4.
|
158
|
-
spacr-0.4.
|
159
|
-
spacr-0.4.
|
160
|
-
spacr-0.4.
|
161
|
-
spacr-0.4.
|
156
|
+
spacr-0.4.15.dist-info/LICENSE,sha256=SR-2MeGc6SCM1UORJYyarSWY_A-JaOMFDj7ReSs9tRM,1083
|
157
|
+
spacr-0.4.15.dist-info/METADATA,sha256=S7GQ5vQOQmp_uZPNThj1d29xrjSf_joXTOUVX96UDCY,6073
|
158
|
+
spacr-0.4.15.dist-info/WHEEL,sha256=HiCZjzuy6Dw0hdX5R3LCFPDmFS4BWl8H-8W39XfmgX4,91
|
159
|
+
spacr-0.4.15.dist-info/entry_points.txt,sha256=BMC0ql9aNNpv8lUZ8sgDLQMsqaVnX5L535gEhKUP5ho,296
|
160
|
+
spacr-0.4.15.dist-info/top_level.txt,sha256=GJPU8FgwRXGzKeut6JopsSRY2R8T3i9lDgya42tLInY,6
|
161
|
+
spacr-0.4.15.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|