cellects 0.3.1__py3-none-any.whl → 0.3.5__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.
- cellects/core/cellects_paths.py +1 -1
- cellects/core/script_based_run.py +5 -1
- cellects/gui/advanced_parameters.py +21 -32
- cellects/gui/cellects.py +10 -4
- cellects/gui/custom_widgets.py +4 -103
- cellects/gui/first_window.py +37 -43
- cellects/gui/if_several_folders_window.py +11 -18
- cellects/gui/image_analysis_window.py +103 -119
- cellects/gui/required_output.py +7 -16
- cellects/gui/video_analysis_window.py +50 -65
- cellects/image_analysis/shape_descriptors.py +1 -1
- cellects/utils/load_display_save.py +2 -2
- {cellects-0.3.1.dist-info → cellects-0.3.5.dist-info}/METADATA +10 -10
- {cellects-0.3.1.dist-info → cellects-0.3.5.dist-info}/RECORD +18 -18
- {cellects-0.3.1.dist-info → cellects-0.3.5.dist-info}/LICENSE +0 -0
- {cellects-0.3.1.dist-info → cellects-0.3.5.dist-info}/WHEEL +0 -0
- {cellects-0.3.1.dist-info → cellects-0.3.5.dist-info}/entry_points.txt +0 -0
- {cellects-0.3.1.dist-info → cellects-0.3.5.dist-info}/top_level.txt +0 -0
cellects/gui/first_window.py
CHANGED
|
@@ -73,12 +73,12 @@ class FirstWindow(MainTabsType):
|
|
|
73
73
|
self.data_tab.set_in_use()
|
|
74
74
|
self.image_tab.set_not_usable()
|
|
75
75
|
self.video_tab.set_not_usable()
|
|
76
|
-
self.
|
|
77
|
-
self.
|
|
78
|
-
self.
|
|
79
|
-
self.
|
|
80
|
-
self.
|
|
81
|
-
self.
|
|
76
|
+
self.thread_dict = {}
|
|
77
|
+
self.thread_dict["LookForData"] = LookForDataThreadInFirstW(self.parent())
|
|
78
|
+
self.thread_dict["RunAll"] = RunAllThread(self.parent())
|
|
79
|
+
self.thread_dict["LoadDataToRunCellectsQuickly"] = LoadDataToRunCellectsQuicklyThread(self.parent())
|
|
80
|
+
self.thread_dict["GetFirstIm"] = GetFirstImThread(self.parent())
|
|
81
|
+
self.thread_dict["GetExifDataThread"] = GetExifDataThread(self.parent())
|
|
82
82
|
self.instantiate: bool = True
|
|
83
83
|
self.title_label = FixedText('Cellects', police=60, night_mode=self.parent().po.all['night_mode'])
|
|
84
84
|
self.title_label.setAlignment(QtCore.Qt.AlignHCenter)
|
|
@@ -86,7 +86,7 @@ class FirstWindow(MainTabsType):
|
|
|
86
86
|
|
|
87
87
|
self.Vlayout.addWidget(self.title_label)
|
|
88
88
|
self.Vlayout.addWidget(self.subtitle_line)
|
|
89
|
-
self.Vlayout.addItem(
|
|
89
|
+
self.Vlayout.addItem(QtWidgets.QSpacerItem(1, 1, QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.MinimumExpanding))
|
|
90
90
|
|
|
91
91
|
# 1) Set if this a Image list or Videos
|
|
92
92
|
# Open the layout:
|
|
@@ -99,10 +99,10 @@ class FirstWindow(MainTabsType):
|
|
|
99
99
|
self.im_or_vid.setFixedWidth(150)
|
|
100
100
|
self.im_or_vid.currentTextChanged.connect(self.im2vid)
|
|
101
101
|
# Set their positions on layout
|
|
102
|
-
self.second_row_layout.addItem(
|
|
102
|
+
self.second_row_layout.addItem(QtWidgets.QSpacerItem(1, 1, QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Maximum))
|
|
103
103
|
self.second_row_layout.addWidget(self.im_or_vid_label)
|
|
104
104
|
self.second_row_layout.addWidget(self.im_or_vid)
|
|
105
|
-
self.second_row_layout.addItem(
|
|
105
|
+
self.second_row_layout.addItem(QtWidgets.QSpacerItem(1, 1, QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Maximum))
|
|
106
106
|
self.second_row_widget.setLayout(self.second_row_layout)
|
|
107
107
|
self.Vlayout.addWidget(self.second_row_widget)
|
|
108
108
|
|
|
@@ -143,13 +143,13 @@ class FirstWindow(MainTabsType):
|
|
|
143
143
|
self.extension.textChanged.connect(self.re_instantiate_widgets)
|
|
144
144
|
|
|
145
145
|
# Set their positions on layout
|
|
146
|
-
self.third_row_layout.addItem(
|
|
146
|
+
self.third_row_layout.addItem(QtWidgets.QSpacerItem(1, 1, QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Maximum))
|
|
147
147
|
self.third_row_layout.addWidget(self.radical_label)
|
|
148
148
|
self.third_row_layout.addWidget(self.radical)
|
|
149
|
-
# self.third_row_layout.addItem(
|
|
149
|
+
# self.third_row_layout.addItem(QtWidgets.QSpacerItem(1, 1, QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Maximum))
|
|
150
150
|
self.third_row_layout.addWidget(self.extension_label)
|
|
151
151
|
self.third_row_layout.addWidget(self.extension)
|
|
152
|
-
self.third_row_layout.addItem(
|
|
152
|
+
self.third_row_layout.addItem(QtWidgets.QSpacerItem(1, 1, QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Maximum))
|
|
153
153
|
self.third_row_widget.setLayout(self.third_row_layout)
|
|
154
154
|
self.Vlayout.addWidget(self.third_row_widget)
|
|
155
155
|
# If im_or_vid changes, adjust these 2 widgets
|
|
@@ -180,13 +180,13 @@ class FirstWindow(MainTabsType):
|
|
|
180
180
|
|
|
181
181
|
self.fourth_row_widget = QtWidgets.QWidget()
|
|
182
182
|
self.fourth_row_layout = QtWidgets.QHBoxLayout()
|
|
183
|
-
self.fourth_row_layout.addItem(
|
|
183
|
+
self.fourth_row_layout.addItem(QtWidgets.QSpacerItem(1, 1, QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Maximum))
|
|
184
184
|
self.fourth_row_layout.addWidget(self.arena_number_label)
|
|
185
185
|
self.fourth_row_layout.addWidget(self.arena_number)
|
|
186
|
-
self.fourth_row_layout.addItem(
|
|
186
|
+
self.fourth_row_layout.addItem(QtWidgets.QSpacerItem(1, 1, QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Maximum))
|
|
187
187
|
self.fourth_row_widget.setLayout(self.fourth_row_layout)
|
|
188
188
|
self.Vlayout.addWidget(self.fourth_row_widget)
|
|
189
|
-
self.Vlayout.addItem(
|
|
189
|
+
self.Vlayout.addItem(QtWidgets.QSpacerItem(1, 1, QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.MinimumExpanding))
|
|
190
190
|
|
|
191
191
|
# Add the central image display widget
|
|
192
192
|
self.display_image = np.zeros((self.parent().im_max_height, self.parent().im_max_width, 3), np.uint8)
|
|
@@ -215,11 +215,11 @@ class FirstWindow(MainTabsType):
|
|
|
215
215
|
self.Run_all_directly.clicked.connect(self.Run_all_directly_is_clicked)
|
|
216
216
|
self.Run_all_directly.setVisible(False)
|
|
217
217
|
|
|
218
|
-
self.shortcuts_layout.addItem(
|
|
218
|
+
self.shortcuts_layout.addItem(QtWidgets.QSpacerItem(1, 1, QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Maximum))
|
|
219
219
|
self.shortcuts_layout.addWidget(self.advanced_parameters)
|
|
220
220
|
self.shortcuts_layout.addWidget(self.required_outputs)
|
|
221
221
|
self.shortcuts_layout.addWidget(self.Run_all_directly)
|
|
222
|
-
self.shortcuts_layout.addItem(
|
|
222
|
+
self.shortcuts_layout.addItem(QtWidgets.QSpacerItem(1, 1, QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Maximum))
|
|
223
223
|
self.shortcuts_widget.setLayout(self.shortcuts_layout)
|
|
224
224
|
self.Vlayout.addWidget(self.shortcuts_widget)
|
|
225
225
|
|
|
@@ -236,7 +236,7 @@ class FirstWindow(MainTabsType):
|
|
|
236
236
|
self.image_tab.clicked.connect(self.next_is_clicked)
|
|
237
237
|
self.next.clicked.connect(self.next_is_clicked)
|
|
238
238
|
# Add widgets to the last_row_layout
|
|
239
|
-
self.last_row_layout.addItem(
|
|
239
|
+
self.last_row_layout.addItem(QtWidgets.QSpacerItem(1, 1, QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Maximum))
|
|
240
240
|
self.last_row_layout.addWidget(self.message)
|
|
241
241
|
self.last_row_layout.addWidget(self.next)
|
|
242
242
|
# Close the last_row_layout
|
|
@@ -342,7 +342,7 @@ class FirstWindow(MainTabsType):
|
|
|
342
342
|
Checks if certain threads are running, updates parent object's attributes,
|
|
343
343
|
and starts a data-looking thread if conditions are met.
|
|
344
344
|
"""
|
|
345
|
-
if not self.
|
|
345
|
+
if not self.thread_dict["LookForData"].isRunning() and not self.thread_dict["RunAll"].isRunning():
|
|
346
346
|
self.parent().po.all['im_or_vid'] = self.im_or_vid.currentIndex()
|
|
347
347
|
self.parent().po.all['radical'] = self.radical.text()
|
|
348
348
|
self.parent().po.all['extension'] = self.extension.text()
|
|
@@ -360,8 +360,8 @@ class FirstWindow(MainTabsType):
|
|
|
360
360
|
self.message.setText('')
|
|
361
361
|
self.message.setText(f"Looking for {self.parent().po.all['radical']}***{self.parent().po.all['extension']} Wait...")
|
|
362
362
|
self.message.setStyleSheet("color: rgb(230, 145, 18)")
|
|
363
|
-
self.
|
|
364
|
-
self.
|
|
363
|
+
self.thread_dict["LookForData"].start()
|
|
364
|
+
self.thread_dict["LookForData"].finished.connect(self.when_look_for_data_finished)
|
|
365
365
|
else:
|
|
366
366
|
self.message.setText('Analysis has already begun, wait or restart Cellects.')
|
|
367
367
|
|
|
@@ -389,8 +389,8 @@ class FirstWindow(MainTabsType):
|
|
|
389
389
|
self.instantiate = False
|
|
390
390
|
self.parent().change_widget(1) # IfSeveralFoldersWindow
|
|
391
391
|
else:
|
|
392
|
-
self.
|
|
393
|
-
self.
|
|
392
|
+
self.thread_dict["GetFirstIm"].start()
|
|
393
|
+
self.thread_dict["GetFirstIm"].message_when_thread_finished.connect(self.first_im_read)
|
|
394
394
|
|
|
395
395
|
def first_im_read(self, greyscale):
|
|
396
396
|
"""
|
|
@@ -409,7 +409,7 @@ class FirstWindow(MainTabsType):
|
|
|
409
409
|
self.parent().change_widget(2) # imageanalysiswindow
|
|
410
410
|
# From now on, image analysis will be available from video analysis:
|
|
411
411
|
self.parent().videoanalysiswindow.image_tab.set_not_in_use()
|
|
412
|
-
self.
|
|
412
|
+
self.thread_dict["GetExifDataThread"].start()
|
|
413
413
|
|
|
414
414
|
def required_outputs_is_clicked(self):
|
|
415
415
|
"""
|
|
@@ -433,7 +433,7 @@ class FirstWindow(MainTabsType):
|
|
|
433
433
|
This function updates the display for advanced parameters only if no Exif data reading thread is running.
|
|
434
434
|
If a thread is active, it informs the user to wait or restart Cellects.
|
|
435
435
|
"""
|
|
436
|
-
if self.
|
|
436
|
+
if self.thread_dict["GetExifDataThread"].isRunning():
|
|
437
437
|
self.message.setText("Reading data, wait or restart Cellects")
|
|
438
438
|
else:
|
|
439
439
|
self.parent().last_is_first = True
|
|
@@ -451,7 +451,7 @@ class FirstWindow(MainTabsType):
|
|
|
451
451
|
This function also save the id of the following window for later use.
|
|
452
452
|
"""
|
|
453
453
|
if self.video_tab.state != "not_usable":
|
|
454
|
-
if self.
|
|
454
|
+
if self.thread_dict["LookForData"].isRunning() or self.thread_dict["LoadDataToRunCellectsQuickly"].isRunning() or self.thread_dict["GetFirstIm"].isRunning() or self.thread_dict["RunAll"].isRunning():
|
|
455
455
|
self.message.setText("Wait for the analysis to end, or restart Cellects")
|
|
456
456
|
else:
|
|
457
457
|
self.parent().last_tab = "data_specifications"
|
|
@@ -471,12 +471,12 @@ class FirstWindow(MainTabsType):
|
|
|
471
471
|
- The method updates the UI to indicate that an analysis has started and displays
|
|
472
472
|
progress messages.
|
|
473
473
|
"""
|
|
474
|
-
if not self.
|
|
474
|
+
if not self.thread_dict["LookForData"].isRunning() and not self.thread_dict["RunAll"].isRunning():
|
|
475
475
|
self.parent().po.motion = None
|
|
476
476
|
self.message.setText("Complete analysis has started, wait until this message disappear...")
|
|
477
|
-
self.
|
|
478
|
-
self.
|
|
479
|
-
self.
|
|
477
|
+
self.thread_dict["RunAll"].start()
|
|
478
|
+
self.thread_dict["RunAll"].message_from_thread.connect(self.display_message_from_thread)
|
|
479
|
+
self.thread_dict["RunAll"].image_from_thread.connect(self.display_image_during_thread)
|
|
480
480
|
self.display_image.setVisible(True)
|
|
481
481
|
|
|
482
482
|
def pathway_changed(self):
|
|
@@ -496,8 +496,8 @@ class FirstWindow(MainTabsType):
|
|
|
496
496
|
This method performs actions to prepare the application for loading data from a new pathway.
|
|
497
497
|
It ensures that certain widgets are hidden and starts necessary background processes.
|
|
498
498
|
"""
|
|
499
|
-
if self.
|
|
500
|
-
self.
|
|
499
|
+
if self.thread_dict["LoadDataToRunCellectsQuickly"].isRunning():
|
|
500
|
+
self.thread_dict["LoadDataToRunCellectsQuickly"].wait()
|
|
501
501
|
if os.path.isdir(Path(self.global_pathway.text())):
|
|
502
502
|
self.parent().po.all['global_pathway'] = self.global_pathway.text()
|
|
503
503
|
logging.info(f"Dir: {self.parent().po.all['global_pathway']}")
|
|
@@ -514,8 +514,8 @@ class FirstWindow(MainTabsType):
|
|
|
514
514
|
self.instantiate = True
|
|
515
515
|
self.video_tab.set_not_usable()
|
|
516
516
|
# 2) Load the dict
|
|
517
|
-
self.
|
|
518
|
-
self.
|
|
517
|
+
self.thread_dict["LoadDataToRunCellectsQuickly"].start()
|
|
518
|
+
self.thread_dict["LoadDataToRunCellectsQuickly"].message_from_thread.connect(self.load_data_quickly_finished)
|
|
519
519
|
# 3) go to another func to change, put visible and re_instantiate
|
|
520
520
|
else:
|
|
521
521
|
self.Run_all_directly.setVisible(False)
|
|
@@ -525,7 +525,7 @@ class FirstWindow(MainTabsType):
|
|
|
525
525
|
|
|
526
526
|
def load_data_quickly_finished(self, message: str):
|
|
527
527
|
"""
|
|
528
|
-
Set up the UI components for a new
|
|
528
|
+
Set up the UI components for a new one_experiment.
|
|
529
529
|
|
|
530
530
|
Parameters
|
|
531
531
|
----------
|
|
@@ -535,7 +535,7 @@ class FirstWindow(MainTabsType):
|
|
|
535
535
|
Notes
|
|
536
536
|
-----
|
|
537
537
|
This function sets several visibility flags and values for UI components
|
|
538
|
-
in preparation for starting an
|
|
538
|
+
in preparation for starting an one_experiment.
|
|
539
539
|
"""
|
|
540
540
|
self.image_tab.set_not_in_use()
|
|
541
541
|
self.message.setText(message)
|
|
@@ -565,10 +565,4 @@ class FirstWindow(MainTabsType):
|
|
|
565
565
|
"""
|
|
566
566
|
self.instantiate = True
|
|
567
567
|
# Since we re-instantiate everything, image analysis will no longer be available from video analysis:
|
|
568
|
-
self.parent().videoanalysiswindow.image_tab.set_not_usable()
|
|
569
|
-
|
|
570
|
-
def closeEvent(self, event):
|
|
571
|
-
"""
|
|
572
|
-
Handle the close event for a QWidget.
|
|
573
|
-
"""
|
|
574
|
-
event.accept
|
|
568
|
+
self.parent().videoanalysiswindow.image_tab.set_not_usable()
|
|
@@ -66,15 +66,15 @@ class IfSeveralFoldersWindow(WindowType):
|
|
|
66
66
|
This method assumes that the parent widget has a 'po' attribute with specific settings and variables.
|
|
67
67
|
"""
|
|
68
68
|
logging.info("Initialize IfSeveralFoldersWindow")
|
|
69
|
-
self.
|
|
70
|
-
self.
|
|
69
|
+
self.thread_dict = {}
|
|
70
|
+
self.thread_dict["LoadFirstFolderIfSeveral"] = LoadFirstFolderIfSeveralThread(self.parent())
|
|
71
71
|
self.next_clicked_once:bool = False
|
|
72
72
|
self.layout = QtWidgets.QVBoxLayout()
|
|
73
73
|
|
|
74
74
|
self.title_label = FixedText('Select folders to analyze', police=30, night_mode=self.parent().po.all['night_mode'])
|
|
75
75
|
self.title_label.setAlignment(QtCore.Qt.AlignHCenter)
|
|
76
76
|
self.layout.addWidget(self.title_label)
|
|
77
|
-
self.layout.addItem(
|
|
77
|
+
self.layout.addItem(QtWidgets.QSpacerItem(1, 1, QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.MinimumExpanding))
|
|
78
78
|
|
|
79
79
|
# 1) add a check box allowing to select every folders
|
|
80
80
|
self.cb_layout = QtWidgets.QHBoxLayout()
|
|
@@ -85,7 +85,7 @@ class IfSeveralFoldersWindow(WindowType):
|
|
|
85
85
|
self.cb.clicked.connect(self.checked)
|
|
86
86
|
self.cb_layout.addWidget(self.cb_label)
|
|
87
87
|
self.cb_layout.addWidget(self.cb)
|
|
88
|
-
self.cb_layout.addItem(
|
|
88
|
+
self.cb_layout.addItem(QtWidgets.QSpacerItem(1, 1, QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Maximum))
|
|
89
89
|
self.cb_widget.setLayout(self.cb_layout)
|
|
90
90
|
self.layout.addWidget(self.cb_widget)
|
|
91
91
|
|
|
@@ -122,7 +122,7 @@ class IfSeveralFoldersWindow(WindowType):
|
|
|
122
122
|
self.Run_all_directly.clicked.connect(self.Run_all_directly_is_clicked)
|
|
123
123
|
self.Video_analysis_window.setVisible(False)
|
|
124
124
|
self.Run_all_directly.setVisible(False)
|
|
125
|
-
self.shortcuts_layout.addItem(
|
|
125
|
+
self.shortcuts_layout.addItem(QtWidgets.QSpacerItem(1, 1, QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.MinimumExpanding))
|
|
126
126
|
self.shortcuts_layout.addWidget(self.Video_analysis_window)
|
|
127
127
|
self.shortcuts_layout.addWidget(self.Run_all_directly)
|
|
128
128
|
self.shortcuts_widget.setLayout(self.shortcuts_layout)
|
|
@@ -144,11 +144,11 @@ class IfSeveralFoldersWindow(WindowType):
|
|
|
144
144
|
self.next = PButton('Next', night_mode=self.parent().po.all['night_mode'])
|
|
145
145
|
self.next.clicked.connect(self.next_is_clicked)
|
|
146
146
|
self.last_row_layout.addWidget(self.previous)
|
|
147
|
-
self.last_row_layout.addItem(
|
|
147
|
+
self.last_row_layout.addItem(QtWidgets.QSpacerItem(1, 1, QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Maximum))
|
|
148
148
|
self.last_row_layout.addWidget(self.message)
|
|
149
149
|
self.last_row_layout.addWidget(self.next)
|
|
150
150
|
self.last_row_widget.setLayout(self.last_row_layout)
|
|
151
|
-
self.layout.addItem(
|
|
151
|
+
self.layout.addItem(QtWidgets.QSpacerItem(1, 1, QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.MinimumExpanding))
|
|
152
152
|
self.layout.addWidget(self.last_row_widget)
|
|
153
153
|
self.setLayout(self.layout)
|
|
154
154
|
|
|
@@ -219,8 +219,8 @@ class IfSeveralFoldersWindow(WindowType):
|
|
|
219
219
|
self.parent().po.all['sample_number_per_folder'] = sample_number_per_folder
|
|
220
220
|
self.parent().po.update_folder_id(self.parent().po.all['first_folder_sample_number'],
|
|
221
221
|
self.parent().po.all['folder_list'][0])
|
|
222
|
-
self.
|
|
223
|
-
self.
|
|
222
|
+
self.thread_dict["LoadFirstFolderIfSeveral"].start()
|
|
223
|
+
self.thread_dict["LoadFirstFolderIfSeveral"].message_when_thread_finished.connect(self.first_folder_loaded)
|
|
224
224
|
|
|
225
225
|
def first_folder_loaded(self, first_exp_ready_to_run: bool):
|
|
226
226
|
"""
|
|
@@ -229,7 +229,7 @@ class IfSeveralFoldersWindow(WindowType):
|
|
|
229
229
|
Parameters
|
|
230
230
|
----------
|
|
231
231
|
first_exp_ready_to_run : bool
|
|
232
|
-
Indicates if the
|
|
232
|
+
Indicates if the one_experiment data is ready to be run.
|
|
233
233
|
"""
|
|
234
234
|
if first_exp_ready_to_run:
|
|
235
235
|
self.cb_widget.setVisible(False)
|
|
@@ -278,11 +278,4 @@ class IfSeveralFoldersWindow(WindowType):
|
|
|
278
278
|
window and then updates the state accordingly.
|
|
279
279
|
"""
|
|
280
280
|
self.parent().firstwindow.Run_all_directly_is_clicked()
|
|
281
|
-
self.previous_is_clicked()
|
|
282
|
-
|
|
283
|
-
def closeEvent(self, event):
|
|
284
|
-
"""
|
|
285
|
-
Handle the close event for a QWidget.
|
|
286
|
-
"""
|
|
287
|
-
event.accept
|
|
288
|
-
|
|
281
|
+
self.previous_is_clicked()
|