celldetective 1.3.4.post1__py3-none-any.whl → 1.3.6.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/_version.py +1 -1
- celldetective/events.py +10 -5
- celldetective/filters.py +11 -0
- celldetective/gui/btrack_options.py +151 -1
- celldetective/gui/classifier_widget.py +44 -15
- celldetective/gui/configure_new_exp.py +13 -0
- celldetective/gui/control_panel.py +4 -2
- celldetective/gui/generic_signal_plot.py +2 -6
- celldetective/gui/gui_utils.py +170 -12
- celldetective/gui/measurement_options.py +85 -54
- celldetective/gui/neighborhood_options.py +1 -1
- celldetective/gui/plot_signals_ui.py +3 -4
- celldetective/gui/process_block.py +8 -6
- celldetective/gui/signal_annotator.py +10 -3
- celldetective/gui/signal_annotator2.py +146 -193
- celldetective/gui/survival_ui.py +121 -34
- celldetective/gui/tableUI.py +26 -12
- celldetective/gui/thresholds_gui.py +9 -52
- celldetective/gui/viewers.py +58 -21
- celldetective/io.py +1087 -161
- celldetective/measure.py +175 -102
- celldetective/preprocessing.py +2 -2
- celldetective/relative_measurements.py +6 -9
- celldetective/scripts/measure_cells.py +13 -3
- celldetective/scripts/segment_cells.py +0 -1
- celldetective/scripts/track_cells.py +25 -1
- celldetective/signals.py +9 -7
- celldetective/tracking.py +130 -81
- celldetective/utils.py +28 -7
- {celldetective-1.3.4.post1.dist-info → celldetective-1.3.6.post1.dist-info}/METADATA +3 -2
- {celldetective-1.3.4.post1.dist-info → celldetective-1.3.6.post1.dist-info}/RECORD +35 -35
- {celldetective-1.3.4.post1.dist-info → celldetective-1.3.6.post1.dist-info}/LICENSE +0 -0
- {celldetective-1.3.4.post1.dist-info → celldetective-1.3.6.post1.dist-info}/WHEEL +0 -0
- {celldetective-1.3.4.post1.dist-info → celldetective-1.3.6.post1.dist-info}/entry_points.txt +0 -0
- {celldetective-1.3.4.post1.dist-info → celldetective-1.3.6.post1.dist-info}/top_level.txt +0 -0
celldetective/_version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "1.3.
|
|
1
|
+
__version__ = "1.3.6.post1"
|
celldetective/events.py
CHANGED
|
@@ -143,7 +143,7 @@ def switch_to_events(classes, event_times, max_times, origin_times=None, left_ce
|
|
|
143
143
|
survival_times = [s*FrameToMin for s in survival_times]
|
|
144
144
|
return events, survival_times
|
|
145
145
|
|
|
146
|
-
def compute_survival(df, class_of_interest, t_event, t_reference=None, FrameToMin=1, cut_observation_time=None):
|
|
146
|
+
def compute_survival(df, class_of_interest, t_event, t_reference=None, FrameToMin=1, cut_observation_time=None, pairs=False):
|
|
147
147
|
|
|
148
148
|
"""
|
|
149
149
|
Computes survival analysis for a specific class of interest within a dataset, returning a fitted Kaplan-Meier
|
|
@@ -190,9 +190,14 @@ def compute_survival(df, class_of_interest, t_event, t_reference=None, FrameToMi
|
|
|
190
190
|
assert t_event in cols,"The event time cannot be found in the dataframe..."
|
|
191
191
|
left_censored = False
|
|
192
192
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
193
|
+
if not pairs:
|
|
194
|
+
groupby_cols = ['position','TRACK_ID']
|
|
195
|
+
else:
|
|
196
|
+
groupby_cols = ['position','REFERENCE_ID','NEIGHBOR_ID']
|
|
197
|
+
|
|
198
|
+
classes = df.groupby(groupby_cols)[class_of_interest].min().values
|
|
199
|
+
event_times = df.groupby(groupby_cols)[t_event].min().values
|
|
200
|
+
max_times = df.groupby(groupby_cols)['FRAME'].max().values
|
|
196
201
|
|
|
197
202
|
if t_reference=="0" or t_reference==0:
|
|
198
203
|
t_reference = None
|
|
@@ -202,7 +207,7 @@ def compute_survival(df, class_of_interest, t_event, t_reference=None, FrameToMi
|
|
|
202
207
|
if t_reference is not None:
|
|
203
208
|
left_censored = True
|
|
204
209
|
assert t_reference in cols,"The reference time cannot be found in the dataframe..."
|
|
205
|
-
first_detections = df.groupby(
|
|
210
|
+
first_detections = df.groupby(groupby_cols)[t_reference].max().values
|
|
206
211
|
|
|
207
212
|
events, survival_times = switch_to_events(classes, event_times, max_times, origin_times=first_detections, left_censored=left_censored, FrameToMin=FrameToMin, cut_observation_time=cut_observation_time)
|
|
208
213
|
ks = KaplanMeierFitter()
|
celldetective/filters.py
CHANGED
|
@@ -127,3 +127,14 @@ def tophat_filter(img, size, connectivity=4, interpolate=True, *kwargs):
|
|
|
127
127
|
structure = snd.generate_binary_structure(rank=2, connectivity=connectivity)
|
|
128
128
|
img = snd.white_tophat(img.astype(float), structure=structure, size=size, *kwargs)
|
|
129
129
|
return img
|
|
130
|
+
|
|
131
|
+
def invert_filter(img, value=65535, *kwargs):
|
|
132
|
+
|
|
133
|
+
img = img.astype(float)
|
|
134
|
+
|
|
135
|
+
image_fill = np.zeros_like(img)
|
|
136
|
+
image_fill[:,:] = value
|
|
137
|
+
|
|
138
|
+
inverted = np.subtract(image_fill, img, where=img==img)
|
|
139
|
+
return inverted
|
|
140
|
+
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
from PyQt5.QtWidgets import QMainWindow, QApplication, QMessageBox, QScrollArea, QComboBox, QFrame, QCheckBox, QFileDialog, QGridLayout, QTextEdit, QLineEdit, QVBoxLayout, QWidget, QLabel, QHBoxLayout, QPushButton
|
|
1
|
+
from PyQt5.QtWidgets import QRadioButton, QButtonGroup, QMainWindow, QApplication, QMessageBox, QScrollArea, QComboBox, QFrame, QCheckBox, QFileDialog, QGridLayout, QTextEdit, QLineEdit, QVBoxLayout, QWidget, QLabel, QHBoxLayout, QPushButton
|
|
2
2
|
from PyQt5.QtCore import Qt, QSize
|
|
3
|
+
from PyQt5.QtGui import QDoubleValidator
|
|
4
|
+
|
|
3
5
|
from celldetective.gui.gui_utils import center_window, FeatureChoice, ListWidget, QHSeperationLine, FigureCanvas, help_generic
|
|
4
6
|
from superqt import QLabeledDoubleSlider,QLabeledSlider
|
|
5
7
|
from superqt.fonticon import icon
|
|
@@ -30,6 +32,8 @@ class ConfigTracking(QMainWindow, Styles):
|
|
|
30
32
|
self.setWindowTitle("Configure tracking")
|
|
31
33
|
self.mode = self.parent_window.mode
|
|
32
34
|
self.exp_dir = self.parent_window.exp_dir
|
|
35
|
+
self.floatValidator = QDoubleValidator()
|
|
36
|
+
|
|
33
37
|
if self.mode=="targets":
|
|
34
38
|
self.config_name = os.sep.join(["configs", "btrack_config_targets.json"])
|
|
35
39
|
self.track_instructions_write_path = self.parent_window.exp_dir + os.sep.join(["configs","tracking_instructions_targets.json"])
|
|
@@ -68,9 +72,25 @@ class ConfigTracking(QMainWindow, Styles):
|
|
|
68
72
|
main_layout.setContentsMargins(30,30,30,30)
|
|
69
73
|
|
|
70
74
|
# First collapsable Frame CONFIG
|
|
75
|
+
|
|
76
|
+
self.btrack_option = QRadioButton('bTrack')
|
|
77
|
+
self.btrack_option.setChecked(True)
|
|
78
|
+
|
|
79
|
+
self.trackpy_option = QRadioButton('trackpy')
|
|
80
|
+
self.tracker_option_group = QButtonGroup()
|
|
81
|
+
self.tracker_option_group.addButton(self.btrack_option)
|
|
82
|
+
self.tracker_option_group.addButton(self.trackpy_option)
|
|
83
|
+
|
|
71
84
|
self.config_frame = QFrame()
|
|
72
85
|
self.config_frame.setFrameStyle(QFrame.StyledPanel | QFrame.Raised)
|
|
73
86
|
self.populate_config_frame()
|
|
87
|
+
|
|
88
|
+
tracker_hbox = QHBoxLayout()
|
|
89
|
+
tracker_hbox.setContentsMargins(15,15,15,15)
|
|
90
|
+
tracker_hbox.addWidget(self.btrack_option, 50, alignment=Qt.AlignCenter)
|
|
91
|
+
tracker_hbox.addWidget(self.trackpy_option, 50, alignment=Qt.AlignCenter)
|
|
92
|
+
main_layout.addLayout(tracker_hbox)
|
|
93
|
+
|
|
74
94
|
main_layout.addWidget(self.config_frame)
|
|
75
95
|
|
|
76
96
|
# Second collapsable frame FEATURES
|
|
@@ -79,6 +99,12 @@ class ConfigTracking(QMainWindow, Styles):
|
|
|
79
99
|
self.populate_features_frame()
|
|
80
100
|
main_layout.addWidget(self.features_frame)
|
|
81
101
|
|
|
102
|
+
self.config_trackpy_frame = QFrame()
|
|
103
|
+
self.config_trackpy_frame.setFrameStyle(QFrame.StyledPanel | QFrame.Raised)
|
|
104
|
+
self.populate_config_trackpy_frame()
|
|
105
|
+
main_layout.addWidget(self.config_trackpy_frame)
|
|
106
|
+
self.config_trackpy_frame.hide()
|
|
107
|
+
|
|
82
108
|
# Third collapsable frame POST-PROCESSING
|
|
83
109
|
self.post_proc_frame = QFrame()
|
|
84
110
|
self.post_proc_frame.setFrameStyle(QFrame.StyledPanel | QFrame.Raised)
|
|
@@ -102,9 +128,27 @@ class ConfigTracking(QMainWindow, Styles):
|
|
|
102
128
|
self.setCentralWidget(self.scroll_area)
|
|
103
129
|
self.show()
|
|
104
130
|
|
|
131
|
+
self.btrack_option.toggled.connect(self.show_tracking_options)
|
|
132
|
+
self.trackpy_option.toggled.connect(self.show_tracking_options)
|
|
133
|
+
|
|
105
134
|
QApplication.processEvents()
|
|
106
135
|
self.adjustScrollArea()
|
|
107
136
|
|
|
137
|
+
def show_tracking_options(self):
|
|
138
|
+
|
|
139
|
+
if self.btrack_option.isChecked():
|
|
140
|
+
self.config_frame.show()
|
|
141
|
+
self.features_frame.show()
|
|
142
|
+
self.config_trackpy_frame.hide()
|
|
143
|
+
#self.scroll_area.setMinimumHeight(min(int(930), int(0.9*self.screen_height)))
|
|
144
|
+
#self.adjustSize()
|
|
145
|
+
else:
|
|
146
|
+
self.config_frame.hide()
|
|
147
|
+
self.features_frame.hide()
|
|
148
|
+
self.config_trackpy_frame.show()
|
|
149
|
+
#self.scroll_area.setMinimumHeight(self.minimum_height)
|
|
150
|
+
#self.adjustSize()
|
|
151
|
+
|
|
108
152
|
|
|
109
153
|
def populate_post_proc_frame(self):
|
|
110
154
|
|
|
@@ -539,6 +583,29 @@ class ConfigTracking(QMainWindow, Styles):
|
|
|
539
583
|
self.collapse_config_btn.clicked.connect(self.collapse_config_advanced)
|
|
540
584
|
#self.ContentsConfig.hide()
|
|
541
585
|
|
|
586
|
+
def populate_config_trackpy_frame(self):
|
|
587
|
+
|
|
588
|
+
grid = QGridLayout(self.config_trackpy_frame)
|
|
589
|
+
panel_title = QLabel(f"CONFIGURATION")
|
|
590
|
+
panel_title.setStyleSheet("""
|
|
591
|
+
font-weight: bold;
|
|
592
|
+
padding: 0px;
|
|
593
|
+
""")
|
|
594
|
+
|
|
595
|
+
grid.addWidget(panel_title, 0, 0, 1, 4, alignment=Qt.AlignCenter)
|
|
596
|
+
|
|
597
|
+
self.collapse_config_trackpy_btn = QPushButton()
|
|
598
|
+
self.collapse_config_trackpy_btn.setIcon(icon(MDI6.chevron_down,color="black"))
|
|
599
|
+
self.collapse_config_trackpy_btn.setIconSize(QSize(20, 20))
|
|
600
|
+
self.collapse_config_trackpy_btn.setStyleSheet(self.button_select_all)
|
|
601
|
+
grid.addWidget(self.collapse_config_trackpy_btn, 0, 0, 1, 4, alignment=Qt.AlignRight)
|
|
602
|
+
self.generate_config_trackpy_panel_contents()
|
|
603
|
+
grid.addWidget(self.ContentsConfigTrackpy, 1, 0, 1, 4, alignment=Qt.AlignTop)
|
|
604
|
+
self.collapse_config_trackpy_btn.clicked.connect(lambda: self.ContentsConfigTrackpy.setHidden(not self.ContentsConfigTrackpy.isHidden()))
|
|
605
|
+
self.collapse_config_trackpy_btn.clicked.connect(self.collapse_config_trackpy_advanced)
|
|
606
|
+
#self.ContentsConfig.hide()
|
|
607
|
+
|
|
608
|
+
|
|
542
609
|
def collapse_config_advanced(self):
|
|
543
610
|
|
|
544
611
|
"""
|
|
@@ -561,6 +628,56 @@ class ConfigTracking(QMainWindow, Styles):
|
|
|
561
628
|
self.collapse_config_btn.setIconSize(QSize(20, 20))
|
|
562
629
|
self.scroll_area.setMinimumHeight(min(int(930), int(0.9*self.screen_height)))
|
|
563
630
|
|
|
631
|
+
def collapse_config_trackpy_advanced(self):
|
|
632
|
+
|
|
633
|
+
"""
|
|
634
|
+
Switch the chevron icon and adjust the size for the CONFIG frame.
|
|
635
|
+
"""
|
|
636
|
+
|
|
637
|
+
|
|
638
|
+
post_open = not self.ContentsPostProc.isHidden()
|
|
639
|
+
is_open = np.array([post_open])
|
|
640
|
+
|
|
641
|
+
if self.ContentsConfigTrackpy.isHidden():
|
|
642
|
+
self.collapse_config_trackpy_btn.setIcon(icon(MDI6.chevron_down,color="black"))
|
|
643
|
+
self.collapse_config_trackpy_btn.setIconSize(QSize(20, 20))
|
|
644
|
+
if len(is_open[is_open])==0:
|
|
645
|
+
self.scroll_area.setMinimumHeight(int(self.minimum_height))
|
|
646
|
+
self.adjustSize()
|
|
647
|
+
else:
|
|
648
|
+
self.collapse_config_trackpy_btn.setIcon(icon(MDI6.chevron_up,color="black"))
|
|
649
|
+
self.collapse_config_trackpy_btn.setIconSize(QSize(20, 20))
|
|
650
|
+
self.scroll_area.setMinimumHeight(min(int(930), int(0.9*self.screen_height)))
|
|
651
|
+
|
|
652
|
+
|
|
653
|
+
def generate_config_trackpy_panel_contents(self):
|
|
654
|
+
|
|
655
|
+
self.ContentsConfigTrackpy = QFrame()
|
|
656
|
+
layout = QVBoxLayout(self.ContentsConfigTrackpy)
|
|
657
|
+
layout.setContentsMargins(0,0,0,0)
|
|
658
|
+
|
|
659
|
+
sr_layout = QHBoxLayout()
|
|
660
|
+
self.search_range_lbl = QLabel("search range [px]: ")
|
|
661
|
+
self.search_range_le = QLineEdit('30')
|
|
662
|
+
self.search_range_le.setPlaceholderText('search distance in pixels')
|
|
663
|
+
self.search_range_le.setValidator(self.floatValidator)
|
|
664
|
+
sr_layout.addWidget(self.search_range_lbl, 30)
|
|
665
|
+
sr_layout.addWidget(self.search_range_le, 70)
|
|
666
|
+
layout.addLayout(sr_layout)
|
|
667
|
+
|
|
668
|
+
memory_layout = QHBoxLayout()
|
|
669
|
+
self.memory_lbl = QLabel("memory [# frames]: ")
|
|
670
|
+
self.memory_slider = QLabeledSlider()
|
|
671
|
+
self.memory_slider.setSingleStep(1)
|
|
672
|
+
self.memory_slider.setTickInterval(1)
|
|
673
|
+
self.memory_slider.setSingleStep(1)
|
|
674
|
+
self.memory_slider.setOrientation(1)
|
|
675
|
+
self.memory_slider.setRange(0,self.parent_window.parent_window.len_movie)
|
|
676
|
+
self.memory_slider.setValue(0)
|
|
677
|
+
memory_layout.addWidget(self.memory_lbl, 30)
|
|
678
|
+
memory_layout.addWidget(self.memory_slider, 70)
|
|
679
|
+
layout.addLayout(memory_layout)
|
|
680
|
+
|
|
564
681
|
|
|
565
682
|
def generate_config_panel_contents(self):
|
|
566
683
|
|
|
@@ -741,7 +858,23 @@ class ConfigTracking(QMainWindow, Styles):
|
|
|
741
858
|
"""
|
|
742
859
|
|
|
743
860
|
print('Writing instructions...')
|
|
861
|
+
|
|
862
|
+
if self.btrack_option.isChecked():
|
|
863
|
+
btrack_option = True
|
|
864
|
+
else:
|
|
865
|
+
btrack_option = False
|
|
866
|
+
|
|
867
|
+
# Fetch trackpky params
|
|
868
|
+
if not btrack_option:
|
|
869
|
+
search_range = int(self.search_range_le.text().replace(',','.'))
|
|
870
|
+
memory = self.memory_slider.value()
|
|
871
|
+
else:
|
|
872
|
+
search_range = None
|
|
873
|
+
memory = None
|
|
874
|
+
|
|
744
875
|
tracking_options = {'btrack_config_path': self.config_path}
|
|
876
|
+
tracking_options.update({'btrack_option': btrack_option, 'search_range': search_range, 'memory': memory})
|
|
877
|
+
|
|
745
878
|
if not self.features_ticked:
|
|
746
879
|
features = None
|
|
747
880
|
masked_channels = None
|
|
@@ -850,6 +983,23 @@ class ConfigTracking(QMainWindow, Styles):
|
|
|
850
983
|
self.ContentsFeatures.hide()
|
|
851
984
|
self.uncheck_features()
|
|
852
985
|
|
|
986
|
+
btrack_option = True
|
|
987
|
+
if 'btrack_option' in tracking_instructions:
|
|
988
|
+
btrack_option = tracking_instructions['btrack_option']
|
|
989
|
+
if btrack_option:
|
|
990
|
+
self.btrack_option.click()
|
|
991
|
+
else:
|
|
992
|
+
self.trackpy_option.click()
|
|
993
|
+
|
|
994
|
+
if 'search_range' in tracking_instructions:
|
|
995
|
+
search_range = tracking_instructions['search_range']
|
|
996
|
+
if search_range is not None:
|
|
997
|
+
self.search_range_le.setText(str(search_range).replace('.',','))
|
|
998
|
+
if 'memory' in tracking_instructions:
|
|
999
|
+
memory = tracking_instructions['memory']
|
|
1000
|
+
if memory is not None:
|
|
1001
|
+
self.memory_slider.setValue(memory)
|
|
1002
|
+
|
|
853
1003
|
# Uncheck channels that are masked
|
|
854
1004
|
mask_channels = tracking_instructions['mask_channels']
|
|
855
1005
|
if (mask_channels is not None) and len(mask_channels)>0:
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from PyQt5.QtWidgets import QWidget, QLineEdit, QMessageBox, QHBoxLayout, QVBoxLayout, QPushButton, QLabel, \
|
|
2
|
-
QCheckBox, QRadioButton, QButtonGroup
|
|
2
|
+
QCheckBox, QRadioButton, QButtonGroup, QComboBox
|
|
3
3
|
from PyQt5.QtCore import Qt, QSize
|
|
4
4
|
from superqt import QLabeledSlider,QLabeledDoubleSlider, QSearchableComboBox
|
|
5
5
|
from superqt.fonticon import icon
|
|
@@ -95,7 +95,6 @@ class ClassifierWidget(QWidget, Styles):
|
|
|
95
95
|
layout.addLayout(slider_alpha_hbox)
|
|
96
96
|
|
|
97
97
|
|
|
98
|
-
|
|
99
98
|
self.features_cb = [QSearchableComboBox() for i in range(2)]
|
|
100
99
|
self.log_btns = [QPushButton() for i in range(2)]
|
|
101
100
|
|
|
@@ -129,7 +128,6 @@ class ClassifierWidget(QWidget, Styles):
|
|
|
129
128
|
layout.addLayout(hbox_classify)
|
|
130
129
|
|
|
131
130
|
self.time_corr = QCheckBox('Time correlated')
|
|
132
|
-
self.time_corr.toggled.connect(self.activate_time_corr_options)
|
|
133
131
|
if "TRACK_ID" in self.df.columns:
|
|
134
132
|
self.time_corr.setEnabled(True)
|
|
135
133
|
else:
|
|
@@ -150,19 +148,24 @@ class ClassifierWidget(QWidget, Styles):
|
|
|
150
148
|
|
|
151
149
|
self.irreversible_event_btn = QRadioButton('irreversible event')
|
|
152
150
|
self.unique_state_btn = QRadioButton('unique state')
|
|
151
|
+
self.transient_event_btn = QRadioButton('transient event')
|
|
153
152
|
time_corr_btn_group = QButtonGroup()
|
|
154
153
|
self.unique_state_btn.click()
|
|
155
|
-
self.time_corr_options = [self.irreversible_event_btn, self.unique_state_btn]
|
|
156
|
-
|
|
157
|
-
for btn in self.time_corr_options:
|
|
158
|
-
time_corr_btn_group.addButton(btn)
|
|
159
|
-
btn.setEnabled(False)
|
|
160
154
|
|
|
161
155
|
time_corr_layout = QHBoxLayout()
|
|
162
|
-
time_corr_layout.addWidget(self.unique_state_btn,
|
|
163
|
-
time_corr_layout.addWidget(self.irreversible_event_btn,
|
|
156
|
+
time_corr_layout.addWidget(self.unique_state_btn, 33, alignment=Qt.AlignCenter)
|
|
157
|
+
time_corr_layout.addWidget(self.irreversible_event_btn, 33,alignment=Qt.AlignCenter)
|
|
158
|
+
time_corr_layout.addWidget(self.transient_event_btn, 33,alignment=Qt.AlignCenter)
|
|
164
159
|
layout.addLayout(time_corr_layout)
|
|
165
160
|
|
|
161
|
+
self.prereq_event_check = QCheckBox('prerequisite event:')
|
|
162
|
+
self.prereq_event_check.toggled.connect(self.activate_prereq_cb)
|
|
163
|
+
self.prereq_event_cb = QComboBox()
|
|
164
|
+
event_cols = ['--'] + [c.replace('t_','') for c in self.cols if c.startswith('t_')]
|
|
165
|
+
self.prereq_event_cb.addItems(event_cols)
|
|
166
|
+
self.prereq_event_check.setEnabled(False)
|
|
167
|
+
self.prereq_event_cb.setEnabled(False)
|
|
168
|
+
|
|
166
169
|
self.r2_slider = QLabeledDoubleSlider()
|
|
167
170
|
self.r2_slider.setValue(0.75)
|
|
168
171
|
self.r2_slider.setRange(0,1)
|
|
@@ -170,18 +173,34 @@ class ClassifierWidget(QWidget, Styles):
|
|
|
170
173
|
self.r2_slider.setOrientation(1)
|
|
171
174
|
self.r2_label = QLabel('R2 tolerance:')
|
|
172
175
|
self.r2_label.setToolTip('Minimum R2 between the fit sigmoid and the binary response to the filters to accept the event.')
|
|
176
|
+
|
|
173
177
|
r2_threshold_layout = QHBoxLayout()
|
|
174
|
-
r2_threshold_layout.addWidget(QLabel(''),
|
|
175
|
-
r2_threshold_layout.addWidget(self.r2_label,
|
|
176
|
-
r2_threshold_layout.addWidget(self.r2_slider,
|
|
177
|
-
|
|
178
|
+
r2_threshold_layout.addWidget(QLabel(''), 33)
|
|
179
|
+
r2_threshold_layout.addWidget(self.r2_label, 13)
|
|
180
|
+
r2_threshold_layout.addWidget(self.r2_slider, 20)
|
|
181
|
+
r2_threshold_layout.addWidget(QLabel(''), 33)
|
|
182
|
+
|
|
183
|
+
layout.addLayout(r2_threshold_layout)
|
|
178
184
|
|
|
185
|
+
self.time_corr_options = [self.irreversible_event_btn, self.unique_state_btn, self.prereq_event_check, self.prereq_event_cb, self.transient_event_btn]
|
|
186
|
+
for btn in [self.irreversible_event_btn, self.unique_state_btn, self.transient_event_btn]:
|
|
187
|
+
time_corr_btn_group.addButton(btn)
|
|
188
|
+
btn.setEnabled(False)
|
|
189
|
+
self.time_corr.toggled.connect(self.activate_time_corr_options)
|
|
190
|
+
|
|
179
191
|
self.irreversible_event_btn.clicked.connect(self.activate_r2)
|
|
180
192
|
self.unique_state_btn.clicked.connect(self.activate_r2)
|
|
193
|
+
self.transient_event_btn.clicked.connect(self.activate_r2)
|
|
181
194
|
|
|
182
195
|
for wg in [self.r2_slider, self.r2_label]:
|
|
183
196
|
wg.setEnabled(False)
|
|
184
197
|
|
|
198
|
+
prereq_layout = QHBoxLayout()
|
|
199
|
+
prereq_layout.setContentsMargins(30,0,0,0)
|
|
200
|
+
prereq_layout.addWidget(self.prereq_event_check, 20)
|
|
201
|
+
prereq_layout.addWidget(self.prereq_event_cb, 80)
|
|
202
|
+
layout.addLayout(prereq_layout)
|
|
203
|
+
|
|
185
204
|
layout.addWidget(QLabel())
|
|
186
205
|
|
|
187
206
|
self.submit_btn = QPushButton('apply')
|
|
@@ -193,6 +212,12 @@ class ClassifierWidget(QWidget, Styles):
|
|
|
193
212
|
self.frame_slider.valueChanged.connect(self.set_frame)
|
|
194
213
|
self.alpha_slider.valueChanged.connect(self.set_transparency)
|
|
195
214
|
|
|
215
|
+
def activate_prereq_cb(self):
|
|
216
|
+
if self.prereq_event_check.isChecked():
|
|
217
|
+
self.prereq_event_cb.setEnabled(True)
|
|
218
|
+
else:
|
|
219
|
+
self.prereq_event_cb.setEnabled(False)
|
|
220
|
+
|
|
196
221
|
def activate_submit_btn(self):
|
|
197
222
|
|
|
198
223
|
if self.property_query_le.text()=='':
|
|
@@ -416,7 +441,11 @@ class ClassifierWidget(QWidget, Styles):
|
|
|
416
441
|
self.df = self.df.drop(list(set(name_map.values()) & set(self.df.columns)), axis=1).rename(columns=name_map)
|
|
417
442
|
self.df.reset_index(inplace=True, drop=True)
|
|
418
443
|
|
|
419
|
-
|
|
444
|
+
pre_event = None
|
|
445
|
+
if self.prereq_event_check.isChecked() and "t_"+self.prereq_event_cb.currentText() in self.cols:
|
|
446
|
+
pre_event = self.prereq_event_cb.currentText()
|
|
447
|
+
|
|
448
|
+
self.df = interpret_track_classification(self.df, self.class_name_user, irreversible_event=self.irreversible_event_btn.isChecked(), unique_state=self.unique_state_btn.isChecked(), transient_event=self.transient_event_btn.isChecked(),r2_threshold=self.r2_slider.value(), pre_event=pre_event)
|
|
420
449
|
|
|
421
450
|
else:
|
|
422
451
|
self.group_name_user = 'group_' + self.name_le.text()
|
|
@@ -453,6 +453,9 @@ class ConfigNewExperiment(QMainWindow, Styles):
|
|
|
453
453
|
config.set('Labels', 'concentrations', self.concentrations)
|
|
454
454
|
config.set('Labels', 'pharmaceutical_agents', self.pharmaceutical_agents)
|
|
455
455
|
|
|
456
|
+
config.add_section('Metadata')
|
|
457
|
+
config.set('Metadata', 'concentration_units', self.concentration_units)
|
|
458
|
+
|
|
456
459
|
# save to a file
|
|
457
460
|
with open('config.ini', 'w') as configfile:
|
|
458
461
|
config.write(configfile)
|
|
@@ -480,6 +483,8 @@ class SetupConditionLabels(QWidget, Styles):
|
|
|
480
483
|
self.antibodies_cbs = [QLineEdit() for i in range(self.n_wells)]
|
|
481
484
|
self.concentrations_cbs = [QLineEdit() for i in range(self.n_wells)]
|
|
482
485
|
self.pharmaceutical_agents_cbs = [QLineEdit() for i in range(self.n_wells)]
|
|
486
|
+
self.concentration_units_le = QLineEdit('pM')
|
|
487
|
+
self.concentration_units_le.setPlaceholderText('concentration units')
|
|
483
488
|
|
|
484
489
|
for i in range(self.n_wells):
|
|
485
490
|
hbox = QHBoxLayout()
|
|
@@ -504,6 +509,12 @@ class SetupConditionLabels(QWidget, Styles):
|
|
|
504
509
|
|
|
505
510
|
self.layout.addLayout(hbox)
|
|
506
511
|
|
|
512
|
+
concentration_units_layout = QHBoxLayout()
|
|
513
|
+
concentration_units_layout.addWidget(QLabel('concentration\nunits: '),5,alignment=Qt.AlignLeft)
|
|
514
|
+
concentration_units_layout.addWidget(self.concentration_units_le,10)
|
|
515
|
+
concentration_units_layout.addWidget(QLabel(''), 85)
|
|
516
|
+
self.layout.addLayout(concentration_units_layout)
|
|
517
|
+
|
|
507
518
|
btn_hbox = QHBoxLayout()
|
|
508
519
|
btn_hbox.setContentsMargins(0,20,0,0)
|
|
509
520
|
self.skip_btn = QPushButton('Skip')
|
|
@@ -556,6 +567,8 @@ class SetupConditionLabels(QWidget, Styles):
|
|
|
556
567
|
pharamaceutical_text = [c.text() for c in self.pharmaceutical_agents_cbs]
|
|
557
568
|
self.parent_window.pharmaceutical_agents = ','.join(pharamaceutical_text)
|
|
558
569
|
|
|
570
|
+
self.parent_window.concentration_units = self.concentration_units_le.text()
|
|
571
|
+
|
|
559
572
|
|
|
560
573
|
|
|
561
574
|
|
|
@@ -93,6 +93,9 @@ class ControlPanel(QMainWindow, Styles):
|
|
|
93
93
|
self.screen_width = desktop.screenGeometry().width()
|
|
94
94
|
self.scroll.setMinimumWidth(440)
|
|
95
95
|
|
|
96
|
+
self.well_list.setCurrentIndex(0)
|
|
97
|
+
#self.position_list.setCurrentIndex(0)
|
|
98
|
+
|
|
96
99
|
def init_wells_and_positions(self):
|
|
97
100
|
|
|
98
101
|
"""
|
|
@@ -151,10 +154,8 @@ class ControlPanel(QMainWindow, Styles):
|
|
|
151
154
|
#self.locate_selected_position()
|
|
152
155
|
|
|
153
156
|
self.well_list.activated.connect(self.display_positions)
|
|
154
|
-
self.well_list.setCurrentIndex(0)
|
|
155
157
|
|
|
156
158
|
self.position_list.activated.connect(self.update_position_options)
|
|
157
|
-
self.position_list.setCurrentIndex(0)
|
|
158
159
|
|
|
159
160
|
self.view_stack_btn = QPushButton()
|
|
160
161
|
self.view_stack_btn.setStyleSheet(self.button_select_all)
|
|
@@ -337,6 +338,7 @@ class ControlPanel(QMainWindow, Styles):
|
|
|
337
338
|
self.antibodies = get_experiment_antibodies(self.exp_dir)
|
|
338
339
|
self.pharmaceutical_agents = get_experiment_pharmaceutical_agents(self.exp_dir)
|
|
339
340
|
|
|
341
|
+
self.metadata = ConfigSectionMap(self.exp_config,"Metadata")
|
|
340
342
|
print('Experiment configuration successfully read...')
|
|
341
343
|
|
|
342
344
|
def closeEvent(self, event):
|
|
@@ -62,6 +62,7 @@ class GenericSignalPlotWidget(QWidget, Styles):
|
|
|
62
62
|
self.setLayout(self.layout)
|
|
63
63
|
self.setAttribute(Qt.WA_DeleteOnClose)
|
|
64
64
|
|
|
65
|
+
|
|
65
66
|
def populate_widget(self):
|
|
66
67
|
|
|
67
68
|
self.plot_options = [QRadioButton() for i in range(3)]
|
|
@@ -221,18 +222,13 @@ class GenericSignalPlotWidget(QWidget, Styles):
|
|
|
221
222
|
self.alpha_slider = QLabeledDoubleSlider()
|
|
222
223
|
alpha_hbox = QuickSliderLayout(label='single-cell\nsignal alpha: ',
|
|
223
224
|
slider=self.alpha_slider,
|
|
224
|
-
slider_initial_value=
|
|
225
|
+
slider_initial_value=self.alpha_setting,
|
|
225
226
|
slider_range=(0,1),
|
|
226
227
|
decimal_option=True,
|
|
227
228
|
precision=1.0E-05,
|
|
228
229
|
)
|
|
229
230
|
self.alpha_slider.valueChanged.connect(self.submit_alpha)
|
|
230
231
|
self.cell_lines_alpha_wdg.setLayout(alpha_hbox)
|
|
231
|
-
|
|
232
|
-
# self.submit_alpha_btn = QPushButton('submit')
|
|
233
|
-
# self.submit_alpha_btn.setStyleSheet(self.button_style_sheet_2)
|
|
234
|
-
# self.submit_alpha_btn.clicked.connect(self.submit_alpha)
|
|
235
|
-
# alpha_hbox.addWidget(self.submit_alpha_btn, 10)
|
|
236
232
|
self.layout.addWidget(self.cell_lines_alpha_wdg)
|
|
237
233
|
|
|
238
234
|
self.select_option = [QRadioButton() for i in range(2)]
|