celldetective 1.3.3.post1__tar.gz → 1.3.4.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.3.3.post1 → celldetective-1.3.4.post1}/PKG-INFO +2 -1
- celldetective-1.3.4.post1/celldetective/__main__.py +66 -0
- celldetective-1.3.4.post1/celldetective/_version.py +1 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/extra_properties.py +21 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/filters.py +15 -2
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/InitWindow.py +28 -34
- celldetective-1.3.4.post1/celldetective/gui/analyze_block.py +81 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/classifier_widget.py +1 -1
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/control_panel.py +98 -27
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/generic_signal_plot.py +35 -18
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/gui_utils.py +143 -2
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/layouts.py +7 -6
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/measurement_options.py +3 -11
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/plot_measurements.py +5 -13
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/plot_signals_ui.py +30 -30
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/process_block.py +61 -103
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/signal_annotator.py +50 -32
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/signal_annotator2.py +7 -4
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/styles.py +13 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/survival_ui.py +8 -21
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/tableUI.py +1 -2
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/thresholds_gui.py +0 -6
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/viewers.py +1 -5
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/io.py +31 -4
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/measure.py +8 -5
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/neighborhood.py +0 -2
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/scripts/measure_cells.py +21 -9
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/signals.py +78 -66
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/tracking.py +19 -13
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective.egg-info/PKG-INFO +2 -1
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective.egg-info/requires.txt +1 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/tests/test_qt.py +5 -3
- celldetective-1.3.3.post1/celldetective/__main__.py +0 -40
- celldetective-1.3.3.post1/celldetective/_version.py +0 -1
- celldetective-1.3.3.post1/celldetective/gui/analyze_block.py +0 -576
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/LICENSE +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/README.md +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/__init__.py +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/datasets/segmentation_annotations/blank +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/datasets/signal_annotations/blank +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/events.py +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/__init__.py +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/about.py +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/btrack_options.py +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/configure_new_exp.py +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/help/DL-segmentation-strategy.json +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/help/Threshold-vs-DL.json +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/help/cell-populations.json +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/help/exp-structure.json +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/help/feature-btrack.json +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/help/neighborhood.json +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/help/prefilter-for-segmentation.json +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/help/preprocessing.json +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/help/propagate-classification.json +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/help/track-postprocessing.json +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/help/tracking.json +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/json_readers.py +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/neighborhood_options.py +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/retrain_segmentation_model_options.py +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/retrain_signal_model_options.py +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/seg_model_loader.py +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/signal_annotator_options.py +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/icons/logo-large.png +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/icons/logo.png +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/icons/signals_icon.png +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/icons/splash-test.png +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/icons/splash.png +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/icons/splash0.png +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/icons/survival2.png +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/icons/vignette_signals2.png +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/icons/vignette_signals2.svg +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/links/zenodo.json +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/models/pair_signal_detection/blank +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/models/segmentation_effectors/blank +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/models/segmentation_effectors/ricm_bf_all_last/config_input.json +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/models/segmentation_effectors/ricm_bf_all_last/ricm_bf_all_last +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/models/segmentation_effectors/ricm_bf_all_last/training_instructions.json +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/models/segmentation_effectors/test-transfer/config_input.json +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/models/segmentation_effectors/test-transfer/test-transfer +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/models/segmentation_generic/blank +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/models/segmentation_targets/blank +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/models/signal_detection/blank +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/models/tracking_configs/biased_motion.json +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/models/tracking_configs/mcf7.json +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/models/tracking_configs/no_z_motion.json +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/models/tracking_configs/ricm.json +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/models/tracking_configs/ricm2.json +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/preprocessing.py +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/relative_measurements.py +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/scripts/analyze_signals.py +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/scripts/measure_relative.py +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/scripts/segment_cells.py +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/scripts/segment_cells_thresholds.py +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/scripts/track_cells.py +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/scripts/train_segmentation_model.py +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/scripts/train_signal_model.py +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/segmentation.py +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/utils.py +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective.egg-info/SOURCES.txt +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective.egg-info/dependency_links.txt +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective.egg-info/entry_points.txt +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective.egg-info/not-zip-safe +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective.egg-info/top_level.txt +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/setup.cfg +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/setup.py +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/tests/__init__.py +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/tests/test_events.py +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/tests/test_filters.py +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/tests/test_io.py +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/tests/test_measure.py +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/tests/test_neighborhood.py +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/tests/test_preprocessing.py +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/tests/test_segmentation.py +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/tests/test_signals.py +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/tests/test_tracking.py +0 -0
- {celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/tests/test_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: celldetective
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.4.post1
|
|
4
4
|
Summary: description
|
|
5
5
|
Home-page: http://github.com/remyeltorro/celldetective
|
|
6
6
|
Author: Rémy Torro
|
|
@@ -41,6 +41,7 @@ Requires-Dist: pytest
|
|
|
41
41
|
Requires-Dist: pytest-qt
|
|
42
42
|
Requires-Dist: h5py
|
|
43
43
|
Requires-Dist: cliffs_delta
|
|
44
|
+
Requires-Dist: requests
|
|
44
45
|
|
|
45
46
|
# Celldetective
|
|
46
47
|
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
import sys
|
|
3
|
+
from PyQt5.QtWidgets import QApplication, QSplashScreen
|
|
4
|
+
from PyQt5.QtGui import QPixmap
|
|
5
|
+
from os import sep
|
|
6
|
+
from celldetective.utils import get_software_location
|
|
7
|
+
from time import time, sleep
|
|
8
|
+
|
|
9
|
+
#os.environ['QT_DEBUG_PLUGINS'] = '1'
|
|
10
|
+
|
|
11
|
+
if __name__ == "__main__":
|
|
12
|
+
|
|
13
|
+
splash=True
|
|
14
|
+
print('Loading the libraries...')
|
|
15
|
+
|
|
16
|
+
App = QApplication(sys.argv)
|
|
17
|
+
App.setStyle("Fusion")
|
|
18
|
+
|
|
19
|
+
software_location = get_software_location()
|
|
20
|
+
|
|
21
|
+
if splash:
|
|
22
|
+
start = time()
|
|
23
|
+
splash_pix = QPixmap(sep.join([software_location,'celldetective','icons','splash.png']))
|
|
24
|
+
splash = QSplashScreen(splash_pix)
|
|
25
|
+
splash.setMask(splash_pix.mask())
|
|
26
|
+
splash.show()
|
|
27
|
+
#App.processEvents(QEventLoop.AllEvents, 300)
|
|
28
|
+
while time() - start < 1:
|
|
29
|
+
sleep(0.001)
|
|
30
|
+
App.processEvents()
|
|
31
|
+
|
|
32
|
+
try:
|
|
33
|
+
|
|
34
|
+
import requests
|
|
35
|
+
import re
|
|
36
|
+
from celldetective import __version__
|
|
37
|
+
|
|
38
|
+
package = 'celldetective'
|
|
39
|
+
response = requests.get(f'https://pypi.org/pypi/{package}/json')
|
|
40
|
+
latest_version = response.json()['info']['version']
|
|
41
|
+
|
|
42
|
+
latest_version_num = re.sub('[^0-9]','', latest_version)
|
|
43
|
+
current_version_num = re.sub('[^0-9]','',__version__)
|
|
44
|
+
|
|
45
|
+
if len(latest_version_num)!=len(current_version_num):
|
|
46
|
+
max_length = max([len(latest_version_num),len(current_version_num)])
|
|
47
|
+
latest_version_num = int(latest_version_num.zfill(max_length - len(latest_version_num)))
|
|
48
|
+
current_version_num = int(current_version_num.zfill(max_length - len(current_version_num)))
|
|
49
|
+
|
|
50
|
+
if latest_version_num > current_version_num:
|
|
51
|
+
print('Update is available...\nPlease update using `pip install --upgrade celldetective`...')
|
|
52
|
+
|
|
53
|
+
except Exception as e:
|
|
54
|
+
|
|
55
|
+
print(f"{e=}")
|
|
56
|
+
|
|
57
|
+
from celldetective.gui.InitWindow import AppInitWindow
|
|
58
|
+
|
|
59
|
+
print('Libraries successfully loaded...')
|
|
60
|
+
|
|
61
|
+
window = AppInitWindow(App, software_location=software_location)
|
|
62
|
+
|
|
63
|
+
if splash:
|
|
64
|
+
splash.finish(window)
|
|
65
|
+
|
|
66
|
+
sys.exit(App.exec())
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.3.4.post1"
|
|
@@ -29,6 +29,27 @@ from celldetective.utils import interpolate_nan, contour_of_instance_segmentatio
|
|
|
29
29
|
|
|
30
30
|
# Percentiles
|
|
31
31
|
|
|
32
|
+
def custom_area(regionmask):
|
|
33
|
+
return np.sum(regionmask)
|
|
34
|
+
|
|
35
|
+
def intensity_area_under_one(regionmask, intensity_image):
|
|
36
|
+
|
|
37
|
+
subregion = regionmask[intensity_image<1]
|
|
38
|
+
if len(subregion)>0:
|
|
39
|
+
return np.sum(subregion)
|
|
40
|
+
else:
|
|
41
|
+
return 0.0
|
|
42
|
+
|
|
43
|
+
def intensity_fraction_of_area_under_one(regionmask, intensity_image):
|
|
44
|
+
|
|
45
|
+
subregion = regionmask[intensity_image<1]
|
|
46
|
+
area = np.sum(regionmask)
|
|
47
|
+
|
|
48
|
+
if len(subregion) > 0:
|
|
49
|
+
return float(np.sum(subregion)) / float(area)
|
|
50
|
+
else:
|
|
51
|
+
return 0.0
|
|
52
|
+
|
|
32
53
|
def intensity_percentile_ninety_nine(regionmask, intensity_image):
|
|
33
54
|
return np.nanpercentile(intensity_image[regionmask],99)
|
|
34
55
|
|
|
@@ -4,15 +4,19 @@ import scipy.ndimage as snd
|
|
|
4
4
|
import numpy as np
|
|
5
5
|
|
|
6
6
|
def gauss_filter(img, sigma, interpolate=True, *kwargs):
|
|
7
|
+
|
|
7
8
|
if interpolate:
|
|
8
9
|
img = interpolate_nan(img.astype(float))
|
|
10
|
+
|
|
9
11
|
return snd.gaussian_filter(img.astype(float), sigma, *kwargs)
|
|
10
12
|
|
|
11
13
|
def median_filter(img, size, interpolate=True, *kwargs):
|
|
14
|
+
|
|
12
15
|
if interpolate:
|
|
13
16
|
img = interpolate_nan(img.astype(float))
|
|
14
17
|
|
|
15
18
|
size = int(size)
|
|
19
|
+
|
|
16
20
|
return snd.median_filter(img, size, *kwargs)
|
|
17
21
|
|
|
18
22
|
def maximum_filter(img, size, interpolate=True, *kwargs):
|
|
@@ -65,13 +69,17 @@ def std_filter(img, size, interpolate=True):
|
|
|
65
69
|
|
|
66
70
|
if interpolate:
|
|
67
71
|
img = interpolate_nan(img.astype(float))
|
|
72
|
+
|
|
68
73
|
size = int(size)
|
|
69
74
|
img = img.astype(float)
|
|
75
|
+
|
|
70
76
|
win_mean = snd.uniform_filter(img, (size,size), mode='wrap')
|
|
71
77
|
win_sqr_mean = snd.uniform_filter(img**2, (size, size), mode='wrap')
|
|
72
|
-
win_sqr_mean[win_sqr_mean!=win_sqr_mean] = 0.
|
|
73
78
|
win_sqr_mean[win_sqr_mean<=0.] = 0. # add this to prevent sqrt from breaking
|
|
74
|
-
|
|
79
|
+
|
|
80
|
+
sub = np.subtract(win_sqr_mean,win_mean**2)
|
|
81
|
+
sub[sub<=0.] = 0.
|
|
82
|
+
img = np.sqrt(sub)
|
|
75
83
|
|
|
76
84
|
return img
|
|
77
85
|
|
|
@@ -96,16 +104,21 @@ def local_filter(img, *kwargs):
|
|
|
96
104
|
return binary.astype(float)
|
|
97
105
|
|
|
98
106
|
def niblack_filter(img, *kwargs):
|
|
107
|
+
|
|
99
108
|
thresh = threshold_niblack(img, *kwargs)
|
|
100
109
|
binary = img >= thresh
|
|
101
110
|
return binary.astype(float)
|
|
102
111
|
|
|
103
112
|
def sauvola_filter(img, *kwargs):
|
|
113
|
+
|
|
104
114
|
thresh = threshold_sauvola(img, *kwargs)
|
|
105
115
|
binary = img >= thresh
|
|
106
116
|
return binary.astype(float)
|
|
107
117
|
|
|
108
118
|
def log_filter(img, sigma, *kwargs):
|
|
119
|
+
|
|
120
|
+
if interpolate:
|
|
121
|
+
img = interpolate_nan(img.astype(float))
|
|
109
122
|
return snd.gaussian_laplace(img.astype(float), sigma, *kwargs)
|
|
110
123
|
|
|
111
124
|
def tophat_filter(img, size, connectivity=4, interpolate=True, *kwargs):
|
|
@@ -1,48 +1,49 @@
|
|
|
1
|
-
from PyQt5.QtWidgets import QApplication, QMainWindow
|
|
2
|
-
from celldetective.utils import get_software_location, download_zenodo_file
|
|
3
1
|
import os
|
|
2
|
+
|
|
3
|
+
from PyQt5.QtWidgets import QApplication, QMainWindow
|
|
4
4
|
from PyQt5.QtWidgets import QFileDialog, QWidget, QVBoxLayout, QCheckBox, QHBoxLayout, QLabel, QLineEdit, QPushButton, QMessageBox, QMenu, QAction
|
|
5
5
|
from PyQt5.QtCore import Qt, QUrl
|
|
6
6
|
from PyQt5.QtGui import QIcon, QDesktopServices, QIntValidator
|
|
7
|
+
|
|
7
8
|
from glob import glob
|
|
8
9
|
from superqt.fonticon import icon
|
|
9
10
|
from fonticon_mdi6 import MDI6
|
|
10
|
-
|
|
11
|
-
from celldetective.gui import Styles, ControlPanel, ConfigNewExperiment
|
|
12
|
-
from celldetective.gui.gui_utils import center_window
|
|
13
|
-
import subprocess
|
|
14
|
-
import os
|
|
11
|
+
|
|
15
12
|
from celldetective.gui.about import AboutWidget
|
|
16
13
|
from celldetective.io import correct_annotation
|
|
17
|
-
import
|
|
18
|
-
import
|
|
14
|
+
from celldetective.utils import download_zenodo_file
|
|
15
|
+
from celldetective.gui.gui_utils import center_window
|
|
16
|
+
from celldetective.gui import Styles, ControlPanel, ConfigNewExperiment
|
|
17
|
+
|
|
18
|
+
import gc
|
|
19
|
+
from subprocess import check_output, Popen
|
|
20
|
+
from psutil import cpu_count
|
|
19
21
|
import json
|
|
20
22
|
|
|
21
|
-
class AppInitWindow(QMainWindow):
|
|
23
|
+
class AppInitWindow(QMainWindow, Styles):
|
|
22
24
|
|
|
23
25
|
"""
|
|
24
26
|
Initial window to set the experiment folder or create a new one.
|
|
25
27
|
"""
|
|
26
28
|
|
|
27
|
-
def __init__(self, parent_window=None):
|
|
29
|
+
def __init__(self, parent_window=None, software_location=None):
|
|
30
|
+
|
|
28
31
|
super().__init__()
|
|
29
32
|
|
|
30
33
|
self.parent_window = parent_window
|
|
31
|
-
self.Styles = Styles()
|
|
32
|
-
self.init_styles()
|
|
33
34
|
self.setWindowTitle("celldetective")
|
|
34
35
|
|
|
35
|
-
self.n_threads = min([1,
|
|
36
|
+
self.n_threads = min([1,cpu_count()])
|
|
36
37
|
|
|
37
38
|
try:
|
|
38
|
-
|
|
39
|
+
check_output('nvidia-smi')
|
|
39
40
|
print('NVIDIA GPU detected (activate or disable in Memory & Threads)...')
|
|
40
41
|
self.use_gpu = True
|
|
41
42
|
except Exception: # this command not being found can raise quite a few different errors depending on the configuration
|
|
42
43
|
print('No NVIDIA GPU detected...')
|
|
43
44
|
self.use_gpu = False
|
|
44
|
-
|
|
45
|
-
self.soft_path =
|
|
45
|
+
|
|
46
|
+
self.soft_path = software_location
|
|
46
47
|
self.onlyInt = QIntValidator()
|
|
47
48
|
self.setWindowIcon(QIcon(os.sep.join([self.soft_path,'celldetective','icons','logo.png'])))
|
|
48
49
|
center_window(self)
|
|
@@ -65,6 +66,7 @@ class AppInitWindow(QMainWindow):
|
|
|
65
66
|
self.show()
|
|
66
67
|
|
|
67
68
|
def closeEvent(self, event):
|
|
69
|
+
|
|
68
70
|
QApplication.closeAllWindows()
|
|
69
71
|
event.accept()
|
|
70
72
|
gc.collect()
|
|
@@ -188,6 +190,9 @@ class AppInitWindow(QMainWindow):
|
|
|
188
190
|
def download_spreading_assay_demo(self):
|
|
189
191
|
|
|
190
192
|
self.target_dir = str(QFileDialog.getExistingDirectory(self, 'Select Folder for Download'))
|
|
193
|
+
if self.target_dir=='':
|
|
194
|
+
return None
|
|
195
|
+
|
|
191
196
|
if not os.path.exists(os.sep.join([self.target_dir,'demo_ricm'])):
|
|
192
197
|
download_zenodo_file('demo_ricm', self.target_dir)
|
|
193
198
|
self.experiment_path_selection.setText(os.sep.join([self.target_dir, 'demo_ricm']))
|
|
@@ -196,6 +201,9 @@ class AppInitWindow(QMainWindow):
|
|
|
196
201
|
def download_cytotoxicity_assay_demo(self):
|
|
197
202
|
|
|
198
203
|
self.target_dir = str(QFileDialog.getExistingDirectory(self, 'Select Folder for Download'))
|
|
204
|
+
if self.target_dir=='':
|
|
205
|
+
return None
|
|
206
|
+
|
|
199
207
|
if not os.path.exists(os.sep.join([self.target_dir,'demo_adcc'])):
|
|
200
208
|
download_zenodo_file('demo_adcc', self.target_dir)
|
|
201
209
|
self.experiment_path_selection.setText(os.sep.join([self.target_dir, 'demo_adcc']))
|
|
@@ -302,9 +310,10 @@ class AppInitWindow(QMainWindow):
|
|
|
302
310
|
QDesktopServices.openUrl(doc_url)
|
|
303
311
|
|
|
304
312
|
def open_models_folder(self):
|
|
313
|
+
|
|
305
314
|
path = os.sep.join([self.soft_path,'celldetective','models',os.sep])
|
|
306
315
|
try:
|
|
307
|
-
|
|
316
|
+
Popen(f'explorer {os.path.realpath(path)}')
|
|
308
317
|
except:
|
|
309
318
|
|
|
310
319
|
try:
|
|
@@ -312,9 +321,6 @@ class AppInitWindow(QMainWindow):
|
|
|
312
321
|
except:
|
|
313
322
|
return None
|
|
314
323
|
|
|
315
|
-
|
|
316
|
-
#os.system(f'start {os.path.realpath(path)}')
|
|
317
|
-
|
|
318
324
|
def create_buttons_hbox(self):
|
|
319
325
|
|
|
320
326
|
self.buttons_layout = QHBoxLayout()
|
|
@@ -344,18 +350,6 @@ class AppInitWindow(QMainWindow):
|
|
|
344
350
|
else:
|
|
345
351
|
self.validate_button.setEnabled(False)
|
|
346
352
|
|
|
347
|
-
def init_styles(self):
|
|
348
|
-
|
|
349
|
-
"""
|
|
350
|
-
Initialize styles.
|
|
351
|
-
"""
|
|
352
|
-
|
|
353
|
-
self.qtab_style = self.Styles.qtab_style
|
|
354
|
-
self.button_style_sheet = self.Styles.button_style_sheet
|
|
355
|
-
self.button_style_sheet_2 = self.Styles.button_style_sheet_2
|
|
356
|
-
self.button_style_sheet_2_not_done = self.Styles.button_style_sheet_2_not_done
|
|
357
|
-
self.button_style_sheet_3 = self.Styles.button_style_sheet_3
|
|
358
|
-
self.button_select_all = self.Styles.button_select_all
|
|
359
353
|
|
|
360
354
|
def set_experiment_path(self, path):
|
|
361
355
|
self.experiment_path_selection.setText(path)
|
|
@@ -414,7 +408,7 @@ class AppInitWindow(QMainWindow):
|
|
|
414
408
|
self.experiment_path_selection.setText(self.foldername)
|
|
415
409
|
else:
|
|
416
410
|
return None
|
|
417
|
-
if not os.path.exists(self.foldername
|
|
411
|
+
if not os.path.exists(os.sep.join([self.foldername,"config.ini"])):
|
|
418
412
|
msgBox = QMessageBox()
|
|
419
413
|
msgBox.setIcon(QMessageBox.Warning)
|
|
420
414
|
msgBox.setText("No configuration can be found in the selected folder...")
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
from PyQt5.QtWidgets import QFrame, QLabel, QPushButton, QVBoxLayout, \
|
|
2
|
+
QSpacerItem, QSizePolicy
|
|
3
|
+
from PyQt5.QtCore import Qt, QSize
|
|
4
|
+
from PyQt5.QtGui import QIcon
|
|
5
|
+
from celldetective.gui.plot_measurements import ConfigMeasurementsPlot
|
|
6
|
+
from celldetective.gui import ConfigSurvival, ConfigSignalPlot
|
|
7
|
+
import os
|
|
8
|
+
from celldetective.gui import Styles
|
|
9
|
+
|
|
10
|
+
class AnalysisPanel(QFrame, Styles):
|
|
11
|
+
def __init__(self, parent_window, title=None):
|
|
12
|
+
|
|
13
|
+
super().__init__()
|
|
14
|
+
self.parent_window = parent_window
|
|
15
|
+
self.title = title
|
|
16
|
+
if self.title is None:
|
|
17
|
+
self.title=''
|
|
18
|
+
self.exp_channels = self.parent_window.exp_channels
|
|
19
|
+
self.exp_dir = self.parent_window.exp_dir
|
|
20
|
+
self.soft_path = self.parent_window.parent_window.soft_path
|
|
21
|
+
|
|
22
|
+
self.setFrameStyle(QFrame.StyledPanel | QFrame.Raised)
|
|
23
|
+
self.grid = QVBoxLayout(self)
|
|
24
|
+
self.grid.setSpacing(20)
|
|
25
|
+
self.generate_header()
|
|
26
|
+
|
|
27
|
+
def generate_header(self):
|
|
28
|
+
|
|
29
|
+
"""
|
|
30
|
+
Read the mode and prepare a collapsable block to process a specific cell population.
|
|
31
|
+
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
panel_title = QLabel("Survival")
|
|
35
|
+
panel_title.setStyleSheet("""
|
|
36
|
+
font-weight: bold;
|
|
37
|
+
padding: 0px;
|
|
38
|
+
""")
|
|
39
|
+
|
|
40
|
+
self.grid.addWidget(panel_title, alignment=Qt.AlignCenter)
|
|
41
|
+
|
|
42
|
+
self.survival_btn = QPushButton("plot survival")
|
|
43
|
+
self.survival_btn.setIcon(QIcon(QIcon(os.sep.join([self.soft_path,'celldetective','icons','survival2.png']))))
|
|
44
|
+
self.survival_btn.setStyleSheet(self.button_style_sheet_2)
|
|
45
|
+
self.survival_btn.setIconSize(QSize(35, 35))
|
|
46
|
+
self.survival_btn.clicked.connect(self.configure_survival)
|
|
47
|
+
self.grid.addWidget(self.survival_btn)
|
|
48
|
+
|
|
49
|
+
signal_lbl = QLabel("Single-cell signals")
|
|
50
|
+
signal_lbl.setStyleSheet("""
|
|
51
|
+
font-weight: bold;
|
|
52
|
+
padding: 0px;
|
|
53
|
+
""")
|
|
54
|
+
|
|
55
|
+
self.grid.addWidget(signal_lbl, alignment=Qt.AlignCenter)
|
|
56
|
+
|
|
57
|
+
self.plot_signal_btn = QPushButton("plot signals")
|
|
58
|
+
self.plot_signal_btn.setIcon(QIcon(QIcon(os.sep.join([self.soft_path,'celldetective','icons','signals_icon.png']))))
|
|
59
|
+
self.plot_signal_btn.setStyleSheet(self.button_style_sheet_2)
|
|
60
|
+
self.plot_signal_btn.setIconSize(QSize(35, 35))
|
|
61
|
+
self.plot_signal_btn.clicked.connect(self.configure_plot_signals)
|
|
62
|
+
self.grid.addWidget(self.plot_signal_btn)
|
|
63
|
+
|
|
64
|
+
verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
|
|
65
|
+
self.grid.addItem(verticalSpacer)
|
|
66
|
+
|
|
67
|
+
def configure_survival(self):
|
|
68
|
+
print('survival analysis starting!!!')
|
|
69
|
+
self.configSurvival = ConfigSurvival(self)
|
|
70
|
+
self.configSurvival.show()
|
|
71
|
+
|
|
72
|
+
def configure_plot_signals(self):
|
|
73
|
+
print('Configure a signal collapse representation...')
|
|
74
|
+
self.ConfigSignalPlot = ConfigSignalPlot(self)
|
|
75
|
+
self.ConfigSignalPlot.show()
|
|
76
|
+
|
|
77
|
+
def configure_plot_measurements(self):
|
|
78
|
+
|
|
79
|
+
print('plot measurements analysis starting!!!')
|
|
80
|
+
self.ConfigMeasurementsPlot_wg = ConfigMeasurementsPlot(self)
|
|
81
|
+
self.ConfigMeasurementsPlot_wg.show()
|
{celldetective-1.3.3.post1 → celldetective-1.3.4.post1}/celldetective/gui/classifier_widget.py
RENAMED
|
@@ -10,7 +10,7 @@ import numpy as np
|
|
|
10
10
|
import matplotlib.pyplot as plt
|
|
11
11
|
import json
|
|
12
12
|
|
|
13
|
-
from celldetective.gui.gui_utils import FigureCanvas, center_window, color_from_status, help_generic
|
|
13
|
+
from celldetective.gui.gui_utils import FigureCanvas, center_window, color_from_status, help_generic
|
|
14
14
|
from celldetective.gui import Styles
|
|
15
15
|
from celldetective.utils import get_software_location
|
|
16
16
|
from celldetective.measure import classify_cells_from_query, interpret_track_classification
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
from PyQt5.QtWidgets import QMainWindow,
|
|
1
|
+
from PyQt5.QtWidgets import QMainWindow, QPushButton, QHBoxLayout, QLabel, QWidget, QGridLayout, QFrame, \
|
|
2
2
|
QTabWidget, QVBoxLayout, QMessageBox, QScrollArea, QDesktopWidget
|
|
3
3
|
from PyQt5.QtCore import Qt, QSize
|
|
4
|
-
from celldetective.gui.gui_utils import center_window, QHSeperationLine
|
|
4
|
+
from celldetective.gui.gui_utils import center_window, QHSeperationLine, QCheckableComboBox
|
|
5
5
|
from celldetective.utils import _extract_labels_from_config, ConfigSectionMap, extract_experiment_channels, extract_identity_col
|
|
6
6
|
from celldetective.gui import ConfigEditor, ProcessPanel, PreprocessingPanel, AnalysisPanel, NeighPanel
|
|
7
7
|
from celldetective.io import get_experiment_wells, get_config, get_spatial_calibration, get_temporal_calibration, get_experiment_concentrations, get_experiment_cell_types, get_experiment_antibodies, get_experiment_pharmaceutical_agents
|
|
@@ -18,6 +18,7 @@ from celldetective.utils import extract_experiment_channels
|
|
|
18
18
|
from celldetective.gui import Styles
|
|
19
19
|
import pandas as pd
|
|
20
20
|
|
|
21
|
+
|
|
21
22
|
class ControlPanel(QMainWindow, Styles):
|
|
22
23
|
|
|
23
24
|
def __init__(self, parent_window=None, exp_dir=""):
|
|
@@ -90,7 +91,7 @@ class ControlPanel(QMainWindow, Styles):
|
|
|
90
91
|
self.initial_width = self.size().width()
|
|
91
92
|
self.screen_height = desktop.screenGeometry().height()
|
|
92
93
|
self.screen_width = desktop.screenGeometry().width()
|
|
93
|
-
self.scroll.setMinimumWidth(
|
|
94
|
+
self.scroll.setMinimumWidth(440)
|
|
94
95
|
|
|
95
96
|
def init_wells_and_positions(self):
|
|
96
97
|
|
|
@@ -138,23 +139,23 @@ class ControlPanel(QMainWindow, Styles):
|
|
|
138
139
|
self.edit_config_button.clicked.connect(self.open_config_editor)
|
|
139
140
|
self.edit_config_button.setStyleSheet(self.button_select_all)
|
|
140
141
|
|
|
141
|
-
self.well_list =
|
|
142
|
+
self.well_list = QCheckableComboBox(obj='well', parent_window=self)
|
|
142
143
|
thresh = 32
|
|
143
|
-
self.well_truncated = [w[:thresh - 3]+'...' if len(w)>thresh else w for w in self.well_labels]
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
self.well_list.setItemData(i, self.well_labels[i], Qt.ToolTipRole)
|
|
147
|
-
self.well_list.addItems(["*"])
|
|
148
|
-
self.well_list.activated.connect(self.display_positions)
|
|
149
|
-
self.to_disable.append(self.well_list)
|
|
144
|
+
self.well_truncated = [w[:thresh - 3]+'...' if len(w)>thresh else w for w in self.well_labels]
|
|
145
|
+
for i in range(len(self.well_truncated)):
|
|
146
|
+
self.well_list.addItem(self.well_truncated[i], tooltip=self.well_labels[i])
|
|
150
147
|
|
|
151
|
-
self.position_list =
|
|
152
|
-
self.position_list.addItems(["*"])
|
|
148
|
+
self.position_list = QCheckableComboBox(obj='position', parent_window=self)
|
|
153
149
|
self.position_list.addItems(self.positions[0])
|
|
154
|
-
self.position_list.activated.connect(self.update_position_options)
|
|
155
150
|
self.to_disable.append(self.position_list)
|
|
156
151
|
#self.locate_selected_position()
|
|
157
152
|
|
|
153
|
+
self.well_list.activated.connect(self.display_positions)
|
|
154
|
+
self.well_list.setCurrentIndex(0)
|
|
155
|
+
|
|
156
|
+
self.position_list.activated.connect(self.update_position_options)
|
|
157
|
+
self.position_list.setCurrentIndex(0)
|
|
158
|
+
|
|
158
159
|
self.view_stack_btn = QPushButton()
|
|
159
160
|
self.view_stack_btn.setStyleSheet(self.button_select_all)
|
|
160
161
|
self.view_stack_btn.setIcon(icon(MDI6.image_check, color="black"))
|
|
@@ -163,6 +164,24 @@ class ControlPanel(QMainWindow, Styles):
|
|
|
163
164
|
self.view_stack_btn.clicked.connect(self.view_current_stack)
|
|
164
165
|
self.view_stack_btn.setEnabled(False)
|
|
165
166
|
|
|
167
|
+
self.select_all_wells_btn = QPushButton()
|
|
168
|
+
self.select_all_wells_btn.setIcon(icon(MDI6.select_all,color="black"))
|
|
169
|
+
self.select_all_wells_btn.setIconSize(QSize(20, 20))
|
|
170
|
+
self.select_all_wells_btn.setToolTip("Select all wells.")
|
|
171
|
+
self.select_all_wells_btn.clicked.connect(self.select_all_wells)
|
|
172
|
+
self.select_all_wells_btn.setStyleSheet(self.button_select_all)
|
|
173
|
+
self.select_all_wells_option = False
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
self.select_all_pos_btn = QPushButton()
|
|
177
|
+
self.select_all_pos_btn.setIcon(icon(MDI6.select_all,color="black"))
|
|
178
|
+
self.select_all_pos_btn.setIconSize(QSize(20, 20))
|
|
179
|
+
self.select_all_pos_btn.setToolTip("Select all positions.")
|
|
180
|
+
self.select_all_pos_btn.clicked.connect(self.select_all_positions)
|
|
181
|
+
self.select_all_pos_btn.setStyleSheet(self.button_select_all)
|
|
182
|
+
self.select_all_pos_option = False
|
|
183
|
+
|
|
184
|
+
|
|
166
185
|
well_lbl = QLabel('Well: ')
|
|
167
186
|
well_lbl.setAlignment(Qt.AlignRight)
|
|
168
187
|
|
|
@@ -196,20 +215,52 @@ class ControlPanel(QMainWindow, Styles):
|
|
|
196
215
|
# Well row
|
|
197
216
|
well_hbox = QHBoxLayout()
|
|
198
217
|
well_hbox.addWidget(well_lbl, 25, alignment=Qt.AlignVCenter)
|
|
199
|
-
|
|
218
|
+
well_subhbox = QHBoxLayout()
|
|
219
|
+
well_subhbox.addWidget(self.well_list, 95)
|
|
220
|
+
well_subhbox.addWidget(self.select_all_wells_btn, 5)
|
|
221
|
+
well_hbox.addLayout(well_subhbox, 75)
|
|
200
222
|
vbox.addLayout(well_hbox)
|
|
201
223
|
|
|
202
224
|
# Position row
|
|
203
225
|
position_hbox = QHBoxLayout()
|
|
204
226
|
position_hbox.addWidget(pos_lbl, 25, alignment=Qt.AlignVCenter)
|
|
205
227
|
pos_subhbox = QHBoxLayout()
|
|
206
|
-
pos_subhbox.addWidget(self.position_list,
|
|
228
|
+
pos_subhbox.addWidget(self.position_list, 90)
|
|
229
|
+
pos_subhbox.addWidget(self.select_all_pos_btn, 5)
|
|
207
230
|
pos_subhbox.addWidget(self.view_stack_btn, 5)
|
|
208
231
|
position_hbox.addLayout(pos_subhbox, 75)
|
|
209
232
|
vbox.addLayout(position_hbox)
|
|
210
233
|
|
|
211
234
|
vbox.addWidget(hsep)
|
|
212
235
|
|
|
236
|
+
def select_all_wells(self):
|
|
237
|
+
|
|
238
|
+
if not self.select_all_wells_option:
|
|
239
|
+
self.well_list.selectAll()
|
|
240
|
+
self.select_all_wells_option = True
|
|
241
|
+
self.select_all_wells_btn.setIcon(icon(MDI6.select_all,color=self.celldetective_blue))
|
|
242
|
+
self.select_all_wells_btn.setIconSize(QSize(20, 20))
|
|
243
|
+
self.display_positions()
|
|
244
|
+
else:
|
|
245
|
+
self.well_list.unselectAll()
|
|
246
|
+
self.select_all_wells_option = False
|
|
247
|
+
self.select_all_wells_btn.setIcon(icon(MDI6.select_all,color="black"))
|
|
248
|
+
self.select_all_wells_btn.setIconSize(QSize(20, 20))
|
|
249
|
+
self.display_positions()
|
|
250
|
+
|
|
251
|
+
def select_all_positions(self):
|
|
252
|
+
|
|
253
|
+
if not self.select_all_pos_option:
|
|
254
|
+
self.position_list.selectAll()
|
|
255
|
+
self.select_all_pos_option = True
|
|
256
|
+
self.select_all_pos_btn.setIcon(icon(MDI6.select_all,color=self.celldetective_blue))
|
|
257
|
+
self.select_all_pos_btn.setIconSize(QSize(20, 20))
|
|
258
|
+
else:
|
|
259
|
+
self.position_list.unselectAll()
|
|
260
|
+
self.select_all_pos_option = False
|
|
261
|
+
self.select_all_pos_btn.setIcon(icon(MDI6.select_all,color="black"))
|
|
262
|
+
self.select_all_pos_btn.setIconSize(QSize(20, 20))
|
|
263
|
+
|
|
213
264
|
def locate_image(self):
|
|
214
265
|
|
|
215
266
|
"""
|
|
@@ -341,17 +392,30 @@ class ControlPanel(QMainWindow, Styles):
|
|
|
341
392
|
Show the positions as the well is changed.
|
|
342
393
|
"""
|
|
343
394
|
|
|
344
|
-
if self.well_list.
|
|
395
|
+
if self.well_list.isMultipleSelection():
|
|
396
|
+
|
|
345
397
|
self.position_list.clear()
|
|
346
|
-
self.position_list.addItems(["*"])
|
|
347
398
|
position_linspace = np.linspace(0,len(self.positions[0])-1,len(self.positions[0]),dtype=int)
|
|
348
399
|
position_linspace = [str(s) for s in position_linspace]
|
|
349
400
|
self.position_list.addItems(position_linspace)
|
|
401
|
+
if self.select_all_pos_option:
|
|
402
|
+
self.select_all_pos_btn.click()
|
|
403
|
+
self.select_all_pos_btn.click()
|
|
404
|
+
|
|
405
|
+
elif not self.well_list.isAnySelected():
|
|
406
|
+
|
|
407
|
+
self.position_list.unselectAll()
|
|
408
|
+
if self.select_all_pos_option:
|
|
409
|
+
self.select_all_pos_btn.click()
|
|
410
|
+
|
|
350
411
|
else:
|
|
351
|
-
pos_index = self.well_list.
|
|
412
|
+
pos_index = self.well_list.getSelectedIndices()[0]
|
|
352
413
|
self.position_list.clear()
|
|
353
|
-
self.position_list.addItems(["*"])
|
|
354
414
|
self.position_list.addItems(self.positions[pos_index])
|
|
415
|
+
if self.select_all_pos_option:
|
|
416
|
+
self.select_all_pos_btn.click()
|
|
417
|
+
self.position_list.setCurrentIndex(0)
|
|
418
|
+
|
|
355
419
|
self.update_position_options()
|
|
356
420
|
|
|
357
421
|
def open_config_editor(self):
|
|
@@ -366,7 +430,7 @@ class ControlPanel(QMainWindow, Styles):
|
|
|
366
430
|
|
|
367
431
|
"""
|
|
368
432
|
|
|
369
|
-
if self.well_list.
|
|
433
|
+
if self.well_list.isMultipleSelection():
|
|
370
434
|
msgBox = QMessageBox()
|
|
371
435
|
msgBox.setIcon(QMessageBox.Critical)
|
|
372
436
|
msgBox.setText("Please select a single well...")
|
|
@@ -376,12 +440,12 @@ class ControlPanel(QMainWindow, Styles):
|
|
|
376
440
|
if returnValue == QMessageBox.Ok:
|
|
377
441
|
return False
|
|
378
442
|
else:
|
|
379
|
-
self.well_index = [self.well_list.currentIndex()]
|
|
443
|
+
self.well_index = self.well_list.getSelectedIndices() #[self.well_list.currentIndex()]
|
|
380
444
|
|
|
381
445
|
for w_idx in self.well_index:
|
|
382
446
|
|
|
383
447
|
pos = self.positions[w_idx]
|
|
384
|
-
if self.position_list.
|
|
448
|
+
if not self.position_list.isSingleSelection():
|
|
385
449
|
msgBox = QMessageBox()
|
|
386
450
|
msgBox.setIcon(QMessageBox.Critical)
|
|
387
451
|
msgBox.setText("Please select a single position...")
|
|
@@ -391,11 +455,12 @@ class ControlPanel(QMainWindow, Styles):
|
|
|
391
455
|
if returnValue == QMessageBox.Ok:
|
|
392
456
|
return False
|
|
393
457
|
else:
|
|
394
|
-
pos_indices =
|
|
458
|
+
pos_indices = self.position_list.getSelectedIndices()
|
|
395
459
|
|
|
396
460
|
well = self.wells[w_idx]
|
|
397
461
|
|
|
398
462
|
for pos_idx in pos_indices:
|
|
463
|
+
|
|
399
464
|
self.pos = natsorted(glob(well+f"{os.path.split(well)[-1].replace('W','').replace(os.sep,'')}*{os.sep}"))[pos_idx]
|
|
400
465
|
if not os.path.exists(self.pos + 'output'):
|
|
401
466
|
os.mkdir(self.pos + 'output')
|
|
@@ -405,6 +470,7 @@ class ControlPanel(QMainWindow, Styles):
|
|
|
405
470
|
return True
|
|
406
471
|
|
|
407
472
|
def create_config_dir(self):
|
|
473
|
+
|
|
408
474
|
self.config_folder = self.exp_dir+'configs'+os.sep
|
|
409
475
|
if not os.path.exists(self.config_folder):
|
|
410
476
|
os.mkdir(self.config_folder)
|
|
@@ -413,7 +479,8 @@ class ControlPanel(QMainWindow, Styles):
|
|
|
413
479
|
|
|
414
480
|
self.pos = self.position_list.currentText()
|
|
415
481
|
panels = [self.ProcessEffectors, self.ProcessTargets]
|
|
416
|
-
|
|
482
|
+
|
|
483
|
+
if self.position_list.isMultipleSelection() or not self.position_list.isAnySelected():
|
|
417
484
|
|
|
418
485
|
for p in panels:
|
|
419
486
|
p.check_seg_btn.setEnabled(False)
|
|
@@ -443,7 +510,9 @@ class ControlPanel(QMainWindow, Styles):
|
|
|
443
510
|
self.ProcessEffectors.delete_tracks_btn.hide()
|
|
444
511
|
|
|
445
512
|
self.view_stack_btn.setEnabled(False)
|
|
446
|
-
|
|
513
|
+
|
|
514
|
+
elif self.well_list.isMultipleSelection():
|
|
515
|
+
|
|
447
516
|
self.ProcessTargets.view_tab_btn.setEnabled(True)
|
|
448
517
|
self.ProcessEffectors.view_tab_btn.setEnabled(True)
|
|
449
518
|
self.NeighPanel.view_tab_btn.setEnabled(True)
|
|
@@ -455,7 +524,9 @@ class ControlPanel(QMainWindow, Styles):
|
|
|
455
524
|
self.ProcessTargets.delete_tracks_btn.hide()
|
|
456
525
|
self.ProcessEffectors.delete_tracks_btn.hide()
|
|
457
526
|
else:
|
|
458
|
-
|
|
527
|
+
|
|
528
|
+
if self.well_list.isAnySelected() and self.position_list.isAnySelected():
|
|
529
|
+
|
|
459
530
|
self.locate_selected_position()
|
|
460
531
|
self.view_stack_btn.setEnabled(True)
|
|
461
532
|
# if os.path.exists(os.sep.join([self.pos,'labels_effectors', os.sep])):
|