celldetective 1.2.1__tar.gz → 1.2.2.post1__tar.gz
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-1.2.1 → celldetective-1.2.2.post1}/PKG-INFO +19 -12
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/README.md +12 -6
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/__main__.py +12 -5
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/events.py +28 -2
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/gui/about.py +0 -1
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/gui/analyze_block.py +3 -18
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/gui/btrack_options.py +126 -21
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/gui/classifier_widget.py +67 -111
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/gui/configure_new_exp.py +37 -4
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/gui/control_panel.py +14 -30
- celldetective-1.2.2.post1/celldetective/gui/generic_signal_plot.py +793 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/gui/gui_utils.py +401 -226
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/gui/json_readers.py +0 -2
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/gui/layouts.py +269 -25
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/gui/measurement_options.py +14 -23
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/gui/neighborhood_options.py +3 -15
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/gui/plot_measurements.py +10 -23
- celldetective-1.2.2.post1/celldetective/gui/plot_signals_ui.py +437 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/gui/process_block.py +320 -186
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/gui/retrain_segmentation_model_options.py +30 -47
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/gui/retrain_signal_model_options.py +5 -14
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/gui/seg_model_loader.py +129 -113
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/gui/signal_annotator.py +89 -99
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/gui/signal_annotator2.py +5 -9
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/gui/styles.py +32 -0
- celldetective-1.2.2.post1/celldetective/gui/survival_ui.py +277 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/gui/tableUI.py +0 -1
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/gui/thresholds_gui.py +38 -11
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/gui/viewers.py +6 -7
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/io.py +60 -82
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/measure.py +374 -15
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/neighborhood.py +1 -7
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/preprocessing.py +2 -4
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/relative_measurements.py +0 -3
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/scripts/analyze_signals.py +0 -1
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/scripts/measure_cells.py +1 -3
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/scripts/measure_relative.py +1 -2
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/scripts/segment_cells.py +16 -12
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/scripts/segment_cells_thresholds.py +17 -10
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/scripts/track_cells.py +18 -18
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/scripts/train_segmentation_model.py +1 -2
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/scripts/train_signal_model.py +0 -3
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/segmentation.py +1 -1
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/signals.py +17 -8
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/tracking.py +2 -1
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/utils.py +42 -2
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective.egg-info/PKG-INFO +19 -12
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective.egg-info/SOURCES.txt +1 -6
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective.egg-info/requires.txt +6 -5
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/setup.py +1 -1
- celldetective-1.2.1/celldetective/gui/plot_signals_ui.py +0 -1071
- celldetective-1.2.1/celldetective/gui/survival_ui.py +0 -940
- celldetective-1.2.1/celldetective/models/segmentation_effectors/primNK_cfse/config_input.json +0 -29
- celldetective-1.2.1/celldetective/models/segmentation_effectors/primNK_cfse/cp-cfse-transfer +0 -0
- celldetective-1.2.1/celldetective/models/segmentation_effectors/primNK_cfse/training_instructions.json +0 -37
- celldetective-1.2.1/celldetective/models/segmentation_effectors/ricm-bimodal/config_input.json +0 -130
- celldetective-1.2.1/celldetective/models/segmentation_effectors/ricm-bimodal/ricm-bimodal +0 -0
- celldetective-1.2.1/celldetective/models/segmentation_effectors/ricm-bimodal/training_instructions.json +0 -37
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/LICENSE +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/__init__.py +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/datasets/segmentation_annotations/blank +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/datasets/signal_annotations/blank +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/extra_properties.py +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/filters.py +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/gui/__init__.py +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/gui/signal_annotator_options.py +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/icons/logo-large.png +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/icons/logo.png +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/icons/signals_icon.png +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/icons/splash-test.png +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/icons/splash.png +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/icons/splash0.png +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/icons/survival2.png +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/icons/vignette_signals2.png +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/icons/vignette_signals2.svg +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/links/zenodo.json +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/models/pair_signal_detection/blank +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/models/segmentation_effectors/blank +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/models/segmentation_generic/blank +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/models/segmentation_targets/blank +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/models/signal_detection/blank +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/models/tracking_configs/mcf7.json +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/models/tracking_configs/ricm.json +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective/models/tracking_configs/ricm2.json +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective.egg-info/dependency_links.txt +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective.egg-info/entry_points.txt +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective.egg-info/not-zip-safe +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/celldetective.egg-info/top_level.txt +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/setup.cfg +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/tests/__init__.py +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/tests/test_events.py +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/tests/test_filters.py +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/tests/test_io.py +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/tests/test_measure.py +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/tests/test_neighborhood.py +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/tests/test_preprocessing.py +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/tests/test_segmentation.py +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/tests/test_signals.py +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/tests/test_tracking.py +0 -0
- {celldetective-1.2.1 → celldetective-1.2.2.post1}/tests/test_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: celldetective
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.2.post1
|
|
4
4
|
Summary: description
|
|
5
5
|
Home-page: http://github.com/remyeltorro/celldetective
|
|
6
6
|
Author: Rémy Torro
|
|
@@ -12,14 +12,14 @@ Requires-Dist: wheel
|
|
|
12
12
|
Requires-Dist: nbsphinx
|
|
13
13
|
Requires-Dist: nbsphinx_link
|
|
14
14
|
Requires-Dist: sphinx_rtd_theme
|
|
15
|
-
Requires-Dist: sphinx
|
|
16
|
-
Requires-Dist: jinja2
|
|
15
|
+
Requires-Dist: sphinx
|
|
16
|
+
Requires-Dist: jinja2
|
|
17
17
|
Requires-Dist: ipykernel
|
|
18
18
|
Requires-Dist: stardist
|
|
19
19
|
Requires-Dist: cellpose<3
|
|
20
20
|
Requires-Dist: scikit-learn
|
|
21
21
|
Requires-Dist: btrack
|
|
22
|
-
Requires-Dist: tensorflow
|
|
22
|
+
Requires-Dist: tensorflow~=2.15.0
|
|
23
23
|
Requires-Dist: napari
|
|
24
24
|
Requires-Dist: tqdm
|
|
25
25
|
Requires-Dist: mahotas
|
|
@@ -32,10 +32,11 @@ Requires-Dist: seaborn
|
|
|
32
32
|
Requires-Dist: opencv-python-headless==4.7.0.72
|
|
33
33
|
Requires-Dist: liblapack
|
|
34
34
|
Requires-Dist: gputools
|
|
35
|
-
Requires-Dist: lmfit
|
|
36
|
-
Requires-Dist: superqt[cmap]
|
|
35
|
+
Requires-Dist: lmfit
|
|
36
|
+
Requires-Dist: superqt[cmap]
|
|
37
37
|
Requires-Dist: setuptools
|
|
38
38
|
Requires-Dist: matplotlib_scalebar
|
|
39
|
+
Requires-Dist: numpy==1.26.4
|
|
39
40
|
|
|
40
41
|
# Celldetective
|
|
41
42
|
|
|
@@ -166,23 +167,25 @@ steps.
|
|
|
166
167
|
|
|
167
168
|
To use the software, you must install python, *e.g.* through
|
|
168
169
|
[Anaconda](https://www.anaconda.com/download). We developed and tested
|
|
169
|
-
the software in Python 3.9.
|
|
170
|
+
the software in Python 3.9 and more recently 3.11.
|
|
170
171
|
|
|
171
172
|
# Installation
|
|
172
173
|
|
|
173
174
|
## Stable release
|
|
174
175
|
|
|
175
|
-
Celldetective
|
|
176
|
+
Celldetective requires a version of Python between 3.9 and 3.11 (included). If your Python version is older or more recent, consider using `conda` to create an environment as described below.
|
|
177
|
+
|
|
178
|
+
With the proper Python version, Celldetective can be directly installed with `pip`:
|
|
176
179
|
|
|
177
180
|
``` bash
|
|
178
181
|
pip install celldetective
|
|
179
182
|
```
|
|
180
183
|
|
|
181
|
-
We recommend that you create an environment to use Celldetective, *e.g.*
|
|
184
|
+
We recommend that you create an environment to use Celldetective, to protect your package versions and fix the Python version *e.g.*
|
|
182
185
|
with `conda`:
|
|
183
186
|
|
|
184
187
|
``` bash
|
|
185
|
-
conda create -n celldetective python=3.
|
|
188
|
+
conda create -n celldetective python=3.11 pyqt
|
|
186
189
|
conda activate celldetective
|
|
187
190
|
pip install celldetective
|
|
188
191
|
```
|
|
@@ -208,6 +211,10 @@ will be immediately available in the python environment:
|
|
|
208
211
|
git clone git://github.com/remyeltorro/celldetective.git
|
|
209
212
|
cd celldetective
|
|
210
213
|
|
|
214
|
+
# optional: create an environment
|
|
215
|
+
conda create -n celldetective python=3.11 pyqt
|
|
216
|
+
conda activate celldetective
|
|
217
|
+
|
|
211
218
|
# install the celldetective package in editable/development mode
|
|
212
219
|
pip install -r requirements.txt
|
|
213
220
|
pip install -e .
|
|
@@ -230,10 +237,10 @@ with package requirements for other projects. Run the following lines to
|
|
|
230
237
|
create an environment named \"celldetective\":
|
|
231
238
|
|
|
232
239
|
``` bash
|
|
233
|
-
conda create -n celldetective python=3.
|
|
240
|
+
conda create -n celldetective python=3.11 pyqt
|
|
234
241
|
conda activate celldetective
|
|
235
242
|
pip install -r requirements.txt
|
|
236
|
-
pip install .
|
|
243
|
+
pip install -e .
|
|
237
244
|
```
|
|
238
245
|
|
|
239
246
|
The installation of the dependencies will take a few minutes (up to half
|
|
@@ -127,23 +127,25 @@ steps.
|
|
|
127
127
|
|
|
128
128
|
To use the software, you must install python, *e.g.* through
|
|
129
129
|
[Anaconda](https://www.anaconda.com/download). We developed and tested
|
|
130
|
-
the software in Python 3.9.
|
|
130
|
+
the software in Python 3.9 and more recently 3.11.
|
|
131
131
|
|
|
132
132
|
# Installation
|
|
133
133
|
|
|
134
134
|
## Stable release
|
|
135
135
|
|
|
136
|
-
Celldetective
|
|
136
|
+
Celldetective requires a version of Python between 3.9 and 3.11 (included). If your Python version is older or more recent, consider using `conda` to create an environment as described below.
|
|
137
|
+
|
|
138
|
+
With the proper Python version, Celldetective can be directly installed with `pip`:
|
|
137
139
|
|
|
138
140
|
``` bash
|
|
139
141
|
pip install celldetective
|
|
140
142
|
```
|
|
141
143
|
|
|
142
|
-
We recommend that you create an environment to use Celldetective, *e.g.*
|
|
144
|
+
We recommend that you create an environment to use Celldetective, to protect your package versions and fix the Python version *e.g.*
|
|
143
145
|
with `conda`:
|
|
144
146
|
|
|
145
147
|
``` bash
|
|
146
|
-
conda create -n celldetective python=3.
|
|
148
|
+
conda create -n celldetective python=3.11 pyqt
|
|
147
149
|
conda activate celldetective
|
|
148
150
|
pip install celldetective
|
|
149
151
|
```
|
|
@@ -169,6 +171,10 @@ will be immediately available in the python environment:
|
|
|
169
171
|
git clone git://github.com/remyeltorro/celldetective.git
|
|
170
172
|
cd celldetective
|
|
171
173
|
|
|
174
|
+
# optional: create an environment
|
|
175
|
+
conda create -n celldetective python=3.11 pyqt
|
|
176
|
+
conda activate celldetective
|
|
177
|
+
|
|
172
178
|
# install the celldetective package in editable/development mode
|
|
173
179
|
pip install -r requirements.txt
|
|
174
180
|
pip install -e .
|
|
@@ -191,10 +197,10 @@ with package requirements for other projects. Run the following lines to
|
|
|
191
197
|
create an environment named \"celldetective\":
|
|
192
198
|
|
|
193
199
|
``` bash
|
|
194
|
-
conda create -n celldetective python=3.
|
|
200
|
+
conda create -n celldetective python=3.11 pyqt
|
|
195
201
|
conda activate celldetective
|
|
196
202
|
pip install -r requirements.txt
|
|
197
|
-
pip install .
|
|
203
|
+
pip install -e .
|
|
198
204
|
```
|
|
199
205
|
|
|
200
206
|
The installation of the dependencies will take a few minutes (up to half
|
|
@@ -27,10 +27,10 @@ class AppInitWindow(QMainWindow):
|
|
|
27
27
|
|
|
28
28
|
try:
|
|
29
29
|
subprocess.check_output('nvidia-smi')
|
|
30
|
-
print('
|
|
30
|
+
print('NVIDIA GPU detected (activate or disable in Memory & Threads)...')
|
|
31
31
|
self.use_gpu = True
|
|
32
32
|
except Exception: # this command not being found can raise quite a few different errors depending on the configuration
|
|
33
|
-
print('No
|
|
33
|
+
print('No NVIDIA GPU detected...')
|
|
34
34
|
self.use_gpu = False
|
|
35
35
|
|
|
36
36
|
self.soft_path = get_software_location()
|
|
@@ -170,13 +170,16 @@ class AppInitWindow(QMainWindow):
|
|
|
170
170
|
|
|
171
171
|
self.recentFileActs = []
|
|
172
172
|
self.threads_config_path = os.sep.join([self.soft_path,'celldetective','threads.json'])
|
|
173
|
+
print('Reading previous Memory & Threads settings...')
|
|
173
174
|
if os.path.exists(self.threads_config_path):
|
|
174
175
|
with open(self.threads_config_path, 'r') as f:
|
|
175
176
|
self.threads_config = json.load(f)
|
|
176
177
|
if 'use_gpu' in self.threads_config:
|
|
177
178
|
self.use_gpu = bool(self.threads_config['use_gpu'])
|
|
179
|
+
print(f'Use GPU: {self.use_gpu}...')
|
|
178
180
|
if 'n_threads' in self.threads_config:
|
|
179
181
|
self.n_threads = int(self.threads_config['n_threads'])
|
|
182
|
+
print(f'Number of threads: {self.n_threads}...')
|
|
180
183
|
|
|
181
184
|
|
|
182
185
|
def reload_previous_experiments(self):
|
|
@@ -250,9 +253,9 @@ class AppInitWindow(QMainWindow):
|
|
|
250
253
|
self.open_directory()
|
|
251
254
|
|
|
252
255
|
def load_recent_exp(self, path):
|
|
253
|
-
|
|
254
|
-
print('you selected path ', path)
|
|
256
|
+
|
|
255
257
|
self.experiment_path_selection.setText(path)
|
|
258
|
+
print(f'Attempt to load experiment folder: {path}...')
|
|
256
259
|
self.open_directory()
|
|
257
260
|
|
|
258
261
|
def open_about_window(self):
|
|
@@ -351,7 +354,7 @@ class AppInitWindow(QMainWindow):
|
|
|
351
354
|
print(f"Found {self.number_of_wells} wells...")
|
|
352
355
|
number_pos = []
|
|
353
356
|
for w in wells:
|
|
354
|
-
position_folders = glob(os.sep.join([w,f"{w.split(os.sep)[-
|
|
357
|
+
position_folders = glob(os.sep.join([w,f"{w.split(os.sep)[-1][1]}*", os.sep]))
|
|
355
358
|
number_pos.append(len(position_folders))
|
|
356
359
|
print(f"Number of positions per well: {number_pos}")
|
|
357
360
|
|
|
@@ -393,6 +396,7 @@ if __name__ == "__main__":
|
|
|
393
396
|
# myappid = 'mycompany.myproduct.subproduct.version' # arbitrary string
|
|
394
397
|
# ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid)
|
|
395
398
|
splash=True
|
|
399
|
+
print('Loading the libraries...')
|
|
396
400
|
|
|
397
401
|
App = QApplication(sys.argv)
|
|
398
402
|
#App.setWindowIcon(QIcon(os.sep.join([get_software_location(),'celldetective','icons','mexican-hat.png'])))
|
|
@@ -425,7 +429,10 @@ if __name__ == "__main__":
|
|
|
425
429
|
import psutil
|
|
426
430
|
import subprocess
|
|
427
431
|
import json
|
|
432
|
+
# import matplotlib
|
|
433
|
+
# matplotlib.rcParams.update({'font.size': 8})
|
|
428
434
|
|
|
435
|
+
print('Libraries successfully loaded...')
|
|
429
436
|
|
|
430
437
|
window = AppInitWindow(App)
|
|
431
438
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import numpy as np
|
|
2
|
-
|
|
2
|
+
from lifelines import KaplanMeierFitter
|
|
3
3
|
|
|
4
4
|
def switch_to_events(classes, event_times, max_times, origin_times=None, left_censored=True, FrameToMin=None):
|
|
5
5
|
|
|
@@ -104,4 +104,30 @@ def switch_to_events(classes, event_times, max_times, origin_times=None, left_ce
|
|
|
104
104
|
if FrameToMin is not None:
|
|
105
105
|
#print('convert to minutes!', FrameToMin)
|
|
106
106
|
survival_times = [s*FrameToMin for s in survival_times]
|
|
107
|
-
return events, survival_times
|
|
107
|
+
return events, survival_times
|
|
108
|
+
|
|
109
|
+
def compute_survival(df, class_of_interest, t_event, t_reference=None, FrameToMin=1):
|
|
110
|
+
|
|
111
|
+
cols = list(df.columns)
|
|
112
|
+
assert class_of_interest in cols,"The requested class cannot be found in the dataframe..."
|
|
113
|
+
assert t_event in cols,"The event time cannot be found in the dataframe..."
|
|
114
|
+
left_censored = False
|
|
115
|
+
|
|
116
|
+
classes = df.groupby(['position','TRACK_ID'])[class_of_interest].min().values
|
|
117
|
+
event_times = df.groupby(['position','TRACK_ID'])[t_event].min().values
|
|
118
|
+
max_times = df.groupby(['position','TRACK_ID'])['FRAME'].max().values
|
|
119
|
+
|
|
120
|
+
if t_reference is not None:
|
|
121
|
+
left_censored = True
|
|
122
|
+
assert t_reference in cols,"The reference time cannot be found in the dataframe..."
|
|
123
|
+
first_detections = df.groupby(['position','TRACK_ID'])[t_reference].max().values
|
|
124
|
+
|
|
125
|
+
events, survival_times = switch_to_events(classes, event_times, max_times, origin_times=first_detections, left_censored=left_censored, FrameToMin=FrameToMin)
|
|
126
|
+
ks = KaplanMeierFitter()
|
|
127
|
+
if len(events)>0:
|
|
128
|
+
ks.fit(survival_times, event_observed=events)
|
|
129
|
+
else:
|
|
130
|
+
ks = None
|
|
131
|
+
|
|
132
|
+
return ks
|
|
133
|
+
|
|
@@ -1,25 +1,10 @@
|
|
|
1
|
-
from PyQt5.QtWidgets import QFrame,
|
|
2
|
-
|
|
1
|
+
from PyQt5.QtWidgets import QFrame, QLabel, QPushButton, QVBoxLayout, \
|
|
2
|
+
QSpacerItem, QSizePolicy
|
|
3
3
|
from PyQt5.QtCore import Qt, QSize
|
|
4
4
|
from PyQt5.QtGui import QIcon
|
|
5
|
-
|
|
6
|
-
from superqt.fonticon import icon
|
|
7
|
-
from fonticon_mdi6 import MDI6
|
|
8
|
-
import gc
|
|
9
|
-
|
|
10
5
|
from celldetective.gui.plot_measurements import ConfigMeasurementsPlot
|
|
11
|
-
from celldetective.io import get_segmentation_models_list, control_segmentation_napari, get_signal_models_list, control_tracking_btrack
|
|
12
6
|
from celldetective.gui import ConfigSurvival, ConfigSignalPlot
|
|
13
|
-
from celldetective.gui.gui_utils import QHSeperationLine
|
|
14
|
-
from celldetective.segmentation import segment_at_position, segment_from_threshold_at_position
|
|
15
|
-
from celldetective.tracking import track_at_position
|
|
16
|
-
from celldetective.measure import measure_at_position
|
|
17
|
-
from celldetective.signals import analyze_signals_at_position
|
|
18
|
-
import numpy as np
|
|
19
|
-
from glob import glob
|
|
20
|
-
from natsort import natsorted
|
|
21
7
|
import os
|
|
22
|
-
import pandas as pd
|
|
23
8
|
from celldetective.gui import Styles
|
|
24
9
|
|
|
25
10
|
class AnalysisPanel(QFrame, Styles):
|
|
@@ -94,7 +79,7 @@ class AnalysisPanel(QFrame, Styles):
|
|
|
94
79
|
self.configSurvival.show()
|
|
95
80
|
|
|
96
81
|
def configure_plot_signals(self):
|
|
97
|
-
print('
|
|
82
|
+
print('Configure a signal collapse representation...')
|
|
98
83
|
self.ConfigSignalPlot = ConfigSignalPlot(self)
|
|
99
84
|
self.ConfigSignalPlot.show()
|
|
100
85
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from PyQt5.QtWidgets import 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 celldetective.gui.gui_utils import center_window, FeatureChoice, ListWidget, QHSeperationLine, FigureCanvas
|
|
4
|
-
from superqt import
|
|
3
|
+
from celldetective.gui.gui_utils import center_window, FeatureChoice, ListWidget, QHSeperationLine, FigureCanvas, help_generic
|
|
4
|
+
from superqt import QLabeledDoubleSlider,QLabeledSlider
|
|
5
5
|
from superqt.fonticon import icon
|
|
6
6
|
from fonticon_mdi6 import MDI6
|
|
7
7
|
from celldetective.utils import extract_experiment_channels, get_software_location
|
|
@@ -47,8 +47,9 @@ class ConfigTracking(QMainWindow, Styles):
|
|
|
47
47
|
|
|
48
48
|
center_window(self)
|
|
49
49
|
self.setMinimumWidth(540)
|
|
50
|
-
self.
|
|
51
|
-
self.
|
|
50
|
+
self.minimum_height = 300
|
|
51
|
+
# self.setMinimumHeight(int(0.3*self.screen_height))
|
|
52
|
+
# self.setMaximumHeight(int(0.8*self.screen_height))
|
|
52
53
|
self.populate_widget()
|
|
53
54
|
self.load_previous_tracking_instructions()
|
|
54
55
|
|
|
@@ -116,7 +117,6 @@ class ConfigTracking(QMainWindow, Styles):
|
|
|
116
117
|
self.select_post_proc_btn = QPushButton()
|
|
117
118
|
self.select_post_proc_btn.clicked.connect(self.activate_post_proc_options)
|
|
118
119
|
self.select_post_proc_btn.setStyleSheet(self.button_select_all)
|
|
119
|
-
grid.addWidget(self.select_post_proc_btn, 0,0,1,4,alignment=Qt.AlignLeft)
|
|
120
120
|
|
|
121
121
|
self.post_proc_lbl = QLabel("POST-PROCESSING")
|
|
122
122
|
self.post_proc_lbl.setStyleSheet("""
|
|
@@ -125,19 +125,100 @@ class ConfigTracking(QMainWindow, Styles):
|
|
|
125
125
|
""")
|
|
126
126
|
grid.addWidget(self.post_proc_lbl, 0, 0, 1, 4, alignment=Qt.AlignCenter)
|
|
127
127
|
|
|
128
|
+
title_hbox = QHBoxLayout()
|
|
129
|
+
|
|
128
130
|
self.collapse_post_proc_btn = QPushButton()
|
|
129
131
|
self.collapse_post_proc_btn.setIcon(icon(MDI6.chevron_down,color="black"))
|
|
130
132
|
self.collapse_post_proc_btn.setIconSize(QSize(20, 20))
|
|
131
133
|
self.collapse_post_proc_btn.setStyleSheet(self.button_select_all)
|
|
132
|
-
grid.addWidget(self.collapse_post_proc_btn, 0, 0, 1, 4, alignment=Qt.AlignRight)
|
|
134
|
+
#grid.addWidget(self.collapse_post_proc_btn, 0, 0, 1, 4, alignment=Qt.AlignRight)
|
|
135
|
+
|
|
136
|
+
self.help_post_btn = QPushButton()
|
|
137
|
+
self.help_post_btn.setIcon(icon(MDI6.help_circle,color=self.help_color))
|
|
138
|
+
self.help_post_btn.setIconSize(QSize(20, 20))
|
|
139
|
+
self.help_post_btn.clicked.connect(self.help_post)
|
|
140
|
+
self.help_post_btn.setStyleSheet(self.button_select_all)
|
|
141
|
+
self.help_post_btn.setToolTip("Help.")
|
|
142
|
+
|
|
143
|
+
title_hbox.addWidget(self.select_post_proc_btn, 5)
|
|
144
|
+
title_hbox.addWidget(QLabel(), 85, alignment=Qt.AlignCenter)
|
|
145
|
+
title_hbox.addWidget(self.help_post_btn, 5)
|
|
146
|
+
title_hbox.addWidget(self.collapse_post_proc_btn, 5)
|
|
147
|
+
grid.addLayout(title_hbox, 0,0,1,4)
|
|
133
148
|
|
|
134
149
|
self.generate_post_proc_panel_contents()
|
|
135
150
|
grid.addWidget(self.ContentsPostProc, 1, 0, 1, 4, alignment=Qt.AlignTop)
|
|
136
151
|
self.collapse_post_proc_btn.clicked.connect(lambda: self.ContentsPostProc.setHidden(not self.ContentsPostProc.isHidden()))
|
|
137
|
-
|
|
152
|
+
self.collapse_post_proc_btn.clicked.connect(self.collapse_post_advanced)
|
|
138
153
|
self.ContentsPostProc.hide()
|
|
139
154
|
self.uncheck_post_proc()
|
|
140
155
|
|
|
156
|
+
def collapse_post_advanced(self):
|
|
157
|
+
|
|
158
|
+
features_open = not self.ContentsFeatures.isHidden()
|
|
159
|
+
config_open = not self.ContentsConfig.isHidden()
|
|
160
|
+
post_open = not self.ContentsPostProc.isHidden()
|
|
161
|
+
is_open = np.array([features_open, config_open, post_open])
|
|
162
|
+
|
|
163
|
+
if self.ContentsPostProc.isHidden():
|
|
164
|
+
self.collapse_post_proc_btn.setIcon(icon(MDI6.chevron_down,color="black"))
|
|
165
|
+
self.collapse_post_proc_btn.setIconSize(QSize(20, 20))
|
|
166
|
+
if len(is_open[is_open])==0:
|
|
167
|
+
self.scroll_area.setMinimumHeight(int(self.minimum_height))
|
|
168
|
+
self.adjustSize()
|
|
169
|
+
else:
|
|
170
|
+
self.collapse_post_proc_btn.setIcon(icon(MDI6.chevron_up,color="black"))
|
|
171
|
+
self.collapse_post_proc_btn.setIconSize(QSize(20, 20))
|
|
172
|
+
self.scroll_area.setMinimumHeight(min(int(930), int(0.9*self.screen_height)))
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def help_post(self):
|
|
176
|
+
|
|
177
|
+
"""
|
|
178
|
+
Helper for track post-processing strategy.
|
|
179
|
+
"""
|
|
180
|
+
|
|
181
|
+
dict_path = os.sep.join([get_software_location(),'celldetective','gui','help','track-postprocessing.json'])
|
|
182
|
+
|
|
183
|
+
with open(dict_path) as f:
|
|
184
|
+
d = json.load(f)
|
|
185
|
+
|
|
186
|
+
suggestion = help_generic(d)
|
|
187
|
+
if isinstance(suggestion, str):
|
|
188
|
+
print(f"{suggestion=}")
|
|
189
|
+
msgBox = QMessageBox()
|
|
190
|
+
msgBox.setIcon(QMessageBox.Information)
|
|
191
|
+
msgBox.setTextFormat(Qt.RichText)
|
|
192
|
+
msgBox.setText(rf"{suggestion}")
|
|
193
|
+
msgBox.setWindowTitle("Info")
|
|
194
|
+
msgBox.setStandardButtons(QMessageBox.Ok)
|
|
195
|
+
returnValue = msgBox.exec()
|
|
196
|
+
if returnValue == QMessageBox.Ok:
|
|
197
|
+
return None
|
|
198
|
+
|
|
199
|
+
def help_feature(self):
|
|
200
|
+
|
|
201
|
+
"""
|
|
202
|
+
Helper for track post-processing strategy.
|
|
203
|
+
"""
|
|
204
|
+
|
|
205
|
+
dict_path = os.sep.join([get_software_location(),'celldetective','gui','help','feature-btrack.json'])
|
|
206
|
+
|
|
207
|
+
with open(dict_path) as f:
|
|
208
|
+
d = json.load(f)
|
|
209
|
+
|
|
210
|
+
suggestion = help_generic(d)
|
|
211
|
+
if isinstance(suggestion, str):
|
|
212
|
+
print(f"{suggestion=}")
|
|
213
|
+
msgBox = QMessageBox()
|
|
214
|
+
msgBox.setIcon(QMessageBox.Information)
|
|
215
|
+
msgBox.setTextFormat(Qt.RichText)
|
|
216
|
+
msgBox.setText(rf"{suggestion}")
|
|
217
|
+
msgBox.setWindowTitle("Info")
|
|
218
|
+
msgBox.setStandardButtons(QMessageBox.Ok)
|
|
219
|
+
returnValue = msgBox.exec()
|
|
220
|
+
if returnValue == QMessageBox.Ok:
|
|
221
|
+
return None
|
|
141
222
|
|
|
142
223
|
def populate_features_frame(self):
|
|
143
224
|
|
|
@@ -146,12 +227,11 @@ class ConfigTracking(QMainWindow, Styles):
|
|
|
146
227
|
"""
|
|
147
228
|
|
|
148
229
|
grid = QGridLayout(self.features_frame)
|
|
149
|
-
|
|
230
|
+
title_hbox = QHBoxLayout()
|
|
231
|
+
|
|
150
232
|
self.select_features_btn = QPushButton()
|
|
151
233
|
self.select_features_btn.clicked.connect(self.activate_feature_options)
|
|
152
234
|
self.select_features_btn.setStyleSheet(self.button_select_all)
|
|
153
|
-
grid.addWidget(self.select_features_btn, 0,0,1,4,alignment=Qt.AlignLeft)
|
|
154
|
-
|
|
155
235
|
|
|
156
236
|
self.feature_lbl = QLabel("FEATURES")
|
|
157
237
|
self.feature_lbl.setStyleSheet("""
|
|
@@ -164,7 +244,19 @@ class ConfigTracking(QMainWindow, Styles):
|
|
|
164
244
|
self.collapse_features_btn.setIcon(icon(MDI6.chevron_down,color="black"))
|
|
165
245
|
self.collapse_features_btn.setIconSize(QSize(20, 20))
|
|
166
246
|
self.collapse_features_btn.setStyleSheet(self.button_select_all)
|
|
167
|
-
|
|
247
|
+
|
|
248
|
+
self.help_feature_btn = QPushButton()
|
|
249
|
+
self.help_feature_btn.setIcon(icon(MDI6.help_circle,color=self.help_color))
|
|
250
|
+
self.help_feature_btn.setIconSize(QSize(20, 20))
|
|
251
|
+
self.help_feature_btn.clicked.connect(self.help_feature)
|
|
252
|
+
self.help_feature_btn.setStyleSheet(self.button_select_all)
|
|
253
|
+
self.help_feature_btn.setToolTip("Help.")
|
|
254
|
+
|
|
255
|
+
title_hbox.addWidget(self.select_features_btn, 5)
|
|
256
|
+
title_hbox.addWidget(QLabel(), 85, alignment=Qt.AlignCenter)
|
|
257
|
+
title_hbox.addWidget(self.help_feature_btn, 5)
|
|
258
|
+
title_hbox.addWidget(self.collapse_features_btn, 5)
|
|
259
|
+
grid.addLayout(title_hbox, 0,0,1,4)
|
|
168
260
|
|
|
169
261
|
self.generate_feature_panel_contents()
|
|
170
262
|
grid.addWidget(self.ContentsFeatures, 1, 0, 1, 4, alignment=Qt.AlignTop)
|
|
@@ -179,16 +271,22 @@ class ConfigTracking(QMainWindow, Styles):
|
|
|
179
271
|
Switch the chevron icon and adjust the size for the FEATURES frame.
|
|
180
272
|
"""
|
|
181
273
|
|
|
274
|
+
features_open = not self.ContentsFeatures.isHidden()
|
|
275
|
+
config_open = not self.ContentsConfig.isHidden()
|
|
276
|
+
post_open = not self.ContentsPostProc.isHidden()
|
|
277
|
+
is_open = np.array([features_open, config_open, post_open])
|
|
278
|
+
|
|
182
279
|
if self.ContentsFeatures.isHidden():
|
|
183
280
|
self.collapse_features_btn.setIcon(icon(MDI6.chevron_down,color="black"))
|
|
184
281
|
self.collapse_features_btn.setIconSize(QSize(20, 20))
|
|
185
|
-
|
|
186
|
-
|
|
282
|
+
if len(is_open[is_open])==0:
|
|
283
|
+
self.scroll_area.setMinimumHeight(int(self.minimum_height))
|
|
284
|
+
self.adjustSize()
|
|
187
285
|
else:
|
|
188
286
|
self.collapse_features_btn.setIcon(icon(MDI6.chevron_up,color="black"))
|
|
189
287
|
self.collapse_features_btn.setIconSize(QSize(20, 20))
|
|
190
|
-
self.
|
|
191
|
-
|
|
288
|
+
self.scroll_area.setMinimumHeight(min(int(930), int(0.9*self.screen_height)))
|
|
289
|
+
|
|
192
290
|
|
|
193
291
|
def generate_post_proc_panel_contents(self):
|
|
194
292
|
|
|
@@ -273,7 +371,7 @@ class ConfigTracking(QMainWindow, Styles):
|
|
|
273
371
|
self.add_feature_btn.setToolTip("Add feature")
|
|
274
372
|
self.add_feature_btn.setIconSize(QSize(20, 20))
|
|
275
373
|
|
|
276
|
-
self.features_list = ListWidget(
|
|
374
|
+
self.features_list = ListWidget(FeatureChoice, initial_features=['area','intensity_mean',])
|
|
277
375
|
|
|
278
376
|
self.del_feature_btn.clicked.connect(self.features_list.removeSel)
|
|
279
377
|
self.add_feature_btn.clicked.connect(self.features_list.addItem)
|
|
@@ -447,16 +545,22 @@ class ConfigTracking(QMainWindow, Styles):
|
|
|
447
545
|
Switch the chevron icon and adjust the size for the CONFIG frame.
|
|
448
546
|
"""
|
|
449
547
|
|
|
548
|
+
features_open = not self.ContentsFeatures.isHidden()
|
|
549
|
+
config_open = not self.ContentsConfig.isHidden()
|
|
550
|
+
post_open = not self.ContentsPostProc.isHidden()
|
|
551
|
+
is_open = np.array([features_open, config_open, post_open])
|
|
552
|
+
|
|
450
553
|
if self.ContentsConfig.isHidden():
|
|
451
554
|
self.collapse_config_btn.setIcon(icon(MDI6.chevron_down,color="black"))
|
|
452
555
|
self.collapse_config_btn.setIconSize(QSize(20, 20))
|
|
453
|
-
|
|
454
|
-
|
|
556
|
+
if len(is_open[is_open])==0:
|
|
557
|
+
self.scroll_area.setMinimumHeight(int(self.minimum_height))
|
|
558
|
+
self.adjustSize()
|
|
455
559
|
else:
|
|
456
560
|
self.collapse_config_btn.setIcon(icon(MDI6.chevron_up,color="black"))
|
|
457
561
|
self.collapse_config_btn.setIconSize(QSize(20, 20))
|
|
458
|
-
self.
|
|
459
|
-
|
|
562
|
+
self.scroll_area.setMinimumHeight(min(int(930), int(0.9*self.screen_height)))
|
|
563
|
+
|
|
460
564
|
|
|
461
565
|
def generate_config_panel_contents(self):
|
|
462
566
|
|
|
@@ -884,7 +988,8 @@ class ConfigTracking(QMainWindow, Styles):
|
|
|
884
988
|
self.fig, self.ax = plt.subplots(1,1,figsize=(4,3))
|
|
885
989
|
self.hist_window = FigureCanvas(self.fig, title="Haralick: control digitized histogram")
|
|
886
990
|
self.ax.clear()
|
|
887
|
-
|
|
991
|
+
flat = norm_img.flatten()
|
|
992
|
+
self.ax.hist(flat[flat==flat], bins=self.haralick_options['n_intensity_bins'])
|
|
888
993
|
self.ax.set_xlabel('gray level value')
|
|
889
994
|
self.ax.set_ylabel('#')
|
|
890
995
|
plt.tight_layout()
|