spacr 0.2.45__tar.gz → 0.2.53__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.
Files changed (123) hide show
  1. {spacr-0.2.45/spacr.egg-info → spacr-0.2.53}/PKG-INFO +6 -4
  2. {spacr-0.2.45 → spacr-0.2.53}/setup.py +7 -5
  3. {spacr-0.2.45 → spacr-0.2.53}/spacr/core.py +27 -21
  4. {spacr-0.2.45 → spacr-0.2.53}/spacr/gui.py +0 -2
  5. {spacr-0.2.45 → spacr-0.2.53}/spacr/gui_core.py +113 -127
  6. {spacr-0.2.45 → spacr-0.2.53}/spacr/gui_elements.py +367 -152
  7. {spacr-0.2.45 → spacr-0.2.53}/spacr/gui_utils.py +71 -66
  8. {spacr-0.2.45 → spacr-0.2.53}/spacr/io.py +24 -19
  9. {spacr-0.2.45 → spacr-0.2.53}/spacr/measure.py +196 -145
  10. {spacr-0.2.45 → spacr-0.2.53}/spacr/plot.py +2 -42
  11. spacr-0.2.53/spacr/resources/font/open_sans/OFL.txt +93 -0
  12. spacr-0.2.53/spacr/resources/font/open_sans/OpenSans-Italic-VariableFont_wdth,wght.ttf +0 -0
  13. spacr-0.2.53/spacr/resources/font/open_sans/OpenSans-VariableFont_wdth,wght.ttf +0 -0
  14. spacr-0.2.53/spacr/resources/font/open_sans/README.txt +100 -0
  15. spacr-0.2.53/spacr/resources/font/open_sans/static/OpenSans-Bold.ttf +0 -0
  16. spacr-0.2.53/spacr/resources/font/open_sans/static/OpenSans-BoldItalic.ttf +0 -0
  17. spacr-0.2.53/spacr/resources/font/open_sans/static/OpenSans-ExtraBold.ttf +0 -0
  18. spacr-0.2.53/spacr/resources/font/open_sans/static/OpenSans-ExtraBoldItalic.ttf +0 -0
  19. spacr-0.2.53/spacr/resources/font/open_sans/static/OpenSans-Italic.ttf +0 -0
  20. spacr-0.2.53/spacr/resources/font/open_sans/static/OpenSans-Light.ttf +0 -0
  21. spacr-0.2.53/spacr/resources/font/open_sans/static/OpenSans-LightItalic.ttf +0 -0
  22. spacr-0.2.53/spacr/resources/font/open_sans/static/OpenSans-Medium.ttf +0 -0
  23. spacr-0.2.53/spacr/resources/font/open_sans/static/OpenSans-MediumItalic.ttf +0 -0
  24. spacr-0.2.53/spacr/resources/font/open_sans/static/OpenSans-Regular.ttf +0 -0
  25. spacr-0.2.53/spacr/resources/font/open_sans/static/OpenSans-SemiBold.ttf +0 -0
  26. spacr-0.2.53/spacr/resources/font/open_sans/static/OpenSans-SemiBoldItalic.ttf +0 -0
  27. spacr-0.2.53/spacr/resources/font/open_sans/static/OpenSans_Condensed-Bold.ttf +0 -0
  28. spacr-0.2.53/spacr/resources/font/open_sans/static/OpenSans_Condensed-BoldItalic.ttf +0 -0
  29. spacr-0.2.53/spacr/resources/font/open_sans/static/OpenSans_Condensed-ExtraBold.ttf +0 -0
  30. spacr-0.2.53/spacr/resources/font/open_sans/static/OpenSans_Condensed-ExtraBoldItalic.ttf +0 -0
  31. spacr-0.2.53/spacr/resources/font/open_sans/static/OpenSans_Condensed-Italic.ttf +0 -0
  32. spacr-0.2.53/spacr/resources/font/open_sans/static/OpenSans_Condensed-Light.ttf +0 -0
  33. spacr-0.2.53/spacr/resources/font/open_sans/static/OpenSans_Condensed-LightItalic.ttf +0 -0
  34. spacr-0.2.53/spacr/resources/font/open_sans/static/OpenSans_Condensed-Medium.ttf +0 -0
  35. spacr-0.2.53/spacr/resources/font/open_sans/static/OpenSans_Condensed-MediumItalic.ttf +0 -0
  36. spacr-0.2.53/spacr/resources/font/open_sans/static/OpenSans_Condensed-Regular.ttf +0 -0
  37. spacr-0.2.53/spacr/resources/font/open_sans/static/OpenSans_Condensed-SemiBold.ttf +0 -0
  38. spacr-0.2.53/spacr/resources/font/open_sans/static/OpenSans_Condensed-SemiBoldItalic.ttf +0 -0
  39. spacr-0.2.53/spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-Bold.ttf +0 -0
  40. spacr-0.2.53/spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-BoldItalic.ttf +0 -0
  41. spacr-0.2.53/spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-ExtraBold.ttf +0 -0
  42. spacr-0.2.53/spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-ExtraBoldItalic.ttf +0 -0
  43. spacr-0.2.53/spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-Italic.ttf +0 -0
  44. spacr-0.2.53/spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-Light.ttf +0 -0
  45. spacr-0.2.53/spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-LightItalic.ttf +0 -0
  46. spacr-0.2.53/spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-Medium.ttf +0 -0
  47. spacr-0.2.53/spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-MediumItalic.ttf +0 -0
  48. spacr-0.2.53/spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-Regular.ttf +0 -0
  49. spacr-0.2.53/spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-SemiBold.ttf +0 -0
  50. spacr-0.2.53/spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-SemiBoldItalic.ttf +0 -0
  51. {spacr-0.2.45 → spacr-0.2.53}/spacr/sequencing.py +107 -13
  52. {spacr-0.2.45 → spacr-0.2.53}/spacr/settings.py +27 -84
  53. {spacr-0.2.45 → spacr-0.2.53}/spacr/utils.py +9 -9
  54. {spacr-0.2.45 → spacr-0.2.53/spacr.egg-info}/PKG-INFO +6 -4
  55. spacr-0.2.53/spacr.egg-info/SOURCES.txt +120 -0
  56. {spacr-0.2.45 → spacr-0.2.53}/spacr.egg-info/requires.txt +5 -3
  57. spacr-0.2.45/spacr.egg-info/SOURCES.txt +0 -80
  58. {spacr-0.2.45 → spacr-0.2.53}/LICENSE +0 -0
  59. {spacr-0.2.45 → spacr-0.2.53}/MANIFEST.in +0 -0
  60. {spacr-0.2.45 → spacr-0.2.53}/README.rst +0 -0
  61. {spacr-0.2.45 → spacr-0.2.53}/setup.cfg +0 -0
  62. {spacr-0.2.45 → spacr-0.2.53}/spacr/__init__.py +0 -0
  63. {spacr-0.2.45 → spacr-0.2.53}/spacr/__main__.py +0 -0
  64. {spacr-0.2.45 → spacr-0.2.53}/spacr/app_annotate.py +0 -0
  65. {spacr-0.2.45 → spacr-0.2.53}/spacr/app_classify.py +0 -0
  66. {spacr-0.2.45 → spacr-0.2.53}/spacr/app_make_masks.py +0 -0
  67. {spacr-0.2.45 → spacr-0.2.53}/spacr/app_mask.py +0 -0
  68. {spacr-0.2.45 → spacr-0.2.53}/spacr/app_measure.py +0 -0
  69. {spacr-0.2.45 → spacr-0.2.53}/spacr/app_sequencing.py +0 -0
  70. {spacr-0.2.45 → spacr-0.2.53}/spacr/app_umap.py +0 -0
  71. {spacr-0.2.45 → spacr-0.2.53}/spacr/chris.py +0 -0
  72. {spacr-0.2.45 → spacr-0.2.53}/spacr/deep_spacr.py +0 -0
  73. {spacr-0.2.45 → spacr-0.2.53}/spacr/graph_learning.py +0 -0
  74. {spacr-0.2.45 → spacr-0.2.53}/spacr/logger.py +0 -0
  75. {spacr-0.2.45 → spacr-0.2.53}/spacr/resources/icons/abort.png +0 -0
  76. {spacr-0.2.45 → spacr-0.2.53}/spacr/resources/icons/annotate.png +0 -0
  77. {spacr-0.2.45 → spacr-0.2.53}/spacr/resources/icons/cellpose_all.png +0 -0
  78. {spacr-0.2.45 → spacr-0.2.53}/spacr/resources/icons/cellpose_masks.png +0 -0
  79. {spacr-0.2.45 → spacr-0.2.53}/spacr/resources/icons/classify.png +0 -0
  80. {spacr-0.2.45 → spacr-0.2.53}/spacr/resources/icons/default.png +0 -0
  81. {spacr-0.2.45 → spacr-0.2.53}/spacr/resources/icons/download.png +0 -0
  82. {spacr-0.2.45 → spacr-0.2.53}/spacr/resources/icons/logo.pdf +0 -0
  83. {spacr-0.2.45 → spacr-0.2.53}/spacr/resources/icons/logo_spacr.png +0 -0
  84. {spacr-0.2.45 → spacr-0.2.53}/spacr/resources/icons/logo_spacr_1.png +0 -0
  85. {spacr-0.2.45 → spacr-0.2.53}/spacr/resources/icons/make_masks.png +0 -0
  86. {spacr-0.2.45 → spacr-0.2.53}/spacr/resources/icons/map_barcodes.png +0 -0
  87. {spacr-0.2.45 → spacr-0.2.53}/spacr/resources/icons/mask.png +0 -0
  88. {spacr-0.2.45 → spacr-0.2.53}/spacr/resources/icons/measure.png +0 -0
  89. {spacr-0.2.45 → spacr-0.2.53}/spacr/resources/icons/ml_analyze.png +0 -0
  90. {spacr-0.2.45 → spacr-0.2.53}/spacr/resources/icons/recruitment.png +0 -0
  91. {spacr-0.2.45 → spacr-0.2.53}/spacr/resources/icons/regression.png +0 -0
  92. {spacr-0.2.45 → spacr-0.2.53}/spacr/resources/icons/run.png +0 -0
  93. {spacr-0.2.45 → spacr-0.2.53}/spacr/resources/icons/sequencing.png +0 -0
  94. {spacr-0.2.45 → spacr-0.2.53}/spacr/resources/icons/settings.png +0 -0
  95. {spacr-0.2.45 → spacr-0.2.53}/spacr/resources/icons/spacr_logo_rotation.gif +0 -0
  96. {spacr-0.2.45 → spacr-0.2.53}/spacr/resources/icons/train_cellpose.png +0 -0
  97. {spacr-0.2.45 → spacr-0.2.53}/spacr/resources/icons/umap.png +0 -0
  98. {spacr-0.2.45 → spacr-0.2.53}/spacr/resources/models/cp/toxo_plaque_cyto_e25000_X1120_Y1120.CP_model +0 -0
  99. {spacr-0.2.45 → spacr-0.2.53}/spacr/resources/models/cp/toxo_plaque_cyto_e25000_X1120_Y1120.CP_model_settings.csv +0 -0
  100. {spacr-0.2.45 → spacr-0.2.53}/spacr/resources/models/cp/toxo_pv_lumen.CP_model +0 -0
  101. {spacr-0.2.45 → spacr-0.2.53}/spacr/sim.py +0 -0
  102. {spacr-0.2.45 → spacr-0.2.53}/spacr/sim_app.py +0 -0
  103. {spacr-0.2.45 → spacr-0.2.53}/spacr/timelapse.py +0 -0
  104. {spacr-0.2.45 → spacr-0.2.53}/spacr/version.py +0 -0
  105. {spacr-0.2.45 → spacr-0.2.53}/spacr.egg-info/dependency_links.txt +0 -0
  106. {spacr-0.2.45 → spacr-0.2.53}/spacr.egg-info/entry_points.txt +0 -0
  107. {spacr-0.2.45 → spacr-0.2.53}/spacr.egg-info/top_level.txt +0 -0
  108. {spacr-0.2.45 → spacr-0.2.53}/tests/test_annotate_app.py +0 -0
  109. {spacr-0.2.45 → spacr-0.2.53}/tests/test_core.py +0 -0
  110. {spacr-0.2.45 → spacr-0.2.53}/tests/test_gui_classify_app.py +0 -0
  111. {spacr-0.2.45 → spacr-0.2.53}/tests/test_gui_mask_app.py +0 -0
  112. {spacr-0.2.45 → spacr-0.2.53}/tests/test_gui_measure_app.py +0 -0
  113. {spacr-0.2.45 → spacr-0.2.53}/tests/test_gui_sim_app.py +0 -0
  114. {spacr-0.2.45 → spacr-0.2.53}/tests/test_gui_utils.py +0 -0
  115. {spacr-0.2.45 → spacr-0.2.53}/tests/test_io.py +0 -0
  116. {spacr-0.2.45 → spacr-0.2.53}/tests/test_mask_app.py +0 -0
  117. {spacr-0.2.45 → spacr-0.2.53}/tests/test_measure.py +0 -0
  118. {spacr-0.2.45 → spacr-0.2.53}/tests/test_plot.py +0 -0
  119. {spacr-0.2.45 → spacr-0.2.53}/tests/test_sim.py +0 -0
  120. {spacr-0.2.45 → spacr-0.2.53}/tests/test_timelapse.py +0 -0
  121. {spacr-0.2.45 → spacr-0.2.53}/tests/test_train.py +0 -0
  122. {spacr-0.2.45 → spacr-0.2.53}/tests/test_umap.py +0 -0
  123. {spacr-0.2.45 → spacr-0.2.53}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: spacr
