cellects 0.1.2__py3-none-any.whl → 0.2.6__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 (38) hide show
  1. cellects/__main__.py +65 -25
  2. cellects/config/all_vars_dict.py +18 -17
  3. cellects/core/cellects_threads.py +1034 -396
  4. cellects/core/motion_analysis.py +1664 -2010
  5. cellects/core/one_image_analysis.py +1082 -1061
  6. cellects/core/program_organizer.py +1687 -1316
  7. cellects/core/script_based_run.py +80 -76
  8. cellects/gui/advanced_parameters.py +390 -330
  9. cellects/gui/cellects.py +102 -91
  10. cellects/gui/custom_widgets.py +16 -33
  11. cellects/gui/first_window.py +226 -104
  12. cellects/gui/if_several_folders_window.py +117 -68
  13. cellects/gui/image_analysis_window.py +866 -454
  14. cellects/gui/required_output.py +104 -57
  15. cellects/gui/ui_strings.py +840 -0
  16. cellects/gui/video_analysis_window.py +333 -155
  17. cellects/image_analysis/cell_leaving_detection.py +64 -4
  18. cellects/image_analysis/image_segmentation.py +451 -22
  19. cellects/image_analysis/morphological_operations.py +2166 -1635
  20. cellects/image_analysis/network_functions.py +616 -253
  21. cellects/image_analysis/one_image_analysis_threads.py +94 -153
  22. cellects/image_analysis/oscillations_functions.py +131 -0
  23. cellects/image_analysis/progressively_add_distant_shapes.py +2 -3
  24. cellects/image_analysis/shape_descriptors.py +517 -466
  25. cellects/utils/formulas.py +169 -6
  26. cellects/utils/load_display_save.py +362 -109
  27. cellects/utils/utilitarian.py +86 -9
  28. cellects-0.2.6.dist-info/LICENSE +675 -0
  29. cellects-0.2.6.dist-info/METADATA +829 -0
  30. cellects-0.2.6.dist-info/RECORD +44 -0
  31. cellects/core/one_video_per_blob.py +0 -540
  32. cellects/image_analysis/cluster_flux_study.py +0 -102
  33. cellects-0.1.2.dist-info/LICENSE.odt +0 -0
  34. cellects-0.1.2.dist-info/METADATA +0 -132
  35. cellects-0.1.2.dist-info/RECORD +0 -44
  36. {cellects-0.1.2.dist-info → cellects-0.2.6.dist-info}/WHEEL +0 -0
  37. {cellects-0.1.2.dist-info → cellects-0.2.6.dist-info}/entry_points.txt +0 -0
  38. {cellects-0.1.2.dist-info → cellects-0.2.6.dist-info}/top_level.txt +0 -0
cellects/gui/cellects.py CHANGED
@@ -1,21 +1,24 @@
1
1
  #!/usr/bin/env python3
2
+
2
3
  """
3
- This module contains the Widget that stacks all Cellects widget.
4
- An important note is that user-friendliness and versatility are at the core of Cellects’ development.
5
- Henceforth, the general workflow is in fact, a user-assisted workflow. Every step of the general workflow can
6
- be fine-tuned by the user to cope with various imaging conditions. At every step, automatic algorithms suggest options
7
- to help the user to find the best parameters.
4
+ Main window for Cellects application managing stacked workflow steps.
5
+
6
+ This module implements a user-assisted image analysis workflow using a QStackedWidget to navigate between configuration
7
+ and analysis phases. It provides windows for data setup, image/video processing, output requirements, and
8
+ advanced parameters. Automatic algorithm suggestions are offered at each step while allowing full user customization.
9
+ Uses SaveAllVarsThread in background operations to maintain UI responsiveness.
10
+
11
+ Main Components
12
+ CellectsMainWidget : Central stacked widget managing workflow navigation
13
+
14
+ Notes
15
+ Uses QThread for background operations to maintain UI responsiveness.
8
16
  """
9
17
  import logging
10
18
  import signal
11
-
12
- # necessary on OSX
13
- # pip install cython pyobjus
14
- import sys
15
19
  import numpy as np
16
20
  from PySide6 import QtWidgets, QtGui
17
21
  from screeninfo import get_monitors
18
-
19
22
  from cellects.core.program_organizer import ProgramOrganizer
20
23
  from cellects.core.cellects_threads import SaveAllVarsThread
21
24
  from cellects.gui.advanced_parameters import AdvancedParameters
@@ -25,13 +28,46 @@ from cellects.gui.image_analysis_window import ImageAnalysisWindow
25
28
  from cellects.gui.required_output import RequiredOutput
