spacr 0.2.4__py3-none-any.whl → 0.2.8__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.
Files changed (63) hide show
  1. spacr/__init__.py +1 -11
  2. spacr/core.py +277 -349
  3. spacr/deep_spacr.py +248 -269
  4. spacr/gui.py +58 -54
  5. spacr/gui_core.py +689 -535
  6. spacr/gui_elements.py +1002 -153
  7. spacr/gui_utils.py +452 -107
  8. spacr/io.py +158 -91
  9. spacr/measure.py +199 -151
  10. spacr/plot.py +159 -47
  11. spacr/resources/font/open_sans/OFL.txt +93 -0
  12. spacr/resources/font/open_sans/OpenSans-Italic-VariableFont_wdth,wght.ttf +0 -0
  13. spacr/resources/font/open_sans/OpenSans-VariableFont_wdth,wght.ttf +0 -0
  14. spacr/resources/font/open_sans/README.txt +100 -0
  15. spacr/resources/font/open_sans/static/OpenSans-Bold.ttf +0 -0
  16. spacr/resources/font/open_sans/static/OpenSans-BoldItalic.ttf +0 -0
  17. spacr/resources/font/open_sans/static/OpenSans-ExtraBold.ttf +0 -0
  18. spacr/resources/font/open_sans/static/OpenSans-ExtraBoldItalic.ttf +0 -0
  19. spacr/resources/font/open_sans/static/OpenSans-Italic.ttf +0 -0
  20. spacr/resources/font/open_sans/static/OpenSans-Light.ttf +0 -0
  21. spacr/resources/font/open_sans/static/OpenSans-LightItalic.ttf +0 -0
  22. spacr/resources/font/open_sans/static/OpenSans-Medium.ttf +0 -0
  23. spacr/resources/font/open_sans/static/OpenSans-MediumItalic.ttf +0 -0
  24. spacr/resources/font/open_sans/static/OpenSans-Regular.ttf +0 -0
  25. spacr/resources/font/open_sans/static/OpenSans-SemiBold.ttf +0 -0
  26. spacr/resources/font/open_sans/static/OpenSans-SemiBoldItalic.ttf +0 -0
  27. spacr/resources/font/open_sans/static/OpenSans_Condensed-Bold.ttf +0 -0
  28. spacr/resources/font/open_sans/static/OpenSans_Condensed-BoldItalic.ttf +0 -0
  29. spacr/resources/font/open_sans/static/OpenSans_Condensed-ExtraBold.ttf +0 -0
  30. spacr/resources/font/open_sans/static/OpenSans_Condensed-ExtraBoldItalic.ttf +0 -0
  31. spacr/resources/font/open_sans/static/OpenSans_Condensed-Italic.ttf +0 -0
  32. spacr/resources/font/open_sans/static/OpenSans_Condensed-Light.ttf +0 -0
  33. spacr/resources/font/open_sans/static/OpenSans_Condensed-LightItalic.ttf +0 -0
  34. spacr/resources/font/open_sans/static/OpenSans_Condensed-Medium.ttf +0 -0
  35. spacr/resources/font/open_sans/static/OpenSans_Condensed-MediumItalic.ttf +0 -0
  36. spacr/resources/font/open_sans/static/OpenSans_Condensed-Regular.ttf +0 -0
  37. spacr/resources/font/open_sans/static/OpenSans_Condensed-SemiBold.ttf +0 -0
  38. spacr/resources/font/open_sans/static/OpenSans_Condensed-SemiBoldItalic.ttf +0 -0
  39. spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-Bold.ttf +0 -0
  40. spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-BoldItalic.ttf +0 -0
  41. spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-ExtraBold.ttf +0 -0
  42. spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-ExtraBoldItalic.ttf +0 -0
  43. spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-Italic.ttf +0 -0
  44. spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-Light.ttf +0 -0
  45. spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-LightItalic.ttf +0 -0
  46. spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-Medium.ttf +0 -0
  47. spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-MediumItalic.ttf +0 -0
  48. spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-Regular.ttf +0 -0
  49. spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-SemiBold.ttf +0 -0
  50. spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-SemiBoldItalic.ttf +0 -0
  51. spacr/resources/icons/logo.pdf +2786 -6
  52. spacr/resources/icons/logo_spacr.png +0 -0
  53. spacr/resources/icons/logo_spacr_1.png +0 -0
  54. spacr/sequencing.py +477 -587
  55. spacr/settings.py +217 -144
  56. spacr/utils.py +46 -46
  57. {spacr-0.2.4.dist-info → spacr-0.2.8.dist-info}/METADATA +46 -35
  58. spacr-0.2.8.dist-info/RECORD +100 -0
  59. {spacr-0.2.4.dist-info → spacr-0.2.8.dist-info}/WHEEL +1 -1
  60. spacr-0.2.4.dist-info/RECORD +0 -58
  61. {spacr-0.2.4.dist-info → spacr-0.2.8.dist-info}/LICENSE +0 -0
  62. {spacr-0.2.4.dist-info → spacr-0.2.8.dist-info}/entry_points.txt +0 -0
  63. {spacr-0.2.4.dist-info → spacr-0.2.8.dist-info}/top_level.txt +0 -0
