spacr 0.2.41__tar.gz → 0.2.46__tar.gz
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-0.2.41/spacr.egg-info → spacr-0.2.46}/PKG-INFO +1 -1
- {spacr-0.2.41 → spacr-0.2.46}/setup.py +1 -1
- {spacr-0.2.41 → spacr-0.2.46}/spacr/core.py +46 -66
- {spacr-0.2.41 → spacr-0.2.46}/spacr/gui.py +20 -38
- {spacr-0.2.41 → spacr-0.2.46}/spacr/gui_core.py +327 -625
- {spacr-0.2.41 → spacr-0.2.46}/spacr/gui_elements.py +175 -24
- spacr-0.2.46/spacr/gui_utils.py +624 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/io.py +43 -46
- {spacr-0.2.41 → spacr-0.2.46}/spacr/plot.py +106 -0
- spacr-0.2.46/spacr/resources/icons/logo.pdf +2786 -6
- spacr-0.2.46/spacr/resources/icons/logo_spacr.png +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/settings.py +0 -2
- {spacr-0.2.41 → spacr-0.2.46}/spacr/utils.py +4 -24
- {spacr-0.2.41 → spacr-0.2.46/spacr.egg-info}/PKG-INFO +1 -1
- {spacr-0.2.41 → spacr-0.2.46}/spacr.egg-info/SOURCES.txt +2 -0
- spacr-0.2.41/spacr/gui_utils.py +0 -362
- {spacr-0.2.41 → spacr-0.2.46}/LICENSE +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/MANIFEST.in +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/README.rst +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/setup.cfg +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/__init__.py +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/__main__.py +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/app_annotate.py +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/app_classify.py +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/app_make_masks.py +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/app_mask.py +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/app_measure.py +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/app_sequencing.py +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/app_umap.py +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/chris.py +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/deep_spacr.py +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/graph_learning.py +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/logger.py +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/measure.py +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/resources/icons/abort.png +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/resources/icons/annotate.png +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/resources/icons/cellpose_all.png +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/resources/icons/cellpose_masks.png +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/resources/icons/classify.png +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/resources/icons/default.png +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/resources/icons/download.png +0 -0
- /spacr-0.2.41/spacr/resources/icons/logo_spacr.png → /spacr-0.2.46/spacr/resources/icons/logo_spacr_1.png +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/resources/icons/make_masks.png +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/resources/icons/map_barcodes.png +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/resources/icons/mask.png +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/resources/icons/measure.png +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/resources/icons/ml_analyze.png +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/resources/icons/recruitment.png +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/resources/icons/regression.png +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/resources/icons/run.png +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/resources/icons/sequencing.png +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/resources/icons/settings.png +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/resources/icons/spacr_logo_rotation.gif +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/resources/icons/train_cellpose.png +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/resources/icons/umap.png +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/resources/models/cp/toxo_plaque_cyto_e25000_X1120_Y1120.CP_model +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/resources/models/cp/toxo_plaque_cyto_e25000_X1120_Y1120.CP_model_settings.csv +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/resources/models/cp/toxo_pv_lumen.CP_model +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/sequencing.py +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/sim.py +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/sim_app.py +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/timelapse.py +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr/version.py +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr.egg-info/dependency_links.txt +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr.egg-info/entry_points.txt +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr.egg-info/requires.txt +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/spacr.egg-info/top_level.txt +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/tests/test_annotate_app.py +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/tests/test_core.py +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/tests/test_gui_classify_app.py +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/tests/test_gui_mask_app.py +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/tests/test_gui_measure_app.py +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/tests/test_gui_sim_app.py +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/tests/test_gui_utils.py +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/tests/test_io.py +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/tests/test_mask_app.py +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/tests/test_measure.py +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/tests/test_plot.py +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/tests/test_sim.py +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/tests/test_timelapse.py +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/tests/test_train.py +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/tests/test_umap.py +0 -0
- {spacr-0.2.41 → spacr-0.2.46}/tests/test_utils.py +0 -0
@@ -39,6 +39,10 @@ matplotlib.use('Agg')
|
|
39
39
|
|
40
40
|
from .logger import log_function_call
|
41
41
|
|
42
|
+
import warnings
|
43
|
+
warnings.filterwarnings("ignore", message="3D stack used, but stitch_threshold=0 and do_3D=False, so masks are made per plane only")
|
44
|
+
|
45
|
+
|
42
46
|
def analyze_plaques(folder):
|
43
47
|
summary_data = []
|
44
48
|
details_data = []
|
@@ -80,7 +84,6 @@ def analyze_plaques(folder):
|
|
80
84
|
|
81
85
|
print(f"Analysis completed and saved to database '{db_name}'.")
|
82
86
|
|
83
|
-
|
84
87
|
def train_cellpose(settings):
|
85
88
|
|
86
89
|
from .io import _load_normalized_images_and_labels, _load_images_and_labels
|
@@ -1032,10 +1035,6 @@ def apply_model_to_tar(tar_path, model_path, file_type='cell_png', image_size=22
|
|
1032
1035
|
files_to_process = len(data_loader)
|
1033
1036
|
print_progress(files_processed, files_to_process, n_jobs=n_jobs, time_ls=time_ls, batch_size=batch_size, operation_type="Tar dataset")
|
1034
1037
|
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
1038
|
-
|
1039
1038
|
data = {'path':filenames_list, 'pred':prediction_pos_probs}
|
1040
1039
|
df = pd.DataFrame(data, index=None)
|
1041
1040
|
df = process_vision_results(df, threshold)
|
@@ -1695,9 +1694,9 @@ def analyze_recruitment(src, metadata_settings={}, advanced_settings={}):
|
|
1695
1694
|
def preprocess_generate_masks(src, settings={}):
|
1696
1695
|
|
1697
1696
|
from .io import preprocess_img_data, _load_and_concatenate_arrays
|
1698
|
-
from .plot import
|
1699
|
-
from .utils import _pivot_counts_table, check_mask_folder, adjust_cell_masks
|
1700
|
-
from .settings import set_default_settings_preprocess_generate_masks
|
1697
|
+
from .plot import plot_image_mask_overlay, plot_arrays
|
1698
|
+
from .utils import _pivot_counts_table, check_mask_folder, adjust_cell_masks, print_progress
|
1699
|
+
from .settings import set_default_settings_preprocess_generate_masks
|
1701
1700
|
|
1702
1701
|
settings = set_default_settings_preprocess_generate_masks(src, settings)
|
1703
1702
|
settings_df = pd.DataFrame(list(settings.items()), columns=['Key', 'Value'])
|
@@ -1745,6 +1744,10 @@ def preprocess_generate_masks(src, settings={}):
|
|
1745
1744
|
if check_mask_folder(src, 'pathogen_mask_stack'):
|
1746
1745
|
generate_cellpose_masks(mask_src, settings, 'pathogen')
|
1747
1746
|
|
1747
|
+
#if settings['organelle'] != None:
|
1748
|
+
# if check_mask_folder(src, 'organelle_mask_stack'):
|
1749
|
+
# generate_cellpose_masks(mask_src, settings, 'organelle')
|
1750
|
+
|
1748
1751
|
if settings['adjust_cells']:
|
1749
1752
|
if settings['pathogen_channel'] != None and settings['cell_channel'] != None and settings['nucleus_channel'] != None:
|
1750
1753
|
|
@@ -1752,12 +1755,8 @@ def preprocess_generate_masks(src, settings={}):
|
|
1752
1755
|
cell_folder = os.path.join(mask_src, 'cell_mask_stack')
|
1753
1756
|
nuclei_folder = os.path.join(mask_src, 'nucleus_mask_stack')
|
1754
1757
|
parasite_folder = os.path.join(mask_src, 'pathogen_mask_stack')
|
1755
|
-
#
|
1758
|
+
#organelle_folder = os.path.join(mask_src, 'organelle_mask_stack')
|
1756
1759
|
|
1757
|
-
#process_masks(cell_folder, image_folder, settings['cell_channel'], settings['batch_size'], n_clusters=2, plot=settings['plot'])
|
1758
|
-
#process_masks(nuclei_folder, image_folder, settings['nucleus_channel'], settings['batch_size'], n_clusters=2, plot=settings['plot'])
|
1759
|
-
#process_masks(parasite_folder, image_folder, settings['pathogen_channel'], settings['batch_size'], n_clusters=2, plot=settings['plot'])
|
1760
|
-
|
1761
1760
|
adjust_cell_masks(parasite_folder, cell_folder, nuclei_folder, overlap_threshold=5, perimeter_threshold=30)
|
1762
1761
|
stop = time.time()
|
1763
1762
|
adjust_time = (stop-start)/60
|
@@ -1771,38 +1770,28 @@ def preprocess_generate_masks(src, settings={}):
|
|
1771
1770
|
|
1772
1771
|
if settings['plot']:
|
1773
1772
|
if not settings['timelapse']:
|
1774
|
-
plot_dims = len(settings['channels'])
|
1775
|
-
overlay_channels = [2,1,0]
|
1776
|
-
cell_mask_dim = nucleus_mask_dim = pathogen_mask_dim = None
|
1777
|
-
plot_counter = plot_dims
|
1778
|
-
|
1779
|
-
if settings['cell_channel'] is not None:
|
1780
|
-
cell_mask_dim = plot_counter
|
1781
|
-
plot_counter += 1
|
1782
|
-
|
1783
|
-
if settings['nucleus_channel'] is not None:
|
1784
|
-
nucleus_mask_dim = plot_counter
|
1785
|
-
plot_counter += 1
|
1786
|
-
|
1787
|
-
if settings['pathogen_channel'] is not None:
|
1788
|
-
pathogen_mask_dim = plot_counter
|
1789
|
-
|
1790
|
-
overlay_channels = [settings['nucleus_channel'], settings['pathogen_channel'], settings['cell_channel']]
|
1791
|
-
overlay_channels = [element for element in overlay_channels if element is not None]
|
1792
|
-
|
1793
|
-
plot_settings = set_default_plot_merge_settings()
|
1794
|
-
plot_settings['channel_dims'] = settings['channels']
|
1795
|
-
plot_settings['cell_mask_dim'] = cell_mask_dim
|
1796
|
-
plot_settings['nucleus_mask_dim'] = nucleus_mask_dim
|
1797
|
-
plot_settings['pathogen_mask_dim'] = pathogen_mask_dim
|
1798
|
-
plot_settings['overlay_chans'] = overlay_channels
|
1799
|
-
plot_settings['nr'] = settings['examples_to_plot']
|
1800
1773
|
|
1801
1774
|
if settings['test_mode'] == True:
|
1802
|
-
|
1775
|
+
settings['examples_to_plot'] = len(os.path.join(src,'merged'))
|
1803
1776
|
|
1804
1777
|
try:
|
1805
|
-
|
1778
|
+
merged_src = os.path.join(src,'merged')
|
1779
|
+
files = os.listdir(merged_src)
|
1780
|
+
random.shuffle(files)
|
1781
|
+
time_ls = []
|
1782
|
+
|
1783
|
+
for i, file in enumerate(files):
|
1784
|
+
start = time.time()
|
1785
|
+
if i+1 <= settings['examples_to_plot']:
|
1786
|
+
file_path = os.path.join(merged_src, file)
|
1787
|
+
plot_image_mask_overlay(file_path, settings['channels'], settings['cell_channel'], settings['nucleus_channel'], settings['pathogen_channel'], figuresize=10, normalize=True, thickness=3, save_pdf=True)
|
1788
|
+
stop = time.time()
|
1789
|
+
duration = stop-start
|
1790
|
+
time_ls.append(duration)
|
1791
|
+
files_processed = i+1
|
1792
|
+
files_to_process = settings['examples_to_plot']
|
1793
|
+
print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls, batch_size=None, operation_type="Plot mask outlines")
|
1794
|
+
print("Successfully completed run")
|
1806
1795
|
except Exception as e:
|
1807
1796
|
print(f'Failed to plot image mask overly. Error: {e}')
|
1808
1797
|
else:
|
@@ -2010,7 +1999,7 @@ def generate_cellpose_masks(src, settings, object_type):
|
|
2010
1999
|
|
2011
2000
|
if object_type == 'pathogen' and not settings['pathogen_model'] is None:
|
2012
2001
|
model_name = settings['pathogen_model']
|
2013
|
-
|
2002
|
+
|
2014
2003
|
model = _choose_model(model_name, device, object_type=object_type, restore_type=None, object_settings=object_settings)
|
2015
2004
|
|
2016
2005
|
chans = [2, 1] if model_name == 'cyto2' else [0,0] if model_name == 'nucleus' else [2,0] if model_name == 'cyto' else [2, 0] if model_name == 'cyto3' else [2, 0]
|
@@ -2022,16 +2011,19 @@ def generate_cellpose_masks(src, settings, object_type):
|
|
2022
2011
|
|
2023
2012
|
average_sizes = []
|
2024
2013
|
time_ls = []
|
2014
|
+
|
2015
|
+
files_to_process = len(paths)
|
2025
2016
|
for file_index, path in enumerate(paths):
|
2026
2017
|
name = os.path.basename(path)
|
2027
2018
|
name, ext = os.path.splitext(name)
|
2028
2019
|
output_folder = os.path.join(os.path.dirname(path), object_type+'_mask_stack')
|
2029
2020
|
os.makedirs(output_folder, exist_ok=True)
|
2030
2021
|
overall_average_size = 0
|
2022
|
+
|
2031
2023
|
with np.load(path) as data:
|
2032
2024
|
stack = data['data']
|
2033
2025
|
filenames = data['filenames']
|
2034
|
-
|
2026
|
+
|
2035
2027
|
for i, filename in enumerate(filenames):
|
2036
2028
|
output_path = os.path.join(output_folder, filename)
|
2037
2029
|
|
@@ -2057,11 +2049,9 @@ def generate_cellpose_masks(src, settings, object_type):
|
|
2057
2049
|
batch_size = len(stack)
|
2058
2050
|
print(f'Cut batch at indecies: {timelapse_frame_limits}, New batch_size: {batch_size} ')
|
2059
2051
|
|
2060
|
-
files_processed = 0
|
2061
2052
|
for i in range(0, stack.shape[0], batch_size):
|
2062
|
-
mask_stack = []
|
2063
2053
|
start = time.time()
|
2064
|
-
|
2054
|
+
mask_stack = []
|
2065
2055
|
if stack.shape[3] == 1:
|
2066
2056
|
batch = stack[i: i+batch_size, :, :, [0,0]].astype(stack.dtype)
|
2067
2057
|
else:
|
@@ -2072,7 +2062,6 @@ def generate_cellpose_masks(src, settings, object_type):
|
|
2072
2062
|
if not settings['plot']:
|
2073
2063
|
batch, batch_filenames = _check_masks(batch, batch_filenames, output_folder)
|
2074
2064
|
if batch.size == 0:
|
2075
|
-
print(f'Processing {file_index}/{len(paths)}: Images/npz {batch.shape[0]}')
|
2076
2065
|
continue
|
2077
2066
|
|
2078
2067
|
batch = prepare_batch_for_cellpose(batch)
|
@@ -2083,16 +2072,14 @@ def generate_cellpose_masks(src, settings, object_type):
|
|
2083
2072
|
save_path = os.path.join(movie_path, f'timelapse_{object_type}_{name}.mp4')
|
2084
2073
|
_npz_to_movie(batch, batch_filenames, save_path, fps=2)
|
2085
2074
|
|
2086
|
-
|
2087
|
-
|
2088
|
-
|
2089
|
-
|
2090
|
-
|
2091
|
-
|
2092
|
-
|
2093
|
-
|
2094
|
-
# 'norm3D':True} #compute normalization across entire z-stack rather than plane-by-plane in stitching mode.
|
2095
|
-
|
2075
|
+
stop = time.time()
|
2076
|
+
duration = (stop - start)
|
2077
|
+
time_ls.append(duration)
|
2078
|
+
files_processed = (file_index+1)*len(batch_filenames)
|
2079
|
+
files_processed = len(paths)*batch.shape[0]
|
2080
|
+
print('file_index', file_index, 'len(paths)', len(paths), 'batch.shape[0]', batch.shape[0])
|
2081
|
+
print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls, batch_size=batch.shape[0], operation_type=f'{object_type}_mask_gen')
|
2082
|
+
|
2096
2083
|
output = model.eval(x=batch,
|
2097
2084
|
batch_size=cellpose_batch_size,
|
2098
2085
|
normalize=False,
|
@@ -2202,16 +2189,8 @@ def generate_cellpose_masks(src, settings, object_type):
|
|
2202
2189
|
|
2203
2190
|
average_sizes.append(average_obj_size)
|
2204
2191
|
overall_average_size = np.mean(average_sizes) if len(average_sizes) > 0 else 0
|
2192
|
+
print(f'object_size:{object_type}: {overall_average_size:.3f} px2')
|
2205
2193
|
|
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
|
-
|
2215
2194
|
if not timelapse:
|
2216
2195
|
if settings['plot']:
|
2217
2196
|
plot_masks(batch, mask_stack, flows, figuresize=figuresize, cmap='inferno', nr=batch_size)
|
@@ -2222,6 +2201,7 @@ def generate_cellpose_masks(src, settings, object_type):
|
|
2222
2201
|
np.save(output_filename, mask)
|
2223
2202
|
mask_stack = []
|
2224
2203
|
batch_filenames = []
|
2204
|
+
|
2225
2205
|
gc.collect()
|
2226
2206
|
torch.cuda.empty_cache()
|
2227
2207
|
return
|
@@ -15,30 +15,29 @@ class MainApp(tk.Tk):
|
|
15
15
|
self.title("SpaCr GUI Collection")
|
16
16
|
self.configure(bg='#333333') # Set window background to dark gray
|
17
17
|
|
18
|
-
# Initialize style and apply dark style to the main window
|
19
18
|
style = ttk.Style()
|
20
19
|
self.color_settings = set_dark_style(style, parent_frame=self)
|
21
|
-
self.main_buttons = {}
|
22
|
-
self.additional_buttons = {}
|
20
|
+
self.main_buttons = {}
|
21
|
+
self.additional_buttons = {}
|
23
22
|
|
24
23
|
self.main_gui_apps = {
|
25
|
-
"Mask": (lambda frame: initiate_root(
|
26
|
-
"Measure": (lambda frame: initiate_root(
|
27
|
-
"Annotate": (lambda frame: initiate_root(
|
28
|
-
"Make Masks": (lambda frame: initiate_root(
|
29
|
-
"Classify": (lambda frame: initiate_root(
|
24
|
+
"Mask": (lambda frame: initiate_root(self, 'mask'), "Generate cellpose masks for cells, nuclei and pathogen images."),
|
25
|
+
"Measure": (lambda frame: initiate_root(self, 'measure'), "Measure single object intensity and morphological feature. Crop and save single object image"),
|
26
|
+
"Annotate": (lambda frame: initiate_root(self, 'annotate'), "Annotation single object images on a grid. Annotations are saved to database."),
|
27
|
+
"Make Masks": (lambda frame: initiate_root(self, 'make_masks'), "Adjust pre-existing Cellpose models to your specific dataset for improved performance"),
|
28
|
+
"Classify": (lambda frame: initiate_root(self, 'classify'), "Train Torch Convolutional Neural Networks (CNNs) or Transformers to classify single object images."),
|
30
29
|
}
|
31
30
|
|
32
31
|
self.additional_gui_apps = {
|
33
|
-
"Sequencing": (lambda frame: initiate_root(
|
34
|
-
"Umap": (lambda frame: initiate_root(
|
35
|
-
"Train Cellpose": (lambda frame: initiate_root(
|
36
|
-
"ML Analyze": (lambda frame: initiate_root(
|
37
|
-
"Cellpose Masks": (lambda frame: initiate_root(
|
38
|
-
"Cellpose All": (lambda frame: initiate_root(
|
39
|
-
"Map Barcodes": (lambda frame: initiate_root(
|
40
|
-
"Regression": (lambda frame: initiate_root(
|
41
|
-
"Recruitment": (lambda frame: initiate_root(
|
32
|
+
"Sequencing": (lambda frame: initiate_root(self, 'sequencing'), "Analyze sequencing data."),
|
33
|
+
"Umap": (lambda frame: initiate_root(self, 'umap'), "Generate UMAP embeddings with datapoints represented as images."),
|
34
|
+
"Train Cellpose": (lambda frame: initiate_root(self, 'train_cellpose'), "Train custom Cellpose models."),
|
35
|
+
"ML Analyze": (lambda frame: initiate_root(self, 'ml_analyze'), "Machine learning analysis of data."),
|
36
|
+
"Cellpose Masks": (lambda frame: initiate_root(self, 'cellpose_masks'), "Generate Cellpose masks."),
|
37
|
+
"Cellpose All": (lambda frame: initiate_root(self, 'cellpose_all'), "Run Cellpose on all images."),
|
38
|
+
"Map Barcodes": (lambda frame: initiate_root(self, 'map_barcodes'), "Map barcodes to data."),
|
39
|
+
"Regression": (lambda frame: initiate_root(self, 'regression'), "Perform regression analysis."),
|
40
|
+
"Recruitment": (lambda frame: initiate_root(self, 'recruitment'), "Analyze recruitment data.")
|
42
41
|
}
|
43
42
|
|
44
43
|
self.selected_app = tk.StringVar()
|
@@ -50,32 +49,25 @@ class MainApp(tk.Tk):
|
|
50
49
|
self.load_app(default_app, self.additional_gui_apps[default_app][0])
|
51
50
|
|
52
51
|
def create_widgets(self):
|
53
|
-
# Create the menu bar
|
54
52
|
create_menu_bar(self)
|
55
53
|
|
56
|
-
# Create a canvas to hold the selected app and other elements
|
57
54
|
self.canvas = tk.Canvas(self, highlightthickness=0)
|
58
55
|
self.canvas.grid(row=0, column=0, sticky="nsew")
|
59
56
|
self.grid_rowconfigure(0, weight=1)
|
60
57
|
self.grid_columnconfigure(0, weight=1)
|
61
58
|
|
62
|
-
# Create a frame inside the canvas to hold the main content
|
63
59
|
self.content_frame = tk.Frame(self.canvas)
|
64
60
|
self.content_frame.grid(row=0, column=0, sticky="nsew")
|
65
61
|
|
66
|
-
# Center the content frame within the canvas
|
67
62
|
self.canvas.create_window((self.winfo_screenwidth() // 2, self.winfo_screenheight() // 2), window=self.content_frame, anchor="center")
|
68
63
|
|
69
|
-
# Apply dark style to canvas and content_frame
|
70
64
|
set_dark_style(ttk.Style(), containers=[self.canvas, self.content_frame])
|
71
65
|
|
72
|
-
# Create startup screen with buttons for each main GUI app and drop-down for additional apps
|
73
66
|
self.create_startup_screen()
|
74
67
|
|
75
68
|
def create_startup_screen(self):
|
76
69
|
self.clear_frame(self.content_frame)
|
77
70
|
|
78
|
-
# Create frames for the grids
|
79
71
|
main_buttons_frame = tk.Frame(self.content_frame)
|
80
72
|
main_buttons_frame.pack(pady=10)
|
81
73
|
set_dark_style(ttk.Style(), containers=[main_buttons_frame])
|
@@ -84,41 +76,33 @@ class MainApp(tk.Tk):
|
|
84
76
|
additional_buttons_frame.pack(pady=10)
|
85
77
|
set_dark_style(ttk.Style(), containers=[additional_buttons_frame])
|
86
78
|
|
87
|
-
# Create a frame for the description below the icon grids
|
88
79
|
description_frame = tk.Frame(self.content_frame, height=70)
|
89
80
|
description_frame.pack(fill=tk.X, pady=10)
|
90
|
-
description_frame.pack_propagate(False)
|
81
|
+
description_frame.pack_propagate(False)
|
91
82
|
set_dark_style(ttk.Style(), containers=[description_frame])
|
92
83
|
|
93
|
-
# Use a Label widget to display descriptions
|
94
84
|
self.description_label = tk.Label(description_frame, text="", wraplength=800, justify="center", font=('Helvetica', 12), fg=self.color_settings['fg_color'], bg=self.color_settings['bg_color'])
|
95
85
|
self.description_label.pack(fill=tk.BOTH, pady=10)
|
96
86
|
|
97
|
-
# Load the logo image and place it in the main apps row
|
98
87
|
logo_button = spacrButton(main_buttons_frame, text="SpaCr", command=lambda: self.load_app("logo_spacr", initiate_root), icon_name="logo_spacr", size=100, show_text=False)
|
99
88
|
logo_button.grid(row=0, column=0, padx=5, pady=5)
|
100
89
|
self.main_buttons[logo_button] = "SpaCr provides a flexible toolset to extract single-cell images and measurements from high-content cell painting experiments, train deep-learning models to classify cellular/subcellular phenotypes, simulate, and analyze pooled CRISPR-Cas9 imaging screens.."
|
101
90
|
|
102
|
-
# Create icon buttons for the main apps
|
103
91
|
for i, (app_name, app_data) in enumerate(self.main_gui_apps.items()):
|
104
92
|
app_func, app_desc = app_data
|
105
93
|
button = spacrButton(main_buttons_frame, text=app_name, command=lambda app_name=app_name, app_func=app_func: self.load_app(app_name, app_func), icon_name=app_name.lower(), size=100, show_text=False)
|
106
94
|
button.grid(row=0, column=i + 1, padx=5, pady=5)
|
107
95
|
self.main_buttons[button] = app_desc
|
108
96
|
|
109
|
-
# Create icon buttons for the additional apps
|
110
97
|
for i, (app_name, app_data) in enumerate(self.additional_gui_apps.items()):
|
111
98
|
app_func, app_desc = app_data
|
112
99
|
button = spacrButton(additional_buttons_frame, text=app_name, command=lambda app_name=app_name, app_func=app_func: self.load_app(app_name, app_func), icon_name=app_name.lower(), size=75, show_text=False)
|
113
100
|
button.grid(row=0, column=i, padx=5, pady=5)
|
114
101
|
self.additional_buttons[button] = app_desc
|
115
102
|
|
116
|
-
# Update description initially
|
117
103
|
self.update_description()
|
118
|
-
#
|
119
104
|
|
120
105
|
def update_description(self):
|
121
|
-
# Check all buttons and update description if any has the active color
|
122
106
|
for button, desc in {**self.main_buttons, **self.additional_buttons}.items():
|
123
107
|
if button.canvas.itemcget(button.button_bg, "fill") == self.color_settings['active_color']:
|
124
108
|
self.show_description(desc)
|
@@ -128,18 +112,16 @@ class MainApp(tk.Tk):
|
|
128
112
|
def show_description(self, description):
|
129
113
|
if self.description_label.winfo_exists():
|
130
114
|
self.description_label.config(text=description)
|
131
|
-
self.description_label.update_idletasks()
|
115
|
+
self.description_label.update_idletasks()
|
132
116
|
|
133
117
|
def clear_description(self):
|
134
118
|
if self.description_label.winfo_exists():
|
135
119
|
self.description_label.config(text="")
|
136
|
-
self.description_label.update_idletasks()
|
120
|
+
self.description_label.update_idletasks()
|
137
121
|
|
138
122
|
def load_app(self, app_name, app_func):
|
139
|
-
# Clear the current content frame
|
140
123
|
self.clear_frame(self.canvas)
|
141
124
|
|
142
|
-
# Initialize the selected app
|
143
125
|
app_frame = tk.Frame(self.canvas)
|
144
126
|
app_frame.pack(fill=tk.BOTH, expand=True)
|
145
127
|
set_dark_style(ttk.Style(), containers=[app_frame])
|
@@ -155,4 +137,4 @@ def gui_app():
|
|
155
137
|
|
156
138
|
if __name__ == "__main__":
|
157
139
|
set_start_method('spawn', force=True)
|
158
|
-
gui_app()
|
140
|
+
gui_app()
|