26
29
  from cellects.gui.video_analysis_window import VideoAnalysisWindow
27
30
 
28
- from cellects.core.cellects_paths import ICONS_DIR
29
-
30
31
 
31
32
  class CellectsMainWidget(QtWidgets.QStackedWidget):
32
- """ Main widget: this is the main window """
33
+ """ Main widget: this is the main window of the Cellects application. """
33
34
 
34
35
  def __init__(self):
36
+ """
37
+
38
+ Initializes the Cellects application window and sets up initial state.
39
+
40
+ Sets the title, dimensions, and default values for various attributes
41
+ required to manage the GUI's state and display settings.
42
+ Initializes a ProgramOrganizer object and loads its variable dictionary.
43
+
44
+ Attributes
45
+ ----------
46
+ pre_processing_done : bool
47
+ Indicates whether pre-processing has been completed.
48
+ last_is_first : bool
49
+ Tracks if the last operation was the first in sequence.
50
+ last_tab : str
51
+ The most recently accessed tab name (default: "data_specifications").
52
+ screen_height : int
53
+ Height of the monitor in pixels.
54
+ screen_width : int
55
+ Width of the monitor in pixels.
56
+ im_max_width : int
57
+ Maximum width allowed for displayed images (default: 570).
58
+ im_max_height : int
59
+ Maximum height allowed for displayed images (default: 266).
60
+ image_window_width_diff : int
61
+ Difference in width between image window and max image size.
62
+ image_window_height_diff : int
63
+ Difference in height between image window and max image size.
64
+ image_to_display : ndarray
65
+ Placeholder for the image to be displayed (initialized as zeros).
66
+ i : int
67
+ Counter or index used in the application.
68
+ po : ProgramOrganizer
69
+ Instance managing the organization and variables of the program.
70
+ """
35
71
  super().__init__()
36
72
 
37
73
  self.setWindowTitle('Cellects')
@@ -41,41 +77,32 @@ class CellectsMainWidget(QtWidgets.QStackedWidget):
41
77
  self.pre_processing_done: bool = False
42
78
  self.screen_height = get_monitors()[0].height
43
79
  self.screen_width = get_monitors()[0].width
44
- self.im_max_width = 570 # self.screen_width // 5 374, 296
45
- self.im_max_height = 266 # self.screen_height // 5 (1369, 778) (1380, 834)
46
- # self.image_window_width_ratio = 570/1380
47
- # self.image_window_height_ratio = 266/750
80
+ self.im_max_width = 570
81
+ self.im_max_height = 266
48
82
  self.image_window_width_diff = 1380 - 570
49
83
  self.image_window_height_diff = 750 - 266
50
84
  self.image_to_display = np.zeros((self.im_max_height, self.im_max_width, 3), np.uint8)
51
- # self.im_max_height = (2 * self.screen_height // 3) // 3
52
- # self.im_max_width = (2 * self.screen_width // 3) // 4
53
85
  self.i = 1
54
86
  self.po = ProgramOrganizer()
55
- # self.subwidgets_stack.po = self.po
56
- self.po.load_variable_dict()
57
- # self.parent().po.all['night_mode'] = True
58
87
 
59
- # self.resize(4 * self.screen_width // 5, 4 * self.screen_height // 5)
88
+ self.po.load_variable_dict()
60
89
  self.resize(1380, 750)
61
90
 
62
- # self.setMaximumWidth(self.screen_width)
63
- # self.setMaximumHeight(self.screen_height)
64
- #
65
- # self.setSizePolicy(
66
- # QtWidgets.QSizePolicy.Maximum,
67
- # QtWidgets.QSizePolicy.Maximum)
68
- #
69
- # self.setSizePolicy(
70
- # QtWidgets.QSizePolicy.Minimum,
71
- # QtWidgets.QSizePolicy.Minimum)
72
- # self.setSizePolicy(
73
- # QtWidgets.QSizePolicy.Expanding,
74
- # QtWidgets.QSizePolicy.Expanding)
75
-
76
91
  def instantiate(self):
77
-
78
- logging.info("instantiate")
92
+ """
93
+ Initiates the Cellects application by setting up the main window and starting various threads.
94
+
95
+ Extended Description
96
+ ---------------------
97
+ This method is responsible for initializing the Cellects application. It sets up the main window, creates necessary widgets, and starts the required threads for background operations.
98
+
99
+ Other Parameters
100
+ ----------------
101
+ night_mode : bool, optional
102
+ Indicates whether the application should run in night mode. This parameter is managed by another part of
103
+ the code and should not be set directly.
104
+ """
105
+ logging.info("Instantiate Cellects")
79
106
  self.firstwindow = FirstWindow(
80
107
  self,
81
108
  night_mode=self.po.all['night_mode'])