3
- Version: 0.2.45
3
+ Version: 0.2.53
4
4
  Summary: Spatial phenotype analysis of crisp screens (SpaCr)
5
5
  Home-page: https://github.com/EinarOlafsson/spacr
6
6
  Author: Einar Birnir Olafsson
@@ -9,9 +9,9 @@ Classifier: Programming Language :: Python :: 3
9
9
  Classifier: License :: OSI Approved :: MIT License
10
10
  Classifier: Operating System :: OS Independent
11
11
  License-File: LICENSE
12
- Requires-Dist: torch<3.0,>=2.2.1
13
- Requires-Dist: torchvision<1.0,>=0.17.1
14
- Requires-Dist: torch-geometric<3.0,>=2.5.1
12
+ Requires-Dist: torch<3.0,>=2.0
13
+ Requires-Dist: torchvision<1.0,>=0.1
14
+ Requires-Dist: torch-geometric<3.0,>=2.5
15
15
  Requires-Dist: numpy<2.0,>=1.26.4
16
16
  Requires-Dist: pandas<3.0,>=2.2.1
17
17
  Requires-Dist: statsmodels<1.0,>=0.14.1
@@ -42,6 +42,8 @@ Requires-Dist: lxml<6.0,>=5.1.0
42
42
  Requires-Dist: psutil<6.0,>=5.9.8
