cellects 0.1.2__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/__init__.py +0 -0
- cellects/__main__.py +49 -0
- cellects/config/__init__.py +0 -0
- cellects/config/all_vars_dict.py +155 -0
- cellects/core/__init__.py +0 -0
- cellects/core/cellects_paths.py +31 -0
- cellects/core/cellects_threads.py +1451 -0
- cellects/core/motion_analysis.py +2010 -0
- cellects/core/one_image_analysis.py +1061 -0
- cellects/core/one_video_per_blob.py +540 -0
- cellects/core/program_organizer.py +1316 -0
- cellects/core/script_based_run.py +154 -0
- cellects/gui/__init__.py +0 -0
- cellects/gui/advanced_parameters.py +1258 -0
- cellects/gui/cellects.py +189 -0
- cellects/gui/custom_widgets.py +790 -0
- cellects/gui/first_window.py +449 -0
- cellects/gui/if_several_folders_window.py +239 -0
- cellects/gui/image_analysis_window.py +2066 -0
- cellects/gui/required_output.py +232 -0
- cellects/gui/video_analysis_window.py +656 -0
- cellects/icons/__init__.py +0 -0
- cellects/icons/cellects_icon.icns +0 -0
- cellects/icons/cellects_icon.ico +0 -0
- cellects/image_analysis/__init__.py +0 -0
- cellects/image_analysis/cell_leaving_detection.py +54 -0
- cellects/image_analysis/cluster_flux_study.py +102 -0
- cellects/image_analysis/image_segmentation.py +706 -0
- cellects/image_analysis/morphological_operations.py +1635 -0
- cellects/image_analysis/network_functions.py +1757 -0
- cellects/image_analysis/one_image_analysis_threads.py +289 -0
- cellects/image_analysis/progressively_add_distant_shapes.py +508 -0
- cellects/image_analysis/shape_descriptors.py +1016 -0
- cellects/utils/__init__.py +0 -0
- cellects/utils/decorators.py +14 -0
- cellects/utils/formulas.py +637 -0
- cellects/utils/load_display_save.py +1054 -0
- cellects/utils/utilitarian.py +490 -0
- cellects-0.1.2.dist-info/LICENSE.odt +0 -0
- cellects-0.1.2.dist-info/METADATA +132 -0
- cellects-0.1.2.dist-info/RECORD +44 -0
- cellects-0.1.2.dist-info/WHEEL +5 -0
- cellects-0.1.2.dist-info/entry_points.txt +2 -0
- cellects-0.1.2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""This module creates the First window of the user interface of Cellects"""
|
|
3
|
+
|
|
4
|
+
import os
|
|
5
|
+
import logging
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
import numpy as np
|
|
8
|
+
import cv2
|
|
9
|
+
from PySide6 import QtWidgets, QtCore
|
|
10
|
+
|
|
11
|
+
from cellects.core.cellects_threads import (
|
|
12
|
+
GetFirstImThread, GetExifDataThread, RunAllThread, LookForDataThreadInFirstW, LoadDataToRunCellectsQuicklyThread)
|
|
13
|
+
from cellects.gui.custom_widgets import (
|
|
14
|
+
MainTabsType, InsertImage, FullScreenImage, PButton, Spinbox,
|
|
15
|
+
Combobox, FixedText, EditText, LineWidget)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class FirstWindow(MainTabsType):
|
|
19
|
+
def __init__(self, parent, night_mode):
|
|
20
|
+
super().__init__(parent, night_mode)
|
|
21
|
+
logging.info("Initialize first window")
|
|
22
|
+
self.setParent(parent)
|
|
23
|
+
self.data_tab.set_in_use()
|
|
24
|
+
self.image_tab.set_not_usable()
|
|
25
|
+
self.video_tab.set_not_usable()
|
|
26
|
+
# self.night_mode_switch(False)
|
|
27
|
+
self.thread = {}
|
|
28
|
+
self.thread["LookForData"] = LookForDataThreadInFirstW(self.parent())
|
|
29
|
+
self.thread["RunAll"] = RunAllThread(self.parent())
|
|
30
|
+
self.thread["LoadDataToRunCellectsQuickly"] = LoadDataToRunCellectsQuicklyThread(self.parent())
|
|
31
|
+
self.thread["GetFirstIm"] = GetFirstImThread(self.parent())
|
|
32
|
+
self.thread["GetExifDataThread"] = GetExifDataThread(self.parent())
|
|
33
|
+
self.instantiate: bool = True
|
|
34
|
+
##
|
|
35
|
+
self.title_label = FixedText('Cellects', police=60, night_mode=self.parent().po.all['night_mode'])
|
|
36
|
+
self.title_label.setAlignment(QtCore.Qt.AlignHCenter)
|
|
37
|
+
# self.subtitle_label = FixedText('A Cell Expansion Computer Tracking Software', police=18, night_mode=self.parent().po.all['night_mode'])
|
|
38
|
+
# self.subtitle_label.setAlignment(QtCore.Qt.AlignHCenter)
|
|
39
|
+
self.subtitle_line = LineWidget(size=[1, 50], night_mode=self.parent().po.all['night_mode'])
|
|
40
|
+
|
|
41
|
+
self.Vlayout.addWidget(self.title_label)
|
|
42
|
+
# self.Vlayout.addWidget(self.subtitle_label)
|
|
43
|
+
self.Vlayout.addWidget(self.subtitle_line)
|
|
44
|
+
self.Vlayout.addItem(self.vertical_space)
|
|
45
|
+
|
|
46
|
+
# 1) Set if this a Image list or Videos
|
|
47
|
+
# Open the layout:
|
|
48
|
+
self.second_row_widget = QtWidgets.QWidget()
|
|
49
|
+
self.second_row_layout = QtWidgets.QHBoxLayout()
|
|
50
|
+
self.im_or_vid_label = FixedText('Image list or Videos:', tip="What type of data do(es) contain(s) folder(s)?", night_mode=self.parent().po.all['night_mode'])
|
|
51
|
+
self.im_or_vid = Combobox(["Image list", "Videos"], self.parent().po.all['im_or_vid'], night_mode=self.parent().po.all['night_mode'])
|
|
52
|
+
self.im_or_vid.setFixedWidth(150)
|
|
53
|
+
# Set their positions on layout
|
|
54
|
+
self.second_row_layout.addItem(self.horizontal_space)
|
|
55
|
+
self.second_row_layout.addWidget(self.im_or_vid_label)
|
|
56
|
+
self.second_row_layout.addWidget(self.im_or_vid)
|
|
57
|
+
self.second_row_layout.addItem(self.horizontal_space)
|
|
58
|
+
self.second_row_widget.setLayout(self.second_row_layout)
|
|
59
|
+
self.Vlayout.addWidget(self.second_row_widget)
|
|
60
|
+
|
|
61
|
+
# 2) Open the third row layout
|
|
62
|
+
self.third_row_widget = QtWidgets.QWidget()
|
|
63
|
+
self.third_row_layout = QtWidgets.QHBoxLayout()
|
|
64
|
+
# Set default images radical and extension widgets
|
|
65
|
+
if self.parent().po.all['im_or_vid'] == 0:
|
|
66
|
+
what = 'Images'
|
|
67
|
+
if self.parent().po.all['extension'] == '.mp4':
|
|
68
|
+
self.parent().po.all['radical'] = 'IMG_'
|
|
69
|
+
self.parent().po.all['extension'] = '.JPG'
|
|
70
|
+
self.arena_number_label = FixedText('Arena number per folder:', tip="If this number is not always the same (depending on the folder), it can be changed later",
|
|
71
|
+
night_mode=self.parent().po.all['night_mode'])
|
|
72
|
+
|
|
73
|
+
else:
|
|
74
|
+
if self.parent().po.all['extension'] == '.JPG':
|
|
75
|
+
self.parent().po.all['radical'] = ''
|
|
76
|
+
self.parent().po.all['extension'] = '.mp4'
|
|
77
|
+
self.arena_number_label = FixedText('Arena number per video:',
|
|
78
|
+
tip="If this number is not always the same (depending on the video), it can be changed later",
|
|
79
|
+
night_mode=self.parent().po.all['night_mode'])
|
|
80
|
+
what = 'Videos'
|
|
81
|
+
self.arena_number_label.setAlignment(QtCore.Qt.AlignVCenter)
|
|
82
|
+
self.arena_number = Spinbox(min=0, max=255, val=self.parent().po.all['first_folder_sample_number'],
|
|
83
|
+
decimals=0, night_mode=self.parent().po.all['night_mode'])
|
|
84
|
+
self.arena_number.valueChanged.connect(self.re_instantiate_widgets)
|
|
85
|
+
self.radical_label = FixedText(what + ' prefix:', tip="Inform the prefix common to each name, if it exists", night_mode=self.parent().po.all['night_mode'])
|
|
86
|
+
self.radical_label.setAlignment(QtCore.Qt.AlignVCenter)
|
|
87
|
+
self.radical = EditText(self.parent().po.all['radical'],
|
|
88
|
+
night_mode=self.parent().po.all['night_mode'])
|
|
89
|
+
self.radical.textChanged.connect(self.re_instantiate_widgets)
|
|
90
|
+
|
|
91
|
+
self.extension_label = FixedText(what + ' extension:', tip="Caps sensitive", night_mode=self.parent().po.all['night_mode'])
|
|
92
|
+
self.extension_label.setAlignment(QtCore.Qt.AlignVCenter)
|
|
93
|
+
self.extension = EditText(self.parent().po.all['extension'],
|
|
94
|
+
night_mode=self.parent().po.all['night_mode'])
|
|
95
|
+
self.extension.textChanged.connect(self.re_instantiate_widgets)
|
|
96
|
+
|
|
97
|
+
# Set their positions on layout
|
|
98
|
+
self.third_row_layout.addItem(self.horizontal_space)
|
|
99
|
+
self.third_row_layout.addWidget(self.radical_label)
|
|
100
|
+
self.third_row_layout.addWidget(self.radical)
|
|
101
|
+
# self.third_row_layout.addItem(self.horizontal_space)
|
|
102
|
+
self.third_row_layout.addWidget(self.extension_label)
|
|
103
|
+
self.third_row_layout.addWidget(self.extension)
|
|
104
|
+
self.third_row_layout.addItem(self.horizontal_space)
|
|
105
|
+
self.third_row_widget.setLayout(self.third_row_layout)
|
|
106
|
+
self.Vlayout.addWidget(self.third_row_widget)
|
|
107
|
+
# If im_or_vid changes, adjust these 2 widgets
|
|
108
|
+
self.im_or_vid.currentTextChanged.connect(self.im2vid)
|
|
109
|
+
|
|
110
|
+
# 3) Get the path to the right folder:
|
|
111
|
+
# Open the layout:
|
|
112
|
+
self.first_row_widget = QtWidgets.QWidget()
|
|
113
|
+
self.first_row_layout = QtWidgets.QHBoxLayout()
|
|
114
|
+
|
|
115
|
+
self.folder_label = FixedText('Folder:',
|
|
116
|
+
tip="Path to the folder containing images or videos\nThe selected folder may also contain several folders of data",
|
|
117
|
+
night_mode=self.parent().po.all['night_mode'])
|
|
118
|
+
self.folder_label.setAlignment(QtCore.Qt.AlignVCenter)
|
|
119
|
+
self.global_pathway = EditText(self.parent().po.all['global_pathway'],
|
|
120
|
+
night_mode=self.parent().po.all['night_mode'])
|
|
121
|
+
self.global_pathway.setSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Maximum)
|
|
122
|
+
self.global_pathway.textChanged.connect(self.pathway_changed)
|
|
123
|
+
self.browse = PButton('Browse', night_mode=self.parent().po.all['night_mode'])
|
|
124
|
+
self.browse.clicked.connect(self.browse_is_clicked)
|
|
125
|
+
|
|
126
|
+
# Set their positions on layout
|
|
127
|
+
self.first_row_layout.addWidget(self.folder_label)
|
|
128
|
+
self.first_row_layout.addWidget(self.global_pathway)
|
|
129
|
+
self.first_row_layout.addWidget(self.browse)
|
|
130
|
+
self.first_row_widget.setLayout(self.first_row_layout)
|
|
131
|
+
self.Vlayout.addWidget(self.first_row_widget)
|
|
132
|
+
|
|
133
|
+
self.fourth_row_widget = QtWidgets.QWidget()
|
|
134
|
+
self.fourth_row_layout = QtWidgets.QHBoxLayout()
|
|
135
|
+
self.fourth_row_layout.addItem(self.horizontal_space)
|
|
136
|
+
self.fourth_row_layout.addWidget(self.arena_number_label)
|
|
137
|
+
self.fourth_row_layout.addWidget(self.arena_number)
|
|
138
|
+
self.fourth_row_layout.addItem(self.horizontal_space)
|
|
139
|
+
self.fourth_row_widget.setLayout(self.fourth_row_layout)
|
|
140
|
+
self.Vlayout.addWidget(self.fourth_row_widget)
|
|
141
|
+
self.Vlayout.addItem(self.vertical_space)
|
|
142
|
+
|
|
143
|
+
# Add the central image display widget
|
|
144
|
+
self.display_image = np.zeros((self.parent().im_max_height, self.parent().im_max_width, 3), np.uint8)
|
|
145
|
+
self.display_image = InsertImage(self.display_image, self.parent().im_max_height, self.parent().im_max_width)
|
|
146
|
+
self.Vlayout.addWidget(self.display_image, alignment=QtCore.Qt.AlignCenter)
|
|
147
|
+
self.display_image.setVisible(False)
|
|
148
|
+
self.display_image.mousePressEvent = self.full_screen_display
|
|
149
|
+
|
|
150
|
+
# Add the display shortcuts option
|
|
151
|
+
#self.shortcut_cb = Checkbox(self.parent().po.all['display_shortcuts'])
|
|
152
|
+
#self.shortcut_cb.stateChanged.connect(self.display_shortcuts_checked)
|
|
153
|
+
#self.shortcut_label = FixedText('Display shortcuts', night_mode=self.parent().po.all['night_mode'])
|
|
154
|
+
#self.shortcut_label.setAlignment(QtCore.Qt.AlignVCenter)
|
|
155
|
+
|
|
156
|
+
# 4) Create the shortcuts row
|
|
157
|
+
self.shortcuts_widget = QtWidgets.QWidget()
|
|
158
|
+
self.shortcuts_layout = QtWidgets.QHBoxLayout()
|
|
159
|
+
# Add shortcuts: Video_analysis and Run directly
|
|
160
|
+
# Shortcut 1 : Advanced Parameters
|
|
161
|
+
self.advanced_parameters = PButton('Advanced Parameters', night_mode=self.parent().po.all['night_mode'])
|
|
162
|
+
self.advanced_parameters.clicked.connect(self.advanced_parameters_is_clicked)
|
|
163
|
+
# Shortcut 2 : Required Outputs
|
|
164
|
+
self.required_outputs = PButton('Required Outputs', night_mode=self.parent().po.all['night_mode'])
|
|
165
|
+
self.required_outputs.clicked.connect(self.required_outputs_is_clicked)
|
|
166
|
+
# Shortcut 3 :
|
|
167
|
+
# self.Video_analysis_window = PButton("Video tracking window", night_mode=self.parent().po.all['night_mode'])
|
|
168
|
+
# self.Video_analysis_window.clicked.connect(self.video_analysis_window_is_clicked)
|
|
169
|
+
self.video_tab.clicked.connect(self.video_analysis_window_is_clicked)
|
|
170
|
+
# Shortcut 4 :
|
|
171
|
+
self.Run_all_directly = PButton("Run all directly", night_mode=self.parent().po.all['night_mode'])
|
|
172
|
+
self.Run_all_directly.clicked.connect(self.Run_all_directly_is_clicked)
|
|
173
|
+
# self.Video_analysis_window.setVisible(False)
|
|
174
|
+
self.Run_all_directly.setVisible(False)
|
|
175
|
+
|
|
176
|
+
self.shortcuts_layout.addItem(self.horizontal_space)
|
|
177
|
+
self.shortcuts_layout.addWidget(self.advanced_parameters)
|
|
178
|
+
self.shortcuts_layout.addWidget(self.required_outputs)
|
|
179
|
+
# self.shortcuts_layout.addWidget(self.Video_analysis_window)
|
|
180
|
+
self.shortcuts_layout.addWidget(self.Run_all_directly)
|
|
181
|
+
self.shortcuts_layout.addItem(self.horizontal_space)
|
|
182
|
+
self.shortcuts_widget.setLayout(self.shortcuts_layout)
|
|
183
|
+
self.Vlayout.addWidget(self.shortcuts_widget)
|
|
184
|
+
|
|
185
|
+
# 5) Open the last row layout
|
|
186
|
+
self.last_row_widget = QtWidgets.QWidget()
|
|
187
|
+
self.last_row_layout = QtWidgets.QHBoxLayout()
|
|
188
|
+
|
|
189
|
+
# Message
|
|
190
|
+
self.message = FixedText('', halign='r', night_mode=self.parent().po.all['night_mode'])
|
|
191
|
+
self.message.setStyleSheet("color: rgb(230, 145, 18)")
|
|
192
|
+
# Next button
|
|
193
|
+
self.next = PButton('Next', night_mode=self.parent().po.all['night_mode'])
|
|
194
|
+
self.image_tab.clicked.connect(self.next_is_clicked)
|
|
195
|
+
self.next.clicked.connect(self.next_is_clicked)
|
|
196
|
+
# Add widgets to the last_row_layout
|
|
197
|
+
#self.last_row_layout.addWidget(self.shortcut_cb)
|
|
198
|
+
#self.last_row_layout.addWidget(self.shortcut_label)
|
|
199
|
+
self.last_row_layout.addItem(self.horizontal_space)
|
|
200
|
+
self.last_row_layout.addWidget(self.message)
|
|
201
|
+
self.last_row_layout.addWidget(self.next)
|
|
202
|
+
# Close the last_row_layout
|
|
203
|
+
self.last_row_widget.setLayout(self.last_row_layout)
|
|
204
|
+
self.Vlayout.addWidget(self.last_row_widget)
|
|
205
|
+
self.setLayout(self.Vlayout)
|
|
206
|
+
|
|
207
|
+
# Check if there is data in the saved folder
|
|
208
|
+
self.pathway_changed()
|
|
209
|
+
|
|
210
|
+
def full_screen_display(self, event):
|
|
211
|
+
self.popup_img = FullScreenImage(self.parent().image_to_display, self.parent().screen_width, self.parent().screen_height)
|
|
212
|
+
self.popup_img.show()
|
|
213
|
+
|
|
214
|
+
def browse_is_clicked(self):
|
|
215
|
+
dialog = QtWidgets.QFileDialog()
|
|
216
|
+
dialog.setDirectory(str(self.parent().po.all['global_pathway']))
|
|
217
|
+
self.parent().po.all['global_pathway'] = dialog.getExistingDirectory(self,
|
|
218
|
+
'Select a folder containing images (/videos) or folders of data images (/videos)')
|
|
219
|
+
self.global_pathway.setText(self.parent().po.all['global_pathway'])
|
|
220
|
+
|
|
221
|
+
def im2vid(self):
|
|
222
|
+
if self.im_or_vid.currentText() == "Image list":
|
|
223
|
+
what = 'Images'
|
|
224
|
+
if self.parent().po.all['extension'] == '.mp4':
|
|
225
|
+
self.parent().po.all['radical'] = 'IMG_'
|
|
226
|
+
self.parent().po.all['extension'] = '.JPG'
|
|
227
|
+
else:
|
|
228
|
+
if self.parent().po.all['extension'] == '.JPG':
|
|
229
|
+
self.parent().po.all['radical'] = ''
|
|
230
|
+
self.parent().po.all['extension'] = '.mp4'
|
|
231
|
+
what = 'Videos'
|
|
232
|
+
self.radical_label.setText(what + ' prefix:')
|
|
233
|
+
self.extension_label.setText(what + ' extension:')
|
|
234
|
+
self.radical.setText(self.parent().po.all['radical'])
|
|
235
|
+
self.extension.setText(self.parent().po.all['extension'])
|
|
236
|
+
|
|
237
|
+
def display_message_from_thread(self, text_from_thread):
|
|
238
|
+
self.message.setText(text_from_thread)
|
|
239
|
+
|
|
240
|
+
def display_image_during_thread(self, dictionary):
|
|
241
|
+
self.message.setText(dictionary['message'])
|
|
242
|
+
self.parent().image_to_display = dictionary['current_image']
|
|
243
|
+
self.display_image.update_image(dictionary['current_image'])
|
|
244
|
+
|
|
245
|
+
def next_is_clicked(self):
|
|
246
|
+
if not self.thread["LookForData"].isRunning() and not self.thread["RunAll"].isRunning():
|
|
247
|
+
self.parent().po.all['im_or_vid'] = self.im_or_vid.currentIndex()
|
|
248
|
+
self.parent().po.all['radical'] = self.radical.text()
|
|
249
|
+
self.parent().po.all['extension'] = self.extension.text()
|
|
250
|
+
#self.parent().po.all['display_shortcuts'] = self.shortcut_cb.isChecked()
|
|
251
|
+
self.parent().po.sample_number = int(self.arena_number.value())
|
|
252
|
+
self.parent().po.all['first_folder_sample_number'] = self.parent().po.sample_number
|
|
253
|
+
self.parent().po.all['sample_number_per_folder'] = [self.parent().po.sample_number]
|
|
254
|
+
if not self.instantiate: # not self.parent().imageanalysiswindow.initialized:
|
|
255
|
+
logging.info("No need to look for data, images or videos already found previously.")
|
|
256
|
+
self.first_im_read(True)
|
|
257
|
+
else:
|
|
258
|
+
self.parent().po.all['global_pathway'] = Path(self.global_pathway.text())
|
|
259
|
+
if not os.path.isdir(Path(self.parent().po.all['global_pathway'])):
|
|
260
|
+
self.message.setText('The folder selected is not valid')
|
|
261
|
+
else:
|
|
262
|
+
self.message.setText('')
|
|
263
|
+
# self.parent().po.all['im_or_vid'] = self.im_or_vid.currentIndex()
|
|
264
|
+
# self.parent().po.all['radical'] = self.radical.text()
|
|
265
|
+
# self.parent().po.all['extension'] = self.extension.text()
|
|
266
|
+
# self.parent().po.all['display_shortcuts'] = self.shortcut_cb.isChecked()
|
|
267
|
+
|
|
268
|
+
self.message.setText(f"Looking for {self.parent().po.all['radical']}***{self.parent().po.all['extension']} Wait...")
|
|
269
|
+
self.message.setStyleSheet("color: rgb(230, 145, 18)")
|
|
270
|
+
self.thread["LookForData"].start()
|
|
271
|
+
self.thread["LookForData"].finished.connect(self.when_look_for_data_finished)
|
|
272
|
+
else:
|
|
273
|
+
self.message.setText('Analysis has already begun, wait or restart Cellects.')
|
|
274
|
+
|
|
275
|
+
def when_look_for_data_finished(self):
|
|
276
|
+
if len(self.parent().po.all['folder_list']) == 0 and len(self.parent().po.data_list) == 0:
|
|
277
|
+
if self.parent().po.all['im_or_vid'] == 1:
|
|
278
|
+
error_message = f"There is no videos ({self.parent().po.all['extension']})in the selected folder and its sub-folders"
|
|
279
|
+
else:
|
|
280
|
+
error_message = f"There is no images ({self.parent().po.all['extension']}) in the selected folder and its sub-folders"
|
|
281
|
+
self.message.setText(error_message)
|
|
282
|
+
# = FixedText(error_message, align='r')
|
|
283
|
+
# self.message.setStyleSheet("color: rgb(230, 145, 18)")
|
|
284
|
+
# self.layout.addWidget(self.message, 12, 0, 12, 3)
|
|
285
|
+
else:
|
|
286
|
+
self.message.setText('')
|
|
287
|
+
# if len(self.parent().po.all['folder_list']) > 0:
|
|
288
|
+
# self.parent().po.update_folder_id(self.parent().po.all['first_folder_sample_number'],
|
|
289
|
+
# self.parent().po.all['folder_list'][0])
|
|
290
|
+
# if self.instantiate: # not self.parent().imageanalysiswindow.initialized:
|
|
291
|
+
# self.thread["GetFirstIm"].start()
|
|
292
|
+
# self.thread["GetFirstIm"].message_when_thread_finished.connect(self.first_im_read)
|
|
293
|
+
# else:
|
|
294
|
+
# self.first_im_read(True)
|
|
295
|
+
# if isinstance(self.parent().po.all['sample_number_per_folder'], int):
|
|
296
|
+
# self.parent().po.all['folder_number'] = 1
|
|
297
|
+
if self.parent().po.all['folder_number'] > 1:
|
|
298
|
+
self.parent().instantiate_widgets()
|
|
299
|
+
self.parent().ifseveralfolderswindow.true_init()
|
|
300
|
+
self.instantiate = False
|
|
301
|
+
self.parent().change_widget(1) # IfSeveralFoldersWindow
|
|
302
|
+
else:
|
|
303
|
+
self.thread["GetFirstIm"].start()
|
|
304
|
+
self.thread["GetFirstIm"].message_when_thread_finished.connect(self.first_im_read)
|
|
305
|
+
|
|
306
|
+
def first_im_read(self, greyscale):
|
|
307
|
+
self.parent().instantiate_widgets()
|
|
308
|
+
self.parent().imageanalysiswindow.true_init()
|
|
309
|
+
self.instantiate = False
|
|
310
|
+
if self.parent().po.first_exp_ready_to_run:
|
|
311
|
+
self.parent().imageanalysiswindow.video_tab.set_not_in_use()
|
|
312
|
+
self.parent().change_widget(2) # imageanalysiswindow
|
|
313
|
+
# From now on, image analysis will be available from video analysis:
|
|
314
|
+
self.parent().videoanalysiswindow.image_tab.set_not_in_use()
|
|
315
|
+
self.thread["GetExifDataThread"].start()
|
|
316
|
+
|
|
317
|
+
def required_outputs_is_clicked(self):
|
|
318
|
+
self.parent().last_is_first = True
|
|
319
|
+
self.parent().change_widget(4) # RequiredOutput
|
|
320
|
+
|
|
321
|
+
def advanced_parameters_is_clicked(self):
|
|
322
|
+
if self.thread["GetExifDataThread"].isRunning():
|
|
323
|
+
self.message.setText("Reading data, wait or restart Cellects")
|
|
324
|
+
else:
|
|
325
|
+
self.parent().last_is_first = True
|
|
326
|
+
self.parent().widget(5).update_csc_editing_display()
|
|
327
|
+
self.parent().change_widget(5) # AdvancedParameters
|
|
328
|
+
|
|
329
|
+
def video_analysis_window_is_clicked(self):
|
|
330
|
+
if self.video_tab.state != "not_usable":
|
|
331
|
+
if self.thread["LookForData"].isRunning() or self.thread["LoadDataToRunCellectsQuickly"].isRunning() or self.thread["GetFirstIm"].isRunning() or self.thread["RunAll"].isRunning():
|
|
332
|
+
self.message.setText("Wait for the analysis to end, or restart Cellects")
|
|
333
|
+
else:
|
|
334
|
+
self.parent().last_tab = "data_specifications"
|
|
335
|
+
# self.parent().po.first_exp_ready_to_run = False
|
|
336
|
+
self.parent().change_widget(3) # Should be VideoAnalysisW
|
|
337
|
+
|
|
338
|
+
def Run_all_directly_is_clicked(self):
|
|
339
|
+
if not self.thread["LookForData"].isRunning() and not self.thread["RunAll"].isRunning():
|
|
340
|
+
self.parent().po.motion = None
|
|
341
|
+
self.message.setText("Complete analysis has started, wait until this message disappear...")
|
|
342
|
+
# if not self.parent().po.first_exp_ready_to_run:
|
|
343
|
+
# self.parent().po.use_data_to_run_cellects_quickly = True
|
|
344
|
+
self.thread["RunAll"].start()
|
|
345
|
+
self.thread["RunAll"].message_from_thread.connect(self.display_message_from_thread)
|
|
346
|
+
self.thread["RunAll"].image_from_thread.connect(self.display_image_during_thread)
|
|
347
|
+
self.display_image.setVisible(True)
|
|
348
|
+
|
|
349
|
+
def pathway_changed(self):
|
|
350
|
+
if self.thread["LoadDataToRunCellectsQuickly"].isRunning():
|
|
351
|
+
self.thread["LoadDataToRunCellectsQuickly"].wait()
|
|
352
|
+
if os.path.isdir(Path(self.global_pathway.text())):
|
|
353
|
+
self.parent().po.all['global_pathway'] = self.global_pathway.text()
|
|
354
|
+
logging.info(f"Dir: {self.parent().po.all['global_pathway']}")
|
|
355
|
+
os.chdir(Path(self.parent().po.all['global_pathway']))
|
|
356
|
+
# 1) Put invisible widgets
|
|
357
|
+
self.radical.setVisible(False)
|
|
358
|
+
self.extension.setVisible(False)
|
|
359
|
+
self.arena_number.setVisible(False)
|
|
360
|
+
self.im_or_vid.setVisible(False)
|
|
361
|
+
self.advanced_parameters.setVisible(False)
|
|
362
|
+
self.required_outputs.setVisible(False)
|
|
363
|
+
# self.Video_analysis_window.setVisible(False)
|
|
364
|
+
self.Run_all_directly.setVisible(False)
|
|
365
|
+
self.next.setVisible(False)
|
|
366
|
+
# 2) Load the dict
|
|
367
|
+
self.thread["LoadDataToRunCellectsQuickly"].start()
|
|
368
|
+
self.thread["LoadDataToRunCellectsQuickly"].message_from_thread.connect(self.load_data_quickly_finished)
|
|
369
|
+
# 3) go to another func to change, put visible and re_instantiate
|
|
370
|
+
else:
|
|
371
|
+
# self.Video_analysis_window.setVisible(False)
|
|
372
|
+
self.Run_all_directly.setVisible(False)
|
|
373
|
+
self.image_tab.set_not_usable()
|
|
374
|
+
self.video_tab.set_not_usable()
|
|
375
|
+
self.message.setText("Please, enter a valid path")
|
|
376
|
+
|
|
377
|
+
def load_data_quickly_finished(self, message):
|
|
378
|
+
self.image_tab.set_not_in_use()
|
|
379
|
+
self.message.setText(message)
|
|
380
|
+
self.radical.setVisible(True)
|
|
381
|
+
self.extension.setVisible(True)
|
|
382
|
+
self.arena_number.setVisible(True)
|
|
383
|
+
self.im_or_vid.setVisible(True)
|
|
384
|
+
self.advanced_parameters.setVisible(True)
|
|
385
|
+
self.required_outputs.setVisible(True)
|
|
386
|
+
self.next.setVisible(True)
|
|
387
|
+
|
|
388
|
+
if self.parent().po.first_exp_ready_to_run:
|
|
389
|
+
self.parent().po.all['folder_number'] = 1
|
|
390
|
+
self.parent().instantiate_widgets(True)
|
|
391
|
+
self.arena_number.setValue(self.parent().po.all['first_folder_sample_number'])
|
|
392
|
+
self.im_or_vid.setCurrentIndex(self.parent().po.all['im_or_vid'])
|
|
393
|
+
self.radical.setText(self.parent().po.all['radical'])
|
|
394
|
+
self.extension.setText(self.parent().po.all['extension'])
|
|
395
|
+
#self.shortcut_cb.setChecked(self.parent().po.all['display_shortcuts'])
|
|
396
|
+
#self.display_shortcuts_checked()
|
|
397
|
+
# self.Video_analysis_window.setVisible(True)
|
|
398
|
+
self.Run_all_directly.setVisible(True)
|
|
399
|
+
self.video_tab.set_not_in_use()
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
def re_instantiate_widgets(self):
|
|
403
|
+
"""
|
|
404
|
+
|
|
405
|
+
:return:
|
|
406
|
+
"""
|
|
407
|
+
self.instantiate = True
|
|
408
|
+
# Since we re-instantiate everything, image analysis will no longer be available from video analysis:
|
|
409
|
+
self.parent().videoanalysiswindow.image_tab.set_not_usable()
|
|
410
|
+
|
|
411
|
+
# self.parent().po.all['radical'] = self.radical.text()
|
|
412
|
+
# self.parent().po.all['extension'] = self.extension.text()
|
|
413
|
+
# self.parent().po.sample_number = int(self.arena_number.value())
|
|
414
|
+
# self.parent().po.all['first_folder_sample_number'] = self.parent().po.sample_number
|
|
415
|
+
# self.parent().po.all['sample_number_per_folder'] = [self.parent().po.sample_number]
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
# Mettre ça en thread ? PB : conflict entre all et vars
|
|
419
|
+
# if os.path.isfile('Data to run Cellects quickly.pkl'):
|
|
420
|
+
# try:
|
|
421
|
+
# with open('Data to run Cellects quickly.pkl', 'rb') as fileopen:
|
|
422
|
+
# data_to_run_cellects_quickly = pickle.load(fileopen)
|
|
423
|
+
# if 'vars' in data_to_run_cellects_quickly:
|
|
424
|
+
# self.vars = data_to_run_cellects_quickly['vars']
|
|
425
|
+
# except EOFError:
|
|
426
|
+
# print("Pickle error: could not load vars from the data folder")
|
|
427
|
+
# self.instantiate = True
|
|
428
|
+
# else:
|
|
429
|
+
# self.instantiate = True
|
|
430
|
+
# if self.instantiate:
|
|
431
|
+
# self.parent().po.all['radical'] = self.radical.text()
|
|
432
|
+
# self.parent().po.all['extension'] = self.extension.text()
|
|
433
|
+
# self.parent().po.sample_number = int(self.arena_number.value())
|
|
434
|
+
# self.parent().po.all['first_folder_sample_number'] = self.parent().po.sample_number
|
|
435
|
+
# self.parent().po.all['sample_number_per_folder'] = [self.parent().po.sample_number]
|
|
436
|
+
|
|
437
|
+
def closeEvent(self, event):
|
|
438
|
+
event.accept
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
# if __name__ == "__main__":
|
|
442
|
+
# from cellects.gui.cellects import CellectsMainWidget
|
|
443
|
+
# import sys
|
|
444
|
+
# app = QtWidgets.QApplication([])
|
|
445
|
+
# parent = CellectsMainWidget()
|
|
446
|
+
# session = FirstWindow(parent, False)
|
|
447
|
+
# parent.insertWidget(0, session)
|
|
448
|
+
# parent.show()
|
|
449
|
+
# sys.exit(app.exec())
|