@@ -88,17 +115,22 @@ class CellectsMainWidget(QtWidgets.QStackedWidget):
88
115
  self.change_widget(0)
89
116
  self.center()
90
117
 
91
- def instantiate_widgets(self, severalfolder_included=True):
92
- print("Widgets are instantiating")
93
- # for widg_i in np.arange(1, 6):
94
- # widget = self.widget(1)
95
- # if widget is not None:
96
- # self.removeWidget(widget)
97
- # # widget.deleteLater()
98
- if severalfolder_included:
118
+ def instantiate_widgets(self, several_folder_included: bool=True):
119
+ """
120
+ Instantiate various windows for the application's GUI.
121
+
122
+ This function configures the main GUI windows for image and video analysis,
123
+ output requirements, and advanced parameters.
124
+
125
+ Parameters
126
+ ----------
127
+ several_folder_included: bool, optional
128
+ A flag to determine whether the `IfSeveralFoldersWindow` should be instantiated. Default is `True`.
129
+ """
130
+ logging.info("Widgets are instantiating")
131
+ if several_folder_included:
99
132
  self.ifseveralfolderswindow = IfSeveralFoldersWindow(self, night_mode=self.po.all['night_mode'])
100
133
  self.insertWidget(1, self.ifseveralfolderswindow)
101
- # self.ifseveralfolderswindow.setVisible(True)
102
134
  self.imageanalysiswindow = ImageAnalysisWindow(self, night_mode=self.po.all['night_mode'])
103
135
  self.insertWidget(2, self.imageanalysiswindow)
104
136
 
@@ -111,20 +143,12 @@ class CellectsMainWidget(QtWidgets.QStackedWidget):
111
143
  self.advancedparameterswindow = AdvancedParameters(self, night_mode=self.po.all['night_mode'])
112
144
  self.insertWidget(5, self.advancedparameterswindow)
113
145
 
114
- # self.requiredoutputwindow = RequiredOutput(
115
- # self, night_mode=self.po.all['night_mode'])
116
- # self.insertWidget(4, self.requiredoutputwindow)
117
- #
118
- # self.advancedparameterswindow = AdvancedParameters(
119
- # self, night_mode=self.po.all['night_mode'])
120
- # self.insertWidget(5, self.requiredoutputwindow)
121
146
 
122
-
123
- def update_widget(self, idx, widget_to_call):
147
+ def update_widget(self, idx: int, widget_to_call):
124
148
  """ Update widget at its position (idx) in the stack """
125
149
  self.insertWidget(idx, widget_to_call)
126
150
 
127
- def change_widget(self, idx):
151
+ def change_widget(self, idx: int):
128
152
  """ Display a widget using its position (idx) in the stack """
129
153
  self.setCurrentIndex(idx) # Index that new widget
130
154
  self.updateGeometry()
@@ -133,6 +157,13 @@ class CellectsMainWidget(QtWidgets.QStackedWidget):
133
157
  self.currentWidget().display_conditionally_visible_widgets()
134
158
 
135
159
  def center(self):
160
+ """
161
+ Centers the window on the screen.
162
+
163
+ Moves the window to the center of the available screen geometry.
164
+ Allows users to always see the application's windows in a consistent
165
+ position, regardless of screen resolution or window size.
166
+ """
136
167
  qr = self.frameGeometry()
137
168
  # cp = QtWidgets.QDesktopWidget().availableGeometry().center() # PyQt 5
138
169
  cp = QtGui.QGuiApplication.primaryScreen().availableGeometry().center() # Pyside 6
@@ -140,6 +171,19 @@ class CellectsMainWidget(QtWidgets.QStackedWidget):
140
171
  self.move(qr.topLeft())
141
172
 
142
173
  def closeEvent(self, event):
