celldetective 1.2.1__py3-none-any.whl → 1.2.2.post1__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.
- celldetective/__main__.py +12 -5
- celldetective/events.py +28 -2
- celldetective/gui/about.py +0 -1
- celldetective/gui/analyze_block.py +3 -18
- celldetective/gui/btrack_options.py +126 -21
- celldetective/gui/classifier_widget.py +67 -111
- celldetective/gui/configure_new_exp.py +37 -4
- celldetective/gui/control_panel.py +14 -30
- celldetective/gui/generic_signal_plot.py +793 -0
- celldetective/gui/gui_utils.py +401 -226
- celldetective/gui/json_readers.py +0 -2
- celldetective/gui/layouts.py +269 -25
- celldetective/gui/measurement_options.py +14 -23
- celldetective/gui/neighborhood_options.py +3 -15
- celldetective/gui/plot_measurements.py +10 -23
- celldetective/gui/plot_signals_ui.py +53 -687
- celldetective/gui/process_block.py +320 -186
- celldetective/gui/retrain_segmentation_model_options.py +30 -47
- celldetective/gui/retrain_signal_model_options.py +5 -14
- celldetective/gui/seg_model_loader.py +129 -113
- celldetective/gui/signal_annotator.py +89 -99
- celldetective/gui/signal_annotator2.py +5 -9
- celldetective/gui/styles.py +32 -0
- celldetective/gui/survival_ui.py +49 -712
- celldetective/gui/tableUI.py +0 -1
- celldetective/gui/thresholds_gui.py +38 -11
- celldetective/gui/viewers.py +6 -7
- celldetective/io.py +60 -82
- celldetective/measure.py +374 -15
- celldetective/neighborhood.py +1 -7
- celldetective/preprocessing.py +2 -4
- celldetective/relative_measurements.py +0 -3
- celldetective/scripts/analyze_signals.py +0 -1
- celldetective/scripts/measure_cells.py +1 -3
- celldetective/scripts/measure_relative.py +1 -2
- celldetective/scripts/segment_cells.py +16 -12
- celldetective/scripts/segment_cells_thresholds.py +17 -10
- celldetective/scripts/track_cells.py +18 -18
- celldetective/scripts/train_segmentation_model.py +1 -2
- celldetective/scripts/train_signal_model.py +0 -3
- celldetective/segmentation.py +1 -1
- celldetective/signals.py +17 -8
- celldetective/tracking.py +2 -1
- celldetective/utils.py +42 -2
- {celldetective-1.2.1.dist-info → celldetective-1.2.2.post1.dist-info}/METADATA +19 -12
- celldetective-1.2.2.post1.dist-info/RECORD +86 -0
- {celldetective-1.2.1.dist-info → celldetective-1.2.2.post1.dist-info}/WHEEL +1 -1
- celldetective/models/segmentation_effectors/primNK_cfse/config_input.json +0 -29
- celldetective/models/segmentation_effectors/primNK_cfse/cp-cfse-transfer +0 -0
- celldetective/models/segmentation_effectors/primNK_cfse/training_instructions.json +0 -37
- celldetective/models/segmentation_effectors/ricm-bimodal/config_input.json +0 -130
- celldetective/models/segmentation_effectors/ricm-bimodal/ricm-bimodal +0 -0
- celldetective/models/segmentation_effectors/ricm-bimodal/training_instructions.json +0 -37
- celldetective-1.2.1.dist-info/RECORD +0 -91
- {celldetective-1.2.1.dist-info → celldetective-1.2.2.post1.dist-info}/LICENSE +0 -0
- {celldetective-1.2.1.dist-info → celldetective-1.2.2.post1.dist-info}/entry_points.txt +0 -0
- {celldetective-1.2.1.dist-info → celldetective-1.2.2.post1.dist-info}/top_level.txt +0 -0
|
@@ -1,23 +1,20 @@
|
|
|
1
1
|
from PyQt5.QtWidgets import QMainWindow, QComboBox, QLabel, QRadioButton, QLineEdit, QFileDialog, QApplication, \
|
|
2
|
-
QPushButton, QWidget, QVBoxLayout, QHBoxLayout, QMessageBox,
|
|
2
|
+
QPushButton, QWidget, QVBoxLayout, QHBoxLayout, QMessageBox, QShortcut, QLineEdit, QSlider, QCheckBox
|
|
3
3
|
from PyQt5.QtCore import Qt, QSize
|
|
4
4
|
from PyQt5.QtGui import QKeySequence, QIntValidator
|
|
5
|
-
from matplotlib.widgets import Slider
|
|
6
|
-
from tifffile import imread
|
|
7
5
|
|
|
8
|
-
from celldetective.gui.gui_utils import center_window,
|
|
9
|
-
from superqt import QLabeledDoubleSlider, QLabeledDoubleRangeSlider,
|
|
6
|
+
from celldetective.gui.gui_utils import center_window, color_from_state
|
|
7
|
+
from superqt import QLabeledDoubleSlider, QLabeledDoubleRangeSlider, QSearchableComboBox
|
|
10
8
|
from celldetective.utils import extract_experiment_channels, get_software_location, _get_img_num_per_channel
|
|
11
|
-
from celldetective.io import auto_load_number_of_frames, load_frames,
|
|
9
|
+
from celldetective.io import auto_load_number_of_frames, load_frames, \
|
|
12
10
|
load_napari_data
|
|
13
|
-
from celldetective.gui.gui_utils import FigureCanvas, color_from_status, color_from_class
|
|
11
|
+
from celldetective.gui.gui_utils import FigureCanvas, color_from_status, color_from_class, ExportPlotBtn
|
|
14
12
|
import json
|
|
15
13
|
import numpy as np
|
|
16
14
|
from superqt.fonticon import icon
|
|
17
15
|
from fonticon_mdi6 import MDI6
|
|
18
16
|
import os
|
|
19
17
|
from glob import glob
|
|
20
|
-
from natsort import natsorted
|
|
21
18
|
import matplotlib.pyplot as plt
|
|
22
19
|
from matplotlib.ticker import MultipleLocator
|
|
23
20
|
from tqdm import tqdm
|
|
@@ -38,6 +35,8 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
38
35
|
def __init__(self, parent_window=None):
|
|
39
36
|
|
|
40
37
|
super().__init__()
|
|
38
|
+
center_window(self)
|
|
39
|
+
|
|
41
40
|
self.parent_window = parent_window
|
|
42
41
|
self.setWindowTitle("Signal annotator")
|
|
43
42
|
self.mode = self.parent_window.mode
|
|
@@ -49,14 +48,15 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
49
48
|
self.recently_modified = False
|
|
50
49
|
self.selection = []
|
|
51
50
|
if self.mode == "targets":
|
|
52
|
-
self.instructions_path = self.exp_dir +
|
|
53
|
-
self.trajectories_path = self.pos + 'output
|
|
51
|
+
self.instructions_path = self.exp_dir + os.sep.join(['configs', 'signal_annotator_config_targets.json'])
|
|
52
|
+
self.trajectories_path = self.pos + os.sep.join(['output','tables','trajectories_targets.csv'])
|
|
54
53
|
elif self.mode == "effectors":
|
|
55
|
-
self.instructions_path = self.exp_dir +
|
|
56
|
-
self.trajectories_path = self.pos + 'output
|
|
54
|
+
self.instructions_path = self.exp_dir + os.sep.join(['configs', 'signal_annotator_config_effectors.json'])
|
|
55
|
+
self.trajectories_path = self.pos + os.sep.join(['output','tables','trajectories_effectors.csv'])
|
|
57
56
|
|
|
58
57
|
self.screen_height = self.parent_window.parent_window.parent_window.screen_height
|
|
59
58
|
self.screen_width = self.parent_window.parent_window.parent_window.screen_width
|
|
59
|
+
#self.setMinimumHeight(int(0.8*self.screen_height))
|
|
60
60
|
self.value_magnitude = 1
|
|
61
61
|
|
|
62
62
|
# default params
|
|
@@ -64,8 +64,6 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
64
64
|
self.time_name = 't0'
|
|
65
65
|
self.status_name = 'status'
|
|
66
66
|
|
|
67
|
-
center_window(self)
|
|
68
|
-
|
|
69
67
|
self.locate_stack()
|
|
70
68
|
self.load_annotator_config()
|
|
71
69
|
self.locate_tracks()
|
|
@@ -78,11 +76,6 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
78
76
|
|
|
79
77
|
self.populate_widget()
|
|
80
78
|
|
|
81
|
-
#self.setMinimumWidth(int(0.8 * self.screen_width))
|
|
82
|
-
# self.setMaximumHeight(int(0.8*self.screen_height))
|
|
83
|
-
#self.setMinimumHeight(int(0.8 * self.screen_height))
|
|
84
|
-
# self.setMaximumHeight(int(0.8*self.screen_height))
|
|
85
|
-
|
|
86
79
|
self.setAttribute(Qt.WA_DeleteOnClose)
|
|
87
80
|
|
|
88
81
|
def populate_widget(self):
|
|
@@ -98,12 +91,13 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
98
91
|
|
|
99
92
|
main_layout.setContentsMargins(30, 30, 30, 30)
|
|
100
93
|
self.left_panel = QVBoxLayout()
|
|
101
|
-
self.left_panel.setContentsMargins(30,
|
|
102
|
-
self.left_panel.setSpacing(
|
|
94
|
+
self.left_panel.setContentsMargins(30, 5, 30, 5)
|
|
95
|
+
self.left_panel.setSpacing(3)
|
|
103
96
|
|
|
104
97
|
self.right_panel = QVBoxLayout()
|
|
105
98
|
|
|
106
99
|
class_hbox = QHBoxLayout()
|
|
100
|
+
class_hbox.setContentsMargins(0,0,0,0)
|
|
107
101
|
class_hbox.addWidget(QLabel('event: '), 25)
|
|
108
102
|
self.class_choice_cb = QComboBox()
|
|
109
103
|
|
|
@@ -140,14 +134,14 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
140
134
|
self.del_class_btn.clicked.connect(self.del_event_class)
|
|
141
135
|
class_hbox.addWidget(self.del_class_btn, 5)
|
|
142
136
|
|
|
143
|
-
self.left_panel.addLayout(class_hbox)
|
|
137
|
+
self.left_panel.addLayout(class_hbox,5)
|
|
144
138
|
|
|
145
139
|
self.cell_info = QLabel('')
|
|
146
|
-
self.left_panel.addWidget(self.cell_info)
|
|
140
|
+
self.left_panel.addWidget(self.cell_info,10)
|
|
147
141
|
|
|
148
142
|
# Annotation buttons
|
|
149
143
|
options_hbox = QHBoxLayout()
|
|
150
|
-
options_hbox.setContentsMargins(
|
|
144
|
+
options_hbox.setContentsMargins(0, 0, 0, 0)
|
|
151
145
|
self.event_btn = QRadioButton('event')
|
|
152
146
|
self.event_btn.setStyleSheet(self.button_style_sheet_2)
|
|
153
147
|
self.event_btn.toggled.connect(self.enable_time_of_interest)
|
|
@@ -160,25 +154,28 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
160
154
|
self.else_btn.setStyleSheet(self.button_style_sheet_2)
|
|
161
155
|
self.else_btn.toggled.connect(self.enable_time_of_interest)
|
|
162
156
|
|
|
163
|
-
self.suppr_btn = QRadioButton('
|
|
157
|
+
self.suppr_btn = QRadioButton('remove')
|
|
158
|
+
self.suppr_btn.setToolTip('Mark for deletion. Upon saving, the cell\nwill be removed from the tables.')
|
|
164
159
|
self.suppr_btn.setStyleSheet(self.button_style_sheet_2)
|
|
165
160
|
self.suppr_btn.toggled.connect(self.enable_time_of_interest)
|
|
166
161
|
|
|
167
|
-
options_hbox.addWidget(self.event_btn, 25)
|
|
168
|
-
options_hbox.addWidget(self.no_event_btn, 25)
|
|
169
|
-
options_hbox.addWidget(self.else_btn, 25)
|
|
170
|
-
options_hbox.addWidget(self.suppr_btn, 25)
|
|
171
|
-
self.left_panel.addLayout(options_hbox)
|
|
162
|
+
options_hbox.addWidget(self.event_btn, 25, alignment=Qt.AlignCenter)
|
|
163
|
+
options_hbox.addWidget(self.no_event_btn, 25, alignment=Qt.AlignCenter)
|
|
164
|
+
options_hbox.addWidget(self.else_btn, 25, alignment=Qt.AlignCenter)
|
|
165
|
+
options_hbox.addWidget(self.suppr_btn, 25, alignment=Qt.AlignCenter)
|
|
166
|
+
self.left_panel.addLayout(options_hbox,5)
|
|
172
167
|
|
|
173
168
|
time_option_hbox = QHBoxLayout()
|
|
174
|
-
time_option_hbox.setContentsMargins(
|
|
169
|
+
time_option_hbox.setContentsMargins(0, 5, 100, 10)
|
|
175
170
|
self.time_of_interest_label = QLabel('time of interest: ')
|
|
176
|
-
time_option_hbox.addWidget(self.time_of_interest_label,
|
|
171
|
+
time_option_hbox.addWidget(self.time_of_interest_label, 10)
|
|
177
172
|
self.time_of_interest_le = QLineEdit()
|
|
178
|
-
time_option_hbox.addWidget(self.time_of_interest_le,
|
|
179
|
-
|
|
173
|
+
time_option_hbox.addWidget(self.time_of_interest_le, 15)
|
|
174
|
+
time_option_hbox.addWidget(QLabel(''), 75)
|
|
175
|
+
self.left_panel.addLayout(time_option_hbox,5)
|
|
180
176
|
|
|
181
177
|
main_action_hbox = QHBoxLayout()
|
|
178
|
+
main_action_hbox.setContentsMargins(0,0,0,0)
|
|
182
179
|
self.correct_btn = QPushButton('correct')
|
|
183
180
|
self.correct_btn.setIcon(icon(MDI6.redo_variant, color="white"))
|
|
184
181
|
self.correct_btn.setIconSize(QSize(20, 20))
|
|
@@ -193,7 +190,7 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
193
190
|
self.cancel_btn.setEnabled(False)
|
|
194
191
|
self.cancel_btn.clicked.connect(self.cancel_selection)
|
|
195
192
|
main_action_hbox.addWidget(self.cancel_btn)
|
|
196
|
-
self.left_panel.addLayout(main_action_hbox)
|
|
193
|
+
self.left_panel.addLayout(main_action_hbox,5)
|
|
197
194
|
|
|
198
195
|
self.annotation_btns_to_hide = [self.event_btn, self.no_event_btn,
|
|
199
196
|
self.else_btn, self.time_of_interest_label,
|
|
@@ -210,7 +207,8 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
210
207
|
self.no_event_shortcut.setEnabled(False)
|
|
211
208
|
|
|
212
209
|
# Cell signals
|
|
213
|
-
|
|
210
|
+
|
|
211
|
+
self.left_panel.addWidget(self.cell_fcanvas, 45)
|
|
214
212
|
|
|
215
213
|
plot_buttons_hbox = QHBoxLayout()
|
|
216
214
|
plot_buttons_hbox.setContentsMargins(0, 0, 0, 0)
|
|
@@ -232,10 +230,13 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
232
230
|
self.log_btn.clicked.connect(self.switch_to_log)
|
|
233
231
|
plot_buttons_hbox.addWidget(self.log_btn, 5)
|
|
234
232
|
|
|
235
|
-
self.
|
|
233
|
+
self.export_plot_btn = ExportPlotBtn(self.cell_fig, export_dir = self.exp_dir)
|
|
234
|
+
plot_buttons_hbox.addWidget(self.export_plot_btn, 5)
|
|
235
|
+
|
|
236
|
+
self.left_panel.addLayout(plot_buttons_hbox,5)
|
|
236
237
|
|
|
237
238
|
signal_choice_vbox = QVBoxLayout()
|
|
238
|
-
signal_choice_vbox.setContentsMargins(30, 0, 30,
|
|
239
|
+
signal_choice_vbox.setContentsMargins(30, 0, 30, 0)
|
|
239
240
|
for i in range(len(self.signal_choice_cb)):
|
|
240
241
|
hlayout = QHBoxLayout()
|
|
241
242
|
hlayout.addWidget(self.signal_choice_label[i], 20)
|
|
@@ -247,9 +248,10 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
247
248
|
# self.log_btns[i].setStyleSheet(self.parent.parent.parent.button_select_all)
|
|
248
249
|
# self.log_btns[i].clicked.connect(lambda ch, i=i: self.switch_to_log(i))
|
|
249
250
|
|
|
250
|
-
self.left_panel.addLayout(signal_choice_vbox)
|
|
251
|
+
self.left_panel.addLayout(signal_choice_vbox,15)
|
|
251
252
|
|
|
252
253
|
btn_hbox = QHBoxLayout()
|
|
254
|
+
btn_hbox.setContentsMargins(0,10,0,0)
|
|
253
255
|
self.save_btn = QPushButton('Save')
|
|
254
256
|
self.save_btn.setStyleSheet(self.button_style_sheet)
|
|
255
257
|
self.save_btn.clicked.connect(self.save_trajectories)
|
|
@@ -261,7 +263,7 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
261
263
|
self.export_btn.setIcon(icon(MDI6.export, color="black"))
|
|
262
264
|
self.export_btn.setIconSize(QSize(25, 25))
|
|
263
265
|
btn_hbox.addWidget(self.export_btn, 10)
|
|
264
|
-
self.left_panel.addLayout(btn_hbox)
|
|
266
|
+
self.left_panel.addLayout(btn_hbox,5)
|
|
265
267
|
|
|
266
268
|
# Animation
|
|
267
269
|
animation_buttons_box = QHBoxLayout()
|
|
@@ -315,9 +317,6 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
315
317
|
self.contrast_slider.setSingleStep(0.001)
|
|
316
318
|
self.contrast_slider.setTickInterval(0.001)
|
|
317
319
|
self.contrast_slider.setOrientation(1)
|
|
318
|
-
print(self.stack.shape, np.unique(self.stack))
|
|
319
|
-
print('range: ',
|
|
320
|
-
[np.nanpercentile(self.stack, 0.001), np.nanpercentile(self.stack, 99.999)])
|
|
321
320
|
self.contrast_slider.setRange(
|
|
322
321
|
*[np.nanpercentile(self.stack, 0.001), np.nanpercentile(self.stack, 99.999)])
|
|
323
322
|
self.contrast_slider.setValue(
|
|
@@ -477,14 +476,12 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
477
476
|
self.time_name = self.expected_time
|
|
478
477
|
self.status_name = self.expected_status
|
|
479
478
|
|
|
480
|
-
print('selection and expected names: ', self.class_name, self.expected_time, self.expected_status)
|
|
481
479
|
cols = list(self.df_tracks.columns)
|
|
482
480
|
|
|
483
481
|
if self.time_name in cols and self.class_name in cols and not self.status_name in cols:
|
|
484
482
|
# only create the status column if it does not exist to not erase static classification results
|
|
485
483
|
self.make_status_column()
|
|
486
484
|
elif self.time_name in cols and self.class_name in cols and self.df_tracks[self.status_name].isnull().all():
|
|
487
|
-
print('this is the case!', )
|
|
488
485
|
self.make_status_column()
|
|
489
486
|
elif self.time_name in cols and self.class_name in cols:
|
|
490
487
|
# all good, do nothing
|
|
@@ -643,7 +640,7 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
643
640
|
|
|
644
641
|
"""
|
|
645
642
|
|
|
646
|
-
movies = glob(self.pos + f"
|
|
643
|
+
movies = glob(self.pos + os.sep.join(["movie", f"{self.parent_window.parent_window.movie_prefix}*.tif"]))
|
|
647
644
|
|
|
648
645
|
if len(movies) == 0:
|
|
649
646
|
msgBox = QMessageBox()
|
|
@@ -782,8 +779,8 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
782
779
|
# self.loc_t, self.loc_idx = np.where(self.tracks==self.track_of_interest)
|
|
783
780
|
|
|
784
781
|
def make_status_column(self):
|
|
785
|
-
|
|
786
|
-
print('
|
|
782
|
+
|
|
783
|
+
print(f'Generating status information for class `{self.class_name}` and time `{self.time_name}`...')
|
|
787
784
|
for tid, group in self.df_tracks.groupby('TRACK_ID'):
|
|
788
785
|
|
|
789
786
|
indices = group.index
|
|
@@ -811,7 +808,7 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
811
808
|
# self.log_btns = [QPushButton() for i in range(self.n_signals)]
|
|
812
809
|
|
|
813
810
|
signals = list(self.df_tracks.columns)
|
|
814
|
-
|
|
811
|
+
|
|
815
812
|
to_remove = ['TRACK_ID', 'FRAME', 'x_anim', 'y_anim', 't', 'state', 'generation', 'root', 'parent', 'class_id',
|
|
816
813
|
'class', 't0', 'POSITION_X', 'POSITION_Y', 'position', 'well', 'well_index', 'well_name',
|
|
817
814
|
'pos_name', 'index','class_color','status_color']
|
|
@@ -840,7 +837,6 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
840
837
|
self.lines[i].set_xdata([])
|
|
841
838
|
self.lines[i].set_ydata([])
|
|
842
839
|
else:
|
|
843
|
-
print(f'plot signal {signal_choice} for cell {self.track_of_interest}')
|
|
844
840
|
xdata = self.df_tracks.loc[self.df_tracks['TRACK_ID'] == self.track_of_interest, 'FRAME'].to_numpy()
|
|
845
841
|
ydata = self.df_tracks.loc[
|
|
846
842
|
self.df_tracks['TRACK_ID'] == self.track_of_interest, signal_choice].to_numpy()
|
|
@@ -867,7 +863,7 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
867
863
|
self.cell_ax.legend()
|
|
868
864
|
self.cell_fcanvas.canvas.draw()
|
|
869
865
|
except Exception as e:
|
|
870
|
-
|
|
866
|
+
pass
|
|
871
867
|
|
|
872
868
|
if len(range_values)>0:
|
|
873
869
|
range_values = np.array(range_values)
|
|
@@ -901,12 +897,10 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
901
897
|
Load settings from config or set default values.
|
|
902
898
|
"""
|
|
903
899
|
|
|
904
|
-
print('Reading instructions..')
|
|
905
900
|
if os.path.exists(self.instructions_path):
|
|
906
901
|
with open(self.instructions_path, 'r') as f:
|
|
907
902
|
|
|
908
903
|
instructions = json.load(f)
|
|
909
|
-
print(f'Reading instructions: {instructions}')
|
|
910
904
|
|
|
911
905
|
if 'rgb_mode' in instructions:
|
|
912
906
|
self.rgb_mode = instructions['rgb_mode']
|
|
@@ -949,7 +943,8 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
949
943
|
|
|
950
944
|
self.img_num_channels = _get_img_num_per_channel(self.channels, self.len_movie, self.nbr_channels)
|
|
951
945
|
self.stack = []
|
|
952
|
-
|
|
946
|
+
disable_tqdm = not len(self.target_channels)>1
|
|
947
|
+
for ch in tqdm(self.target_channels, desc="channel",disable=disable_tqdm):
|
|
953
948
|
target_ch_name = ch[0]
|
|
954
949
|
if self.percentile_mode:
|
|
955
950
|
normalize_kwargs = {"percentiles": (ch[1], ch[2]), "values": None}
|
|
@@ -981,8 +976,6 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
981
976
|
if self.log_option:
|
|
982
977
|
self.stack[np.where(self.stack > 0.)] = np.log(self.stack[np.where(self.stack > 0.)])
|
|
983
978
|
|
|
984
|
-
print(f'Load stack of shape: {self.stack.shape}.')
|
|
985
|
-
|
|
986
979
|
def closeEvent(self, event):
|
|
987
980
|
|
|
988
981
|
self.stop()
|
|
@@ -1034,8 +1027,8 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
1034
1027
|
|
|
1035
1028
|
def create_cell_signal_canvas(self):
|
|
1036
1029
|
|
|
1037
|
-
self.cell_fig, self.cell_ax = plt.subplots()
|
|
1038
|
-
self.cell_fcanvas = FigureCanvas(self.cell_fig, interactive=
|
|
1030
|
+
self.cell_fig, self.cell_ax = plt.subplots(tight_layout=True)
|
|
1031
|
+
self.cell_fcanvas = FigureCanvas(self.cell_fig, interactive=True)
|
|
1039
1032
|
self.cell_ax.clear()
|
|
1040
1033
|
|
|
1041
1034
|
spacing = 0.5
|
|
@@ -1066,6 +1059,9 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
1066
1059
|
|
|
1067
1060
|
def on_scatter_pick(self, event):
|
|
1068
1061
|
|
|
1062
|
+
self.correct_btn.disconnect()
|
|
1063
|
+
self.correct_btn.clicked.connect(self.show_annotation_buttons)
|
|
1064
|
+
|
|
1069
1065
|
ind = event.ind
|
|
1070
1066
|
|
|
1071
1067
|
if len(ind) > 1:
|
|
@@ -1085,7 +1081,7 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
1085
1081
|
self.no_event_shortcut.setEnabled(True)
|
|
1086
1082
|
|
|
1087
1083
|
self.track_of_interest = self.tracks[self.framedata][ind]
|
|
1088
|
-
print(f'You selected
|
|
1084
|
+
print(f'You selected cell #{self.track_of_interest}...')
|
|
1089
1085
|
self.give_cell_information()
|
|
1090
1086
|
self.plot_signals()
|
|
1091
1087
|
|
|
@@ -1135,7 +1131,7 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
1135
1131
|
if len(min_values) > 0:
|
|
1136
1132
|
self.cell_ax.set_ylim(np.amin(min_values), np.amax(max_values))
|
|
1137
1133
|
except Exception as e:
|
|
1138
|
-
|
|
1134
|
+
pass
|
|
1139
1135
|
|
|
1140
1136
|
def draw_frame(self, framedata):
|
|
1141
1137
|
|
|
@@ -1196,7 +1192,7 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
1196
1192
|
|
|
1197
1193
|
self.df_tracks = self.df_tracks.drop(self.df_tracks[self.df_tracks[self.class_name] > 2].index)
|
|
1198
1194
|
self.df_tracks.to_csv(self.trajectories_path, index=False)
|
|
1199
|
-
print('
|
|
1195
|
+
print('Table successfully exported...')
|
|
1200
1196
|
self.extract_scatter_from_trajectories()
|
|
1201
1197
|
|
|
1202
1198
|
# self.give_cell_information()
|
|
@@ -1217,7 +1213,6 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
1217
1213
|
while len(np.where(self.stack[self.last_key].flatten() == 0)[0]) > 0.99 * len(
|
|
1218
1214
|
self.stack[self.last_key].flatten()):
|
|
1219
1215
|
self.last_key -= 1
|
|
1220
|
-
print(f'Last frame is {len(self.stack) - 1}; last not black is {self.last_key}')
|
|
1221
1216
|
self.anim._drawn_artists = self.draw_frame(self.last_key)
|
|
1222
1217
|
self.anim._drawn_artists = sorted(self.anim._drawn_artists, key=lambda x: x.get_zorder())
|
|
1223
1218
|
for a in self.anim._drawn_artists:
|
|
@@ -1238,7 +1233,6 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
1238
1233
|
self.first_frame_btn.disconnect()
|
|
1239
1234
|
|
|
1240
1235
|
self.first_key = 0
|
|
1241
|
-
print(f'First frame is {0}')
|
|
1242
1236
|
self.anim._drawn_artists = self.draw_frame(0)
|
|
1243
1237
|
self.anim._drawn_artists = sorted(self.anim._drawn_artists, key=lambda x: x.get_zorder())
|
|
1244
1238
|
for a in self.anim._drawn_artists:
|
|
@@ -1275,8 +1269,6 @@ class SignalAnnotator(QMainWindow, Styles):
|
|
|
1275
1269
|
# Here auto add all available channels
|
|
1276
1270
|
training_set.append(signals)
|
|
1277
1271
|
|
|
1278
|
-
print(training_set)
|
|
1279
|
-
|
|
1280
1272
|
pathsave = QFileDialog.getSaveFileName(self, "Select file name", self.exp_dir + auto_dataset_name, ".npy")[0]
|
|
1281
1273
|
if pathsave != '':
|
|
1282
1274
|
if not pathsave.endswith(".npy"):
|
|
@@ -1420,10 +1412,10 @@ class MeasureAnnotator(SignalAnnotator):
|
|
|
1420
1412
|
self.cell_fcanvas = FigureCanvas(self.cell_fig, interactive=False)
|
|
1421
1413
|
self.cell_ax.clear()
|
|
1422
1414
|
|
|
1423
|
-
spacing = 0.5
|
|
1424
|
-
minorLocator = MultipleLocator(1)
|
|
1425
|
-
self.cell_ax.xaxis.set_minor_locator(minorLocator)
|
|
1426
|
-
self.cell_ax.xaxis.set_major_locator(MultipleLocator(5))
|
|
1415
|
+
# spacing = 0.5
|
|
1416
|
+
# minorLocator = MultipleLocator(1)
|
|
1417
|
+
# self.cell_ax.xaxis.set_minor_locator(minorLocator)
|
|
1418
|
+
# self.cell_ax.xaxis.set_major_locator(MultipleLocator(5))
|
|
1427
1419
|
self.cell_ax.grid(which='major')
|
|
1428
1420
|
self.cell_ax.set_xlabel("time [frame]")
|
|
1429
1421
|
self.cell_ax.set_ylabel("signal")
|
|
@@ -1526,7 +1518,7 @@ class MeasureAnnotator(SignalAnnotator):
|
|
|
1526
1518
|
for i in range(len(self.signal_choice_cb)):
|
|
1527
1519
|
signal_choice = self.signal_choice_cb[i].currentText()
|
|
1528
1520
|
if signal_choice != "--":
|
|
1529
|
-
print(f'plot signal {signal_choice} for cell {self.track_of_interest} at frame {current_frame}')
|
|
1521
|
+
#print(f'plot signal {signal_choice} for cell {self.track_of_interest} at frame {current_frame}')
|
|
1530
1522
|
if 'TRACK_ID' in self.df_tracks.columns:
|
|
1531
1523
|
ydata = self.df_tracks.loc[
|
|
1532
1524
|
(self.df_tracks['TRACK_ID'] == self.track_of_interest) &
|
|
@@ -1560,7 +1552,7 @@ class MeasureAnnotator(SignalAnnotator):
|
|
|
1560
1552
|
self.del_shortcut.setEnabled(True)
|
|
1561
1553
|
self.no_event_shortcut.setEnabled(True)
|
|
1562
1554
|
self.track_of_interest = self.tracks[self.framedata][ind]
|
|
1563
|
-
print(f'You selected
|
|
1555
|
+
print(f'You selected cell #{self.track_of_interest}...')
|
|
1564
1556
|
self.give_cell_information()
|
|
1565
1557
|
if len(self.cell_ax.lines) > 0:
|
|
1566
1558
|
self.cell_ax.lines[-1].remove() # Remove the last line (red points) from the plot
|
|
@@ -1600,20 +1592,23 @@ class MeasureAnnotator(SignalAnnotator):
|
|
|
1600
1592
|
self.button_widget.setLayout(main_layout)
|
|
1601
1593
|
|
|
1602
1594
|
main_layout.setContentsMargins(30, 30, 30, 30)
|
|
1595
|
+
|
|
1603
1596
|
self.left_panel = QVBoxLayout()
|
|
1604
|
-
self.left_panel.setContentsMargins(30,
|
|
1605
|
-
self.left_panel.setSpacing(
|
|
1597
|
+
self.left_panel.setContentsMargins(30, 5, 30, 5)
|
|
1598
|
+
#self.left_panel.setSpacing(3)
|
|
1606
1599
|
|
|
1607
1600
|
self.right_panel = QVBoxLayout()
|
|
1608
1601
|
|
|
1609
1602
|
class_hbox = QHBoxLayout()
|
|
1603
|
+
class_hbox.setContentsMargins(0,0,0,0)
|
|
1604
|
+
class_hbox.setSpacing(0)
|
|
1605
|
+
|
|
1610
1606
|
class_hbox.addWidget(QLabel('characteristic \n group: '), 25)
|
|
1611
1607
|
self.class_choice_cb = QComboBox()
|
|
1612
1608
|
|
|
1613
1609
|
cols = np.array(self.df_tracks.columns)
|
|
1614
1610
|
self.class_cols = np.array([c.startswith('group') or c.startswith('status') for c in list(self.df_tracks.columns)])
|
|
1615
1611
|
self.class_cols = list(cols[self.class_cols])
|
|
1616
|
-
print(self.class_cols)
|
|
1617
1612
|
|
|
1618
1613
|
try:
|
|
1619
1614
|
self.class_cols.remove('group_id')
|
|
@@ -1644,13 +1639,15 @@ class MeasureAnnotator(SignalAnnotator):
|
|
|
1644
1639
|
self.del_class_btn.clicked.connect(self.del_event_class)
|
|
1645
1640
|
class_hbox.addWidget(self.del_class_btn, 5)
|
|
1646
1641
|
|
|
1647
|
-
self.left_panel.addLayout(class_hbox)
|
|
1642
|
+
self.left_panel.addLayout(class_hbox,5)
|
|
1648
1643
|
|
|
1649
1644
|
self.cell_info = QLabel('')
|
|
1650
|
-
self.left_panel.addWidget(self.cell_info)
|
|
1645
|
+
self.left_panel.addWidget(self.cell_info,5)
|
|
1651
1646
|
|
|
1652
1647
|
time_option_hbox = QHBoxLayout()
|
|
1653
|
-
time_option_hbox.setContentsMargins(100,
|
|
1648
|
+
time_option_hbox.setContentsMargins(100, 0, 100, 0)
|
|
1649
|
+
time_option_hbox.setSpacing(0)
|
|
1650
|
+
|
|
1654
1651
|
self.time_of_interest_label = QLabel('phenotype: ')
|
|
1655
1652
|
time_option_hbox.addWidget(self.time_of_interest_label, 30)
|
|
1656
1653
|
self.time_of_interest_le = QLineEdit()
|
|
@@ -1663,9 +1660,12 @@ class MeasureAnnotator(SignalAnnotator):
|
|
|
1663
1660
|
self.del_cell_btn.setIconSize(QSize(20, 20))
|
|
1664
1661
|
self.del_cell_btn.clicked.connect(self.del_cell)
|
|
1665
1662
|
time_option_hbox.addWidget(self.del_cell_btn)
|
|
1666
|
-
self.left_panel.addLayout(time_option_hbox)
|
|
1663
|
+
self.left_panel.addLayout(time_option_hbox,5)
|
|
1667
1664
|
|
|
1668
1665
|
main_action_hbox = QHBoxLayout()
|
|
1666
|
+
main_action_hbox.setContentsMargins(0,0,0,0)
|
|
1667
|
+
main_action_hbox.setSpacing(0)
|
|
1668
|
+
|
|
1669
1669
|
self.correct_btn = QPushButton('correct')
|
|
1670
1670
|
self.correct_btn.setIcon(icon(MDI6.redo_variant, color="white"))
|
|
1671
1671
|
self.correct_btn.setIconSize(QSize(20, 20))
|
|
@@ -1680,7 +1680,7 @@ class MeasureAnnotator(SignalAnnotator):
|
|
|
1680
1680
|
self.cancel_btn.setEnabled(False)
|
|
1681
1681
|
self.cancel_btn.clicked.connect(self.cancel_selection)
|
|
1682
1682
|
main_action_hbox.addWidget(self.cancel_btn)
|
|
1683
|
-
self.left_panel.addLayout(main_action_hbox)
|
|
1683
|
+
self.left_panel.addLayout(main_action_hbox,5)
|
|
1684
1684
|
|
|
1685
1685
|
self.annotation_btns_to_hide = [self.time_of_interest_label,
|
|
1686
1686
|
self.time_of_interest_le,
|
|
@@ -1697,7 +1697,8 @@ class MeasureAnnotator(SignalAnnotator):
|
|
|
1697
1697
|
self.no_event_shortcut.setEnabled(False)
|
|
1698
1698
|
|
|
1699
1699
|
# Cell signals
|
|
1700
|
-
self.
|
|
1700
|
+
self.cell_fcanvas.setMinimumHeight(int(0.2*self.screen_height))
|
|
1701
|
+
self.left_panel.addWidget(self.cell_fcanvas,90)
|
|
1701
1702
|
|
|
1702
1703
|
plot_buttons_hbox = QHBoxLayout()
|
|
1703
1704
|
plot_buttons_hbox.setContentsMargins(0, 0, 0, 0)
|
|
@@ -1723,7 +1724,7 @@ class MeasureAnnotator(SignalAnnotator):
|
|
|
1723
1724
|
self.log_btn.clicked.connect(self.switch_to_log)
|
|
1724
1725
|
plot_buttons_hbox.addWidget(self.log_btn, 5)
|
|
1725
1726
|
|
|
1726
|
-
self.left_panel.addLayout(plot_buttons_hbox)
|
|
1727
|
+
self.left_panel.addLayout(plot_buttons_hbox,5)
|
|
1727
1728
|
|
|
1728
1729
|
signal_choice_vbox = QVBoxLayout()
|
|
1729
1730
|
signal_choice_vbox.setContentsMargins(30, 0, 30, 50)
|
|
@@ -1738,14 +1739,13 @@ class MeasureAnnotator(SignalAnnotator):
|
|
|
1738
1739
|
# self.log_btns[i].setStyleSheet(self.parent.parent.parent.button_select_all)
|
|
1739
1740
|
# self.log_btns[i].clicked.connect(lambda ch, i=i: self.switch_to_log(i))
|
|
1740
1741
|
|
|
1741
|
-
self.left_panel.addLayout(signal_choice_vbox)
|
|
1742
|
+
self.left_panel.addLayout(signal_choice_vbox,10)
|
|
1742
1743
|
|
|
1743
1744
|
btn_hbox = QHBoxLayout()
|
|
1744
1745
|
self.save_btn = QPushButton('Save')
|
|
1745
1746
|
self.save_btn.setStyleSheet(self.button_style_sheet)
|
|
1746
1747
|
self.save_btn.clicked.connect(self.save_trajectories)
|
|
1747
1748
|
btn_hbox.addWidget(self.save_btn, 90)
|
|
1748
|
-
self.left_panel.addLayout(btn_hbox)
|
|
1749
1749
|
|
|
1750
1750
|
self.export_btn = QPushButton('')
|
|
1751
1751
|
self.export_btn.setStyleSheet(self.button_select_all)
|
|
@@ -1753,7 +1753,7 @@ class MeasureAnnotator(SignalAnnotator):
|
|
|
1753
1753
|
self.export_btn.setIcon(icon(MDI6.export, color="black"))
|
|
1754
1754
|
self.export_btn.setIconSize(QSize(25, 25))
|
|
1755
1755
|
btn_hbox.addWidget(self.export_btn, 10)
|
|
1756
|
-
self.left_panel.addLayout(btn_hbox)
|
|
1756
|
+
self.left_panel.addLayout(btn_hbox,5)
|
|
1757
1757
|
|
|
1758
1758
|
# Animation
|
|
1759
1759
|
animation_buttons_box = QHBoxLayout()
|
|
@@ -1805,8 +1805,6 @@ class MeasureAnnotator(SignalAnnotator):
|
|
|
1805
1805
|
self.contrast_slider.setSingleStep(0.001)
|
|
1806
1806
|
self.contrast_slider.setTickInterval(0.001)
|
|
1807
1807
|
self.contrast_slider.setOrientation(1)
|
|
1808
|
-
print('range: ',
|
|
1809
|
-
[np.nanpercentile(self.img.flatten(), 0.001), np.nanpercentile(self.img.flatten(), 99.999)])
|
|
1810
1808
|
self.contrast_slider.setRange(
|
|
1811
1809
|
*[np.nanpercentile(self.img, 0.001), np.nanpercentile(self.img, 99.999)])
|
|
1812
1810
|
self.contrast_slider.setValue(
|
|
@@ -1961,9 +1959,8 @@ class MeasureAnnotator(SignalAnnotator):
|
|
|
1961
1959
|
cell_status = f"phenotype: {self.df_tracks.loc[self.df_tracks['ID'] == self.track_of_interest, self.status_name].to_numpy()[0]}\n"
|
|
1962
1960
|
self.cell_info.setText(cell_selected + cell_status)
|
|
1963
1961
|
except Exception as e:
|
|
1964
|
-
print(
|
|
1965
|
-
|
|
1966
|
-
|
|
1962
|
+
print(e)
|
|
1963
|
+
|
|
1967
1964
|
def create_new_event_class(self):
|
|
1968
1965
|
|
|
1969
1966
|
# display qwidget to name the event
|
|
@@ -2051,7 +2048,7 @@ class MeasureAnnotator(SignalAnnotator):
|
|
|
2051
2048
|
try:
|
|
2052
2049
|
self.status_scatter.set_edgecolors(self.colors[self.framedata][:, 0])
|
|
2053
2050
|
except Exception as e:
|
|
2054
|
-
|
|
2051
|
+
pass
|
|
2055
2052
|
|
|
2056
2053
|
self.current_label = self.labels[self.current_frame]
|
|
2057
2054
|
self.current_label = contour_of_instance_segmentation(self.current_label, 5)
|
|
@@ -2067,7 +2064,6 @@ class MeasureAnnotator(SignalAnnotator):
|
|
|
2067
2064
|
self.status_name=self.target_class
|
|
2068
2065
|
else:
|
|
2069
2066
|
self.status_name = self.class_choice_cb.currentText()
|
|
2070
|
-
print('selection and expected names: ', self.status_name)
|
|
2071
2067
|
|
|
2072
2068
|
if self.status_name not in self.df_tracks.columns:
|
|
2073
2069
|
self.make_status_column()
|
|
@@ -2103,7 +2099,6 @@ class MeasureAnnotator(SignalAnnotator):
|
|
|
2103
2099
|
if self.status_name == "state_firstdetection":
|
|
2104
2100
|
pass
|
|
2105
2101
|
else:
|
|
2106
|
-
print('remaking the group column')
|
|
2107
2102
|
self.df_tracks.loc[:, self.status_name] = 0
|
|
2108
2103
|
all_states = self.df_tracks.loc[:, self.status_name].tolist()
|
|
2109
2104
|
all_states = np.array(all_states)
|
|
@@ -2303,8 +2298,6 @@ class MeasureAnnotator(SignalAnnotator):
|
|
|
2303
2298
|
self.current_stack[np.where(self.current_stack > 0.)] = np.log(
|
|
2304
2299
|
self.current_stack[np.where(self.current_stack > 0.)])
|
|
2305
2300
|
|
|
2306
|
-
print(f'Load stack of shape: {self.current_stack.shape}.')
|
|
2307
|
-
|
|
2308
2301
|
def changed_channel(self):
|
|
2309
2302
|
|
|
2310
2303
|
self.reload_frame()
|
|
@@ -2342,7 +2335,7 @@ class MeasureAnnotator(SignalAnnotator):
|
|
|
2342
2335
|
pass
|
|
2343
2336
|
|
|
2344
2337
|
self.df_tracks.to_csv(self.trajectories_path, index=False)
|
|
2345
|
-
print('
|
|
2338
|
+
print('Table successfully exported...')
|
|
2346
2339
|
self.update_frame()
|
|
2347
2340
|
|
|
2348
2341
|
|
|
@@ -2399,9 +2392,8 @@ class MeasureAnnotator(SignalAnnotator):
|
|
|
2399
2392
|
|
|
2400
2393
|
"""
|
|
2401
2394
|
|
|
2402
|
-
print("this is the loaded position: ", self.pos)
|
|
2403
2395
|
if isinstance(self.pos, str):
|
|
2404
|
-
movies = glob(self.pos + f"
|
|
2396
|
+
movies = glob(self.pos + os.sep.join(['movie',f"{self.parent_window.parent_window.movie_prefix}*.tif"]))
|
|
2405
2397
|
|
|
2406
2398
|
else:
|
|
2407
2399
|
msgBox = QMessageBox()
|
|
@@ -2437,8 +2429,6 @@ class MeasureAnnotator(SignalAnnotator):
|
|
|
2437
2429
|
self.nbr_channels = len(self.channels)
|
|
2438
2430
|
self.current_channel = 0
|
|
2439
2431
|
self.img = load_frames(0, self.stack_path, normalize_input=False)
|
|
2440
|
-
print(self.img.shape)
|
|
2441
|
-
print(f'{self.stack_path} successfully located.')
|
|
2442
2432
|
|
|
2443
2433
|
def reload_frame(self):
|
|
2444
2434
|
|
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
import copy
|
|
2
|
-
|
|
3
1
|
from PyQt5.QtWidgets import QMainWindow, QComboBox, QLabel, QRadioButton, QLineEdit, QFileDialog, QApplication, \
|
|
4
|
-
QPushButton, QWidget, QVBoxLayout, QHBoxLayout, QMessageBox,
|
|
5
|
-
QButtonGroup
|
|
2
|
+
QPushButton, QWidget, QVBoxLayout, QHBoxLayout, QMessageBox, QShortcut, QLineEdit, \
|
|
3
|
+
QButtonGroup
|
|
6
4
|
from PyQt5.QtCore import Qt, QSize
|
|
7
5
|
from PyQt5.QtGui import QKeySequence
|
|
8
|
-
from
|
|
9
|
-
from celldetective.gui import
|
|
10
|
-
from
|
|
11
|
-
from superqt import QLabeledDoubleSlider, QLabeledDoubleRangeSlider, QLabeledSlider, QSearchableComboBox
|
|
6
|
+
from celldetective.gui import Styles
|
|
7
|
+
from celldetective.gui.gui_utils import center_window
|
|
8
|
+
from superqt import QLabeledDoubleRangeSlider, QSearchableComboBox
|
|
12
9
|
from celldetective.utils import extract_experiment_channels, get_software_location, _get_img_num_per_channel
|
|
13
10
|
from celldetective.io import auto_load_number_of_frames, load_frames
|
|
14
11
|
from celldetective.gui.gui_utils import FigureCanvas, color_from_status, color_from_class
|
|
@@ -18,7 +15,6 @@ from superqt.fonticon import icon
|
|
|
18
15
|
from fonticon_mdi6 import MDI6
|
|
19
16
|
import os
|
|
20
17
|
from glob import glob
|
|
21
|
-
from natsort import natsorted
|
|
22
18
|
import matplotlib.pyplot as plt
|
|
23
19
|
from matplotlib.ticker import MultipleLocator
|
|
24
20
|
from tqdm import tqdm
|
celldetective/gui/styles.py
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
from celldetective.utils import get_software_location
|
|
2
|
+
from PyQt5.QtGui import QIcon
|
|
3
|
+
import os
|
|
4
|
+
|
|
1
5
|
class Styles(object):
|
|
2
6
|
|
|
3
7
|
def __init__(self):
|
|
@@ -6,7 +10,11 @@ class Styles(object):
|
|
|
6
10
|
self.init_tab_styles()
|
|
7
11
|
self.init_label_styles()
|
|
8
12
|
|
|
13
|
+
self.help_color = "#1958b7"
|
|
14
|
+
|
|
15
|
+
|
|
9
16
|
self.celldetective_blue = "#1565c0"
|
|
17
|
+
self.celldetective_icon = QIcon(os.sep.join([get_software_location(),'celldetective','icons','logo.png']))
|
|
10
18
|
|
|
11
19
|
self.action_lbl_style_sheet = """
|
|
12
20
|
font-size: 10px;
|
|
@@ -65,6 +73,30 @@ class Styles(object):
|
|
|
65
73
|
|
|
66
74
|
'''
|
|
67
75
|
|
|
76
|
+
self.button_style_sheet_5 = '''
|
|
77
|
+
QPushButton {
|
|
78
|
+
background-color: transparent;
|
|
79
|
+
border: 3px solid #1565c0;
|
|
80
|
+
color: #000000;
|
|
81
|
+
border-radius: 15px;
|
|
82
|
+
padding: 7px;
|
|
83
|
+
font-size: 12px;
|
|
84
|
+
}
|
|
85
|
+
QPushButton:hover {
|
|
86
|
+
background-color: #ecf0f1;
|
|
87
|
+
}
|
|
88
|
+
QPushButton:pressed {
|
|
89
|
+
background-color: #ff8a00;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
QPushButton:disabled {
|
|
93
|
+
border: 3px solid rgba(21, 101, 192, 0.50);
|
|
94
|
+
color: rgba(21, 101, 192, 0.50);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
'''
|
|
98
|
+
|
|
99
|
+
|
|
68
100
|
self.button_style_sheet_2_not_done = '''
|
|
69
101
|
QPushButton {
|
|
70
102
|
background-color: transparent;
|