spacr 0.2.3__py3-none-any.whl → 0.2.31__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/app_annotate.py +3 -4
- spacr/core.py +58 -229
- spacr/gui_core.py +26 -20
- spacr/gui_elements.py +93 -11
- spacr/gui_utils.py +32 -0
- spacr/io.py +121 -37
- spacr/measure.py +6 -8
- spacr/settings.py +1 -4
- spacr/utils.py +55 -0
- {spacr-0.2.3.dist-info → spacr-0.2.31.dist-info}/METADATA +1 -1
- {spacr-0.2.3.dist-info → spacr-0.2.31.dist-info}/RECORD +15 -15
- {spacr-0.2.3.dist-info → spacr-0.2.31.dist-info}/LICENSE +0 -0
- {spacr-0.2.3.dist-info → spacr-0.2.31.dist-info}/WHEEL +0 -0
- {spacr-0.2.3.dist-info → spacr-0.2.31.dist-info}/entry_points.txt +0 -0
- {spacr-0.2.3.dist-info → spacr-0.2.31.dist-info}/top_level.txt +0 -0
spacr/app_annotate.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
import tkinter as tk
|
2
2
|
from tkinter import ttk
|
3
3
|
from .gui import MainApp
|
4
|
-
from .gui_elements import set_dark_style
|
4
|
+
from .gui_elements import set_dark_style, spacrButton
|
5
5
|
|
6
6
|
def initiate_annotation_app(parent_frame):
|
7
7
|
from .gui_utils import generate_annotate_fields, annotate_app
|
@@ -20,8 +20,6 @@ def initiate_annotation_app(parent_frame):
|
|
20
20
|
settings['img_size'] = list(map(int, settings['img_size'].split(','))) # Convert string to list of integers
|
21
21
|
settings['percentiles'] = list(map(int, settings['percentiles'].split(','))) # Convert string to list of integers
|
22
22
|
settings['normalize'] = settings['normalize'].lower() == 'true'
|
23
|
-
settings['rows'] = int(settings['rows'])
|
24
|
-
settings['columns'] = int(settings['columns'])
|
25
23
|
|
26
24
|
try:
|
27
25
|
settings['measurement'] = settings['measurement'].split(',') if settings['measurement'] else None
|
@@ -40,9 +38,10 @@ def initiate_annotation_app(parent_frame):
|
|
40
38
|
settings[key] = None
|
41
39
|
|
42
40
|
settings_window.destroy()
|
41
|
+
|
43
42
|
annotate_app(parent_frame, settings)
|
44
43
|
|
45
|
-
start_button =
|
44
|
+
start_button = spacrButton(settings_window, text="annotate", command=start_annotation_app, show_text=False)
|
46
45
|
start_button.pack(pady=10)
|
47
46
|
|
48
47
|
def start_annotate_app():
|
spacr/core.py
CHANGED
@@ -974,7 +974,7 @@ def generate_dataset(src, file_metadata=None, experiment='TSG101_screen', sample
|
|
974
974
|
def apply_model_to_tar(tar_path, model_path, file_type='cell_png', image_size=224, batch_size=64, normalize=True, preload='images', n_jobs=10, threshold=0.5, verbose=False):
|
975
975
|
|
976
976
|
from .io import TarImageDataset
|
977
|
-
from .utils import process_vision_results
|
977
|
+
from .utils import process_vision_results, print_progress
|
978
978
|
|
979
979
|
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
|
980
980
|
if normalize:
|
@@ -1015,15 +1015,26 @@ def apply_model_to_tar(tar_path, model_path, file_type='cell_png', image_size=22
|
|
1015
1015
|
|
1016
1016
|
prediction_pos_probs = []
|
1017
1017
|
filenames_list = []
|
1018
|
+
time_ls = []
|
1018
1019
|
gc.collect()
|
1019
1020
|
with torch.no_grad():
|
1020
1021
|
for batch_idx, (batch_images, filenames) in enumerate(data_loader, start=1):
|
1022
|
+
start = time.time()
|
1021
1023
|
images = batch_images.to(torch.float).to(device)
|
1022
1024
|
outputs = model(images)
|
1023
1025
|
batch_prediction_pos_prob = torch.sigmoid(outputs).cpu().numpy()
|
1024
1026
|
prediction_pos_probs.extend(batch_prediction_pos_prob.tolist())
|
1025
1027
|
filenames_list.extend(filenames)
|
1026
|
-
|
1028
|
+
stop = time.time()
|
1029
|
+
duration = stop - start
|
1030
|
+
time_ls.append(duration)
|
1031
|
+
files_processed = batch_idx*batch_size
|
1032
|
+
files_to_process = len(data_loader)
|
1033
|
+
print_progress(files_processed, files_to_process, n_jobs=n_jobs, time_ls=time_ls, batch_size=batch_size, operation_type="Tar dataset")
|
1034
|
+
|
1035
|
+
|
1036
|
+
|
1037
|
+
|
1027
1038
|
|
1028
1039
|
data = {'path':filenames_list, 'pred':prediction_pos_probs}
|
1029
1040
|
df = pd.DataFrame(data, index=None)
|
@@ -1037,6 +1048,7 @@ def apply_model_to_tar(tar_path, model_path, file_type='cell_png', image_size=22
|
|
1037
1048
|
def apply_model(src, model_path, image_size=224, batch_size=64, normalize=True, n_jobs=10):
|
1038
1049
|
|
1039
1050
|
from .io import NoClassDataset
|
1051
|
+
from .utils import print_progress
|
1040
1052
|
|
1041
1053
|
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
|
1042
1054
|
|
@@ -1065,14 +1077,22 @@ def apply_model(src, model_path, image_size=224, batch_size=64, normalize=True,
|
|
1065
1077
|
model = model.to(device)
|
1066
1078
|
prediction_pos_probs = []
|
1067
1079
|
filenames_list = []
|
1080
|
+
time_ls = []
|
1068
1081
|
with torch.no_grad():
|
1069
1082
|
for batch_idx, (batch_images, filenames) in enumerate(data_loader, start=1):
|
1083
|
+
start = time.time()
|
1070
1084
|
images = batch_images.to(torch.float).to(device)
|
1071
1085
|
outputs = model(images)
|
1072
1086
|
batch_prediction_pos_prob = torch.sigmoid(outputs).cpu().numpy()
|
1073
1087
|
prediction_pos_probs.extend(batch_prediction_pos_prob.tolist())
|
1074
1088
|
filenames_list.extend(filenames)
|
1075
|
-
|
1089
|
+
stop = time.time()
|
1090
|
+
duration = stop - start
|
1091
|
+
time_ls.append(duration)
|
1092
|
+
files_processed = batch_idx*batch_size
|
1093
|
+
files_to_process = len(data_loader)
|
1094
|
+
print_progress(files_processed, files_to_process, n_jobs=n_jobs, time_ls=time_ls, batch_size=batch_size, operation_type="Generating predictions")
|
1095
|
+
|
1076
1096
|
data = {'path':filenames_list, 'pred':prediction_pos_probs}
|
1077
1097
|
df = pd.DataFrame(data, index=None)
|
1078
1098
|
df.to_csv(result_loc, index=True, header=True, mode='w')
|
@@ -1164,12 +1184,14 @@ def training_dataset_from_annotation(db_path, dst, annotation_column='test', ann
|
|
1164
1184
|
return class_paths
|
1165
1185
|
|
1166
1186
|
def generate_dataset_from_lists(dst, class_data, classes, test_split=0.1):
|
1187
|
+
from .utils import print_progress
|
1167
1188
|
# Make sure that the length of class_data matches the length of classes
|
1168
1189
|
if len(class_data) != len(classes):
|
1169
1190
|
raise ValueError("class_data and classes must have the same length.")
|
1170
1191
|
|
1171
1192
|
total_files = sum(len(data) for data in class_data)
|
1172
1193
|
processed_files = 0
|
1194
|
+
time_ls = []
|
1173
1195
|
|
1174
1196
|
for cls, data in zip(classes, class_data):
|
1175
1197
|
# Create directories
|
@@ -1183,15 +1205,21 @@ def generate_dataset_from_lists(dst, class_data, classes, test_split=0.1):
|
|
1183
1205
|
|
1184
1206
|
# Copy train files
|
1185
1207
|
for path in train_data:
|
1208
|
+
start = time.time()
|
1186
1209
|
shutil.copy(path, os.path.join(train_class_dir, os.path.basename(path)))
|
1187
1210
|
processed_files += 1
|
1188
|
-
|
1211
|
+
duration = time.time() - start
|
1212
|
+
time_ls.append(duration)
|
1213
|
+
print_progress(processed_files, total_files, n_jobs=1, time_ls=None, batch_size=None, operation_type="Copying files for Train dataset")
|
1189
1214
|
|
1190
1215
|
# Copy test files
|
1191
1216
|
for path in test_data:
|
1217
|
+
start = time.time()
|
1192
1218
|
shutil.copy(path, os.path.join(test_class_dir, os.path.basename(path)))
|
1193
1219
|
processed_files += 1
|
1194
|
-
|
1220
|
+
duration = time.time() - start
|
1221
|
+
time_ls.append(duration)
|
1222
|
+
print_progress(processed_files, total_files, n_jobs=1, time_ls=None, batch_size=None, operation_type="Copying files for Test dataset")
|
1195
1223
|
|
1196
1224
|
# Print summary
|
1197
1225
|
for cls in classes:
|
@@ -1788,16 +1816,13 @@ def preprocess_generate_masks(src, settings={}):
|
|
1788
1816
|
def identify_masks_finetune(settings):
|
1789
1817
|
|
1790
1818
|
from .plot import print_mask_and_flows
|
1791
|
-
from .utils import get_files_from_dir, resize_images_and_labels
|
1819
|
+
from .utils import get_files_from_dir, resize_images_and_labels, print_progress
|
1792
1820
|
from .io import _load_normalized_images_and_labels, _load_images_and_labels
|
1793
1821
|
from .settings import get_identify_masks_finetune_default_settings
|
1794
1822
|
|
1795
1823
|
settings = get_identify_masks_finetune_default_settings(settings)
|
1796
|
-
|
1797
|
-
#User defined settings
|
1798
1824
|
src=settings['src']
|
1799
1825
|
dst=settings['dst']
|
1800
|
-
|
1801
1826
|
model_name=settings['model_name']
|
1802
1827
|
custom_model=settings['custom_model']
|
1803
1828
|
channels = settings['channels']
|
@@ -1903,8 +1928,12 @@ def identify_masks_finetune(settings):
|
|
1903
1928
|
stop = time.time()
|
1904
1929
|
duration = (stop - start)
|
1905
1930
|
time_ls.append(duration)
|
1906
|
-
|
1907
|
-
|
1931
|
+
files_processed = len(images)
|
1932
|
+
files_to_process = file_index+1
|
1933
|
+
print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls)
|
1934
|
+
print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls, batch_size=None, operation_type="")
|
1935
|
+
|
1936
|
+
|
1908
1937
|
if verbose:
|
1909
1938
|
if resize:
|
1910
1939
|
stack = resizescikit(stack, dims, preserve_range=True, anti_aliasing=False).astype(stack.dtype)
|
@@ -1917,212 +1946,6 @@ def identify_masks_finetune(settings):
|
|
1917
1946
|
gc.collect()
|
1918
1947
|
return
|
1919
1948
|
|
1920
|
-
def identify_masks(src, object_type, model_name, batch_size, channels, diameter, minimum_size, maximum_size, filter_intensity, flow_threshold=30, cellprob_threshold=1, figuresize=25, cmap='inferno', refine_masks=True, filter_size=True, filter_dimm=True, remove_border_objects=False, verbose=False, plot=False, merge=False, save=True, start_at=0, file_type='.npz', net_avg=True, resample=True, timelapse=False, timelapse_displacement=None, timelapse_frame_limits=None, timelapse_memory=3, timelapse_remove_transient=False, timelapse_mode='btrack', timelapse_objects='cell'):
|
1921
|
-
"""
|
1922
|
-
Identify masks from the source images.
|
1923
|
-
|
1924
|
-
Args:
|
1925
|
-
src (str): Path to the source images.
|
1926
|
-
object_type (str): Type of object to identify.
|
1927
|
-
model_name (str): Name of the model to use for identification.
|
1928
|
-
batch_size (int): Number of images to process in each batch.
|
1929
|
-
channels (list): List of channel names.
|
1930
|
-
diameter (float): Diameter of the objects to identify.
|
1931
|
-
minimum_size (int): Minimum size of objects to keep.
|
1932
|
-
maximum_size (int): Maximum size of objects to keep.
|
1933
|
-
flow_threshold (int, optional): Threshold for flow detection. Defaults to 30.
|
1934
|
-
cellprob_threshold (int, optional): Threshold for cell probability. Defaults to 1.
|
1935
|
-
figuresize (int, optional): Size of the figure. Defaults to 25.
|
1936
|
-
cmap (str, optional): Colormap for plotting. Defaults to 'inferno'.
|
1937
|
-
refine_masks (bool, optional): Flag indicating whether to refine masks. Defaults to True.
|
1938
|
-
filter_size (bool, optional): Flag indicating whether to filter based on size. Defaults to True.
|
1939
|
-
filter_dimm (bool, optional): Flag indicating whether to filter based on intensity. Defaults to True.
|
1940
|
-
remove_border_objects (bool, optional): Flag indicating whether to remove border objects. Defaults to False.
|
1941
|
-
verbose (bool, optional): Flag indicating whether to display verbose output. Defaults to False.
|
1942
|
-
plot (bool, optional): Flag indicating whether to plot the masks. Defaults to False.
|
1943
|
-
merge (bool, optional): Flag indicating whether to merge adjacent objects. Defaults to False.
|
1944
|
-
save (bool, optional): Flag indicating whether to save the masks. Defaults to True.
|
1945
|
-
start_at (int, optional): Index to start processing from. Defaults to 0.
|
1946
|
-
file_type (str, optional): File type for saving the masks. Defaults to '.npz'.
|
1947
|
-
net_avg (bool, optional): Flag indicating whether to use network averaging. Defaults to True.
|
1948
|
-
resample (bool, optional): Flag indicating whether to resample the images. Defaults to True.
|
1949
|
-
timelapse (bool, optional): Flag indicating whether to generate a timelapse. Defaults to False.
|
1950
|
-
timelapse_displacement (float, optional): Displacement threshold for timelapse. Defaults to None.
|
1951
|
-
timelapse_frame_limits (tuple, optional): Frame limits for timelapse. Defaults to None.
|
1952
|
-
timelapse_memory (int, optional): Memory for timelapse. Defaults to 3.
|
1953
|
-
timelapse_remove_transient (bool, optional): Flag indicating whether to remove transient objects in timelapse. Defaults to False.
|
1954
|
-
timelapse_mode (str, optional): Mode for timelapse. Defaults to 'btrack'.
|
1955
|
-
timelapse_objects (str, optional): Objects to track in timelapse. Defaults to 'cell'.
|
1956
|
-
|
1957
|
-
Returns:
|
1958
|
-
None
|
1959
|
-
"""
|
1960
|
-
|
1961
|
-
from .utils import _masks_to_masks_stack, _filter_cp_masks, _get_cellpose_batch_size
|
1962
|
-
from .io import _create_database, _save_object_counts_to_database, _check_masks, _get_avg_object_size
|
1963
|
-
from .timelapse import _npz_to_movie, _btrack_track_cells, _trackpy_track_cells
|
1964
|
-
from .plot import plot_masks
|
1965
|
-
|
1966
|
-
#Note add logic that handles batches of size 1 as these will break the code batches must all be > 2 images
|
1967
|
-
gc.collect()
|
1968
|
-
|
1969
|
-
if not torch.cuda.is_available():
|
1970
|
-
print(f'Torch CUDA is not available, using CPU')
|
1971
|
-
|
1972
|
-
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
|
1973
|
-
model = cp_models.Cellpose(gpu=True, model_type=model_name, device=device)
|
1974
|
-
|
1975
|
-
if file_type == '.npz':
|
1976
|
-
paths = [os.path.join(src, file) for file in os.listdir(src) if file.endswith('.npz')]
|
1977
|
-
else:
|
1978
|
-
paths = [os.path.join(src, file) for file in os.listdir(src) if file.endswith('.png')]
|
1979
|
-
if timelapse:
|
1980
|
-
print(f'timelaps is only compatible with npz files')
|
1981
|
-
return
|
1982
|
-
|
1983
|
-
chans = [2, 1] if model_name == 'cyto2' else [0,0] if model_name == 'nucleus' else [2,0] if model_name == 'cyto' else [2, 0]
|
1984
|
-
|
1985
|
-
if verbose == True:
|
1986
|
-
print(f'source: {src}')
|
1987
|
-
print()
|
1988
|
-
print(f'Settings: object_type: {object_type}, minimum_size: {minimum_size}, maximum_size:{maximum_size}, figuresize:{figuresize}, cmap:{cmap}, , net_avg:{net_avg}, resample:{resample}')
|
1989
|
-
print()
|
1990
|
-
print(f'Cellpose settings: Model: {model_name}, batch_size: {batch_size}, channels: {channels}, cellpose_chans: {chans}, diameter:{diameter}, flow_threshold:{flow_threshold}, cellprob_threshold:{cellprob_threshold}')
|
1991
|
-
print()
|
1992
|
-
print(f'Bool Settings: verbose:{verbose}, plot:{plot}, merge:{merge}, save:{save}, start_at:{start_at}, file_type:{file_type}, timelapse:{timelapse}')
|
1993
|
-
print()
|
1994
|
-
|
1995
|
-
count_loc = os.path.dirname(src)+'/measurements/measurements.db'
|
1996
|
-
os.makedirs(os.path.dirname(src)+'/measurements', exist_ok=True)
|
1997
|
-
_create_database(count_loc)
|
1998
|
-
|
1999
|
-
average_sizes = []
|
2000
|
-
time_ls = []
|
2001
|
-
for file_index, path in enumerate(paths):
|
2002
|
-
|
2003
|
-
name = os.path.basename(path)
|
2004
|
-
name, ext = os.path.splitext(name)
|
2005
|
-
if file_type == '.npz':
|
2006
|
-
if start_at:
|
2007
|
-
print(f'starting at file index:{start_at}')
|
2008
|
-
if file_index < start_at:
|
2009
|
-
continue
|
2010
|
-
output_folder = os.path.join(os.path.dirname(path), object_type+'_mask_stack')
|
2011
|
-
os.makedirs(output_folder, exist_ok=True)
|
2012
|
-
overall_average_size = 0
|
2013
|
-
with np.load(path) as data:
|
2014
|
-
stack = data['data']
|
2015
|
-
filenames = data['filenames']
|
2016
|
-
if timelapse:
|
2017
|
-
if len(stack) != batch_size:
|
2018
|
-
print(f'Changed batch_size:{batch_size} to {len(stack)}, data length:{len(stack)}')
|
2019
|
-
batch_size = len(stack)
|
2020
|
-
if isinstance(timelapse_frame_limits, list):
|
2021
|
-
if len(timelapse_frame_limits) >= 2:
|
2022
|
-
stack = stack[timelapse_frame_limits[0]: timelapse_frame_limits[1], :, :, :].astype(stack.dtype)
|
2023
|
-
filenames = filenames[timelapse_frame_limits[0]: timelapse_frame_limits[1]]
|
2024
|
-
batch_size = len(stack)
|
2025
|
-
print(f'Cut batch an indecies: {timelapse_frame_limits}, New batch_size: {batch_size} ')
|
2026
|
-
|
2027
|
-
for i in range(0, stack.shape[0], batch_size):
|
2028
|
-
mask_stack = []
|
2029
|
-
start = time.time()
|
2030
|
-
|
2031
|
-
if stack.shape[3] == 1:
|
2032
|
-
batch = stack[i: i+batch_size, :, :, [0,0]].astype(stack.dtype)
|
2033
|
-
else:
|
2034
|
-
batch = stack[i: i+batch_size, :, :, channels].astype(stack.dtype)
|
2035
|
-
|
2036
|
-
batch_filenames = filenames[i: i+batch_size].tolist()
|
2037
|
-
|
2038
|
-
if not plot:
|
2039
|
-
batch, batch_filenames = _check_masks(batch, batch_filenames, output_folder)
|
2040
|
-
if batch.size == 0:
|
2041
|
-
print(f'Processing: {file_index}/{len(paths)}: Images/N100pz {batch.shape[0]}')
|
2042
|
-
#print(f'Processing {file_index}/{len(paths)}: Images/N100pz {batch.shape[0]}', end='\r', flush=True)
|
2043
|
-
continue
|
2044
|
-
if batch.max() > 1:
|
2045
|
-
batch = batch / batch.max()
|
2046
|
-
|
2047
|
-
if timelapse:
|
2048
|
-
stitch_threshold=100.0
|
2049
|
-
movie_path = os.path.join(os.path.dirname(src), 'movies')
|
2050
|
-
os.makedirs(movie_path, exist_ok=True)
|
2051
|
-
save_path = os.path.join(movie_path, f'timelapse_{object_type}_{name}.mp4')
|
2052
|
-
_npz_to_movie(batch, batch_filenames, save_path, fps=2)
|
2053
|
-
else:
|
2054
|
-
stitch_threshold=0.0
|
2055
|
-
|
2056
|
-
cellpose_batch_size = _get_cellpose_batch_size()
|
2057
|
-
|
2058
|
-
masks, flows, _, _ = model.eval(x=batch,
|
2059
|
-
batch_size=cellpose_batch_size,
|
2060
|
-
normalize=False,
|
2061
|
-
channels=chans,
|
2062
|
-
channel_axis=3,
|
2063
|
-
diameter=diameter,
|
2064
|
-
flow_threshold=flow_threshold,
|
2065
|
-
cellprob_threshold=cellprob_threshold,
|
2066
|
-
rescale=None,
|
2067
|
-
resample=resample,
|
2068
|
-
stitch_threshold=stitch_threshold,
|
2069
|
-
progress=None)
|
2070
|
-
|
2071
|
-
print('Masks shape',masks.shape)
|
2072
|
-
if timelapse:
|
2073
|
-
_save_object_counts_to_database(masks, object_type, batch_filenames, count_loc, added_string='_timelapse')
|
2074
|
-
if object_type in timelapse_objects:
|
2075
|
-
if timelapse_mode == 'btrack':
|
2076
|
-
if not timelapse_displacement is None:
|
2077
|
-
radius = timelapse_displacement
|
2078
|
-
else:
|
2079
|
-
radius = 100
|
2080
|
-
|
2081
|
-
n_jobs = os.cpu_count()-2
|
2082
|
-
if n_jobs < 1:
|
2083
|
-
n_jobs = 1
|
2084
|
-
|
2085
|
-
mask_stack = _btrack_track_cells(src, name, batch_filenames, object_type, plot, save, masks_3D=masks, mode=timelapse_mode, timelapse_remove_transient=timelapse_remove_transient, radius=radius, n_jobs=n_jobs)
|
2086
|
-
if timelapse_mode == 'trackpy':
|
2087
|
-
mask_stack = _trackpy_track_cells(src, name, batch_filenames, object_type, masks, timelapse_displacement, timelapse_memory, timelapse_remove_transient, plot, save, timelapse_mode)
|
2088
|
-
|
2089
|
-
else:
|
2090
|
-
mask_stack = _masks_to_masks_stack(masks)
|
2091
|
-
|
2092
|
-
else:
|
2093
|
-
_save_object_counts_to_database(masks, object_type, batch_filenames, count_loc, added_string='_before_filtration')
|
2094
|
-
mask_stack = _filter_cp_masks(masks, flows, filter_size, filter_intensity, minimum_size, maximum_size, remove_border_objects, merge, batch, plot, figuresize)
|
2095
|
-
_save_object_counts_to_database(mask_stack, object_type, batch_filenames, count_loc, added_string='_after_filtration')
|
2096
|
-
|
2097
|
-
if not np.any(mask_stack):
|
2098
|
-
average_obj_size = 0
|
2099
|
-
else:
|
2100
|
-
average_obj_size = _get_avg_object_size(mask_stack)
|
2101
|
-
|
2102
|
-
average_sizes.append(average_obj_size)
|
2103
|
-
overall_average_size = np.mean(average_sizes) if len(average_sizes) > 0 else 0
|
2104
|
-
|
2105
|
-
stop = time.time()
|
2106
|
-
duration = (stop - start)
|
2107
|
-
time_ls.append(duration)
|
2108
|
-
average_time = np.mean(time_ls) if len(time_ls) > 0 else 0
|
2109
|
-
time_in_min = average_time/60
|
2110
|
-
time_per_mask = average_time/batch_size
|
2111
|
-
print(f'Processing: {len(paths)} files with {batch_size} imgs: {(file_index+1)*(batch_size+1)}/{(len(paths))*(batch_size+1)}: Time/batch {time_in_min:.3f} min: Time/mask {time_per_mask:.3f}sec: {object_type} size: {overall_average_size:.3f} px2')
|
2112
|
-
#print(f'Processing {len(paths)} files with {batch_size} imgs: {(file_index+1)*(batch_size+1)}/{(len(paths))*(batch_size+1)}: Time/batch {time_in_min:.3f} min: Time/mask {time_per_mask:.3f}sec: {object_type} size: {overall_average_size:.3f} px2', end='\r', flush=True)
|
2113
|
-
if not timelapse:
|
2114
|
-
if plot:
|
2115
|
-
plot_masks(batch, mask_stack, flows, figuresize=figuresize, cmap=cmap, nr=batch_size, file_type='.npz')
|
2116
|
-
if save:
|
2117
|
-
if file_type == '.npz':
|
2118
|
-
for mask_index, mask in enumerate(mask_stack):
|
2119
|
-
output_filename = os.path.join(output_folder, batch_filenames[mask_index])
|
2120
|
-
np.save(output_filename, mask)
|
2121
|
-
mask_stack = []
|
2122
|
-
batch_filenames = []
|
2123
|
-
gc.collect()
|
2124
|
-
return
|
2125
|
-
|
2126
1949
|
def all_elements_match(list1, list2):
|
2127
1950
|
# Check if all elements in list1 are in list2
|
2128
1951
|
return all(element in list2 for element in list1)
|
@@ -2141,7 +1964,7 @@ def prepare_batch_for_cellpose(batch):
|
|
2141
1964
|
|
2142
1965
|
def generate_cellpose_masks(src, settings, object_type):
|
2143
1966
|
|
2144
|
-
from .utils import _masks_to_masks_stack, _filter_cp_masks, _get_cellpose_batch_size, _get_cellpose_channels, _choose_model, mask_object_count
|
1967
|
+
from .utils import _masks_to_masks_stack, _filter_cp_masks, _get_cellpose_batch_size, _get_cellpose_channels, _choose_model, mask_object_count, print_progress
|
2145
1968
|
from .io import _create_database, _save_object_counts_to_database, _check_masks, _get_avg_object_size
|
2146
1969
|
from .timelapse import _npz_to_movie, _btrack_track_cells, _trackpy_track_cells
|
2147
1970
|
from .plot import plot_masks
|
@@ -2233,7 +2056,8 @@ def generate_cellpose_masks(src, settings, object_type):
|
|
2233
2056
|
filenames = filenames[timelapse_frame_limits[0]: timelapse_frame_limits[1]]
|
2234
2057
|
batch_size = len(stack)
|
2235
2058
|
print(f'Cut batch at indecies: {timelapse_frame_limits}, New batch_size: {batch_size} ')
|
2236
|
-
|
2059
|
+
|
2060
|
+
files_processed = 0
|
2237
2061
|
for i in range(0, stack.shape[0], batch_size):
|
2238
2062
|
mask_stack = []
|
2239
2063
|
start = time.time()
|
@@ -2379,13 +2203,15 @@ def generate_cellpose_masks(src, settings, object_type):
|
|
2379
2203
|
average_sizes.append(average_obj_size)
|
2380
2204
|
overall_average_size = np.mean(average_sizes) if len(average_sizes) > 0 else 0
|
2381
2205
|
|
2382
|
-
|
2383
|
-
|
2384
|
-
|
2385
|
-
|
2386
|
-
|
2387
|
-
|
2388
|
-
|
2206
|
+
stop = time.time()
|
2207
|
+
duration = (stop - start)
|
2208
|
+
time_ls.append(duration)
|
2209
|
+
files_processed += len(batch_filenames)
|
2210
|
+
#files_processed = (file_index+1)*(batch_size+1)
|
2211
|
+
files_to_process = (len(paths))*(batch_size)
|
2212
|
+
print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls, batch_size=batch_size, operation_type=f'{object_type}_mask_gen')
|
2213
|
+
print(f'object_size:{object_type}): {overall_average_size:.3f} px2')
|
2214
|
+
|
2389
2215
|
if not timelapse:
|
2390
2216
|
if settings['plot']:
|
2391
2217
|
plot_masks(batch, mask_stack, flows, figuresize=figuresize, cmap='inferno', nr=batch_size)
|
@@ -2403,7 +2229,7 @@ def generate_cellpose_masks(src, settings, object_type):
|
|
2403
2229
|
def generate_masks_from_imgs(src, model, model_name, batch_size, diameter, cellprob_threshold, flow_threshold, grayscale, save, normalize, channels, percentiles, circular, invert, plot, resize, target_height, target_width, remove_background, background, Signal_to_noise, verbose):
|
2404
2230
|
|
2405
2231
|
from .io import _load_images_and_labels, _load_normalized_images_and_labels
|
2406
|
-
from .utils import resize_images_and_labels, resizescikit
|
2232
|
+
from .utils import resize_images_and_labels, resizescikit, print_progress
|
2407
2233
|
from .plot import print_mask_and_flows
|
2408
2234
|
|
2409
2235
|
dst = os.path.join(src, model_name)
|
@@ -2462,8 +2288,11 @@ def generate_masks_from_imgs(src, model, model_name, batch_size, diameter, cellp
|
|
2462
2288
|
stop = time.time()
|
2463
2289
|
duration = (stop - start)
|
2464
2290
|
time_ls.append(duration)
|
2465
|
-
|
2466
|
-
|
2291
|
+
files_processed = file_index+1
|
2292
|
+
files_to_process = len(images)
|
2293
|
+
|
2294
|
+
print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls, batch_size=None, operation_type="Generating masks")
|
2295
|
+
|
2467
2296
|
if plot:
|
2468
2297
|
if resize:
|
2469
2298
|
stack = resizescikit(stack, dims, preserve_range=True, anti_aliasing=False).astype(stack.dtype)
|
spacr/gui_core.py
CHANGED
@@ -491,7 +491,7 @@ def setup_button_section(horizontal_container, settings_type='mask', window_dime
|
|
491
491
|
widgets = [categories_label, button_scrollable_frame.scrollable_frame]
|
492
492
|
|
493
493
|
btn_col = 0
|
494
|
-
btn_row =
|
494
|
+
btn_row = 3
|
495
495
|
|
496
496
|
if run:
|
497
497
|
print(f'settings_type: {settings_type}')
|
@@ -518,6 +518,7 @@ def setup_button_section(horizontal_container, settings_type='mask', window_dime
|
|
518
518
|
widgets.append(import_button)
|
519
519
|
btn_row += 1
|
520
520
|
|
521
|
+
# Add the progress bar under the settings category menu
|
521
522
|
progress_bar = spacrProgressBar(button_scrollable_frame.scrollable_frame, orient='horizontal', mode='determinate')
|
522
523
|
progress_bar.grid(row=0, column=0, columnspan=2, pady=5, padx=5, sticky='ew')
|
523
524
|
widgets.append(progress_bar)
|
@@ -528,7 +529,7 @@ def setup_button_section(horizontal_container, settings_type='mask', window_dime
|
|
528
529
|
description_frame = tk.Frame(horizontal_container)
|
529
530
|
horizontal_container.add(description_frame, stretch="always", sticky="nsew")
|
530
531
|
description_frame.grid_columnconfigure(0, weight=1)
|
531
|
-
description_frame.grid_rowconfigure(0, weight=1)
|
532
|
+
description_frame.grid_rowconfigure(0, weight=1) # Add this line to make the row expandable
|
532
533
|
|
533
534
|
description_label = tk.Label(description_frame, text="Module Description", anchor='nw', justify='left', wraplength=width - 50)
|
534
535
|
description_label.grid(row=0, column=0, pady=50, padx=20, sticky='nsew')
|
@@ -609,7 +610,7 @@ def toggle_settings(button_scrollable_frame):
|
|
609
610
|
category_var = tk.StringVar()
|
610
611
|
non_empty_categories = [category for category, settings in categories.items() if any(setting in vars_dict for setting in settings)]
|
611
612
|
category_dropdown = spacrDropdownMenu(button_scrollable_frame.scrollable_frame, category_var, non_empty_categories, command=on_category_select)
|
612
|
-
category_dropdown.grid(row=
|
613
|
+
category_dropdown.grid(row=7, column=0, sticky="ew", pady=2, padx=2)
|
613
614
|
vars_dict = hide_all_settings(vars_dict, categories)
|
614
615
|
|
615
616
|
def process_fig_queue():
|
@@ -641,17 +642,8 @@ def process_fig_queue():
|
|
641
642
|
after_id = canvas_widget.after(100, process_fig_queue)
|
642
643
|
parent_frame.after_tasks.append(after_id)
|
643
644
|
|
644
|
-
def process_console_queue_v1():
|
645
|
-
global q, console_output, parent_frame
|
646
|
-
while not q.empty():
|
647
|
-
message = q.get_nowait()
|
648
|
-
console_output.insert(tk.END, message)
|
649
|
-
console_output.see(tk.END)
|
650
|
-
after_id = console_output.after(100, process_console_queue_v1)
|
651
|
-
parent_frame.after_tasks.append(after_id)
|
652
|
-
|
653
645
|
def process_console_queue():
|
654
|
-
global q, console_output, parent_frame, progress_bar
|
646
|
+
global q, console_output, parent_frame, progress_bar
|
655
647
|
|
656
648
|
# Initialize function attribute if it doesn't exist
|
657
649
|
if not hasattr(process_console_queue, "completed_tasks"):
|
@@ -676,7 +668,6 @@ def process_console_queue():
|
|
676
668
|
|
677
669
|
# Add the task to the completed set
|
678
670
|
process_console_queue.completed_tasks.append(current_progress)
|
679
|
-
#print('completed_tasks', process_console_queue.completed_tasks)
|
680
671
|
|
681
672
|
# Calculate the unique progress count
|
682
673
|
unique_progress_count = len(np.unique(process_console_queue.completed_tasks))
|
@@ -686,13 +677,29 @@ def process_console_queue():
|
|
686
677
|
progress_bar['maximum'] = total_progress
|
687
678
|
progress_bar['value'] = unique_progress_count
|
688
679
|
|
680
|
+
# Extract and update additional information
|
681
|
+
operation_match = re.search(r'operation_type: ([\w\s]+)', clean_message)
|
682
|
+
if operation_match:
|
683
|
+
progress_bar.operation_type = operation_match.group(1)
|
684
|
+
|
685
|
+
time_image_match = re.search(r'Time/image: ([\d.]+) sec', clean_message)
|
686
|
+
if time_image_match:
|
687
|
+
progress_bar.time_image = float(time_image_match.group(1))
|
688
|
+
|
689
|
+
time_batch_match = re.search(r'Time/batch: ([\d.]+) sec', clean_message)
|
690
|
+
if time_batch_match:
|
691
|
+
progress_bar.time_batch = float(time_batch_match.group(1))
|
692
|
+
|
693
|
+
time_left_match = re.search(r'Time_left: ([\d.]+) min', clean_message)
|
694
|
+
if time_left_match:
|
695
|
+
progress_bar.time_left = float(time_left_match.group(1))
|
696
|
+
|
689
697
|
# Update the progress label
|
690
|
-
if progress_label:
|
691
|
-
|
692
|
-
progress_label.config(text=progress_label_text)
|
698
|
+
if progress_bar.progress_label:
|
699
|
+
progress_bar.update_label()
|
693
700
|
|
694
701
|
# Clear completed tasks when progress is complete
|
695
|
-
if unique_progress_count
|
702
|
+
if unique_progress_count >= total_progress:
|
696
703
|
process_console_queue.completed_tasks.clear()
|
697
704
|
except Exception as e:
|
698
705
|
print(f"Error parsing progress message: {e}")
|
@@ -700,9 +707,8 @@ def process_console_queue():
|
|
700
707
|
after_id = console_output.after(100, process_console_queue)
|
701
708
|
parent_frame.after_tasks.append(after_id)
|
702
709
|
|
703
|
-
|
704
710
|
def set_globals(q_var, console_output_var, parent_frame_var, vars_dict_var, canvas_var, canvas_widget_var, scrollable_frame_var, fig_queue_var, progress_bar_var):
|
705
|
-
global q, console_output, parent_frame, vars_dict, canvas, canvas_widget, scrollable_frame,
|
711
|
+
global q, console_output, parent_frame, vars_dict, canvas, canvas_widget, scrollable_frame, fig_queue, progress_bar
|
706
712
|
q = q_var
|
707
713
|
console_output = console_output_var
|
708
714
|
parent_frame = parent_frame_var
|