174
+ """
175
+ Close the application window and handle cleanup.
176
+
177
+ Parameters
178
+ ----------
179
+ event : QCloseEvent
180
+ The close event that triggered this function.
181
+
182
+ Notes
183
+ -----
184
+ This function does not return any value and is intended for event
185
+ handling purposes only.
186
+ """
143
187
  reply = QtWidgets.QMessageBox.question(
144
188
  self,
145
189
  'Closing Cellects',
@@ -151,39 +195,6 @@ class CellectsMainWidget(QtWidgets.QStackedWidget):
151
195
  signal.signal(signal.SIGSEGV, signal.SIG_IGN)
152
196
  logging.info("Closing main window.")
153
197
  event.accept()
154
- # QtWidgets.QApplication.quit()
155
198
  self.close()
156
199
  else:
157
200
  event.ignore()
158
- # self.hide()
159
-
160
- # def update_all_settings(self):
161
- # self.firstwindow
162
- # self.imageanalysiswindow
163
- # self.videoanalysiswindow
164
- # requiredoutputwindow = self.widget(4)
165
- # advancedparameterswindow = self.widget(5)
166
-
167
-
168
-
169
- """
170
- Ajouter
171
- are_gravity_centers_moving
172
- Retirer advanced mode de third widget
173
- Inverser gauche et droite de third widget
174
-
175
- drop_nak1 Réduction de la taille de la forme d'origine lors du passage de
176
- luminosity_segmentation à luminosity_segmentation + gradient_segmentation
177
-
178
- Catégories d'Advanced parameters:
179
-
180
- - Spatio-temporal scales: time interval, timmings, convert,
181
- - Analysis parameters: crop, subtract background
182
- - Computer resources: Parallel, proc, ram,
183
- - Video saving: fps, over unaltered, keep unaltered, save processed
184
- - Special cases: correct error around initial shape, connect distant shape,
185
- appearing size threshold, appearing detection method, oscillation period
186
-
187
- if image_analysis is done:
188
- get_average_pixel_size
189
- """
@@ -65,30 +65,12 @@ class WindowType(QtWidgets.QWidget):
65
65
  self.frame = QtWidgets.QFrame(self)
66
66
  self.frame.setGeometry(QtCore.QRect(0, 0, self.parent().screen_width, self.parent().screen_height))
67
67
  self.display_image = None
68
- # self.setFont(QFont(textfont, textsize, QFont.Medium))
69
- # self.setStyleSheet("background-color: %s; color: %s; font: %s; border-color: %s; selection-color: %s; selection-background-color: %s" % (backgroundcolor, textColor, f"{textsize}pt {textfont};", bordercolor, selectioncolor, selectionbackgroundcolor))
70
- # self.setStyleSheet("background-color: %s; color: %s; border-color: %s; selection-color: %s; selection-background-color: %s" % (backgroundcolor, textColor, bordercolor, selectioncolor, selectionbackgroundcolor))
71
-
72
68
  self.setFont(QFont(textfont, textsize, QFont.Medium))
73
69
  self.night_mode_switch(night_mode)
74
- # self.setStyleSheet("background-color: rgb(50,50,65);"
75
- # "color: rgb(255, 255, 255);\n" # 213, 251, 255
76
- # "font: 15pt \"Calibri\";\n"
77
- # "border-color: rgb(50,50,65);\n"
78
- # # "border-color: rgb(0, 150, 75);\n"
79
- # "selection-color: rgb(1, 152, 117);\n" # 0, 150, 75 0, 132, 66 0, 120, 215
80
- # "selection-background-color:rgb(50,50,65);\n" # jsp
81
- # )
82
- # "selection-background-color:rgb(60, 60, 60);\n" # jsp
83
- # "alternate-background-color: rgb(54, 54, 54);\n" # jsp
84
- # "QToolTip { color: rgb(1, 152, 117); background-color: rgb(64,64,64); border: 0px; };\n"
85
- # "")
86
- # self.titles_font = "font: 24pt"
87
70
  self.horizontal_space = QtWidgets.QSpacerItem(1, 1, QtWidgets.QSizePolicy.MinimumExpanding,
88
71
  QtWidgets.QSizePolicy.Maximum)
89
72
  self.vertical_space = QtWidgets.QSpacerItem(1, 1, QtWidgets.QSizePolicy.Maximum,
90
73
  QtWidgets.QSizePolicy.MinimumExpanding)
91
- # self.resized.connect(self.center_window)
92
74
 
93
75
  def resizeEvent(self, event):
94
76
  '''
@@ -116,13 +98,13 @@ class WindowType(QtWidgets.QWidget):
116
98
  def night_mode_switch(self, night_mode):
117
99
  if night_mode:
118
100
  self.setStyleSheet(
119
- "background-color: %s; color: %s; font: %s; border-color: %s; selection-color: %s; selection-background-color: %s" % (
120
- night_background_color, night_text_Color, f"{textsize}pt {textfont};", night_border_color,
101
+ "background-color: %s; color: %s; font: %s; selection-color: %s; selection-background-color: %s" % (
102
+ night_background_color, night_text_Color, f"{textsize}pt {textfont};",
121
103
  night_selection_color, night_selection_background_color))
122
104
  else:
123
105
  self.setStyleSheet(
124
- "background-color: %s; color: %s; font: %s; border-color: %s; selection-color: %s; selection-background-color: %s" % (
125
- backgroundcolor, textColor, f"{textsize}pt {textfont};", bordercolor, selectioncolor,
106
+ "background-color: %s; color: %s; font: %s; selection-color: %s; selection-background-color: %s" % (
107
+ backgroundcolor, textColor, f"{textsize}pt {textfont};", selectioncolor,
126
108
  selectionbackgroundcolor))
127
109
 
128
110
 
@@ -135,9 +117,9 @@ class MainTabsType(WindowType):
135
117
  self.main_tabs_layout = QtWidgets.QHBoxLayout()
136
118
  self.main_tabs_layout.setContentsMargins(0, 0, 0, 0)
137
119
  self.main_tabs_layout.setSpacing(0)
138
- self.data_tab = MainTabsWidget('Data specifications', night_mode=night_mode)
120
+ self.data_tab = MainTabsWidget('Data localisation', night_mode=night_mode)
139
121
  self.image_tab = MainTabsWidget('Image analysis', night_mode=night_mode)
140
- self.video_tab = MainTabsWidget('Video analysis', night_mode=night_mode)
122
+ self.video_tab = MainTabsWidget('Video tracking', night_mode=night_mode)
141
123
  self.main_tabs_layout.addWidget(self.data_tab)
142
124
  self.main_tabs_layout.addWidget(self.image_tab)
143
125
  self.main_tabs_layout.addWidget(self.video_tab)
@@ -237,7 +219,7 @@ class InsertImage(QtWidgets.QLabel):
237
219
 
238
220
 
239
221
  class PButton(QtWidgets.QPushButton):
240
- def __init__(self, text, fade=True, night_mode=False):
222
+ def __init__(self, text, fade=True, tip=None, night_mode=False):
241
223
  """
242
224
 
243
225
  self.setStyleSheet("background-color: rgb(107, 145, 202);\n"
@@ -248,6 +230,7 @@ class PButton(QtWidgets.QPushButton):
248
230
  """
249
231
  super().__init__()
250
232
  self.setText(text)
233
+ self.setToolTip(tip)
251
234
  self.night_mode_switch(night_mode)
252
235
  self.setFont(buttonfont)
253
236
  # self.setStyleSheet("background-color: rgb(50,50,65);\n" #50,50,65 150, 150, 150 153, 204, 205 122, 0, 61 30, 144, 220
@@ -487,12 +470,6 @@ class Spinbox(QtWidgets.QWidget):
487
470
  "background-color: %s; color: %s; border-color: %s; border: %s; border-radius: %s" % (
488
471
  backgroundcolor, textColor, bordercolor, rollingborder, rollingangles))
489
472
 
490
- # self.setStyleSheet("background-color: rgb(50,50,65);\n"
491
- # "font: 16pt \"Calibri\";\n"
492
- # "border-color: rgb(50,50,65);\n"
493
- # # "border-color: rgb(255, 255, 255);\n"
494
- # "color: rgb(213, 251, 255);\n")
495
-
496
473
 
497
474
  class Combobox(QtWidgets.QComboBox):
498
475
  def __init__(self, items_list, current_idx=None, night_mode=False):
@@ -530,8 +507,14 @@ class Checkbox(QtWidgets.QCheckBox):
530
507
  self.setChecked(set_checked)
531
508
  self.setSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
532
509
  self.setMinimumWidth(75)
533
- # self.setStyleSheet("padding:5px")
534
- self.setStyleSheet("margin-left:50%; margin-right:50%;")
510
+ self.setStyleSheet("QCheckBox::indicator {width: 12px;height: 12px;background-color: transparent;"
511
+ "border-radius: 5px;border-style: solid;border-width: 1px;"
512
+ "border-color: rgb(100,100,100);}"
513
+ "QCheckBox::indicator:checked {background-color: rgb(70,130,180);}"
514
+ "QCheckBox:checked, QCheckBox::indicator:checked {border-color: black black white white;}"
515
+ "QCheckBox:checked {background-color: transparent;}"
516
+ "QCheckBox:margin-left {50%}"
517
+ "QCheckBox:margin-right {50%}")
535
518
  self.setCursor(QtCore.Qt.CursorShape.PointingHandCursor)
536
519
 
537
520