spacr/gui.py CHANGED
@@ -1,44 +1,61 @@
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
6
+ from screeninfo import get_monitors
8
7
 
9
8
  class MainApp(tk.Tk):
10
9
  def __init__(self, default_app=None):
11
10
  super().__init__()
12
- width = self.winfo_screenwidth()
13
- height = self.winfo_screenheight()
11
+
12
+ # Initialize the window
13
+ self.geometry("100x100")
14
+ self.update_idletasks()
15
+
16
+ # Get the current window position
17
+ self.update_idletasks()
18
+ x = self.winfo_x()
19
+ y = self.winfo_y()
20
+
21
+ # Find the monitor where the window is located
22
+ for monitor in get_monitors():
23
+ if monitor.x <= x < monitor.x + monitor.width and monitor.y <= y < monitor.y + monitor.height:
24
+ width = monitor.width
25
+ height = monitor.height
26
+ break
27
+ else:
28
+ monitor = get_monitors()[0]
29
+ width = monitor.width
30
+ height = monitor.height
31
+
32
+ # Set the window size to the dimensions of the monitor where it is located
14
33
  self.geometry(f"{width}x{height}")
15
34
  self.title("SpaCr GUI Collection")
16
35
  self.configure(bg='#333333') # Set window background to dark gray
17
36
 
18
- # Initialize style and apply dark style to the main window
19
37
  style = ttk.Style()
20
38
  self.color_settings = set_dark_style(style, parent_frame=self)
21
- self.main_buttons = {} # Initialize main_buttons dictionary here
22
- self.additional_buttons = {} # Initialize additional_buttons dictionary here
39
+ self.main_buttons = {}
40
+ self.additional_buttons = {}
23
41
 
24
42
  self.main_gui_apps = {
25
- "Mask": (lambda frame: initiate_root(frame, 'mask'), "Generate cellpose masks for cells, nuclei and pathogen images."),
26
- "Measure": (lambda frame: initiate_root(frame, 'measure'), "Measure single object intensity and morphological feature. Crop and save single object image"),
27
- "Annotate": (lambda frame: initiate_root(frame, 'annotate'), "Annotation single object images on a grid. Annotations are saved to database."),
28
- "Make Masks": (lambda frame: initiate_root(frame, 'make_masks'), "Adjust pre-existing Cellpose models to your specific dataset for improved performance"),
29
- "Classify": (lambda frame: initiate_root(frame, 'classify'), "Train Torch Convolutional Neural Networks (CNNs) or Transformers to classify single object images."),
43
+ "Mask": (lambda frame: initiate_root(self, 'mask'), "Generate cellpose masks for cells, nuclei and pathogen images."),
44
+ "Measure": (lambda frame: initiate_root(self, 'measure'), "Measure single object intensity and morphological feature. Crop and save single object image"),
45
+ "Annotate": (lambda frame: initiate_root(self, 'annotate'), "Annotation single object images on a grid. Annotations are saved to database."),
46
+ "Make Masks": (lambda frame: initiate_root(self, 'make_masks'), "Adjust pre-existing Cellpose models to your specific dataset for improved performance"),
47
+ "Classify": (lambda frame: initiate_root(self, 'classify'), "Train Torch Convolutional Neural Networks (CNNs) or Transformers to classify single object images."),
30
48
  }
