spacr 0.0.70__py3-none-any.whl → 0.0.80__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 -1
- spacr/__main__.py +0 -7
- spacr/annotate_app.py +75 -61
- spacr/core.py +39 -246
- spacr/foldseek.py +6 -6
- spacr/get_alfafold_structures.py +3 -3
- spacr/io.py +53 -116
- spacr/measure.py +46 -59
- spacr/plot.py +117 -81
- spacr/sequencing.py +508 -491
- spacr/sim.py +24 -29
- spacr/utils.py +487 -260
- {spacr-0.0.70.dist-info → spacr-0.0.80.dist-info}/METADATA +10 -8
- spacr-0.0.80.dist-info/RECORD +36 -0
- spacr/graph_learning_lap.py +0 -84
- spacr/train.py +0 -667
- spacr/umap.py +0 -0
- spacr-0.0.70.dist-info/RECORD +0 -39
- {spacr-0.0.70.dist-info → spacr-0.0.80.dist-info}/LICENSE +0 -0
- {spacr-0.0.70.dist-info → spacr-0.0.80.dist-info}/WHEEL +0 -0
- {spacr-0.0.70.dist-info → spacr-0.0.80.dist-info}/entry_points.txt +0 -0
- {spacr-0.0.70.dist-info → spacr-0.0.80.dist-info}/top_level.txt +0 -0
spacr/plot.py
CHANGED
@@ -12,17 +12,13 @@ import imageio.v2 as imageio
|
|
12
12
|
from IPython.display import display
|
13
13
|
from skimage.segmentation import find_boundaries
|
14
14
|
from skimage import measure
|
15
|
+
from skimage.measure import find_contours, label, regionprops
|
15
16
|
|
16
17
|
from ipywidgets import IntSlider, interact
|
17
18
|
from IPython.display import Image as ipyimage
|
18
19
|
|
19
20
|
from .logger import log_function_call
|
20
21
|
|
21
|
-
|
22
|
-
#from .io import _save_figure
|
23
|
-
#from .timelapse import _save_mask_timelapse_as_gif
|
24
|
-
#from .utils import normalize_to_dtype, _remove_outside_objects, _remove_multiobject_cells, _find_similar_sized_images, _remove_noninfected
|
25
|
-
|
26
22
|
def plot_masks(batch, masks, flows, cmap='inferno', figuresize=20, nr=1, file_type='.npz', print_object_number=True):
|
27
23
|
"""
|
28
24
|
Plot the masks and flows for a given batch of images.
|
@@ -193,7 +189,7 @@ def _get_colours_merged(outline_color):
|
|
193
189
|
outline_colors = [[1, 0, 0], [0, 0, 1], [0, 1, 0]] # rbg
|
194
190
|
return outline_colors
|
195
191
|
|
196
|
-
def plot_images_and_arrays(folders, lower_percentile=1, upper_percentile=99, threshold=1000, extensions=['.npy', '.tif', '.tiff', '.png']):
|
192
|
+
def plot_images_and_arrays(folders, lower_percentile=1, upper_percentile=99, threshold=1000, extensions=['.npy', '.tif', '.tiff', '.png'], overlay=False, max_nr=None, randomize=True):
|
197
193
|
"""
|
198
194
|
Plot images and arrays from the given folders.
|
199
195
|
|
@@ -203,6 +199,7 @@ def plot_images_and_arrays(folders, lower_percentile=1, upper_percentile=99, thr
|
|
203
199
|
upper_percentile (int, optional): The upper percentile for image normalization. Defaults to 99.
|
204
200
|
threshold (int, optional): The threshold for determining whether to display an image as a mask or normalize it. Defaults to 1000.
|
205
201
|
extensions (list, optional): A list of file extensions to consider. Defaults to ['.npy', '.tif', '.tiff', '.png'].
|
202
|
+
overlay (bool, optional): If True, overlay the outlines of the objects on the image. Defaults to False.
|
206
203
|
"""
|
207
204
|
|
208
205
|
def normalize_image(image, lower=1, upper=99):
|
@@ -226,7 +223,7 @@ def plot_images_and_arrays(folders, lower_percentile=1, upper_percentile=99, thr
|
|
226
223
|
filtered_dict = {k: v for k, v in file_dict.items() if len(v) == len(folders)}
|
227
224
|
return filtered_dict
|
228
225
|
|
229
|
-
def plot_from_file_dict(file_dict, threshold=1000, lower_percentile=1, upper_percentile=99):
|
226
|
+
def plot_from_file_dict(file_dict, threshold=1000, lower_percentile=1, upper_percentile=99, overlay=False, save=False):
|
230
227
|
"""
|
231
228
|
Plot images and arrays from the given file dictionary.
|
232
229
|
|
@@ -235,18 +232,14 @@ def plot_images_and_arrays(folders, lower_percentile=1, upper_percentile=99, thr
|
|
235
232
|
threshold (int, optional): The threshold for determining whether to display an image as a mask or normalize it. Defaults to 1000.
|
236
233
|
lower_percentile (int, optional): The lower percentile for image normalization. Defaults to 1.
|
237
234
|
upper_percentile (int, optional): The upper percentile for image normalization. Defaults to 99.
|
235
|
+
overlay (bool, optional): If True, overlay the outlines of the objects on the image. Defaults to False.
|
238
236
|
"""
|
239
237
|
|
240
238
|
for filename, folder_paths in file_dict.items():
|
241
|
-
|
242
|
-
|
243
|
-
#fig.suptitle(filename)
|
244
|
-
|
245
|
-
# Ensure axes is always a list
|
246
|
-
if num_files == 1:
|
247
|
-
axes = [axes]
|
239
|
+
image_data = None
|
240
|
+
mask_data = None
|
248
241
|
|
249
|
-
for
|
242
|
+
for folder, path in folder_paths.items():
|
250
243
|
if path.endswith('.npy'):
|
251
244
|
data = np.load(path)
|
252
245
|
elif path.endswith('.tif') or path.endswith('.tiff'):
|
@@ -254,25 +247,57 @@ def plot_images_and_arrays(folders, lower_percentile=1, upper_percentile=99, thr
|
|
254
247
|
else:
|
255
248
|
continue
|
256
249
|
|
257
|
-
ax = axes[i]
|
258
250
|
unique_values = np.unique(data)
|
251
|
+
|
259
252
|
if len(unique_values) > threshold:
|
260
|
-
|
261
|
-
data = normalize_image(data, lower_percentile, upper_percentile)
|
262
|
-
ax.imshow(data, cmap='gray')
|
253
|
+
image_data = normalize_image(data, lower_percentile, upper_percentile)
|
263
254
|
else:
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
255
|
+
mask_data = data
|
256
|
+
|
257
|
+
if image_data is not None and mask_data is not None:
|
258
|
+
fig, axes = plt.subplots(1, 2, figsize=(15, 7))
|
259
|
+
|
260
|
+
# Display the mask with random colormap
|
261
|
+
cmap = random_cmap(num_objects=len(np.unique(mask_data)))
|
262
|
+
axes[0].imshow(mask_data, cmap=cmap)
|
263
|
+
axes[0].set_title(f"{filename} - Mask")
|
264
|
+
axes[0].axis('off')
|
265
|
+
|
266
|
+
# Display the normalized image
|
267
|
+
axes[1].imshow(image_data, cmap='gray')
|
268
|
+
if overlay:
|
269
|
+
labeled_mask = label(mask_data)
|
270
|
+
for region in regionprops(labeled_mask):
|
271
|
+
if region.image.shape[0] >= 2 and region.image.shape[1] >= 2:
|
272
|
+
contours = find_contours(region.image, 0.75)
|
273
|
+
for contour in contours:
|
274
|
+
# Adjust contour coordinates relative to the full image
|
275
|
+
contour[:, 0] += region.bbox[0]
|
276
|
+
contour[:, 1] += region.bbox[1]
|
277
|
+
axes[1].plot(contour[:, 1], contour[:, 0], linewidth=2, color='magenta')
|
278
|
+
|
279
|
+
axes[1].set_title(f"{filename} - Normalized Image")
|
280
|
+
axes[1].axis('off')
|
281
|
+
|
282
|
+
plt.tight_layout()
|
283
|
+
plt.show()
|
284
|
+
|
285
|
+
if save:
|
286
|
+
save_path = os.path.join(folder,f"{filename}.png")
|
287
|
+
plt.savefig(save_path)
|
288
|
+
|
289
|
+
if overlay:
|
290
|
+
print(f'Overlay will only work on the first two folders in the list')
|
291
|
+
|
274
292
|
file_dict = find_files(folders, extensions)
|
275
|
-
|
293
|
+
items = list(file_dict.items())
|
294
|
+
if randomize:
|
295
|
+
random.shuffle(items)
|
296
|
+
if isinstance(max_nr, (int, float)):
|
297
|
+
items = items[:int(max_nr)]
|
298
|
+
file_dict = dict(items)
|
299
|
+
|
300
|
+
plot_from_file_dict(file_dict, threshold, lower_percentile, upper_percentile, overlay, save=False)
|
276
301
|
return
|
277
302
|
|
278
303
|
def _filter_objects_in_plot(stack, cell_mask_dim, nucleus_mask_dim, pathogen_mask_dim, mask_dims, filter_min_max, include_multinucleated, include_multiinfected):
|
@@ -739,7 +764,53 @@ def _save_scimg_plot(src, nr_imgs=16, channel_indices=[0,1,2], um_per_pixel=0.1,
|
|
739
764
|
|
740
765
|
return
|
741
766
|
|
742
|
-
def _plot_cropped_arrays(stack, figuresize=20,cmap='inferno'):
|
767
|
+
def _plot_cropped_arrays(stack, filename, figuresize=20, cmap='inferno', threshold=500):
|
768
|
+
"""
|
769
|
+
Plot cropped arrays.
|
770
|
+
|
771
|
+
Args:
|
772
|
+
stack (ndarray): The array to be plotted.
|
773
|
+
figuresize (int, optional): The size of the figure. Defaults to 20.
|
774
|
+
cmap (str, optional): The colormap to be used. Defaults to 'inferno'.
|
775
|
+
threshold (int, optional): The threshold for the number of unique intensity values. Defaults to 1000.
|
776
|
+
|
777
|
+
Returns:
|
778
|
+
None
|
779
|
+
"""
|
780
|
+
#start = time.time()
|
781
|
+
dim = stack.shape
|
782
|
+
|
783
|
+
def plot_single_array(array, ax, title, chosen_cmap):
|
784
|
+
unique_values = np.unique(array)
|
785
|
+
num_unique_values = len(unique_values)
|
786
|
+
|
787
|
+
if num_unique_values <= threshold:
|
788
|
+
chosen_cmap = _generate_mask_random_cmap(array)
|
789
|
+
title = f'{title}, {num_unique_values} (obj.)'
|
790
|
+
|
791
|
+
ax.imshow(array, cmap=chosen_cmap)
|
792
|
+
ax.set_title(title, size=18)
|
793
|
+
ax.axis('off')
|
794
|
+
|
795
|
+
if len(dim) == 2:
|
796
|
+
fig, ax = plt.subplots(1, 1, figsize=(figuresize, figuresize))
|
797
|
+
plot_single_array(stack, ax, 'Channel one', plt.get_cmap(cmap))
|
798
|
+
fig.tight_layout()
|
799
|
+
plt.show()
|
800
|
+
elif len(dim) > 2:
|
801
|
+
num_channels = dim[2]
|
802
|
+
fig, axs = plt.subplots(1, num_channels, figsize=(figuresize, figuresize))
|
803
|
+
for channel in range(num_channels):
|
804
|
+
plot_single_array(stack[:, :, channel], axs[channel], f'C. {channel}', plt.get_cmap(cmap))
|
805
|
+
fig.tight_layout()
|
806
|
+
plt.show()
|
807
|
+
|
808
|
+
#stop = time.time()
|
809
|
+
#duration = stop - start
|
810
|
+
#print('plot_cropped_arrays', duration)
|
811
|
+
print(f'{filename}')
|
812
|
+
|
813
|
+
def _plot_cropped_arrays_v1(stack, figuresize=20, cmap='inferno'):
|
743
814
|
"""
|
744
815
|
Plot cropped arrays.
|
745
816
|
|
@@ -1192,56 +1263,6 @@ def _plot_plates(df, variable, grouping, min_max, cmap, min_count=0):
|
|
1192
1263
|
plt.show()
|
1193
1264
|
return fig
|
1194
1265
|
|
1195
|
-
#def plate_heatmap(src, variable='recruitment', grouping='mean', min_max='allq', cmap='viridis', channel_of_interest=3, min_count=25, verbose=False):
|
1196
|
-
# db_loc = [src+'/measurements/measurements.db']
|
1197
|
-
# tables = ['cell', 'nucleus', 'pathogen','cytoplasm']
|
1198
|
-
# include_multinucleated, include_multiinfected, include_noninfected = True, 2.0, True
|
1199
|
-
# df, _ = spacr.io._read_and_merge_data(db_loc,
|
1200
|
-
# tables,
|
1201
|
-
# verbose=verbose,
|
1202
|
-
# include_multinucleated=include_multinucleated,
|
1203
|
-
# include_multiinfected=include_multiinfected,
|
1204
|
-
# include_noninfected=include_noninfected)
|
1205
|
-
#
|
1206
|
-
# df['recruitment'] = df[f'pathogen_channel_{channel_of_interest}_outside_75_percentile']/df[f'cytoplasm_channel_{channel_of_interest}_mean_intensity']
|
1207
|
-
#
|
1208
|
-
# spacr.plot._plot_plates(df, variable, grouping, min_max, cmap, min_count)
|
1209
|
-
# #display(df)
|
1210
|
-
# #for col in df.columns:
|
1211
|
-
# # print(col)
|
1212
|
-
# return
|
1213
|
-
|
1214
|
-
#from finetune cellpose
|
1215
|
-
#def plot_arrays(src, figuresize=50, cmap='inferno', nr=1, normalize=True, q1=1, q2=99):
|
1216
|
-
# paths = []
|
1217
|
-
# for file in os.listdir(src):
|
1218
|
-
# if file.endswith('.tif') or file.endswith('.tiff'):
|
1219
|
-
# path = os.path.join(src, file)
|
1220
|
-
# paths.append(path)
|
1221
|
-
# paths = random.sample(paths, nr)
|
1222
|
-
# for path in paths:
|
1223
|
-
# print(f'Image path:{path}')
|
1224
|
-
# img = cv2.imread(path, cv2.IMREAD_UNCHANGED)
|
1225
|
-
# if normalize:
|
1226
|
-
# img = normalize_to_dtype(array=img, q1=q1, q2=q2)
|
1227
|
-
# dim = img.shape
|
1228
|
-
# if len(img.shape) > 2:
|
1229
|
-
# array_nr = img.shape[2]
|
1230
|
-
# fig, axs = plt.subplots(1, array_nr, figsize=(figuresize, figuresize))
|
1231
|
-
# for channel in range(array_nr):
|
1232
|
-
# i = np.take(img, [channel], axis=2)
|
1233
|
-
# axs[channel].imshow(i, cmap=plt.get_cmap(cmap))
|
1234
|
-
# axs[channel].set_title('Channel '+str(channel), size=24)
|
1235
|
-
# axs[channel].axis('off')
|
1236
|
-
# else:
|
1237
|
-
# fig, ax = plt.subplots(1, 1, figsize=(figuresize, figuresize))
|
1238
|
-
# ax.imshow(img, cmap=plt.get_cmap(cmap))
|
1239
|
-
# ax.set_title('Channel 0', size=24)
|
1240
|
-
# ax.axis('off')
|
1241
|
-
# fig.tight_layout()
|
1242
|
-
# plt.show()
|
1243
|
-
# return
|
1244
|
-
|
1245
1266
|
def print_mask_and_flows(stack, mask, flows, overlay=False):
|
1246
1267
|
fig, axs = plt.subplots(1, 3, figsize=(30, 10)) # Adjust subplot layout
|
1247
1268
|
|
@@ -1434,3 +1455,18 @@ def plot_comparison_results(comparison_results):
|
|
1434
1455
|
plt.tight_layout()
|
1435
1456
|
plt.show()
|
1436
1457
|
return fig
|
1458
|
+
|
1459
|
+
def plot_object_outlines(src, objects=['nucleus','cell','pathogen'], channels=[0,1,2], max_nr=10):
|
1460
|
+
|
1461
|
+
for object_, channel in zip(objects, channels):
|
1462
|
+
folders = [os.path.join(src, 'norm_channel_stack', f'{object_}_mask_stack'),
|
1463
|
+
os.path.join(src,f'{channel+1}')]
|
1464
|
+
print(folders)
|
1465
|
+
plot_images_and_arrays(folders,
|
1466
|
+
lower_percentile=2,
|
1467
|
+
upper_percentile=99.5,
|
1468
|
+
threshold=1000,
|
1469
|
+
extensions=['.npy', '.tif', '.tiff', '.png'],
|
1470
|
+
overlay=True,
|
1471
|
+
max_nr=10,
|
1472
|
+
randomize=True)
|