celldetective 1.3.3.post1__py3-none-any.whl → 1.3.4.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.
Files changed (35) hide show
  1. celldetective/__main__.py +30 -4
  2. celldetective/_version.py +1 -1
  3. celldetective/extra_properties.py +21 -0
  4. celldetective/filters.py +15 -2
  5. celldetective/gui/InitWindow.py +28 -34
  6. celldetective/gui/analyze_block.py +3 -498
  7. celldetective/gui/classifier_widget.py +1 -1
  8. celldetective/gui/control_panel.py +98 -27
  9. celldetective/gui/generic_signal_plot.py +35 -18
  10. celldetective/gui/gui_utils.py +143 -2
  11. celldetective/gui/layouts.py +7 -6
  12. celldetective/gui/measurement_options.py +3 -11
  13. celldetective/gui/plot_measurements.py +5 -13
  14. celldetective/gui/plot_signals_ui.py +30 -30
  15. celldetective/gui/process_block.py +61 -103
  16. celldetective/gui/signal_annotator.py +50 -32
  17. celldetective/gui/signal_annotator2.py +7 -4
  18. celldetective/gui/styles.py +13 -0
  19. celldetective/gui/survival_ui.py +8 -21
  20. celldetective/gui/tableUI.py +1 -2
  21. celldetective/gui/thresholds_gui.py +0 -6
  22. celldetective/gui/viewers.py +1 -5
  23. celldetective/io.py +31 -4
  24. celldetective/measure.py +8 -5
  25. celldetective/neighborhood.py +0 -2
  26. celldetective/scripts/measure_cells.py +21 -9
  27. celldetective/signals.py +78 -66
  28. celldetective/tracking.py +19 -13
  29. {celldetective-1.3.3.post1.dist-info → celldetective-1.3.4.post1.dist-info}/METADATA +2 -1
  30. {celldetective-1.3.3.post1.dist-info → celldetective-1.3.4.post1.dist-info}/RECORD +35 -35
  31. tests/test_qt.py +5 -3
  32. {celldetective-1.3.3.post1.dist-info → celldetective-1.3.4.post1.dist-info}/LICENSE +0 -0
  33. {celldetective-1.3.3.post1.dist-info → celldetective-1.3.4.post1.dist-info}/WHEEL +0 -0
  34. {celldetective-1.3.3.post1.dist-info → celldetective-1.3.4.post1.dist-info}/entry_points.txt +0 -0
  35. {celldetective-1.3.3.post1.dist-info → celldetective-1.3.4.post1.dist-info}/top_level.txt +0 -0
celldetective/__main__.py CHANGED
@@ -5,6 +5,7 @@ from PyQt5.QtGui import QPixmap
5
5
  from os import sep
6
6
  from celldetective.utils import get_software_location
7
7
  from time import time, sleep
8
+
8
9
  #os.environ['QT_DEBUG_PLUGINS'] = '1'
9
10
 
10
11
  if __name__ == "__main__":
@@ -15,9 +16,11 @@ if __name__ == "__main__":
15
16
  App = QApplication(sys.argv)
16
17
  App.setStyle("Fusion")
17
18
 
19
+ software_location = get_software_location()
20
+
18
21
  if splash:
19
22
  start = time()
20
- splash_pix = QPixmap(sep.join([get_software_location(),'celldetective','icons','splash.png']))
23
+ splash_pix = QPixmap(sep.join([software_location,'celldetective','icons','splash.png']))
21
24
  splash = QSplashScreen(splash_pix)
22
25
  splash.setMask(splash_pix.mask())
23
26
  splash.show()
@@ -26,13 +29,36 @@ if __name__ == "__main__":
26
29
  sleep(0.001)
27
30
  App.processEvents()
28
31
 
29
- from PyQt5.QtWidgets import QFileDialog, QWidget, QVBoxLayout, QCheckBox, QHBoxLayout, QLabel, QLineEdit, QPushButton, QMessageBox, QMenu, QAction
30
- from PyQt5.QtGui import QIcon, QDesktopServices, QIntValidator
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
+
31
57
  from celldetective.gui.InitWindow import AppInitWindow
32
58
 
33
59
  print('Libraries successfully loaded...')
34
60
 
35
- window = AppInitWindow(App)
61
+ window = AppInitWindow(App, software_location=software_location)
36
62
 
37
63
  if splash:
38
64
  splash.finish(window)
celldetective/_version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "1.3.3.post1"
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
 
celldetective/filters.py CHANGED
@@ -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
- img = np.sqrt(win_sqr_mean - win_mean**2)
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
- import gc
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 psutil
18
- import subprocess
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,psutil.cpu_count()])
36
+ self.n_threads = min([1,cpu_count()])
36
37
 
37
38
  try:
38
- subprocess.check_output('nvidia-smi')
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 = get_software_location()
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
- subprocess.Popen(f'explorer {os.path.realpath(path)}')
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+"/config.ini"):
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...")