spacr 0.3.43__py3-none-any.whl → 0.3.45__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/cellpose.py +63 -71
- spacr/io.py +6 -16
- spacr/ml.py +4 -3
- spacr/plot.py +264 -10
- spacr/settings.py +7 -15
- spacr/submodules.py +113 -68
- spacr/toxo.py +5 -116
- spacr/utils.py +37 -5
- {spacr-0.3.43.dist-info → spacr-0.3.45.dist-info}/METADATA +1 -1
- {spacr-0.3.43.dist-info → spacr-0.3.45.dist-info}/RECORD +14 -14
- {spacr-0.3.43.dist-info → spacr-0.3.45.dist-info}/LICENSE +0 -0
- {spacr-0.3.43.dist-info → spacr-0.3.45.dist-info}/WHEEL +0 -0
- {spacr-0.3.43.dist-info → spacr-0.3.45.dist-info}/entry_points.txt +0 -0
- {spacr-0.3.43.dist-info → spacr-0.3.45.dist-info}/top_level.txt +0 -0
spacr/cellpose.py
CHANGED
@@ -5,50 +5,23 @@ from cellpose import models as cp_models
|
|
5
5
|
from IPython.display import display
|
6
6
|
from multiprocessing import Pool
|
7
7
|
from skimage.transform import resize as resizescikit
|
8
|
+
from scipy.ndimage import binary_fill_holes
|
8
9
|
|
9
10
|
def identify_masks_finetune(settings):
|
10
11
|
|
11
12
|
from .plot import print_mask_and_flows
|
12
|
-
from .utils import resize_images_and_labels, print_progress
|
13
|
+
from .utils import resize_images_and_labels, print_progress, save_settings, fill_holes_in_mask
|
13
14
|
from .io import _load_normalized_images_and_labels, _load_images_and_labels
|
14
15
|
from .settings import get_identify_masks_finetune_default_settings
|
15
16
|
|
16
17
|
settings = get_identify_masks_finetune_default_settings(settings)
|
17
|
-
|
18
|
-
dst=settings['
|
19
|
-
model_name=settings['model_name']
|
20
|
-
custom_model=settings['custom_model']
|
21
|
-
channels = settings['channels']
|
22
|
-
background = settings['background']
|
23
|
-
remove_background=settings['remove_background']
|
24
|
-
Signal_to_noise = settings['Signal_to_noise']
|
25
|
-
CP_prob = settings['CP_prob']
|
26
|
-
diameter=settings['diameter']
|
27
|
-
batch_size=settings['batch_size']
|
28
|
-
flow_threshold=settings['flow_threshold']
|
29
|
-
save=settings['save']
|
30
|
-
verbose=settings['verbose']
|
31
|
-
|
32
|
-
# static settings
|
33
|
-
normalize = settings['normalize']
|
34
|
-
percentiles = settings['percentiles']
|
35
|
-
circular = settings['circular']
|
36
|
-
invert = settings['invert']
|
37
|
-
resize = settings['resize']
|
38
|
-
|
39
|
-
if resize:
|
40
|
-
target_height = settings['target_height']
|
41
|
-
target_width = settings['target_width']
|
42
|
-
|
43
|
-
rescale = settings['rescale']
|
44
|
-
resample = settings['resample']
|
45
|
-
grayscale = settings['grayscale']
|
46
|
-
|
18
|
+
save_settings(settings, name='generate_cellpose_masks', show=True)
|
19
|
+
dst = os.path.join(settings['src'], 'masks')
|
47
20
|
os.makedirs(dst, exist_ok=True)
|
48
21
|
|
49
|
-
if not custom_model is None:
|
50
|
-
if not os.path.exists(custom_model):
|
51
|
-
print(f
|
22
|
+
if not settings['custom_model'] is None:
|
23
|
+
if not os.path.exists(settings['custom_model']):
|
24
|
+
print(f"Custom model not found: {settings['custom_model']}")
|
52
25
|
return
|
53
26
|
|
54
27
|
if not torch.cuda.is_available():
|
@@ -56,42 +29,60 @@ def identify_masks_finetune(settings):
|
|
56
29
|
|
57
30
|
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
|
58
31
|
|
59
|
-
if custom_model == None:
|
60
|
-
model = cp_models.CellposeModel(gpu=True, model_type=model_name, device=device)
|
61
|
-
print(f
|
32
|
+
if settings['custom_model'] == None:
|
33
|
+
model = cp_models.CellposeModel(gpu=True, model_type=settings['model_name'], device=device)
|
34
|
+
print(f"Loaded model: {settings['model_name']}")
|
62
35
|
else:
|
63
|
-
model = cp_models.CellposeModel(gpu=torch.cuda.is_available(), model_type=None, pretrained_model=custom_model, diam_mean=diameter, device=device)
|
36
|
+
model = cp_models.CellposeModel(gpu=torch.cuda.is_available(), model_type=None, pretrained_model=settings['custom_model'], diam_mean=settings['diameter'], device=device)
|
64
37
|
print("Pretrained Model Loaded:", model.pretrained_model)
|
65
38
|
|
66
|
-
chans = [2, 1] if model_name == 'cyto2' else [0,0] if model_name == 'nucleus' else [1,0] if model_name == 'cyto' else [2, 0]
|
39
|
+
chans = [2, 1] if settings['model_name'] == 'cyto2' else [0,0] if settings['model_name'] == 'nucleus' else [1,0] if settings['model_name'] == 'cyto' else [2, 0]
|
67
40
|
|
68
|
-
if grayscale:
|
41
|
+
if settings['grayscale']:
|
69
42
|
chans=[0, 0]
|
70
43
|
|
71
|
-
print(f
|
44
|
+
print(f"Using channels: {chans} for model of type {settings['model_name']}")
|
72
45
|
|
73
|
-
if verbose == True:
|
74
|
-
print(f
|
46
|
+
if settings['verbose'] == True:
|
47
|
+
print(f"Cellpose settings: Model: {settings['model_name']}, channels: {settings['channels']}, cellpose_chans: {chans}, diameter:{settings['diameter']}, flow_threshold:{settings['flow_threshold']}, cellprob_threshold:{settings['CP_prob']}")
|
75
48
|
|
76
|
-
|
77
|
-
mask_files = set(os.listdir(os.path.join(src, 'masks')))
|
78
|
-
all_image_files = [f for f in
|
49
|
+
image_files = [os.path.join(settings['src'], f) for f in os.listdir(settings['src']) if f.endswith('.tif')]
|
50
|
+
mask_files = set(os.listdir(os.path.join(settings['src'], 'masks')))
|
51
|
+
all_image_files = [f for f in image_files if os.path.basename(f) not in mask_files]
|
79
52
|
random.shuffle(all_image_files)
|
53
|
+
|
54
|
+
print(f"Found {len(image_files)} Images with {len(mask_files)} masks. Generating masks for {len(all_image_files)} images")
|
55
|
+
|
56
|
+
if len(all_image_files) == 0:
|
57
|
+
print(f"Either no images were found in {settings['src']} or all images have masks in {settings['dst']}")
|
58
|
+
return
|
59
|
+
|
80
60
|
|
81
61
|
time_ls = []
|
82
|
-
for i in range(0, len(all_image_files), batch_size):
|
62
|
+
for i in range(0, len(all_image_files), settings['batch_size']):
|
83
63
|
gc.collect()
|
84
|
-
image_files = all_image_files[i:i+batch_size]
|
64
|
+
image_files = all_image_files[i:i+settings['batch_size']]
|
85
65
|
|
86
|
-
if normalize:
|
87
|
-
images, _, image_names, _, orig_dims = _load_normalized_images_and_labels(image_files=image_files,
|
66
|
+
if settings['normalize']:
|
67
|
+
images, _, image_names, _, orig_dims = _load_normalized_images_and_labels(image_files=image_files,
|
68
|
+
label_files=None,
|
69
|
+
channels=settings['channels'],
|
70
|
+
percentiles=settings['percentiles'],
|
71
|
+
invert=settings['invert'],
|
72
|
+
visualize=settings['verbose'],
|
73
|
+
remove_background=settings['remove_background'],
|
74
|
+
background=settings['background'],
|
75
|
+
Signal_to_noise=settings['Signal_to_noise'],
|
76
|
+
target_height=settings['target_height'],
|
77
|
+
target_width=settings['target_width'])
|
78
|
+
|
88
79
|
images = [np.squeeze(img) if img.shape[-1] == 1 else img for img in images]
|
89
80
|
else:
|
90
|
-
images, _, image_names, _ = _load_images_and_labels(image_files=image_files, label_files=None,
|
81
|
+
images, _, image_names, _ = _load_images_and_labels(image_files=image_files, label_files=None, invert=settings['invert'])
|
91
82
|
images = [np.squeeze(img) if img.shape[-1] == 1 else img for img in images]
|
92
83
|
orig_dims = [(image.shape[0], image.shape[1]) for image in images]
|
93
|
-
if resize:
|
94
|
-
images, _ = resize_images_and_labels(images, None, target_height, target_width, True)
|
84
|
+
if settings['resize']:
|
85
|
+
images, _ = resize_images_and_labels(images, None, settings['target_height'], settings['target_width'], True)
|
95
86
|
|
96
87
|
for file_index, stack in enumerate(images):
|
97
88
|
start = time.time()
|
@@ -99,11 +90,11 @@ def identify_masks_finetune(settings):
|
|
99
90
|
normalize=False,
|
100
91
|
channels=chans,
|
101
92
|
channel_axis=3,
|
102
|
-
diameter=diameter,
|
103
|
-
flow_threshold=flow_threshold,
|
104
|
-
cellprob_threshold=CP_prob,
|
105
|
-
rescale=rescale,
|
106
|
-
resample=resample,
|
93
|
+
diameter=settings['diameter'],
|
94
|
+
flow_threshold=settings['flow_threshold'],
|
95
|
+
cellprob_threshold=settings['CP_prob'],
|
96
|
+
rescale=settings['rescale'],
|
97
|
+
resample=settings['resample'],
|
107
98
|
progress=True)
|
108
99
|
|
109
100
|
if len(output) == 4:
|
@@ -112,8 +103,11 @@ def identify_masks_finetune(settings):
|
|
112
103
|
mask, flows, _ = output
|
113
104
|
else:
|
114
105
|
raise ValueError("Unexpected number of return values from model.eval()")
|
106
|
+
|
107
|
+
if settings['fill_in']:
|
108
|
+
mask = fill_holes_in_mask(mask).astype(mask.dtype)
|
115
109
|
|
116
|
-
if resize:
|
110
|
+
if settings['resize']:
|
117
111
|
dims = orig_dims[file_index]
|
118
112
|
mask = resizescikit(mask, dims, order=0, preserve_range=True, anti_aliasing=False).astype(mask.dtype)
|
119
113
|
|
@@ -122,14 +116,13 @@ def identify_masks_finetune(settings):
|
|
122
116
|
time_ls.append(duration)
|
123
117
|
files_processed = len(images)
|
124
118
|
files_to_process = file_index+1
|
125
|
-
print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls)
|
126
|
-
print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls, batch_size=None, operation_type="")
|
119
|
+
print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls, batch_size=None, operation_type="generate cellpose masks")
|
127
120
|
|
128
|
-
if verbose:
|
129
|
-
if resize:
|
121
|
+
if settings['verbose']:
|
122
|
+
if settings['resize']:
|
130
123
|
stack = resizescikit(stack, dims, preserve_range=True, anti_aliasing=False).astype(stack.dtype)
|
131
|
-
print_mask_and_flows(stack, mask, flows
|
132
|
-
if save:
|
124
|
+
print_mask_and_flows(stack, mask, flows)
|
125
|
+
if settings['save']:
|
133
126
|
os.makedirs(dst, exist_ok=True)
|
134
127
|
output_filename = os.path.join(dst, image_names[file_index])
|
135
128
|
cv2.imwrite(output_filename, mask)
|
@@ -137,7 +130,7 @@ def identify_masks_finetune(settings):
|
|
137
130
|
gc.collect()
|
138
131
|
return
|
139
132
|
|
140
|
-
def generate_masks_from_imgs(src, model, model_name, batch_size, diameter, cellprob_threshold, flow_threshold, grayscale, save, normalize, channels, percentiles,
|
133
|
+
def generate_masks_from_imgs(src, model, model_name, batch_size, diameter, cellprob_threshold, flow_threshold, grayscale, save, normalize, channels, percentiles, invert, plot, resize, target_height, target_width, remove_background, background, Signal_to_noise, verbose):
|
141
134
|
|
142
135
|
from .io import _load_images_and_labels, _load_normalized_images_and_labels
|
143
136
|
from .utils import resize_images_and_labels, resizescikit, print_progress
|
@@ -162,11 +155,11 @@ def generate_masks_from_imgs(src, model, model_name, batch_size, diameter, cellp
|
|
162
155
|
image_files = all_image_files[i:i+batch_size]
|
163
156
|
|
164
157
|
if normalize:
|
165
|
-
images, _, image_names, _, orig_dims = _load_normalized_images_and_labels(image_files, None, channels, percentiles,
|
158
|
+
images, _, image_names, _, orig_dims = _load_normalized_images_and_labels(image_files, None, channels, percentiles, invert, plot, remove_background, background, Signal_to_noise, target_height, target_width)
|
166
159
|
images = [np.squeeze(img) if img.shape[-1] == 1 else img for img in images]
|
167
160
|
orig_dims = [(image.shape[0], image.shape[1]) for image in images]
|
168
161
|
else:
|
169
|
-
images, _, image_names, _ = _load_images_and_labels(image_files, None,
|
162
|
+
images, _, image_names, _ = _load_images_and_labels(image_files, None, invert)
|
170
163
|
images = [np.squeeze(img) if img.shape[-1] == 1 else img for img in images]
|
171
164
|
orig_dims = [(image.shape[0], image.shape[1]) for image in images]
|
172
165
|
if resize:
|
@@ -207,12 +200,11 @@ def generate_masks_from_imgs(src, model, model_name, batch_size, diameter, cellp
|
|
207
200
|
if plot:
|
208
201
|
if resize:
|
209
202
|
stack = resizescikit(stack, dims, preserve_range=True, anti_aliasing=False).astype(stack.dtype)
|
210
|
-
print_mask_and_flows(stack, mask, flows
|
203
|
+
print_mask_and_flows(stack, mask, flows)
|
211
204
|
if save:
|
212
205
|
output_filename = os.path.join(dst, image_names[file_index])
|
213
206
|
cv2.imwrite(output_filename, mask)
|
214
207
|
|
215
|
-
|
216
208
|
def check_cellpose_models(settings):
|
217
209
|
|
218
210
|
from .settings import get_check_cellpose_models_default_settings
|
@@ -231,7 +223,7 @@ def check_cellpose_models(settings):
|
|
231
223
|
|
232
224
|
model = cp_models.CellposeModel(gpu=True, model_type=model_name, device=device)
|
233
225
|
print(f'Using {model_name}')
|
234
|
-
generate_masks_from_imgs(src, model, model_name, settings['batch_size'], settings['diameter'], settings['CP_prob'], settings['flow_threshold'], settings['grayscale'], settings['save'], settings['normalize'], settings['channels'], settings['percentiles'], settings['
|
226
|
+
generate_masks_from_imgs(src, model, model_name, settings['batch_size'], settings['diameter'], settings['CP_prob'], settings['flow_threshold'], settings['grayscale'], settings['save'], settings['normalize'], settings['channels'], settings['percentiles'], settings['invert'], settings['plot'], settings['resize'], settings['target_height'], settings['target_width'], settings['remove_background'], settings['background'], settings['Signal_to_noise'], settings['verbose'])
|
235
227
|
|
236
228
|
return
|
237
229
|
|
spacr/io.py
CHANGED
@@ -129,7 +129,7 @@ def process_non_tif_non_2D_images(folder):
|
|
129
129
|
except Exception as e:
|
130
130
|
print(f"Error processing {filename}: {str(e)}")
|
131
131
|
|
132
|
-
def _load_images_and_labels(image_files, label_files,
|
132
|
+
def _load_images_and_labels(image_files, label_files, invert=False):
|
133
133
|
|
134
134
|
from .utils import invert_image, apply_mask
|
135
135
|
|
@@ -151,8 +151,6 @@ def _load_images_and_labels(image_files, label_files, circular=False, invert=Fal
|
|
151
151
|
image = cellpose.io.imread(img_file)
|
152
152
|
if invert:
|
153
153
|
image = invert_image(image)
|
154
|
-
if circular:
|
155
|
-
image = apply_mask(image, output_value=0)
|
156
154
|
label = cellpose.io.imread(lbl_file)
|
157
155
|
if image.max() > 1:
|
158
156
|
image = image / image.max()
|
@@ -163,16 +161,12 @@ def _load_images_and_labels(image_files, label_files, circular=False, invert=Fal
|
|
163
161
|
image = cellpose.io.imread(img_file)
|
164
162
|
if invert:
|
165
163
|
image = invert_image(image)
|
166
|
-
if circular:
|
167
|
-
image = apply_mask(image, output_value=0)
|
168
164
|
if image.max() > 1:
|
169
165
|
image = image / image.max()
|
170
166
|
images.append(image)
|
171
167
|
elif not image_files is None:
|
172
168
|
for lbl_file in label_files:
|
173
169
|
label = cellpose.io.imread(lbl_file)
|
174
|
-
if circular:
|
175
|
-
label = apply_mask(label, output_value=0)
|
176
170
|
labels.append(label)
|
177
171
|
|
178
172
|
if not image_files is None:
|
@@ -192,9 +186,8 @@ def _load_images_and_labels(image_files, label_files, circular=False, invert=Fal
|
|
192
186
|
return images, labels, image_names, label_names
|
193
187
|
|
194
188
|
def _load_normalized_images_and_labels(image_files, label_files, channels=None, percentiles=None,
|
195
|
-
|
196
|
-
|
197
|
-
target_height=None, target_width=None):
|
189
|
+
invert=False, visualize=False, remove_background=False,
|
190
|
+
background=0, Signal_to_noise=10, target_height=None, target_width=None):
|
198
191
|
|
199
192
|
from .plot import normalize_and_visualize, plot_resize
|
200
193
|
from .utils import invert_image, apply_mask
|
@@ -233,8 +226,6 @@ def _load_normalized_images_and_labels(image_files, label_files, channels=None,
|
|
233
226
|
|
234
227
|
if invert:
|
235
228
|
image = invert_image(image)
|
236
|
-
if circular:
|
237
|
-
image = apply_mask(image, output_value=0)
|
238
229
|
|
239
230
|
# Select specific channels if needed
|
240
231
|
if channels is not None and image.ndim == 3:
|
@@ -301,7 +292,7 @@ def _load_normalized_images_and_labels(image_files, label_files, channels=None,
|
|
301
292
|
|
302
293
|
return normalized_images, labels, image_names, label_names, orig_dims
|
303
294
|
|
304
|
-
def _load_normalized_images_and_labels_v1(image_files, label_files, channels=None, percentiles=None,
|
295
|
+
def _load_normalized_images_and_labels_v1(image_files, label_files, channels=None, percentiles=None, invert=False, visualize=False, remove_background=False, background=0, Signal_to_noise=10, target_height=None, target_width=None):
|
305
296
|
|
306
297
|
from .plot import normalize_and_visualize, plot_resize
|
307
298
|
from .utils import invert_image, apply_mask
|
@@ -339,8 +330,6 @@ def _load_normalized_images_and_labels_v1(image_files, label_files, channels=Non
|
|
339
330
|
orig_dims.append((image.shape[0], image.shape[1]))
|
340
331
|
if invert:
|
341
332
|
image = invert_image(image)
|
342
|
-
if circular:
|
343
|
-
image = apply_mask(image, output_value=0)
|
344
333
|
|
345
334
|
# If specific channels are specified, select them
|
346
335
|
if channels is not None and image.ndim == 3:
|
@@ -2146,7 +2135,8 @@ def _load_and_concatenate_arrays(src, channels, cell_chann_dim, nucleus_chann_di
|
|
2146
2135
|
# For each of the other folders, load the array and add it to 'stack_ls'
|
2147
2136
|
for folder in folder_paths[1:]:
|
2148
2137
|
array_path = os.path.join(folder, filename)
|
2149
|
-
array = np.load(array_path)
|
2138
|
+
#array = np.load(array_path)
|
2139
|
+
array = np.load(array_path, allow_pickle=True)
|
2150
2140
|
if array.ndim == 2:
|
2151
2141
|
array = np.expand_dims(array, axis=-1) # Add an extra dimension if the array is 2D
|
2152
2142
|
stack_ls.append(array)
|
spacr/ml.py
CHANGED
@@ -450,13 +450,14 @@ def perform_regression(settings):
|
|
450
450
|
else:
|
451
451
|
return df
|
452
452
|
|
453
|
-
|
454
|
-
|
455
453
|
settings = get_perform_regression_default_settings(settings)
|
456
454
|
count_data_df, score_data_df = _perform_regression_read_data(settings)
|
457
455
|
results_path, results_path_gene, results_path_grna, hits_path, res_folder, csv_path = _perform_regression_set_paths(settings)
|
458
456
|
save_settings(settings, name='regression', show=True)
|
459
457
|
|
458
|
+
count_source = os.path.dirname(settings['count_data'][0])
|
459
|
+
volcano_path = os.path.join(count_source, 'volcano_plot.pdf')
|
460
|
+
|
460
461
|
if isinstance(settings['filter_value'], list):
|
461
462
|
filter_value = settings['filter_value']
|
462
463
|
else:
|
@@ -548,7 +549,7 @@ def perform_regression(settings):
|
|
548
549
|
base_dir = os.path.dirname(os.path.abspath(__file__))
|
549
550
|
metadata_path = os.path.join(base_dir, 'resources', 'data', 'lopit.csv')
|
550
551
|
|
551
|
-
custom_volcano_plot(data_path, metadata_path, metadata_column='tagm_location', point_size=200, figsize=20, threshold=reg_threshold, split_axis_lims=settings['split_axis_lims'])
|
552
|
+
custom_volcano_plot(data_path, metadata_path, metadata_column='tagm_location', point_size=200, figsize=20, threshold=reg_threshold, split_axis_lims=settings['split_axis_lims'], save_path=volcano_path)
|
552
553
|
#custom_volcano_plot(data_path_gene, metadata_path, metadata_column='tagm_location', point_size=50, figsize=20, threshold=reg_threshold)
|
553
554
|
#custom_volcano_plot(data_path_grna, metadata_path, metadata_column='tagm_location', point_size=50, figsize=20, threshold=reg_threshold)
|
554
555
|
|