spacr 0.1.11__py3-none-any.whl → 0.1.16__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/gui_utils.py CHANGED
@@ -10,7 +10,6 @@ from torchvision import models
10
10
 
11
11
  from tkinter import font as tkFont
12
12
 
13
-
14
13
  from .logger import log_function_call
15
14
 
16
15
  try:
@@ -65,11 +64,11 @@ def load_app(root, app_name, app_func):
65
64
  app_func(root.content_frame)
66
65
 
67
66
  def create_menu_bar(root):
68
- from .gui_mask_app import initiate_mask_root
69
- from .gui_measure_app import initiate_measure_root
70
- from .annotate_app import initiate_annotation_app_root
71
- from .gui_make_masks_app import initiate_mask_app_root
72
- from .gui_classify_app import initiate_classify_root
67
+ from .app_mask import initiate_mask_root
68
+ from .app_measure import initiate_measure_root
69
+ from .app_annotate import initiate_annotation_app_root
70
+ from .app_make_masks import initiate_mask_app_root
71
+ from .app_classify import initiate_classify_root
73
72
 
74
73
  gui_apps = {
75
74
  "Mask": initiate_mask_root,
@@ -96,6 +95,42 @@ def create_menu_bar(root):
96
95
  # Configure the menu for the root window
97
96
  root.config(menu=menu_bar)
98
97
 
98
+ def proceed_with_app(root, app_name, app_func):
99
+
100
+ from .app_mask import gui_mask
101
+ from .app_measure import gui_measure
102
+ from .app_annotate import gui_annotate
103
+ from .app_make_masks import gui_make_masks
104
+ from .app_classify import gui_classify
105
+ from .gui import gui_app
106
+
107
+ # Clear the current content frame
108
+ if hasattr(root, 'content_frame'):
109
+ for widget in root.content_frame.winfo_children():
110
+ widget.destroy()
111
+ else:
112
+ root.content_frame = tk.Frame(root)
113
+ root.content_frame.grid(row=1, column=0, sticky="nsew")
114
+ root.grid_rowconfigure(1, weight=1)
115
+ root.grid_columnconfigure(0, weight=1)
116
+
117
+ # Initialize the new app in the content frame
118
+ if app_name == "Main App":
119
+ root.destroy() # Close the current window
120
+ gui_app() # Open the main app window
121
+ elif app_name == "Mask":
122
+ gui_mask()
123
+ elif app_name == "Measure":
124
+ gui_measure()
125
+ elif app_name == "Annotate":
126
+ gui_annotate()
127
+ elif app_name == "Make Masks":
128
+ gui_make_masks()
129
+ elif app_name == "Classify":
130
+ gui_classify()
131
+ else:
132
+ raise ValueError(f"Invalid app name: {app_name}")
133
+
99
134
  def load_app(root, app_name, app_func):
100
135
  # Cancel all scheduled after tasks
101
136
  if hasattr(root, 'after_tasks'):
@@ -103,35 +138,24 @@ def load_app(root, app_name, app_func):
103
138
  root.after_cancel(task)
104
139
  root.after_tasks = []
105
140
 
106
- def proceed_with_app():
107
- # Clear the current content frame
108
- if hasattr(root, 'content_frame'):
109
- for widget in root.content_frame.winfo_children():
110
- widget.destroy()
111
- else:
112
- root.content_frame = tk.Frame(root)
113
- root.content_frame.grid(row=1, column=0, sticky="nsew")
114
- root.grid_rowconfigure(1, weight=1)
115
- root.grid_columnconfigure(0, weight=1)
116
-
117
- # Initialize the new app in the content frame
118
- app_func(root.content_frame)
119
-
120
141
  # Exit functionality only for the annotation app
121
142
  if app_name != "Annotate" and hasattr(root, 'current_app_exit_func'):
122
143
  root.next_app_func = proceed_with_app
144
+ root.next_app_args = (app_name, app_func) # Ensure correct arguments
123
145
  root.current_app_exit_func()
124
146
  else:
125
- proceed_with_app()
147
+ proceed_with_app(root, app_name, app_func)
126
148
 
127
149
  def create_menu_bar(root):
128
- from .gui_mask_app import initiate_mask_root
129
- from .gui_measure_app import initiate_measure_root
130
- from .annotate_app import initiate_annotation_app_root
131
- from .gui_make_masks_app import initiate_mask_app_root
132
- from .gui_classify_app import initiate_classify_root
150
+ from .app_mask import initiate_mask_root
151
+ from .app_measure import initiate_measure_root
152
+ from .app_annotate import initiate_annotation_app_root
153
+ from .app_make_masks import initiate_mask_app_root
154
+ from .app_classify import initiate_classify_root
155
+ from .gui import gui_app
133
156
 
134
157
  gui_apps = {
158
+ "Main App": gui_app,
135
159
  "Mask": initiate_mask_root,
136
160
  "Measure": initiate_measure_root,
137
161
  "Annotate": initiate_annotation_app_root,
@@ -162,14 +186,19 @@ class CustomButton(tk.Frame):
162
186
  self.text = text
163
187
  self.command = command
164
188
 
165
- self.canvas = tk.Canvas(self, width=150, height=50, highlightthickness=0, bg="black")
189
+ # Detect screen height and calculate button dimensions
190
+ screen_height = self.winfo_screenheight()
191
+ button_height = screen_height // 50
192
+ button_width = button_height * 3
193
+
194
+ self.canvas = tk.Canvas(self, width=button_width, height=button_height, highlightthickness=0, bg="black")
166
195
  self.canvas.grid(row=0, column=0)
167
196
 
168
- self.button_bg = self.create_rounded_rectangle(0, 0, 150, 50, radius=20, fill="#800080")
197
+ self.button_bg = self.create_rounded_rectangle(0, 0, button_width, button_height, radius=20, fill="#800080")
169
198
 
170
199
  # Use the passed font or default to Helvetica if not provided
171
200
  self.font_style = font if font else tkFont.Font(family="Helvetica", size=12, weight=tkFont.NORMAL)
172
- self.button_text = self.canvas.create_text(75, 25, text=self.text, fill="white", font=self.font_style)
201
+ self.button_text = self.canvas.create_text(button_width // 2, button_height // 2, text=self.text, fill="white", font=self.font_style)
173
202
 
174
203
  self.bind("<Enter>", self.on_enter)
175
204
  self.bind("<Leave>", self.on_leave)
@@ -307,38 +336,6 @@ def set_default_font(root, font_name="Helvetica", size=12):
307
336
  root.option_add("*TLabel.Font", default_font)
308
337
  root.option_add("*TEntry.Font", default_font)
309
338
 
310
- def check_and_download_font_v1():
311
- font_name = "Helvetica"
312
- font_dir = "fonts"
313
- font_path = os.path.join(font_dir, "OpenSans-Regular.ttf")
314
-
315
- # Check if the font is already available
316
- available_fonts = list(tkFont.families())
317
- if font_name not in available_fonts:
318
- print(f"Font '{font_name}' not found. Downloading...")
319
- if not os.path.exists(font_dir):
320
- os.makedirs(font_dir)
321
-
322
- if not os.path.exists(font_path):
323
- url = "https://github.com/google/fonts/blob/main/apache/opensans/OpenSans-Regular.ttf?raw=true"
324
- response = requests.get(url)
325
- with open(font_path, "wb") as f:
326
- f.write(response.content)
327
-
328
- # Load the font
329
- try:
330
- tkFont.nametofont("TkDefaultFont").configure(family=font_name, size=10)
331
- tkFont.nametofont("TkTextFont").configure(family=font_name, size=10)
332
- tkFont.nametofont("TkHeadingFont").configure(family=font_name, size=12)
333
- except tk.TclError:
334
- tkFont.nametofont("TkDefaultFont").configure(family="Helvetica", size=10)
335
- tkFont.nametofont("TkTextFont").configure(family="Helvetica", size=10)
336
- tkFont.nametofont("TkHeadingFont").configure(family="Helvetica", size=12)
337
- else:
338
- tkFont.nametofont("TkDefaultFont").configure(family=font_name, size=10)
339
- tkFont.nametofont("TkTextFont").configure(family=font_name, size=10)
340
- tkFont.nametofont("TkHeadingFont").configure(family=font_name, size=12)
341
-
342
339
  def check_and_download_font():
343
340
  font_name = "Helvetica"
344
341
  font_dir = "fonts"
@@ -356,8 +353,6 @@ def check_and_download_font():
356
353
  response = requests.get(url)
357
354
  with open(font_path, "wb") as f:
358
355
  f.write(response.content)
359
-
360
- # Load the font
361
356
  try:
362
357
  tkFont.nametofont("TkDefaultFont").configure(family=font_name, size=10)
363
358
  tkFont.nametofont("TkTextFont").configure(family=font_name, size=10)
@@ -371,32 +366,39 @@ def check_and_download_font():
371
366
  tkFont.nametofont("TkTextFont").configure(family=font_name, size=10)
372
367
  tkFont.nametofont("TkHeadingFont").configure(family=font_name, size=12)
373
368
 
374
- def style_text_boxes_v1(style):
375
- check_and_download_font()
376
- font_style = tkFont.Font(family="Helvetica", size=10) # Define the Helvetica font
377
- style.configure('TEntry', padding='5 5 5 5', borderwidth=1, relief='solid', fieldbackground='#000000', foreground='#ffffff', font=font_style)
378
- style.configure('TCombobox', fieldbackground='#000000', background='#000000', foreground='#ffffff', font=font_style)
369
+ def set_dark_style_v1(style):
370
+ font_style = tkFont.Font(family="Helvetica", size=10)
371
+ style.configure('TEntry', padding='5 5 5 5', borderwidth=1, relief='solid', fieldbackground='black', foreground='#ffffff', font=font_style)
372
+ style.configure('TCombobox', fieldbackground='black', background='black', foreground='#ffffff', font=font_style)
379
373
  style.configure('Custom.TButton', padding='10 10 10 10', borderwidth=1, relief='solid', background='#008080', foreground='#ffffff', font=font_style)
380
374
  style.map('Custom.TButton',
381
375
  background=[('active', '#66b2b2'), ('disabled', '#004d4d'), ('!disabled', '#008080')],
382
376
  foreground=[('active', '#ffffff'), ('disabled', '#888888')])
383
- style.configure('Custom.TLabel', padding='5 5 5 5', borderwidth=1, relief='flat', background='#000000', foreground='#ffffff', font=font_style)
384
- style.configure('TCheckbutton', background='#333333', foreground='#ffffff', indicatoron=False, relief='flat', font=font_style)
377
+ style.configure('Custom.TLabel', padding='5 5 5 5', borderwidth=1, relief='flat', background='black', foreground='#ffffff', font=font_style)
378
+ style.configure('TCheckbutton', background='black', foreground='#ffffff', indicatoron=False, relief='flat', font=font_style)
385
379
  style.map('TCheckbutton', background=[('selected', '#555555'), ('active', '#555555')])
386
380
 
387
- def style_text_boxes(style):
381
+ def set_dark_style(style):
388
382
  font_style = tkFont.Font(family="Helvetica", size=10)
389
- style.configure('TEntry', padding='5 5 5 5', borderwidth=1, relief='solid', fieldbackground='#333333', foreground='#ffffff', font=font_style)
390
- style.configure('TCombobox', fieldbackground='#333333', background='#333333', foreground='#ffffff', font=font_style)
391
- style.configure('Custom.TButton', padding='10 10 10 10', borderwidth=1, relief='solid', background='#008080', foreground='#ffffff', font=font_style)
383
+ style.configure('TEntry', padding='5 5 5 5', borderwidth=1, relief='solid', fieldbackground='black', foreground='#ffffff', font=font_style) # Entry
384
+ style.configure('TCombobox', fieldbackground='black', background='black', foreground='#ffffff', font=font_style) # Combobox
385
+ style.configure('Custom.TButton', padding='10 10 10 10', borderwidth=1, relief='solid', background='#008080', foreground='#ffffff', font=font_style) # Custom Button
392
386
  style.map('Custom.TButton',
393
387
  background=[('active', '#66b2b2'), ('disabled', '#004d4d'), ('!disabled', '#008080')],
394
388
  foreground=[('active', '#ffffff'), ('disabled', '#888888')])
395
- style.configure('Custom.TLabel', padding='5 5 5 5', borderwidth=1, relief='flat', background='#000000', foreground='#ffffff', font=font_style)
396
- style.configure('TCheckbutton', background='#333333', foreground='#ffffff', indicatoron=False, relief='flat', font=font_style)
389
+ style.configure('Custom.TLabel', padding='5 5 5 5', borderwidth=1, relief='flat', background='black', foreground='#ffffff', font=font_style) # Custom Label
390
+ style.configure('TCheckbutton', background='black', foreground='#ffffff', indicatoron=False, relief='flat', font=font_style) # Checkbutton
397
391
  style.map('TCheckbutton', background=[('selected', '#555555'), ('active', '#555555')])
398
-
399
-
392
+ style.configure('TLabel', background='black', foreground='#ffffff', font=font_style) # Label
393
+ style.configure('TFrame', background='black') # Frame
394
+ style.configure('TPanedwindow', background='black') # PanedWindow
395
+ style.configure('TNotebook', background='black', tabmargins=[2, 5, 2, 0]) # Notebook
396
+ style.configure('TNotebook.Tab', background='black', foreground='#ffffff', padding=[5, 5], font=font_style)
397
+ style.map('TNotebook.Tab', background=[('selected', '#555555'), ('active', '#555555')])
398
+ style.configure('TButton', background='black', foreground='#ffffff', padding='5 5 5 5', font=font_style) # Button (regular)
399
+ style.map('TButton', background=[('active', '#555555'), ('disabled', '#333333')])
400
+ style.configure('Vertical.TScrollbar', background='black', troughcolor='black', bordercolor='black') # Scrollbar
401
+ style.configure('Horizontal.TScrollbar', background='black', troughcolor='black', bordercolor='black')
400
402
 
401
403
  def read_settings_from_csv(csv_file_path):
402
404
  settings = {}
@@ -435,36 +437,45 @@ def disable_interactivity(fig):
435
437
  for handler_id in list(handlers.keys()):
436
438
  fig.canvas.mpl_disconnect(handler_id)
437
439
 
438
- class ScrollableFrame(ttk.Frame):
440
+ class ScrollableFrame_v1(ttk.Frame):
439
441
  def __init__(self, container, *args, bg='black', **kwargs):
440
442
  super().__init__(container, *args, **kwargs)
441
- self.configure(style='TFrame') # Ensure this uses the styled frame from dark mode
442
-
443
- canvas = tk.Canvas(self, bg=bg) # Set canvas background to match dark mode
443
+ self.configure(style='TFrame')
444
+ screen_width = self.winfo_screenwidth()
445
+ frame_width = screen_width // 4 # Set the frame width to 1/4th of the screen width
446
+ canvas = tk.Canvas(self, bg=bg, width=frame_width) # Set canvas background to match dark mode
444
447
  scrollbar = ttk.Scrollbar(self, orient="vertical", command=canvas.yview)
445
-
446
- self.scrollable_frame = ttk.Frame(canvas, style='TFrame') # Ensure it uses the styled frame
448
+ self.scrollable_frame = ttk.Frame(canvas, style='TFrame', padding=5) # Ensure it uses the styled frame
447
449
  self.scrollable_frame.bind(
448
450
  "<Configure>",
449
451
  lambda e: canvas.configure(scrollregion=canvas.bbox("all"))
450
452
  )
451
-
452
453
  canvas.create_window((0, 0), window=self.scrollable_frame, anchor="nw")
453
454
  canvas.configure(yscrollcommand=scrollbar.set)
454
-
455
455
  canvas.pack(side="left", fill="both", expand=True)
456
456
  scrollbar.pack(side="right", fill="y")
457
457
 
458
- class StdoutRedirector_v1(object):
459
- def __init__(self, text_widget):
460
- self.text_widget = text_widget
461
-
462
- def write(self, string):
463
- self.text_widget.insert(tk.END, string)
464
- self.text_widget.see(tk.END)
465
-
466
- def flush(self):
467
- pass
458
+ class ScrollableFrame(ttk.Frame):
459
+ def __init__(self, container, width=None, *args, bg='black', **kwargs):
460
+ super().__init__(container, *args, **kwargs)
461
+ self.configure(style='TFrame')
462
+ if width is None:
463
+ screen_width = self.winfo_screenwidth()
464
+ width = screen_width // 4
465
+ canvas = tk.Canvas(self, bg=bg, width=width)
466
+ scrollbar = ttk.Scrollbar(self, orient="vertical", command=canvas.yview)
467
+
468
+ self.scrollable_frame = ttk.Frame(canvas, style='TFrame')
469
+ self.scrollable_frame.bind(
470
+ "<Configure>",
471
+ lambda e: canvas.configure(scrollregion=canvas.bbox("all"))
472
+ )
473
+ canvas.create_window((0, 0), window=self.scrollable_frame, anchor="nw")
474
+ canvas.configure(yscrollcommand=scrollbar.set)
475
+ canvas.pack(side="left", fill="both", expand=True)
476
+ scrollbar.pack(side="right", fill="y")
477
+ for child in self.scrollable_frame.winfo_children():
478
+ child.configure(bg='black')
468
479
 
469
480
  class StdoutRedirector:
470
481
  def __init__(self, text_widget):
@@ -767,7 +778,7 @@ def create_input_field(frame, label_text, row, var_type='entry', options=None, d
767
778
  return (label, entry, var) # Return both the label and the entry, and the variable
768
779
  elif var_type == 'check':
769
780
  var = tk.BooleanVar(value=default_value) # Set default value (True/False)
770
- check = ToggleSwitch(frame, text=label_text, variable=var) # Use ToggleSwitch class
781
+ check = ToggleSwitch(frame, text="", variable=var) # Use ToggleSwitch class
771
782
  check.grid(column=1, row=row, sticky=tk.W, padx=5)
772
783
  return (label, check, var) # Return both the label and the checkbutton, and the variable
773
784
  elif var_type == 'combo':
@@ -780,10 +791,43 @@ def create_input_field(frame, label_text, row, var_type='entry', options=None, d
780
791
  else:
781
792
  var = None # Placeholder in case of an undefined var_type
782
793
  return (label, None, var)
794
+
795
+ def convert_settings_dict_for_gui(settings):
796
+ variables = {}
797
+ special_cases = {
798
+ 'metadata_type': ('combo', ['cellvoyager', 'cq1', 'nikon', 'zeis', 'custom'], 'cellvoyager'),
799
+ 'channels': ('combo', ['[0,1,2,3]', '[0,1,2]', '[0,1]', '[0]'], '[0,1,2,3]'),
800
+ 'magnification': ('combo', [20, 40, 60], 20),
801
+ 'nucleus_channel': ('combo', [0, 1, 2, 3, None], None),
802
+ 'cell_channel': ('combo', [0, 1, 2, 3, None], None),
803
+ 'pathogen_channel': ('combo', [0, 1, 2, 3, None], None),
804
+ 'timelapse_mode': ('combo', ['trackpy', 'btrack'], 'trackpy'),
805
+ 'timelapse_objects': ('combo', ['cell', 'nucleus', 'pathogen', 'cytoplasm', None], None),
806
+ 'model_type': ('combo', ['resnet50', 'other_model'], 'resnet50'),
807
+ 'optimizer_type': ('combo', ['adamw', 'adam'], 'adamw'),
808
+ 'schedule': ('combo', ['reduce_lr_on_plateau', 'step_lr'], 'reduce_lr_on_plateau'),
809
+ 'loss_type': ('combo', ['focal_loss', 'binary_cross_entropy_with_logits'], 'focal_loss'),
810
+ 'normalize_by': ('combo', ['fov', 'png'], 'png'),
811
+ }
812
+ for key, value in settings.items():
813
+ if key in special_cases:
814
+ variables[key] = special_cases[key]
815
+ elif isinstance(value, bool):
816
+ variables[key] = ('check', None, value)
817
+ elif isinstance(value, int) or isinstance(value, float):
818
+ variables[key] = ('entry', None, value)
819
+ elif isinstance(value, str):
820
+ variables[key] = ('entry', None, value)
821
+ elif value is None:
822
+ variables[key] = ('entry', None, value)
823
+ elif isinstance(value, list):
824
+ variables[key] = ('entry', None, str(value))
825
+ return variables
783
826
 
784
827
  def mask_variables():
785
828
  variables = {
786
- 'src': ('entry', None, '/mnt/data/CellVoyager/40x/einar/mitotrackerHeLaToxoDsRed_20240224_123156/test_gui'),
829
+ 'src': ('entry', None, 'path/to/images'),
830
+ 'pathogen_model': ('entry', None, 'path/to/model'),
787
831
  'metadata_type': ('combo', ['cellvoyager', 'cq1', 'nikon', 'zeis', 'custom'], 'cellvoyager'),
788
832
  'custom_regex': ('entry', None, None),
789
833
  'experiment': ('entry', None, 'exp'),
@@ -793,14 +837,17 @@ def mask_variables():
793
837
  'nucleus_background': ('entry', None, 100),
794
838
  'nucleus_Signal_to_noise': ('entry', None, 5),
795
839
  'nucleus_CP_prob': ('entry', None, 0),
840
+ 'remove_background_nucleus': ('check', None, False),
796
841
  'cell_channel': ('combo', [0,1,2,3, None], 3),
797
842
  'cell_background': ('entry', None, 100),
798
843
  'cell_Signal_to_noise': ('entry', None, 5),
799
844
  'cell_CP_prob': ('entry', None, 0),
845
+ 'remove_background_cell': ('check', None, False),
800
846
  'pathogen_channel': ('combo', [0,1,2,3, None], 2),
801
847
  'pathogen_background': ('entry', None, 100),
802
848
  'pathogen_Signal_to_noise': ('entry', None, 3),
803
849
  'pathogen_CP_prob': ('entry', None, 0),
850
+ 'remove_background_pathogen': ('check', None, False),
804
851
  'preprocess': ('check', None, True),
805
852
  'masks': ('check', None, True),
806
853
  'examples_to_plot': ('entry', None, 1),
@@ -816,7 +863,7 @@ def mask_variables():
816
863
  'fps': ('entry', None, 2),
817
864
  'remove_background': ('check', None, True),
818
865
  'lower_quantile': ('entry', None, 0.01),
819
- 'merge': ('check', None, False),
866
+ #'merge': ('check', None, False),
820
867
  'normalize_plots': ('check', None, True),
821
868
  'all_to_mip': ('check', None, False),
822
869
  'pick_slice': ('check', None, False),
@@ -825,6 +872,11 @@ def mask_variables():
825
872
  'plot': ('check', None, True),
826
873
  'workers': ('entry', None, 30),
827
874
  'verbose': ('check', None, True),
875
+ 'filter': ('check', None, True),
876
+ 'merge_pathogens': ('check', None, True),
877
+ 'adjust_cells': ('check', None, True),
878
+ 'test_images': ('entry', None, 10),
879
+ 'random_test': ('check', None, True),
828
880
  }
829
881
  return variables
830
882
 
@@ -845,7 +897,7 @@ def add_mask_gui_defaults(settings):
845
897
 
846
898
  def generate_fields(variables, scrollable_frame):
847
899
  vars_dict = {}
848
- row = 0
900
+ row = 5
849
901
  tooltips = {
850
902
  "src": "Path to the folder containing the images.",
851
903
  "metadata_type": "Type of metadata to expect in the images. This will determine how the images are processed. If 'custom' is selected, you can provide a custom regex pattern to extract metadata from the image names",
@@ -967,12 +1019,6 @@ def create_dark_mode(root, style, console_output):
967
1019
  if console_output != None:
968
1020
  console_output.config(bg=dark_bg, fg=light_text, insertbackground=light_text) #, font=("Helvetica", 12)
969
1021
  root.configure(bg=dark_bg)
970
-
971
- def set_dark_style(style):
972
- style.configure('TFrame', background='black')
973
- style.configure('TLabel', background='black', foreground='white')
974
- style.configure('TEntry', background='black', foreground='white')
975
- style.configure('TCheckbutton', background='black', foreground='white')
976
1022
 
977
1023
  ##@log_function_call
978
1024
  def main_thread_update_function(root, q, fig_queue, canvas_widget, progress_label):
spacr/make_masks_app.py CHANGED
@@ -905,7 +905,9 @@ def initiate_mask_app_root(parent_frame):
905
905
 
906
906
  def gui_make_masks():
907
907
  root = tk.Tk()
908
- root.geometry("1000x800")
908
+ width = root.winfo_screenwidth()
909
+ height = root.winfo_screenheight()
910
+ root.geometry(f"{width}x{height}")
909
911
  root.title("Mask Application")
910
912
 
911
913
  # Clear previous content if any
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: spacr
3
- Version: 0.1.11
3
+ Version: 0.1.16
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,7 +9,6 @@ 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: dgl ==0.9.1
13
12
  Requires-Dist: torch <3.0,>=2.2.1
14
13
  Requires-Dist: torchvision <1.0,>=0.17.1
15
14
  Requires-Dist: torch-geometric <3.0,>=2.5.1
@@ -40,12 +39,8 @@ Requires-Dist: ttf-opensans >=2020.10.30
40
39
  Requires-Dist: customtkinter <6.0,>=5.2.2
41
40
  Requires-Dist: biopython <2.0,>=1.80
42
41
  Requires-Dist: lxml <6.0,>=5.1.0
43
- Requires-Dist: qtpy <2.5,>=2.4.1
44
- Requires-Dist: superqt <0.7,>=0.6.7
45
- Requires-Dist: pyqt6 <6.8,>=6.7.1
46
- Requires-Dist: pyqtgraph <0.14,>=0.13.7
47
42
  Provides-Extra: dev
48
- Requires-Dist: pytest >=3.9 ; extra == 'dev'
43
+ Requires-Dist: pytest <3.11,>=3.9 ; extra == 'dev'
49
44
  Provides-Extra: full
50
45
  Requires-Dist: opencv-python ; extra == 'full'
51
46
  Provides-Extra: headless
@@ -67,7 +62,7 @@ Requires-Dist: opencv-python-headless ; extra == 'headless'
67
62
  SpaCr
68
63
  =====
69
64
 
70
- Spatial phenotype analysis of CRISPR-Cas9 screens (SpaCr). The spatial organization of organelles and proteins within cells constitutes a key level of functional regulation. In the context of infectious disease, the spatial relationships between host cell structures and intracellular pathogens are critical to understand host clearance mechanisms and how pathogens evade them. SpaCr is a Python-based software package for generating single-cell image data for deep-learning sub-cellular/cellular phenotypic classification from pooled genetic CRISPR-Cas9 screens. 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.
65
+ Spatial phenotype analysis of CRISPR-Cas9 screens (SpaCr). The spatial organization of organelles and proteins within cells constitutes a key level of functional regulation. In the context of infectious disease, the spatial relationships between host cell structures and intracellular pathogens are critical to understanding host clearance mechanisms and how pathogens evade them. SpaCr is a Python-based software package for generating single-cell image data for deep-learning sub-cellular/cellular phenotypic classification from pooled genetic CRISPR-Cas9 screens. 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.
71
66
 
72
67
  Features
73
68
  --------
@@ -76,9 +71,9 @@ Features
76
71
 
77
72
  - **Object Measurements:** Measurements for each object including scikit-image-regionprops, intensity percentiles, shannon-entropy, pearsons and manders correlations, homogeneity, and radial distribution. Measurements are saved to a SQL database in object-level tables.
78
73
 
79
- - **Crop Images:** Objects (e.g., cells) can be saved as PNGs from the object area or bounding box area of each object. Object paths are saved in a SQL database that can be annotated and used to train CNNs/Transformer models for classification tasks.
74
+ - **Crop Images:** Save objects (cells, nuclei, pathogen, cytoplasm) as images. Object image paths are saved in a SQL database.
80
75
 
81
- - **Train CNNs or Transformers:** Train Torch Convolutional Neural Networks (CNNs) or Transformers to classify single object images. Train Torch models with IRM/ERM, checkpointing.
76
+ - **Train CNNs or Transformers:** Train Torch models to classify single object images.
82
77
 
83
78
  - **Manual Annotation:** Supports manual annotation of single-cell images and segmentation to refine training datasets for training CNNs/Transformers or cellpose, respectively.
84
79
 
@@ -95,29 +90,20 @@ Features
95
90
  Installation
96
91
  ------------
97
92
 
98
- Requires Tkinter for graphical user interface features.
93
+ If using Windows, switch to Linux—it's free, open-source, and better.
99
94
 
100
- Ubuntu
101
- ~~~~~~
95
+ Before installing SpaCr on OSX ensure OpenMP is installed::
102
96
 
103
- Before installing SpaCr, ensure Tkinter is installed:
97
+ brew install libomp
104
98
 
105
- (Tkinter is included with the standard Python installation on macOS, and Windows)
106
-
107
- On Linux:
108
-
109
- ::
99
+ SpaCr GUI requires Tkinter. On Linux, ensure Tkinter is installed. (Tkinter is included with the standard Python installation on macOS and Windows)::
110
100
 
111
101
  sudo apt-get install python3-tk
112
102
 
113
- Install spacr with pip
114
-
115
- ::
103
+ Install SpaCr with pip::
116
104
 
117
105
  pip install spacr
118
106
 
119
- Run spacr GUI:
120
-
121
- ::
107
+ Run SpaCr GUI::
122
108
 
123
- gui
109
+ spacr
@@ -1,8 +1,14 @@
1
- spacr/__init__.py,sha256=M16gIwyDInyfifwm0w9F0RKEbIoG0O4TMO_bdFYtfBc,1373
1
+ spacr/__init__.py,sha256=xu2zNv8A523YvDACynkThH2CYqN5mafsu9lfKGjMmIM,1278
2
2
  spacr/__main__.py,sha256=bkAJJD2kjIqOP-u1kLvct9jQQCeUXzlEjdgitwi1Lm8,75
3
3
  spacr/alpha.py,sha256=Y95sLEfpK2OSYKRn3M8eUOU33JJeXfV8zhrC4KnwSTY,35244
4
4
  spacr/annotate_app.py,sha256=imQ7ZEXDyM6ce1dxZ1xUS1-KequuF_NCI4xCaPLjvco,29275
5
5
  spacr/annotate_app_v2.py,sha256=imQ7ZEXDyM6ce1dxZ1xUS1-KequuF_NCI4xCaPLjvco,29275
6
+ spacr/app_annotate.py,sha256=27NzovmbcSa-zdqo9WrFfBcggybhVQmKbgSBDTFnSvU,23588
7
+ spacr/app_classify.py,sha256=7UKRGW245Chtxc_oCmyS-4omQpffvzzBvsHmC5ey4v8,8665
8
+ spacr/app_make_masks.py,sha256=ksggY0xBWt7Fgbd451JOabA064kcjiDm8MTslUq1FLo,45088
9
+ spacr/app_make_masks_v2.py,sha256=csZbUFhOfdHCQ1Wi21bgC1PG8ll5InMqUVmY3-90xlc,30543
10
+ spacr/app_mask.py,sha256=dDZyIlI71vSMqBT3tC9I3BN8J0kxRf9-h5gBiI7pWZk,11357
11
+ spacr/app_measure.py,sha256=jOhtqpO6BQSEpeUZA3taR9jThmo0J7BXMq1URzrdyjA,10841
6
12
  spacr/chris.py,sha256=YlBjSgeZaY8HPy6jkrT_ISAnCMAKVfvCxF0I9eAZLFM,2418
7
13
  spacr/classify_app.py,sha256=Zi15ryc1ocYitRF4kyxlC27XxGyzfSPdvj2d6ZrSh7E,8446
8
14
  spacr/cli.py,sha256=507jfOOEV8BoL4eeUcblvH-iiDHdBrEVJLu1ghAAPSc,1800
@@ -11,7 +17,7 @@ spacr/deep_spacr.py,sha256=N0o7ILD2p1FTfU4DFxnpjs00xjLhwib-ev0XGqA6muU,37035
11
17
  spacr/foldseek.py,sha256=YIP1d4Ci6CeA9jSyiv-HTDbNmAmcSM9Y_DaOs7wYzLY,33546
12
18
  spacr/get_alfafold_structures.py,sha256=ehx_MQgb12k3hFecP6cYVlm5TLO8iWjgevy8ESyS3cw,3544
13
19
  spacr/graph_learning.py,sha256=1tR-ZxvXE3dBz1Saw7BeVFcrsUFu9OlUZeZVifih9eo,13070
14
- spacr/gui.py,sha256=5kKGKa-iZ5DxAOquW2IkNCP8C87nVKNOA3eONOa7iHo,6559
20
+ spacr/gui.py,sha256=xyf2bmAck8OrbYlvNLpY6rs4EuhuCOxff3f8ZcEZHBQ,6594
15
21
  spacr/gui_2.py,sha256=ZAI5quQYbhQJ40vK0NCqU_UMSPLkpfeQpomBWUSM0fc,6946
16
22
  spacr/gui_annotate.py,sha256=ugBksLGOHdtOLlEuRyyc59TrkYKu3rDf8JxEgiBSVao,6536
17
23
  spacr/gui_classify_app.py,sha256=Zi15ryc1ocYitRF4kyxlC27XxGyzfSPdvj2d6ZrSh7E,8446
@@ -20,10 +26,10 @@ spacr/gui_make_masks_app_v2.py,sha256=X3izTBXdCZDlkVe-fbG-jmCQtcAbmK0OIivjyWaLhu
20
26
  spacr/gui_mask_app.py,sha256=mhTl_XzXLFl8Tx3WYEMpdYB_qw9u5JJa0EdkvlcIzAE,10706
21
27
  spacr/gui_measure_app.py,sha256=_C1-XFL5HSquUEEbM_NcxdvHx-socPFCx85MBG4d6xo,10598
22
28
  spacr/gui_sim_app.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
- spacr/gui_utils.py,sha256=elvnIAd-bqVmwzDihg-g_RqWayvkrVpZJGDMskdn-HE,55663
29
+ spacr/gui_utils.py,sha256=emUGYxxk9LOsYk2ozLc6mfglzeb4WqBwYhXwitLLJBA,58746
24
30
  spacr/io.py,sha256=IoERqSwoxJrInYl-E0WfwFOEDZXFdJofk5DmpbyLGWM,112077
25
31
  spacr/logger.py,sha256=7Zqr3TuuOQLWT32gYr2q1qvv7x0a2JhLANmZcnBXAW8,670
26
- spacr/make_masks_app.py,sha256=tl4M4Q2WQgrrwjRBJVevxJxpNowqzPhWkdCOm2UfRbw,45053
32
+ spacr/make_masks_app.py,sha256=iGaTwhowoe2JMOSOf8bJwQZTooRhLQx7KO0ewnAmqDY,45138
27
33
  spacr/make_masks_app_v2.py,sha256=X3izTBXdCZDlkVe-fbG-jmCQtcAbmK0OIivjyWaLhug,30576
28
34
  spacr/mask_app.py,sha256=mhTl_XzXLFl8Tx3WYEMpdYB_qw9u5JJa0EdkvlcIzAE,10706
29
35
  spacr/measure.py,sha256=0FRsHF5ftar4JZ0B_6Nq-NlyP5t6aiO0IrskyikIBEE,55000
@@ -40,9 +46,9 @@ spacr/version.py,sha256=axH5tnGwtgSnJHb5IDhiu4Zjk5GhLyAEDRe-rnaoFOA,409
40
46
  spacr/models/cp/toxo_plaque_cyto_e25000_X1120_Y1120.CP_model,sha256=z8BbHWZPRnE9D_BHO0fBREE85c1vkltDs-incs2ytXQ,26566572
41
47
  spacr/models/cp/toxo_plaque_cyto_e25000_X1120_Y1120.CP_model_settings.csv,sha256=fBAGuL_B8ERVdVizO3BHozTDSbZUh1yFzsYK3wkQN68,420
42
48
  spacr/models/cp/toxo_pv_lumen.CP_model,sha256=2y_CindYhmTvVwBH39SNILF3rI3x9SsRn6qrMxHy3l0,26562451
43
- spacr-0.1.11.dist-info/LICENSE,sha256=SR-2MeGc6SCM1UORJYyarSWY_A-JaOMFDj7ReSs9tRM,1083
44
- spacr-0.1.11.dist-info/METADATA,sha256=FykpqeYP5uOY3XnsUaqwe2tSctPILiguTqqPNOJZ4Vg,5301
45
- spacr-0.1.11.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
46
- spacr-0.1.11.dist-info/entry_points.txt,sha256=PxmdWbth1nQzQfE0s2M3XST_of47tBtlBPH20KJrvkE,354
47
- spacr-0.1.11.dist-info/top_level.txt,sha256=GJPU8FgwRXGzKeut6JopsSRY2R8T3i9lDgya42tLInY,6
48
- spacr-0.1.11.dist-info/RECORD,,
49
+ spacr-0.1.16.dist-info/LICENSE,sha256=SR-2MeGc6SCM1UORJYyarSWY_A-JaOMFDj7ReSs9tRM,1083
50
+ spacr-0.1.16.dist-info/METADATA,sha256=-VoJLJbzVVNvGhVmWA2uh5DydW0W4KjiCnz5WYwgLlQ,5004
51
+ spacr-0.1.16.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
52
+ spacr-0.1.16.dist-info/entry_points.txt,sha256=e6tBSk-bac5ypML_iWIROnQ-hDSLZT_sGpGviPNHG4g,277
53
+ spacr-0.1.16.dist-info/top_level.txt,sha256=GJPU8FgwRXGzKeut6JopsSRY2R8T3i9lDgya42tLInY,6
54
+ spacr-0.1.16.dist-info/RECORD,,
@@ -0,0 +1,8 @@
1
+ [console_scripts]
2
+ annotate = spacr.app_annotate:gui_annotate
3
+ classify = spacr.app_classify:gui_classify
4
+ make_masks = spacr.app_make_mask:gui_make_masks
5
+ mask = spacr.app_mask:gui_mask
6
+ measure = spacr.app_measure:gui_measure
7
+ sim = spacr.app_sim:gui_sim
8
+ spacr = spacr.gui:gui_app
@@ -1,9 +0,0 @@
1
- [console_scripts]
2
- annotate = spacr.annotate_app_v2:gui_annotate
3
- classify = spacr.gui_classify_app:gui_classify
4
- gui = spacr.gui:gui_app
5
- make_masks = spacr.gui_make_mask_app:gui_make_masks
6
- make_masks2 = spacr.gui_make_mask_app_v2:gui_make_masks
7
- mask = spacr.gui_mask_app:gui_mask
8
- measure = spacr.gui_measure_app:gui_measure
9
- sim = spacr.gui_sim_app:gui_sim
File without changes