31
49
 
32
50
  self.additional_gui_apps = {
33
- "Sequencing": (lambda frame: initiate_root(frame, 'sequencing'), "Analyze sequencing data."),
34
- "Umap": (lambda frame: initiate_root(frame, 'umap'), "Generate UMAP embeddings with datapoints represented as images."),
35
- "Train Cellpose": (lambda frame: initiate_root(frame, 'train_cellpose'), "Train custom Cellpose models."),
36
- "ML Analyze": (lambda frame: initiate_root(frame, 'ml_analyze'), "Machine learning analysis of data."),
37
- "Cellpose Masks": (lambda frame: initiate_root(frame, 'cellpose_masks'), "Generate Cellpose masks."),
38
- "Cellpose All": (lambda frame: initiate_root(frame, 'cellpose_all'), "Run Cellpose on all images."),
39
- "Map Barcodes": (lambda frame: initiate_root(frame, 'map_barcodes'), "Map barcodes to data."),
40
- "Regression": (lambda frame: initiate_root(frame, 'regression'), "Perform regression analysis."),
41
- "Recruitment": (lambda frame: initiate_root(frame, 'recruitment'), "Analyze recruitment data.")
51
+ "Umap": (lambda frame: initiate_root(self, 'umap'), "Generate UMAP embeddings with datapoints represented as images."),
52
+ "Train Cellpose": (lambda frame: initiate_root(self, 'train_cellpose'), "Train custom Cellpose models."),
53
+ "ML Analyze": (lambda frame: initiate_root(self, 'ml_analyze'), "Machine learning analysis of data."),
54
+ "Cellpose Masks": (lambda frame: initiate_root(self, 'cellpose_masks'), "Generate Cellpose masks."),
55
+ "Cellpose All": (lambda frame: initiate_root(self, 'cellpose_all'), "Run Cellpose on all images."),
56
+ "Map Barcodes": (lambda frame: initiate_root(self, 'map_barcodes'), "Map barcodes to data."),
57
+ "Regression": (lambda frame: initiate_root(self, 'regression'), "Perform regression analysis."),
58
+ "Recruitment": (lambda frame: initiate_root(self, 'recruitment'), "Analyze recruitment data.")
42
59
  }
43
60
 
44
61
  self.selected_app = tk.StringVar()
@@ -50,75 +67,64 @@ class MainApp(tk.Tk):
50
67
  self.load_app(default_app, self.additional_gui_apps[default_app][0])
51
68
 
52
69
  def create_widgets(self):
53
- # Create the menu bar
54
70
  create_menu_bar(self)
55
71
 
56
- # Create a canvas to hold the selected app and other elements
57
- self.canvas = tk.Canvas(self, highlightthickness=0)
58
- self.canvas.grid(row=0, column=0, sticky="nsew")
72
+ # Use a grid layout for centering
59
73
  self.grid_rowconfigure(0, weight=1)
60
74
  self.grid_columnconfigure(0, weight=1)
61
75
 
62
- # Create a frame inside the canvas to hold the main content
63
- self.content_frame = tk.Frame(self.canvas)
76
+ self.content_frame = tk.Frame(self)
64
77
  self.content_frame.grid(row=0, column=0, sticky="nsew")
78
+
79
+ # Center the content frame within the window
80
+ self.content_frame.grid_rowconfigure(0, weight=1)
81
+ self.content_frame.grid_columnconfigure(0, weight=1)
65
82
 
