spacr 0.0.20__py3-none-any.whl → 0.0.21__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/alpha.py +291 -14
- spacr/annotate_app.py +2 -2
- spacr/core.py +1301 -426
- spacr/foldseek.py +793 -0
- spacr/get_alfafold_structures.py +72 -0
- spacr/gui_mask_app.py +30 -10
- spacr/gui_utils.py +17 -2
- spacr/io.py +260 -102
- spacr/measure.py +150 -64
- spacr/plot.py +151 -12
- spacr/sim.py +666 -119
- spacr/timelapse.py +139 -9
- spacr/train.py +18 -10
- spacr/utils.py +43 -43
- {spacr-0.0.20.dist-info → spacr-0.0.21.dist-info}/METADATA +5 -2
- spacr-0.0.21.dist-info/RECORD +33 -0
- spacr-0.0.20.dist-info/RECORD +0 -31
- {spacr-0.0.20.dist-info → spacr-0.0.21.dist-info}/LICENSE +0 -0
- {spacr-0.0.20.dist-info → spacr-0.0.21.dist-info}/WHEEL +0 -0
- {spacr-0.0.20.dist-info → spacr-0.0.21.dist-info}/entry_points.txt +0 -0
- {spacr-0.0.20.dist-info → spacr-0.0.21.dist-info}/top_level.txt +0 -0
spacr/io.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import os, re, sqlite3, gc, torch, time, random, shutil, cv2, tarfile, cellpose
|
1
|
+
import os, re, sqlite3, gc, torch, time, random, shutil, cv2, tarfile, cellpose, glob
|
2
2
|
import numpy as np
|
3
3
|
import pandas as pd
|
4
4
|
import tifffile
|
@@ -45,19 +45,19 @@ def _load_images_and_labels(image_files, label_files, circular=False, invert=Fal
|
|
45
45
|
|
46
46
|
if not image_files is None and not label_files is None:
|
47
47
|
for img_file, lbl_file in zip(image_files, label_files):
|
48
|
-
image = cellpose.imread(img_file)
|
48
|
+
image = cellpose.io.imread(img_file)
|
49
49
|
if invert:
|
50
50
|
image = invert_image(image)
|
51
51
|
if circular:
|
52
52
|
image = apply_mask(image, output_value=0)
|
53
|
-
label = cellpose.imread(lbl_file)
|
53
|
+
label = cellpose.io.imread(lbl_file)
|
54
54
|
if image.max() > 1:
|
55
55
|
image = image / image.max()
|
56
56
|
images.append(image)
|
57
57
|
labels.append(label)
|
58
58
|
elif not image_files is None:
|
59
59
|
for img_file in image_files:
|
60
|
-
image = cellpose.imread(img_file)
|
60
|
+
image = cellpose.io.imread(img_file)
|
61
61
|
if invert:
|
62
62
|
image = invert_image(image)
|
63
63
|
if circular:
|
@@ -67,7 +67,7 @@ def _load_images_and_labels(image_files, label_files, circular=False, invert=Fal
|
|
67
67
|
images.append(image)
|
68
68
|
elif not image_files is None:
|
69
69
|
for lbl_file in label_files:
|
70
|
-
label = cellpose.imread(lbl_file)
|
70
|
+
label = cellpose.io.imread(lbl_file)
|
71
71
|
if circular:
|
72
72
|
label = apply_mask(label, output_value=0)
|
73
73
|
labels.append(label)
|
@@ -109,15 +109,17 @@ def _load_normalized_images_and_labels(image_files, label_files, signal_threshol
|
|
109
109
|
|
110
110
|
if label_files is not None:
|
111
111
|
label_names = [os.path.basename(f) for f in label_files]
|
112
|
+
label_dir = os.path.dirname(label_files[0])
|
112
113
|
|
113
114
|
# Load images and check percentiles
|
114
115
|
for i,img_file in enumerate(image_files):
|
115
|
-
|
116
|
+
#print(img_file)
|
117
|
+
image = cellpose.io.imread(img_file)
|
116
118
|
if invert:
|
117
119
|
image = invert_image(image)
|
118
120
|
if circular:
|
119
121
|
image = apply_mask(image, output_value=0)
|
120
|
-
|
122
|
+
#print(image.shape)
|
121
123
|
# If specific channels are specified, select them
|
122
124
|
if channels is not None and image.ndim == 3:
|
123
125
|
image = image[..., channels]
|
@@ -169,7 +171,7 @@ def _load_normalized_images_and_labels(image_files, label_files, signal_threshol
|
|
169
171
|
|
170
172
|
if label_files is not None:
|
171
173
|
for lbl_file in label_files:
|
172
|
-
labels.append(cellpose.imread(lbl_file))
|
174
|
+
labels.append(cellpose.io.imread(lbl_file))
|
173
175
|
else:
|
174
176
|
label_names = []
|
175
177
|
label_dir = None
|
@@ -178,85 +180,6 @@ def _load_normalized_images_and_labels(image_files, label_files, signal_threshol
|
|
178
180
|
|
179
181
|
return normalized_images, labels, image_names, label_names
|
180
182
|
|
181
|
-
class MyDataset(Dataset):
|
182
|
-
"""
|
183
|
-
Custom dataset class for loading and processing image data.
|
184
|
-
|
185
|
-
Args:
|
186
|
-
data_dir (str): The directory path where the data is stored.
|
187
|
-
loader_classes (list): List of class names.
|
188
|
-
transform (callable, optional): A function/transform that takes in an PIL image and returns a transformed version. Default is None.
|
189
|
-
shuffle (bool, optional): Whether to shuffle the dataset. Default is True.
|
190
|
-
load_to_memory (bool, optional): Whether to load images into memory. Default is False.
|
191
|
-
|
192
|
-
Attributes:
|
193
|
-
data_dir (str): The directory path where the data is stored.
|
194
|
-
classes (list): List of class names.
|
195
|
-
transform (callable): A function/transform that takes in an PIL image and returns a transformed version.
|
196
|
-
shuffle (bool): Whether to shuffle the dataset.
|
197
|
-
load_to_memory (bool): Whether to load images into memory.
|
198
|
-
filenames (list): List of file paths.
|
199
|
-
labels (list): List of labels corresponding to each file.
|
200
|
-
images (list): List of loaded images.
|
201
|
-
image_cache (Cache): Cache object for storing loaded images.
|
202
|
-
|
203
|
-
Methods:
|
204
|
-
load_image: Load an image from file.
|
205
|
-
__len__: Get the length of the dataset.
|
206
|
-
shuffle_dataset: Shuffle the dataset.
|
207
|
-
__getitem__: Get an item from the dataset.
|
208
|
-
|
209
|
-
"""
|
210
|
-
|
211
|
-
def _init__(self, data_dir, loader_classes, transform=None, shuffle=True, load_to_memory=False):
|
212
|
-
from .utils import Cache
|
213
|
-
self.data_dir = data_dir
|
214
|
-
self.classes = loader_classes
|
215
|
-
self.transform = transform
|
216
|
-
self.shuffle = shuffle
|
217
|
-
self.load_to_memory = load_to_memory
|
218
|
-
self.filenames = []
|
219
|
-
self.labels = []
|
220
|
-
self.images = []
|
221
|
-
self.image_cache = Cache(50)
|
222
|
-
for class_name in self.classes:
|
223
|
-
class_path = os.path.join(data_dir, class_name)
|
224
|
-
class_files = [os.path.join(class_path, f) for f in os.listdir(class_path) if os.path.isfile(os.path.join(class_path, f))]
|
225
|
-
self.filenames.extend(class_files)
|
226
|
-
self.labels.extend([self.classes.index(class_name)] * len(class_files))
|
227
|
-
if self.shuffle:
|
228
|
-
self.shuffle_dataset()
|
229
|
-
if self.load_to_memory:
|
230
|
-
self.images = [self.load_image(f) for f in self.filenames]
|
231
|
-
|
232
|
-
def load_image(self, img_path):
|
233
|
-
img = self.image_cache.get(img_path)
|
234
|
-
if img is None:
|
235
|
-
img = Image.open(img_path).convert('RGB')
|
236
|
-
self.image_cache.put(img_path, img)
|
237
|
-
return img
|
238
|
-
|
239
|
-
def _len__(self):
|
240
|
-
return len(self.filenames)
|
241
|
-
|
242
|
-
def shuffle_dataset(self):
|
243
|
-
combined = list(zip(self.filenames, self.labels))
|
244
|
-
random.shuffle(combined)
|
245
|
-
self.filenames, self.labels = zip(*combined)
|
246
|
-
|
247
|
-
def _getitem__(self, index):
|
248
|
-
label = self.labels[index]
|
249
|
-
filename = self.filenames[index]
|
250
|
-
if self.load_to_memory:
|
251
|
-
img = self.images[index]
|
252
|
-
else:
|
253
|
-
img = self.load_image(filename)
|
254
|
-
if self.transform is not None:
|
255
|
-
img = self.transform(img)
|
256
|
-
else:
|
257
|
-
img = ToTensor()(img)
|
258
|
-
return img, label, filename
|
259
|
-
|
260
183
|
class CombineLoaders:
|
261
184
|
"""
|
262
185
|
A class that combines multiple data loaders into a single iterator.
|
@@ -383,6 +306,85 @@ class NoClassDataset(Dataset):
|
|
383
306
|
img = ToTensor()(img)
|
384
307
|
# Return both the image and its filename
|
385
308
|
return img, self.filenames[index]
|
309
|
+
|
310
|
+
class MyDataset_v1(Dataset):
|
311
|
+
"""
|
312
|
+
Custom dataset class for loading and processing image data.
|
313
|
+
|
314
|
+
Args:
|
315
|
+
data_dir (str): The directory path where the data is stored.
|
316
|
+
loader_classes (list): List of class names.
|
317
|
+
transform (callable, optional): A function/transform that takes in an PIL image and returns a transformed version. Default is None.
|
318
|
+
shuffle (bool, optional): Whether to shuffle the dataset. Default is True.
|
319
|
+
load_to_memory (bool, optional): Whether to load images into memory. Default is False.
|
320
|
+
|
321
|
+
Attributes:
|
322
|
+
data_dir (str): The directory path where the data is stored.
|
323
|
+
classes (list): List of class names.
|
324
|
+
transform (callable): A function/transform that takes in an PIL image and returns a transformed version.
|
325
|
+
shuffle (bool): Whether to shuffle the dataset.
|
326
|
+
load_to_memory (bool): Whether to load images into memory.
|
327
|
+
filenames (list): List of file paths.
|
328
|
+
labels (list): List of labels corresponding to each file.
|
329
|
+
images (list): List of loaded images.
|
330
|
+
image_cache (Cache): Cache object for storing loaded images.
|
331
|
+
|
332
|
+
Methods:
|
333
|
+
load_image: Load an image from file.
|
334
|
+
__len__: Get the length of the dataset.
|
335
|
+
shuffle_dataset: Shuffle the dataset.
|
336
|
+
__getitem__: Get an item from the dataset.
|
337
|
+
|
338
|
+
"""
|
339
|
+
|
340
|
+
def __init__(self, data_dir, loader_classes, transform=None, shuffle=True, load_to_memory=False):
|
341
|
+
from .utils import Cache
|
342
|
+
self.data_dir = data_dir
|
343
|
+
self.classes = loader_classes
|
344
|
+
self.transform = transform
|
345
|
+
self.shuffle = shuffle
|
346
|
+
self.load_to_memory = load_to_memory
|
347
|
+
self.filenames = []
|
348
|
+
self.labels = []
|
349
|
+
self.images = []
|
350
|
+
self.image_cache = Cache(50)
|
351
|
+
for class_name in self.classes:
|
352
|
+
class_path = os.path.join(data_dir, class_name)
|
353
|
+
class_files = [os.path.join(class_path, f) for f in os.listdir(class_path) if os.path.isfile(os.path.join(class_path, f))]
|
354
|
+
self.filenames.extend(class_files)
|
355
|
+
self.labels.extend([self.classes.index(class_name)] * len(class_files))
|
356
|
+
if self.shuffle:
|
357
|
+
self.shuffle_dataset()
|
358
|
+
if self.load_to_memory:
|
359
|
+
self.images = [self.load_image(f) for f in self.filenames]
|
360
|
+
|
361
|
+
def load_image(self, img_path):
|
362
|
+
img = self.image_cache.get(img_path)
|
363
|
+
if img is None:
|
364
|
+
img = Image.open(img_path).convert('RGB')
|
365
|
+
self.image_cache.put(img_path, img)
|
366
|
+
return img
|
367
|
+
|
368
|
+
def _len__(self):
|
369
|
+
return len(self.filenames)
|
370
|
+
|
371
|
+
def shuffle_dataset(self):
|
372
|
+
combined = list(zip(self.filenames, self.labels))
|
373
|
+
random.shuffle(combined)
|
374
|
+
self.filenames, self.labels = zip(*combined)
|
375
|
+
|
376
|
+
def _getitem__(self, index):
|
377
|
+
label = self.labels[index]
|
378
|
+
filename = self.filenames[index]
|
379
|
+
if self.load_to_memory:
|
380
|
+
img = self.images[index]
|
381
|
+
else:
|
382
|
+
img = self.load_image(filename)
|
383
|
+
if self.transform is not None:
|
384
|
+
img = self.transform(img)
|
385
|
+
else:
|
386
|
+
img = ToTensor()(img)
|
387
|
+
return img, label, filename
|
386
388
|
|
387
389
|
class MyDataset(Dataset):
|
388
390
|
"""
|
@@ -398,7 +400,7 @@ class MyDataset(Dataset):
|
|
398
400
|
specific_labels (list, optional): A list of specific labels corresponding to the specific files. Default is None.
|
399
401
|
"""
|
400
402
|
|
401
|
-
def
|
403
|
+
def __init__(self, data_dir, loader_classes, transform=None, shuffle=True, pin_memory=False, specific_files=None, specific_labels=None):
|
402
404
|
self.data_dir = data_dir
|
403
405
|
self.classes = loader_classes
|
404
406
|
self.transform = transform
|
@@ -427,7 +429,7 @@ class MyDataset(Dataset):
|
|
427
429
|
img = Image.open(img_path).convert('RGB')
|
428
430
|
return img
|
429
431
|
|
430
|
-
def
|
432
|
+
def __len__(self):
|
431
433
|
return len(self.filenames)
|
432
434
|
|
433
435
|
def shuffle_dataset(self):
|
@@ -439,7 +441,7 @@ class MyDataset(Dataset):
|
|
439
441
|
filename = os.path.basename(filepath) # Get just the filename from the full path
|
440
442
|
return filename.split('_')[0]
|
441
443
|
|
442
|
-
def
|
444
|
+
def __getitem__(self, index):
|
443
445
|
label = self.labels[index]
|
444
446
|
filename = self.filenames[index]
|
445
447
|
img = self.load_image(filename)
|
@@ -600,7 +602,7 @@ def _rename_and_organize_image_files(src, regex, batch_size=100, pick_slice=Fals
|
|
600
602
|
shutil.move(os.path.join(src, filename), move)
|
601
603
|
return
|
602
604
|
|
603
|
-
def
|
605
|
+
def _merge_file_v1(chan_dirs, stack_dir, file):
|
604
606
|
"""
|
605
607
|
Merge multiple channels into a single stack and save it as a numpy array.
|
606
608
|
|
@@ -625,15 +627,80 @@ def _merge_file(chan_dirs, stack_dir, file):
|
|
625
627
|
stack = np.concatenate(channels, axis=2)
|
626
628
|
np.save(new_file, stack)
|
627
629
|
|
628
|
-
def
|
630
|
+
def _merge_file_v1(chan_dirs, stack_dir, file):
|
629
631
|
"""
|
630
|
-
|
632
|
+
Merge multiple channels into a single stack and save it as a numpy array.
|
633
|
+
Args:
|
634
|
+
chan_dirs (list): List of directories containing channel images.
|
635
|
+
stack_dir (str): Directory to save the merged stack.
|
636
|
+
file (str): File name of the channel image.
|
637
|
+
|
638
|
+
Returns:
|
639
|
+
None
|
640
|
+
"""
|
641
|
+
new_file = stack_dir / (file.stem + '.npy')
|
642
|
+
if not new_file.exists():
|
643
|
+
stack_dir.mkdir(exist_ok=True)
|
644
|
+
channels = []
|
645
|
+
for i, chan_dir in enumerate(chan_dirs):
|
646
|
+
img_path = str(chan_dir / file.name)
|
647
|
+
img = cv2.imread(img_path, -1)
|
648
|
+
if img is None:
|
649
|
+
print(f"Warning: Failed to read image {img_path}")
|
650
|
+
continue
|
651
|
+
chan = np.expand_dims(img, axis=2)
|
652
|
+
channels.append(chan)
|
653
|
+
del img # Explicitly delete the reference to the image to free up memory
|
654
|
+
if i % 10 == 0: # Periodically suggest garbage collection
|
655
|
+
gc.collect()
|
631
656
|
|
657
|
+
if channels:
|
658
|
+
stack = np.concatenate(channels, axis=2)
|
659
|
+
np.save(new_file, stack)
|
660
|
+
else:
|
661
|
+
print(f"No valid channels to merge for file {file.name}")
|
662
|
+
|
663
|
+
def _merge_file(chan_dirs, stack_dir, file_name):
|
664
|
+
"""
|
665
|
+
Merge multiple channels into a single stack and save it as a numpy array, using os module for path handling.
|
666
|
+
|
632
667
|
Args:
|
633
|
-
|
668
|
+
chan_dirs (list): List of directories containing channel images.
|
669
|
+
stack_dir (str): Directory to save the merged stack.
|
670
|
+
file_name (str): File name of the channel image.
|
634
671
|
|
635
672
|
Returns:
|
636
|
-
|
673
|
+
None
|
674
|
+
"""
|
675
|
+
# Construct new file path
|
676
|
+
file_root, file_ext = os.path.splitext(file_name)
|
677
|
+
new_file = os.path.join(stack_dir, file_root + '.npy')
|
678
|
+
|
679
|
+
# Check if the new file exists and create the stack directory if it doesn't
|
680
|
+
if not os.path.exists(new_file):
|
681
|
+
os.makedirs(stack_dir, exist_ok=True)
|
682
|
+
channels = []
|
683
|
+
for i, chan_dir in enumerate(chan_dirs):
|
684
|
+
img_path = os.path.join(chan_dir, file_name)
|
685
|
+
img = cv2.imread(img_path, -1)
|
686
|
+
if img is None:
|
687
|
+
print(f"Warning: Failed to read image {img_path}")
|
688
|
+
continue
|
689
|
+
chan = np.expand_dims(img, axis=2)
|
690
|
+
channels.append(chan)
|
691
|
+
del img # Explicitly delete the reference to the image to free up memory
|
692
|
+
if i % 10 == 0: # Periodically suggest garbage collection
|
693
|
+
gc.collect()
|
694
|
+
|
695
|
+
if channels:
|
696
|
+
stack = np.concatenate(channels, axis=2)
|
697
|
+
np.save(new_file, stack)
|
698
|
+
else:
|
699
|
+
print(f"No valid channels to merge for file {file_name}")
|
700
|
+
|
701
|
+
def _is_dir_empty(dir_path):
|
702
|
+
"""
|
703
|
+
Check if a directory is empty using os module.
|
637
704
|
"""
|
638
705
|
return len(os.listdir(dir_path)) == 0
|
639
706
|
|
@@ -733,7 +800,7 @@ def _move_to_chan_folder(src, regex, timelapse=False, metadata_type=''):
|
|
733
800
|
shutil.move(os.path.join(src, filename), move)
|
734
801
|
return
|
735
802
|
|
736
|
-
def
|
803
|
+
def _merge_channels_v2(src, plot=False):
|
737
804
|
from .plot import plot_arrays
|
738
805
|
"""
|
739
806
|
Merge the channels in the given source directory and save the merged files in a 'stack' directory.
|
@@ -761,7 +828,8 @@ def _merge_channels(src, plot=False):
|
|
761
828
|
print(f'generated folder with merged arrays: {stack_dir}')
|
762
829
|
|
763
830
|
if _is_dir_empty(stack_dir):
|
764
|
-
with Pool(cpu_count()) as pool:
|
831
|
+
with Pool(max(cpu_count() // 2, 1)) as pool:
|
832
|
+
#with Pool(cpu_count()) as pool:
|
765
833
|
merge_func = partial(_merge_file, chan_dirs, stack_dir)
|
766
834
|
pool.map(merge_func, dir_files)
|
767
835
|
|
@@ -773,6 +841,47 @@ def _merge_channels(src, plot=False):
|
|
773
841
|
|
774
842
|
return
|
775
843
|
|
844
|
+
def _merge_channels(src, plot=False):
|
845
|
+
"""
|
846
|
+
Merge the channels in the given source directory and save the merged files in a 'stack' directory without using multiprocessing.
|
847
|
+
"""
|
848
|
+
|
849
|
+
from .plot import plot_arrays
|
850
|
+
|
851
|
+
stack_dir = os.path.join(src, 'stack')
|
852
|
+
allowed_names = ['01', '02', '03', '04', '00', '1', '2', '3', '4', '0']
|
853
|
+
|
854
|
+
# List directories that match the allowed names
|
855
|
+
chan_dirs = [d for d in os.listdir(src) if os.path.isdir(os.path.join(src, d)) and d in allowed_names]
|
856
|
+
chan_dirs.sort()
|
857
|
+
|
858
|
+
print(f'List of folders in src: {chan_dirs}. Single channel folders.')
|
859
|
+
start_time = time.time()
|
860
|
+
|
861
|
+
# Assuming chan_dirs[0] is not empty and exists, adjust according to your logic
|
862
|
+
first_dir_path = os.path.join(src, chan_dirs[0])
|
863
|
+
dir_files = os.listdir(first_dir_path)
|
864
|
+
|
865
|
+
# Create the 'stack' directory if it doesn't exist
|
866
|
+
if not os.path.exists(stack_dir):
|
867
|
+
os.makedirs(stack_dir, exist_ok=True)
|
868
|
+
print(f'Generated folder with merged arrays: {stack_dir}')
|
869
|
+
|
870
|
+
if _is_dir_empty(stack_dir):
|
871
|
+
for file_name in dir_files:
|
872
|
+
full_file_path = os.path.join(first_dir_path, file_name)
|
873
|
+
if os.path.isfile(full_file_path):
|
874
|
+
_merge_file([os.path.join(src, d) for d in chan_dirs], stack_dir, file_name)
|
875
|
+
|
876
|
+
elapsed_time = time.time() - start_time
|
877
|
+
avg_time = elapsed_time / len(dir_files) if dir_files else 0
|
878
|
+
print(f'Average Time: {avg_time:.3f} sec, Total Elapsed Time: {elapsed_time:.3f} sec')
|
879
|
+
|
880
|
+
if plot:
|
881
|
+
plot_arrays(os.path.join(src, 'stack'))
|
882
|
+
|
883
|
+
return
|
884
|
+
|
776
885
|
def _mip_all(src, include_first_chan=True):
|
777
886
|
|
778
887
|
"""
|
@@ -1206,7 +1315,7 @@ def preprocess_img_data(settings):
|
|
1206
1315
|
print('Found existing channel_stack folder.')
|
1207
1316
|
if os.path.exists(src+'/norm_channel_stack'):
|
1208
1317
|
print('Found existing norm_channel_stack folder. Skipping preprocessing')
|
1209
|
-
return
|
1318
|
+
return settings, src
|
1210
1319
|
|
1211
1320
|
cmap = 'inferno'
|
1212
1321
|
figuresize = 20
|
@@ -1214,8 +1323,10 @@ def preprocess_img_data(settings):
|
|
1214
1323
|
save_dtype = 'uint16'
|
1215
1324
|
correct_illumination = False
|
1216
1325
|
|
1217
|
-
mask_channels = [settings['nucleus_channel'], settings['pathogen_channel'], settings['cell_channel']]
|
1218
|
-
backgrounds = [settings['nucleus_background'], settings['pathogen_background'], settings['cell_background']]
|
1326
|
+
#mask_channels = [settings['nucleus_channel'], settings['pathogen_channel'], settings['cell_channel']]
|
1327
|
+
#backgrounds = [settings['nucleus_background'], settings['pathogen_background'], settings['cell_background']]
|
1328
|
+
mask_channels = [settings['nucleus_channel'], settings['cell_channel'], settings['pathogen_channel']]
|
1329
|
+
backgrounds = [settings['nucleus_background'], settings['cell_background'], settings['pathogen_background']]
|
1219
1330
|
|
1220
1331
|
metadata_type = settings['metadata_type']
|
1221
1332
|
custom_regex = settings['custom_regex']
|
@@ -1230,7 +1341,6 @@ def preprocess_img_data(settings):
|
|
1230
1341
|
pick_slice = settings['pick_slice']
|
1231
1342
|
skip_mode = settings['skip_mode']
|
1232
1343
|
|
1233
|
-
|
1234
1344
|
if not img_format == None:
|
1235
1345
|
if metadata_type == 'cellvoyager':
|
1236
1346
|
regex = f'(?P<plateID>.*)_(?P<wellID>.*)_T(?P<timeID>.*)F(?P<fieldID>.*)L(?P<laserID>..)A(?P<AID>..)Z(?P<sliceID>.*)C(?P<chanID>.*){img_format}'
|
@@ -1248,6 +1358,8 @@ def preprocess_img_data(settings):
|
|
1248
1358
|
print(f'regex mode:{metadata_type} regex:{regex}')
|
1249
1359
|
|
1250
1360
|
if settings.get('test_mode', False):
|
1361
|
+
print(f'Running spacr in test mode')
|
1362
|
+
settings['plot'] = True
|
1251
1363
|
try:
|
1252
1364
|
os.rmdir(os.path.join(src, 'test'))
|
1253
1365
|
print(f"Deleted test directory: {os.path.join(src, 'test')}")
|
@@ -1256,6 +1368,10 @@ def preprocess_img_data(settings):
|
|
1256
1368
|
|
1257
1369
|
src = _run_test_mode(settings['src'], regex, timelapse=timelapse)
|
1258
1370
|
settings['src'] = src
|
1371
|
+
|
1372
|
+
if img_format == None:
|
1373
|
+
if not os.path.exists(src+'/stack'):
|
1374
|
+
_merge_channels(src, plot=False)
|
1259
1375
|
|
1260
1376
|
if not os.path.exists(src+'/stack'):
|
1261
1377
|
try:
|
@@ -2273,6 +2389,8 @@ def convert_numpy_to_tiff(folder_path, limit=None):
|
|
2273
2389
|
for i, filename in enumerate(files):
|
2274
2390
|
if limit is not None and i >= limit:
|
2275
2391
|
break
|
2392
|
+
if not filename.endswith('.npy'):
|
2393
|
+
continue
|
2276
2394
|
|
2277
2395
|
# Construct the full file path
|
2278
2396
|
file_path = os.path.join(folder_path, filename)
|
@@ -2289,7 +2407,47 @@ def convert_numpy_to_tiff(folder_path, limit=None):
|
|
2289
2407
|
print(f"Converted {filename} to {tiff_filename} and saved in 'tiff' subdirectory.")
|
2290
2408
|
return
|
2291
2409
|
|
2292
|
-
|
2410
|
+
def generate_cellpose_train_test(src, test_split=0.1):
|
2411
|
+
|
2412
|
+
mask_src = os.path.join(src, 'masks')
|
2413
|
+
img_paths = glob.glob(os.path.join(src, '*.tif'))
|
2414
|
+
img_filenames = [os.path.basename(file) for file in img_paths + img_paths]
|
2415
|
+
img_filenames = [file for file in img_filenames if os.path.exists(os.path.join(mask_src, file))]
|
2416
|
+
print(f'Found {len(img_filenames)} images with masks')
|
2417
|
+
|
2418
|
+
random.shuffle(img_filenames)
|
2419
|
+
split_index = int(len(img_filenames) * test_split)
|
2420
|
+
train_files = img_filenames[split_index:]
|
2421
|
+
test_files = img_filenames[:split_index]
|
2422
|
+
list_of_lists = [test_files, train_files]
|
2423
|
+
print(f'Split dataset into Train {len(train_files)} and Test {len(test_files)} files')
|
2424
|
+
|
2425
|
+
train_dir = os.path.join(os.path.dirname(src), 'train')
|
2426
|
+
train_dir_masks = os.path.join(train_dir, 'mask')
|
2427
|
+
test_dir = os.path.join(os.path.dirname(src), 'test')
|
2428
|
+
test_dir_masks = os.path.join(test_dir, 'mask')
|
2429
|
+
|
2430
|
+
os.makedirs(train_dir_masks, exist_ok=True)
|
2431
|
+
os.makedirs(test_dir_masks, exist_ok=True)
|
2432
|
+
for i, ls in enumerate(list_of_lists):
|
2433
|
+
|
2434
|
+
if i == 0:
|
2435
|
+
dst = test_dir
|
2436
|
+
dst_mask = test_dir_masks
|
2437
|
+
_type = 'Test'
|
2438
|
+
if i == 1:
|
2439
|
+
dst = train_dir
|
2440
|
+
dst_mask = train_dir_masks
|
2441
|
+
_type = 'Train'
|
2442
|
+
|
2443
|
+
for idx, filename in enumerate(ls):
|
2444
|
+
img_path = os.path.join(src, filename)
|
2445
|
+
mask_path = os.path.join(mask_src, filename)
|
2446
|
+
new_img_path = os.path.join(dst, filename)
|
2447
|
+
new_mask_path = os.path.join(dst_mask, filename)
|
2448
|
+
shutil.copy(img_path, new_img_path)
|
2449
|
+
shutil.copy(mask_path, new_mask_path)
|
2450
|
+
print(f'Copied {idx+1}/{len(ls)} images to {_type} set', end='\r', flush=True)
|
2293
2451
|
|
2294
2452
|
|
2295
2453
|
|