43
43
  Requires-Dist: gputil<2.0,>=1.4.0
44
44
  Requires-Dist: gpustat<2.0,>=1.1.1
45
+ Requires-Dist: pyautogui<1.0,>=0.9.54
46
+ Requires-Dist: tables<4.0,>=3.8.0
45
47
  Requires-Dist: huggingface-hub<0.25,>=0.24.0
46
48
  Provides-Extra: dev
47
49
  Requires-Dist: pytest<3.11,>=3.9; extra == "dev"
@@ -15,9 +15,9 @@ with open("README.rst", "r", encoding="utf-8") as fh:
15
15
  long_description = fh.read()
16
16
 
17
17
  dependencies = [
18
- 'torch>=2.2.1,<3.0',
19
- 'torchvision>=0.17.1,<1.0',
20
- 'torch-geometric>=2.5.1,<3.0',
18
+ 'torch>=2.0,<3.0',
19
+ 'torchvision>=0.1,<1.0',
20
+ 'torch-geometric>=2.5,<3.0',
21
21
  'numpy>=1.26.4,<2.0',
22
22
  'pandas>=2.2.1,<3.0',
23
23
  'statsmodels>=0.14.1,<1.0',
@@ -48,12 +48,14 @@ dependencies = [
48
48
  'psutil>=5.9.8, <6.0',
49
49
  'gputil>=1.4.0, <2.0',
50
50
  'gpustat>=1.1.1,<2.0',
51
+ 'pyautogui>=0.9.54,<1.0',
52
+ 'tables>=3.8.0,<4.0',
51
53
  'huggingface-hub>=0.24.0,<0.25'
52
54
  ]
53
55
 
54
56
  setup(
55
57
  name="spacr",
56
- version="0.2.45",
58
+ version="0.2.53",
57
59
  author="Einar Birnir Olafsson",
58
60
  author_email="olafsson@med.umich.com",
59
61
  description="Spatial phenotype analysis of crisp screens (SpaCr)",
@@ -61,7 +63,7 @@ setup(
61
63
  url="https://github.com/EinarOlafsson/spacr",
62
64
  packages=find_packages(exclude=["tests.*", "tests"]),
63
65
  include_package_data=True,
64
- package_data={'spacr': ['resources/models/cp/*', 'resources/icons/*'],},
66
+ package_data={'spacr': ['resources/models/cp/*', 'resources/icons/*', 'resources/font/**/*'],},
65
67
  install_requires=dependencies,
66
68
  entry_points={
67
69
  'console_scripts': [
@@ -1729,20 +1729,43 @@ def preprocess_generate_masks(src, settings={}):
1729
1729
 
1730
1730
  if settings['preprocess']:
1731
1731
  settings, src = preprocess_img_data(settings)
1732
-
1732
+
1733
+ files_to_process = 3
1734
+ files_processed = 0
1733
1735
  if settings['masks']:
1734
1736
  mask_src = os.path.join(src, 'norm_channel_stack')
1735
1737
  if settings['cell_channel'] != None:
1738
+ time_ls=[]
1736
1739
  if check_mask_folder(src, 'cell_mask_stack'):
1740
+ start = time.time()
1737
1741
  generate_cellpose_masks(mask_src, settings, 'cell')
1742
+ stop = time.time()
1743
+ duration = (stop - start)
1744
+ time_ls.append(duration)
1745
+ files_processed += 1
1746
+ print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls, batch_size=None, operation_type=f'cell_mask_gen')
1738
1747
 
1739
1748
  if settings['nucleus_channel'] != None:
1749
+ time_ls=[]
1740
1750
  if check_mask_folder(src, 'nucleus_mask_stack'):
1751
+ start = time.time()
1741
1752
  generate_cellpose_masks(mask_src, settings, 'nucleus')
1753
+ stop = time.time()
1754
+ duration = (stop - start)
1755
+ time_ls.append(duration)
1756
+ files_processed += 1
1757
+ print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls, batch_size=None, operation_type=f'nucleus_mask_gen')
1742
1758
 
1743
1759
  if settings['pathogen_channel'] != None:
1760
+ time_ls=[]
1744
1761
  if check_mask_folder(src, 'pathogen_mask_stack'):
1762
+ start = time.time()
1745
1763
  generate_cellpose_masks(mask_src, settings, 'pathogen')
1764
+ stop = time.time()
1765
+ duration = (stop - start)
1766
+ time_ls.append(duration)
1767
+ files_processed += 1
1768
+ print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls, batch_size=None, operation_type=f'pathogen_mask_gen')
1746
1769
 
1747
1770
  #if settings['organelle'] != None:
1748
1771
  # if check_mask_folder(src, 'organelle_mask_stack'):
@@ -1782,7 +1805,7 @@ def preprocess_generate_masks(src, settings={}):
1782
1805
 
1783
1806
  for i, file in enumerate(files):
1784
1807
  start = time.time()
1785
- if i <= settings['examples_to_plot']:
1808
+ if i+1 <= settings['examples_to_plot']:
1786
1809
  file_path = os.path.join(merged_src, file)
1787
1810
  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
1811
  stop = time.time()
@@ -2012,9 +2035,7 @@ def generate_cellpose_masks(src, settings, object_type):
2012
2035
  average_sizes = []
2013
2036
  time_ls = []
2014
2037
 
2015
- files_to_process = len(paths)
2016
2038
  for file_index, path in enumerate(paths):
2017
- start = time.time()
2018
2039
  name = os.path.basename(path)
2019
2040
  name, ext = os.path.splitext(name)
2020
2041
  output_folder = os.path.join(os.path.dirname(path), object_type+'_mask_stack')
@@ -2062,7 +2083,6 @@ def generate_cellpose_masks(src, settings, object_type):
2062
2083
  if not settings['plot']:
2063
2084
  batch, batch_filenames = _check_masks(batch, batch_filenames, output_folder)
2064
2085
  if batch.size == 0:
2065
- #print(f'Processing {file_index}/{len(paths)}: Images/npz {batch.shape[0]}')
2066
2086
  continue
2067
2087
 
2068
2088
  batch = prepare_batch_for_cellpose(batch)
@@ -2073,16 +2093,6 @@ def generate_cellpose_masks(src, settings, object_type):
2073
2093
  save_path = os.path.join(movie_path, f'timelapse_{object_type}_{name}.mp4')
2074
2094
  _npz_to_movie(batch, batch_filenames, save_path, fps=2)
2075
2095
 
2076
- #if settings['verbose']:
2077
- #print(f'Processing {file_index}/{len(paths)}: Images/npz {batch.shape[0]}')
2078
-
2079
- #cellpose_normalize_dict = {'lowhigh':[0.0,1.0], #pass in normalization values for 0.0 and 1.0 as list [low, high] if None all other keys ignored
2080
- # 'sharpen':object_settings['diameter']/4, #recommended to be 1/4-1/8 diameter of cells in pixels
2081
- # 'normalize':True, #(if False, all following parameters ignored)
2082
- # 'percentile':[2,98], #[perc_low, perc_high]
2083
- # 'tile_norm':224, #normalize by tile set to e.g. 100 for normailize window to be 100 px
2084
- # 'norm3D':True} #compute normalization across entire z-stack rather than plane-by-plane in stitching mode.
2085
-
2086
2096
  output = model.eval(x=batch,
2087
2097
  batch_size=cellpose_batch_size,
2088
2098
  normalize=False,
@@ -2204,12 +2214,8 @@ def generate_cellpose_masks(src, settings, object_type):
2204
2214
  np.save(output_filename, mask)
2205
2215
  mask_stack = []
2206
2216
  batch_filenames = []
2207
- stop = time.time()
2208
- duration = (stop - start)
2209
- time_ls.append(duration)
2210
- files_processed = file_index+1
2211
- 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')
2212
- #gc.collect()
2217
+
2218
+ gc.collect()
2213
2219
  torch.cuda.empty_cache()
2214
2220
  return
2215
2221
 
@@ -1,7 +1,5 @@
1
1
  import tkinter as tk
2
2
  from tkinter import ttk
3
- from PIL import Image, ImageTk, ImageDraw
4
- import os
5
3
  from multiprocessing import set_start_method
6
4
  from .gui_elements import spacrButton, create_menu_bar, set_dark_style
7
5
  from .gui_core import initiate_root
@@ -1,9 +1,8 @@
1
- import os, traceback, ctypes, requests, csv, time, requests, re
1
+ import traceback, ctypes, csv, re, time
2
2
  import tkinter as tk
3
3
  from tkinter import ttk
4
4
  from tkinter import filedialog
5
5
  from multiprocessing import Process, Value, Queue, set_start_method
6
- from multiprocessing.sharedctypes import Synchronized
7
6
  from tkinter import ttk, scrolledtext
8
7
  from matplotlib.figure import Figure
9
8
  from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
@@ -44,13 +43,15 @@ def toggle_settings(button_scrollable_frame):
44
43
  def toggle_category(settings):
45
44
  for setting in settings:
46
45
  if setting in vars_dict:
47
- label, widget, _ = vars_dict[setting]
46
+ label, widget, _, frame = vars_dict[setting]
48
47
  if widget.grid_info():
49
48
  label.grid_remove()
50
49
  widget.grid_remove()
50
+ frame.grid_remove()
51
51
  else:
52
52
  label.grid()
53
53
  widget.grid()
54
+ frame.grid()
54
55
 
55
56
  def on_category_select(selected_category):
56
57
  if selected_category == "Select Category":
@@ -80,15 +81,20 @@ def process_fig_queue():
80
81
 
81
82
  try:
82
83
  while not fig_queue.empty():
84
+ time.sleep(1)
83
85
  clear_canvas(canvas)
84
86
  fig = fig_queue.get_nowait()
87
+
85
88
  for ax in fig.get_axes():
86
89
  ax.set_xticks([]) # Remove x-axis ticks
87
90
  ax.set_yticks([]) # Remove y-axis ticks
88
91
  ax.xaxis.set_visible(False) # Hide the x-axis
89
92
  ax.yaxis.set_visible(False) # Hide the y-axis
90
- fig.tight_layout()
93
+
94
+ # Adjust layout to minimize spacing between axes
95
+ fig.subplots_adjust(left=0, right=1, top=1, bottom=0, wspace=0.01, hspace=0.01)
91
96
  fig.set_facecolor('black')
97
+
92
98
  canvas.figure = fig
93
99
  fig_width, fig_height = canvas_widget.winfo_width(), canvas_widget.winfo_height()
94
100
  fig.set_size_inches(fig_width / fig.dpi, fig_height / fig.dpi, forward=True)
@@ -96,12 +102,9 @@ def process_fig_queue():
96
102
  except Exception as e:
97
103
  traceback.print_exc()
98
104
  finally:
99
- after_id = canvas_widget.after(100, process_fig_queue)
105
+ after_id = canvas_widget.after(1, process_fig_queue)
100
106
  parent_frame.after_tasks.append(after_id)
101
107
 
102
-
103
-
104
-
105
108
  def set_globals(thread_control_var, 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, usage_bars_var):
106
109
  global thread_control, q, console_output, parent_frame, vars_dict, canvas, canvas_widget, scrollable_frame, fig_queue, progress_bar, usage_bars
107
110
  thread_control = thread_control_var
@@ -169,13 +172,14 @@ def import_settings(settings_type='mask'):
169
172
  def setup_settings_panel(vertical_container, settings_type='mask'):
170
173
  global vars_dict, scrollable_frame
171
174
  from .settings import get_identify_masks_finetune_default_settings, set_default_analyze_screen, set_default_settings_preprocess_generate_masks, get_measure_crop_settings, set_default_train_test_model, get_analyze_reads_default_settings, set_default_umap_image_settings, generate_fields, get_perform_regression_default_settings, get_train_cellpose_default_settings, get_map_barcodes_default_settings, get_analyze_recruitment_default_settings, get_check_cellpose_models_default_settings
172
- from .gui_utils import convert_settings_dict_for_gui, set_element_size
175
+ from .gui_utils import convert_settings_dict_for_gui
176
+ from .gui_elements import set_element_size
173
177
 
174
- size_dict = set_element_size(vertical_container)
178
+ size_dict = set_element_size()
175
179
  settings_width = size_dict['settings_width']
176
180
 
177
181
  # Create a PanedWindow for the settings panel
178
- settings_paned_window = tk.PanedWindow(vertical_container, orient=tk.HORIZONTAL)
182
+ settings_paned_window = tk.PanedWindow(vertical_container, orient=tk.HORIZONTAL, width=size_dict['settings_width'])
179
183
  vertical_container.add(settings_paned_window, stretch="always")
180
184
 
181
185
  settings_frame = tk.Frame(settings_paned_window, width=settings_width)
@@ -229,8 +233,12 @@ def setup_settings_panel(vertical_container, settings_type='mask'):
229
233
 
230
234
  def setup_plot_section(vertical_container):
231
235
  global canvas, canvas_widget
232
- plot_frame = tk.PanedWindow(vertical_container, orient=tk.VERTICAL)
236
+
237
+ # Create a frame for the plot section
238
+ plot_frame = tk.Frame(vertical_container, bg='lightgrey')
233
239
  vertical_container.add(plot_frame, stretch="always")
240
+
241
+ # Set up the plot
234
242
  figure = Figure(figsize=(30, 4), dpi=100)
235
243
  plot = figure.add_subplot(111)
236
244
  plot.plot([], []) # This creates an empty plot.
@@ -238,7 +246,11 @@ def setup_plot_section(vertical_container):
238
246
  canvas = FigureCanvasTkAgg(figure, master=plot_frame)
239
247
  canvas.get_tk_widget().configure(cursor='arrow', highlightthickness=0)
240
248
  canvas_widget = canvas.get_tk_widget()
241
- plot_frame.add(canvas_widget, stretch="always")
249
+ canvas_widget.grid(row=0, column=0, sticky="nsew") # Use grid for the canvas widget
250
+
251
+ plot_frame.grid_rowconfigure(0, weight=1)
252
+ plot_frame.grid_columnconfigure(0, weight=1)
253
+
242
254
  canvas.draw()
243
255
  canvas.figure = figure
244
256
  style_out = set_dark_style(ttk.Style())
@@ -249,62 +261,58 @@ def setup_plot_section(vertical_container):
249
261
  widgets = [canvas_widget]
250
262
  style = ttk.Style(vertical_container)
251
263
  _ = set_dark_style(style, containers=containers, widgets=widgets)
264
+
252
265
  return canvas, canvas_widget
253
266
 
254
267
  def setup_console(vertical_container):
255
268
  global console_output
269
+ from .gui_elements import set_dark_style
256
270
 
257
- # Create a frame to hold the console and button sections
258
- console_button_frame = tk.Frame(vertical_container)
259
- vertical_container.add(console_button_frame, stretch="always")
260
-
261
- # Create a PanedWindow for resizing height
262
- console_paned_window = tk.PanedWindow(console_button_frame, orient=tk.VERTICAL, bg='black')
263
- console_paned_window.pack(fill=tk.BOTH, expand=True)
271
+ # Apply dark style and get style output
272
+ style = ttk.Style()
273
+ style_out = set_dark_style(style)
264
274
 
265
- # Create the main console frame using spacrFrame with textbox=True
266
- console_frame = spacrFrame(console_paned_window, textbox=True)
267
- console_paned_window.add(console_frame, stretch="always")
275
+ # Create a frame for the console section
276
+ console_frame = tk.Frame(vertical_container, bg=style_out['bg_color'])
277
+ vertical_container.add(console_frame, stretch="always")
268
278
 
269
- # Assign the scrollable frame (which is a Text widget) to console_output
270
- console_output = console_frame.scrollable_frame
279
+ # Create a thicker frame at the top for the hover effect
280
+ top_border = tk.Frame(console_frame, height=5, bg=style_out['bg_color'])
281
+ top_border.grid(row=0, column=0, sticky="ew", pady=(0, 2))
271
282
 
272
- # Ensure the Text widget spans the entire console frame
273
- console_output.grid(row=0, column=0, sticky="nsew")
283
+ # Create the scrollable frame (which is a Text widget) with white text
284
+ family = style_out['font_family']
285
+ font_size = style_out['font_size'] - 2
286
+ font_loader = style_out['font_loader']
287
+ console_output = tk.Text(console_frame, bg=style_out['bg_color'], fg=style_out['fg_color'], font=font_loader.get_font(size=font_size), bd=0, highlightthickness=0)
288
+
289
+ console_output.grid(row=1, column=0, sticky="nsew") # Use grid for console_output
274
290
 
275
291
  # Configure the grid to allow expansion
276
- console_frame.grid_rowconfigure(0, weight=1)
292
+ console_frame.grid_rowconfigure(1, weight=1)
277
293
  console_frame.grid_columnconfigure(0, weight=1)
278
294
 
279
- # Create a lower frame to act as the anchor point
280
- lower_frame = tk.Frame(console_paned_window)
281
- console_paned_window.add(lower_frame, minsize=10) # Adjust minsize to ensure usability
295
+ def on_enter(event):
296
+ top_border.config(bg=style_out['active_color'])
282
297
 
283
- # Dynamically adjust the height and width of the console_frame
284
- def adjust_frame_size(event):
285
- console_frame.update_idletasks()
286
- new_width = console_paned_window.winfo_width()
287
- new_height = console_paned_window.winfo_height()
288
- console_frame.config(width=new_width, height=new_height)
289
- console_output.config(width=new_width, height=new_height)
298
+ def on_leave(event):
299
+ top_border.config(bg=style_out['bg_color'])
290
300
 
291
- # Bind the configure event to dynamically adjust size
292
- console_paned_window.bind("<Configure>", adjust_frame_size)
293
-
294
- # Apply dark style to the PanedWindow and lower frame
295
- style = ttk.Style()
296
- set_dark_style(style, containers=[console_paned_window, lower_frame])
301
+ console_output.bind("<Enter>", on_enter)
302
+ console_output.bind("<Leave>", on_leave)
297
303
 
298
304
  return console_output, console_frame
299
305
 
300
-
301
306
  def setup_progress_frame(vertical_container):
302
307
  global progress_output
308
+ style_out = set_dark_style(ttk.Style())
309
+ font_loader = style_out['font_loader']
310
+ font_size = style_out['font_size']
303
311
  progress_frame = tk.Frame(vertical_container)
304
312
  vertical_container.add(progress_frame, stretch="always")
305
313
  label_frame = tk.Frame(progress_frame)
306
314
  label_frame.grid(row=0, column=0, sticky="ew", pady=(5, 0), padx=10)
307
- progress_label = spacrLabel(label_frame, text="Processing: 0%", font=('Helvetica', 12), anchor='w', justify='left', align="left")
315
+ progress_label = spacrLabel(label_frame, text="Processing: 0%", font=font_loader.get_font(size=font_size), anchor='w', justify='left', align="left")
308
316
  progress_label.grid(row=0, column=0, sticky="w")
309
317
  progress_output = scrolledtext.ScrolledText(progress_frame, height=10)
310
318
  progress_output.grid(row=1, column=0, sticky="nsew")
@@ -318,16 +326,15 @@ def setup_progress_frame(vertical_container):
318
326
 
319
327
  def setup_button_section(horizontal_container, settings_type='mask', run=True, abort=True, download=True, import_btn=True):
320
328
  global thread_control, parent_frame, button_frame, button_scrollable_frame, run_button, abort_button, download_dataset_button, import_button, q, fig_queue, vars_dict, progress_bar
321
- from .gui_utils import set_element_size, download_hug_dataset
322
- from .settings import categories
329
+ from .gui_utils import download_hug_dataset
330
+ from .gui_elements import set_element_size
323
331
 
324
-
325
- size_dict = set_element_size(horizontal_container)
332
+ size_dict = set_element_size()
326
333
  button_section_height = size_dict['panel_height']
327
334
  button_frame = tk.Frame(horizontal_container, height=button_section_height)
328
335
 
329
336
  # Prevent the frame from resizing based on the child widget
330
- button_frame.pack_propagate(False)
337
+ #button_frame.pack_propagate(False)
331
338
 
332
339
  horizontal_container.add(button_frame, stretch="always", sticky="nsew")
333
340
  button_scrollable_frame = spacrFrame(button_frame, scrollbar=False)
@@ -338,7 +345,6 @@ def setup_button_section(horizontal_container, settings_type='mask', run=True, a
338
345
  btn_row = 0
339
346
 
340
347
  if run:
341
- print(f'settings_type: {settings_type}')
342
348
  run_button = spacrButton(button_scrollable_frame.scrollable_frame, text="run", command=lambda: start_process(q, fig_queue, settings_type), show_text=False, size=size_dict['btn_size'], animation=False)
343
349
  run_button.grid(row=btn_row, column=btn_col, pady=5, padx=5, sticky='ew')
344
350
  widgets.append(run_button)
@@ -364,7 +370,7 @@ def setup_button_section(horizontal_container, settings_type='mask', run=True, a
364
370
 
365
371
  # Add the progress bar under the settings category menu
366
372
  progress_bar = spacrProgressBar(button_scrollable_frame.scrollable_frame, orient='horizontal', mode='determinate')
367
- progress_bar.grid(row=btn_row, column=0, columnspan=5, pady=5, padx=5, sticky='ew')
373
+ progress_bar.grid(row=btn_row, column=0, columnspan=7, pady=5, padx=5, sticky='ew')
368
374
  progress_bar.set_label_position() # Set the label position after grid placement
369
375
  widgets.append(progress_bar)
370
376
 
@@ -374,11 +380,13 @@ def setup_button_section(horizontal_container, settings_type='mask', run=True, a
374
380
  style = ttk.Style(horizontal_container)
375
381
  _ = set_dark_style(style, containers=[button_frame], widgets=widgets)
376
382
 
377
- return button_scrollable_frame
383
+ return button_scrollable_frame, btn_col
378
384
 
379
- def setup_usage_panel(horizontal_container):
385
+ def setup_usage_panel(horizontal_container, btn_col):
380
386
  global usage_bars
381
- from .gui_utils import set_element_size
387
+ from .gui_elements import set_dark_style, set_element_size
388
+
389
+ usg_col = 1
382
390
 
383
391
  def update_usage(ram_bar, vram_bar, gpu_bar, usage_bars, parent_frame):
384
392
  # Update RAM usage
@@ -402,10 +410,10 @@ def setup_usage_panel(horizontal_container):
402
410
  # Schedule the function to run again after 1000 ms (1 second)
403
411
  parent_frame.after(1000, update_usage, ram_bar, vram_bar, gpu_bar, usage_bars, parent_frame)
404
412
 
405
- size_dict = set_element_size(horizontal_container)
413
+ size_dict = set_element_size()
406
414
  usage_panel_height = size_dict['panel_height']
407
415
  usage_frame = tk.Frame(horizontal_container, height=usage_panel_height)
408
- horizontal_container.add(usage_frame, stretch="always", sticky="nsew")
416
+ horizontal_container.add(usage_frame)
409
417
 
410
418
  usage_frame.grid_rowconfigure(0, weight=0)
411
419
  usage_frame.grid_rowconfigure(1, weight=1)
@@ -415,19 +423,27 @@ def setup_usage_panel(horizontal_container):
415
423
  usage_scrollable_frame = spacrFrame(usage_frame, scrollbar=False)
416
424
  usage_scrollable_frame.grid(row=1, column=0, sticky="nsew", columnspan=2)
417
425
  widgets = [usage_scrollable_frame.scrollable_frame]
426
+
418
427
  usage_bars = []
419
- max_elements_per_column = 6
428
+ max_elements_per_column = 4
420
429
  row = 0
421
430
  col = 0
422
431
 
423
432
  # Initialize RAM, VRAM, and GPU bars as None
424
433
  ram_bar, vram_bar, gpu_bar = None, None, None
434
+
435
+ # Configure the style for the label
436
+ style = ttk.Style()
437
+ style_out = set_dark_style(style)
438
+ font_loader = style_out['font_loader']
439
+ font_size = style_out['font_size'] - 2
440
+ style.configure("usage.TLabel", font=font_loader.get_font(size=font_size), foreground=style_out['fg_color'])
425
441
 
426
442
  # Try adding RAM bar
427
443
  try:
428
444
  ram_info = psutil.virtual_memory()
429
445
  ram_label_text = f"RAM"
430
- label = ttk.Label(usage_scrollable_frame.scrollable_frame, text=ram_label_text, anchor='w')
446
+ label = ttk.Label(usage_scrollable_frame.scrollable_frame, text=ram_label_text, anchor='w', style="usage.TLabel")
431
447
  label.grid(row=row, column=2 * col, pady=5, padx=5, sticky='w')
432
448
  ram_bar = spacrProgressBar(usage_scrollable_frame.scrollable_frame, orient='horizontal', mode='determinate', length=size_dict['bar_size'], label=False)
433
449
  ram_bar.grid(row=row, column=2 * col + 1, pady=5, padx=5, sticky='ew')
@@ -444,7 +460,7 @@ def setup_usage_panel(horizontal_container):
444
460
  if gpus:
445
461
  gpu = gpus[0]
446
462
  vram_label_text = f"VRAM"
447
- label = ttk.Label(usage_scrollable_frame.scrollable_frame, text=vram_label_text, anchor='w')
463
+ label = ttk.Label(usage_scrollable_frame.scrollable_frame, text=vram_label_text, anchor='w', style="usage.TLabel")
448
464
  label.grid(row=row, column=2 * col, pady=5, padx=5, sticky='w')
449
465
  vram_bar = spacrProgressBar(usage_scrollable_frame.scrollable_frame, orient='horizontal', mode='determinate', length=size_dict['bar_size'], label=False)
450
466
  vram_bar.grid(row=row, column=2 * col + 1, pady=5, padx=5, sticky='ew')
@@ -454,7 +470,7 @@ def setup_usage_panel(horizontal_container):
454
470
  row += 1
455
471
 
456
472
  gpu_label_text = f"GPU"
457
- label = ttk.Label(usage_scrollable_frame.scrollable_frame, text=gpu_label_text, anchor='w')
473
+ label = ttk.Label(usage_scrollable_frame.scrollable_frame, text=gpu_label_text, anchor='w', style="usage.TLabel")
458
474
  label.grid(row=row, column=2 * col, pady=5, padx=5, sticky='w')
459
475
  gpu_bar = spacrProgressBar(usage_scrollable_frame.scrollable_frame, orient='horizontal', mode='determinate', length=size_dict['bar_size'], label=False)
460
476
  gpu_bar.grid(row=row, column=2 * col + 1, pady=5, padx=5, sticky='ew')
@@ -474,7 +490,7 @@ def setup_usage_panel(horizontal_container):
474
490
  if row > 0 and row % max_elements_per_column == 0:
475
491
  col += 1
476
492
  row = 0
477
- label = ttk.Label(usage_scrollable_frame.scrollable_frame, text=f"Core {core+1}", anchor='w')
493
+ label = ttk.Label(usage_scrollable_frame.scrollable_frame, text=f"Core {core+1}", anchor='w', style="usage.TLabel")
478
494
  label.grid(row=row, column=2 * col, pady=2, padx=5, sticky='w')
479
495
  bar = spacrProgressBar(usage_scrollable_frame.scrollable_frame, orient='horizontal', mode='determinate', length=size_dict['bar_size'], label=False)
480
496
  bar.grid(row=row, column=2 * col + 1, pady=2, padx=5, sticky='ew')
@@ -494,58 +510,9 @@ def setup_usage_panel(horizontal_container):
494
510
  vram_bar = spacrProgressBar(usage_scrollable_frame.scrollable_frame, orient='horizontal', mode='determinate', length=size_dict['bar_size'], label=False)
495
511
  if gpu_bar is None:
496
512
  gpu_bar = spacrProgressBar(usage_scrollable_frame.scrollable_frame, orient='horizontal', mode='determinate', length=size_dict['bar_size'], label=False)
497
-
498
- update_usage(ram_bar, vram_bar, gpu_bar, usage_bars, usage_frame)
499
- return usage_scrollable_frame, usage_bars
500
-
501
- def setup_help_section(horizontal_container, settings_type='mask'):
502
- from .settings import descriptions
503
- from .gui_utils import set_element_size
504
-
505
- size_dict = set_element_size(horizontal_container)
506
- help_section_height = size_dict['panel_height']
507
-
508
- # Create the frame for the help section
509
- description_frame = tk.Frame(horizontal_container, height=help_section_height)
510
- description_frame.pack_propagate(False)
511
-
512
- # Add the description frame to the horizontal container
513
- horizontal_container.add(description_frame, stretch="always", sticky="nsew")
514
- description_frame.grid_columnconfigure(0, weight=1)
515
- description_frame.grid_rowconfigure(0, weight=1) # Ensure the text widget row is expandable
516
-
517
- style_out = set_dark_style(ttk.Style())
518
- bg_color = style_out['bg_color']
519
- fg_color = style_out['fg_color']
520
-
521
- # Insert the description text
522
- description_text = descriptions.get(settings_type, "No description available for this module.")
523
- first_line, *rest_of_description = description_text.split('\n', 1)
524
-
525
- # Create the first line label
526
- first_line_label = ttk.Label(description_frame, text=first_line, anchor='w', background=bg_color, foreground=fg_color)
527
- first_line_label.grid(row=0, column=0, sticky='ew')
528
-
529
- # Create the text widget with the appropriate background and foreground colors
530
- description_text_widget = tk.Text(description_frame, wrap="word", bg=bg_color, fg=fg_color, bd=0, highlightthickness=0)
531
- description_text_widget.grid(row=1, column=0, sticky="nsew")
532
-
533
- # Insert the rest of the description text
534
- if rest_of_description:
535
- description_text_widget.insert("1.0", rest_of_description[0].lstrip())
536
- description_text_widget.config(state="disabled") # Make the text widget read-only
537
-
538
- def update_wraplength(event):
539
- new_width = event.width - 20 # Adjust as needed
540
- description_text_widget.config(width=new_width)
541
-
542
- description_text_widget.bind('<Configure>', update_wraplength)
543
-
544
- # Apply dark style
545
- style = ttk.Style(horizontal_container)
546
- _ = set_dark_style(style, containers=[description_frame], widgets=[description_text_widget, first_line_label])
547
-
548
- return description_frame
513
+
514
+ update_usage(ram_bar, vram_bar, gpu_bar, usage_bars, usage_frame)
515
+ return usage_scrollable_frame, usage_bars, usg_col
549
516
 
550
517
  def initiate_abort():
551
518
  global thread_control, q, parent_frame
@@ -570,7 +537,6 @@ def start_process(q=None, fig_queue=None, settings_type='mask'):
570
537
  q = Queue()
571
538
  if fig_queue is None:
572
539
  fig_queue = Queue()
573
-
574
540
  try:
575
541
  settings = check_settings(vars_dict, expected_types, q)
576
542
  except ValueError as e:
@@ -602,9 +568,11 @@ def process_console_queue():
602
568
  # Initialize function attribute if it doesn't exist
603
569
  if not hasattr(process_console_queue, "completed_tasks"):
604
570
  process_console_queue.completed_tasks = []
571
+ if not hasattr(process_console_queue, "current_maximum"):
572
+ process_console_queue.current_maximum = None
605
573
 
606
574
  ansi_escape_pattern = re.compile(r'\x1B\[[0-?]*[ -/]*[@-~]')
607
-
575
+
608
576
  while not q.empty():
609
577
  message = q.get_nowait()
610
578
  clean_message = ansi_escape_pattern.sub('', message)
@@ -616,12 +584,18 @@ def process_console_queue():
616
584
  try:
617
585
  # Extract the progress information
618
586
  match = re.search(r'Progress: (\d+)/(\d+), operation_type: ([\w\s]*)(.*)', clean_message)
587
+
619
588
  if match:
620
589
  current_progress = int(match.group(1))
621
590
  total_progress = int(match.group(2))
622
591
  operation_type = match.group(3).strip()
623
592
  time_info = match.group(4).strip()
624
593
 
594
+ # Check if the maximum value has changed
595
+ if process_console_queue.current_maximum != total_progress:
596
+ process_console_queue.current_maximum = total_progress
597
+ process_console_queue.completed_tasks = []
598
+
625
599
  # Add the task to the completed set
626
600
  process_console_queue.completed_tasks.append(current_progress)
627
601
 
@@ -656,16 +630,23 @@ def process_console_queue():
656
630
  # Clear completed tasks when progress is complete
657
631
  if unique_progress_count >= total_progress:
658
632
  process_console_queue.completed_tasks.clear()
633
+
659
634
  except Exception as e:
660
635
  print(f"Error parsing progress message: {e}")
661
-
662
- after_id = console_output.after(100, process_console_queue)
636
+ #else:
637
+ # # Only insert messages that do not start with "Progress:"
638
+ # console_output.insert(tk.END, clean_message + "\n")
639
+ # console_output.see(tk.END)
640
+
641
+ after_id = console_output.after(1, process_console_queue)
663
642
  parent_frame.after_tasks.append(after_id)
664
643
 
644
+
665
645
  def initiate_root(parent, settings_type='mask'):
666
646
  global q, fig_queue, thread_control, parent_frame, scrollable_frame, button_frame, vars_dict, canvas, canvas_widget, button_scrollable_frame, progress_bar
667
- from .gui_utils import main_thread_update_function, setup_frame, set_element_size
668
- from .gui import gui_app
647
+ from .gui_utils import main_thread_update_function, setup_frame
648
+ from .settings import descriptions
649
+
669
650
  set_start_method('spawn', force=True)
670
651
  print("Initializing root with settings_type:", settings_type)
671
652
 
@@ -693,18 +674,23 @@ def initiate_root(parent, settings_type='mask'):
693
674
  initiate_make_mask_app(horizontal_container)
694
675
  else:
695
676
  scrollable_frame, vars_dict = setup_settings_panel(settings_container, settings_type)
677
+ print('setup_settings_panel')
696
678
  canvas, canvas_widget = setup_plot_section(vertical_container)
697
- console_output, console_frame = setup_console(vertical_container)
698
- button_scrollable_frame = setup_button_section(horizontal_container, settings_type)
699
- _, usage_bars = setup_usage_panel(horizontal_container)
700
- _ = setup_help_section(horizontal_container, settings_type)
701
-
679
+ console_output, _ = setup_console(vertical_container)
680
+ button_scrollable_frame, btn_col = setup_button_section(horizontal_container, settings_type)
681
+ _, usage_bars, btn_col = setup_usage_panel(horizontal_container, btn_col)
682
+
702
683
  set_globals(thread_control, q, console_output, parent_frame, vars_dict, canvas, canvas_widget, scrollable_frame, fig_queue, progress_bar, usage_bars)
684
+ description_text = descriptions.get(settings_type, "No description available for this module.")
685
+
703
686
  q.put(f"Console")
687
+ q.put(f" ")
688
+ q.put(description_text)
689
+
704
690
  process_console_queue()
705
691
  process_fig_queue()
706
692
  after_id = parent_window.after(100, lambda: main_thread_update_function(parent_window, q, fig_queue, canvas_widget))
707
693
  parent_window.after_tasks.append(after_id)
708
694
 
709
695
  print("Root initialization complete")
710
- return parent_frame, vars_dict
696
+ return parent_frame, vars_dict