66
- # Center the content frame within the canvas
67
- self.canvas.create_window((self.winfo_screenwidth() // 2, self.winfo_screenheight() // 2), window=self.content_frame, anchor="center")
68
-
69
- # Apply dark style to canvas and content_frame
70
- set_dark_style(ttk.Style(), containers=[self.canvas, self.content_frame])
83
+ self.inner_frame = tk.Frame(self.content_frame)
84
+ self.inner_frame.grid(row=0, column=0)
85
+
86
+ set_dark_style(ttk.Style(), containers=[self.content_frame, self.inner_frame])
71
87
 
72
- # Create startup screen with buttons for each main GUI app and drop-down for additional apps
73
88
  self.create_startup_screen()
74
89
 
75
90
  def create_startup_screen(self):
76
- self.clear_frame(self.content_frame)
91
+ self.clear_frame(self.inner_frame)
77
92
 
78
- # Create frames for the grids
79
- main_buttons_frame = tk.Frame(self.content_frame)
93
+ main_buttons_frame = tk.Frame(self.inner_frame)
80
94
  main_buttons_frame.pack(pady=10)
81
95
  set_dark_style(ttk.Style(), containers=[main_buttons_frame])
82
96
 
83
- additional_buttons_frame = tk.Frame(self.content_frame)
97
+ additional_buttons_frame = tk.Frame(self.inner_frame)
84
98
  additional_buttons_frame.pack(pady=10)
85
99
  set_dark_style(ttk.Style(), containers=[additional_buttons_frame])
86
100
 
87
- # Create a frame for the description below the icon grids
88
- description_frame = tk.Frame(self.content_frame, height=70)
101
+ description_frame = tk.Frame(self.inner_frame, height=70)
89
102
  description_frame.pack(fill=tk.X, pady=10)
90
- description_frame.pack_propagate(False) # Prevent the frame from resizing based on its content
103
+ description_frame.pack_propagate(False)
91
104
  set_dark_style(ttk.Style(), containers=[description_frame])
92
105
 
93
- # Use a Label widget to display descriptions
94
106
  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
107
  self.description_label.pack(fill=tk.BOTH, pady=10)
96
108
 
97
- # Load the logo image and place it in the main apps row
98
109
  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
110
  logo_button.grid(row=0, column=0, padx=5, pady=5)
100
- 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.."
111
+ 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
112
 
102
- # Create icon buttons for the main apps
103
113
  for i, (app_name, app_data) in enumerate(self.main_gui_apps.items()):
104
114
  app_func, app_desc = app_data
105
115
  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
116
  button.grid(row=0, column=i + 1, padx=5, pady=5)
107
117
  self.main_buttons[button] = app_desc
108
118
 
109
- # Create icon buttons for the additional apps
110
119
  for i, (app_name, app_data) in enumerate(self.additional_gui_apps.items()):
111
120
  app_func, app_desc = app_data
112
121
  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
122
  button.grid(row=0, column=i, padx=5, pady=5)
114
123
  self.additional_buttons[button] = app_desc
115
124
 
116
- # Update description initially
117
125
  self.update_description()
118
- #
119
126
 
120
127
  def update_description(self):
121
- # Check all buttons and update description if any has the active color
122
128
  for button, desc in {**self.main_buttons, **self.additional_buttons}.items():
123
129
  if button.canvas.itemcget(button.button_bg, "fill") == self.color_settings['active_color']:
124
130
  self.show_description(desc)
@@ -128,19 +134,17 @@ class MainApp(tk.Tk):
128
134
  def show_description(self, description):
129
135
  if self.description_label.winfo_exists():
130
136
  self.description_label.config(text=description)
131
- self.description_label.update_idletasks() # Ensure the label updates immediately
137
+ self.description_label.update_idletasks()
132
138
 
133
139
  def clear_description(self):
134
140
  if self.description_label.winfo_exists():
135
141
  self.description_label.config(text="")
136
- self.description_label.update_idletasks() # Ensure the label updates immediately
142
+ self.description_label.update_idletasks()
137
143
 
138
144
  def load_app(self, app_name, app_func):
139
- # Clear the current content frame
140
- self.clear_frame(self.canvas)
145
+ self.clear_frame(self.inner_frame)
141
146
 
142
- # Initialize the selected app
143
- app_frame = tk.Frame(self.canvas)
147
+ app_frame = tk.Frame(self.inner_frame)
144
148
  app_frame.pack(fill=tk.BOTH, expand=True)
145
149
  set_dark_style(ttk.Style(), containers=[app_frame])
146
150
  app_func(app_frame)