dcscope 2.22.1__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 (267) hide show
  1. dcscope/__init__.py +17 -0
  2. dcscope/__main__.py +44 -0
  3. dcscope/_version.py +21 -0
  4. dcscope/extensions.py +250 -0
  5. dcscope/gui/__init__.py +2 -0
  6. dcscope/gui/analysis/__init__.py +10 -0
  7. dcscope/gui/analysis/ana_basins.py +110 -0
  8. dcscope/gui/analysis/ana_basins.ui +143 -0
  9. dcscope/gui/analysis/ana_filter.py +341 -0
  10. dcscope/gui/analysis/ana_filter.ui +364 -0
  11. dcscope/gui/analysis/ana_log.py +122 -0
  12. dcscope/gui/analysis/ana_log.ui +100 -0
  13. dcscope/gui/analysis/ana_meta.py +207 -0
  14. dcscope/gui/analysis/ana_meta.ui +141 -0
  15. dcscope/gui/analysis/ana_plot.py +638 -0
  16. dcscope/gui/analysis/ana_plot.ui +1060 -0
  17. dcscope/gui/analysis/ana_slot.py +504 -0
  18. dcscope/gui/analysis/ana_slot.ui +684 -0
  19. dcscope/gui/analysis/ana_tables.py +227 -0
  20. dcscope/gui/analysis/ana_tables.ui +195 -0
  21. dcscope/gui/analysis/ana_view.py +69 -0
  22. dcscope/gui/analysis/ana_view.ui +269 -0
  23. dcscope/gui/analysis/dlg_slot_reorder.py +55 -0
  24. dcscope/gui/analysis/dlg_slot_reorder.ui +138 -0
  25. dcscope/gui/bulk/__init__.py +2 -0
  26. dcscope/gui/bulk/bulk_emodulus.py +200 -0
  27. dcscope/gui/bulk/bulk_emodulus.ui +245 -0
  28. dcscope/gui/compute/__init__.py +3 -0
  29. dcscope/gui/compute/comp_lme4.py +115 -0
  30. dcscope/gui/compute/comp_lme4.ui +194 -0
  31. dcscope/gui/compute/comp_lme4_dataset.py +51 -0
  32. dcscope/gui/compute/comp_lme4_dataset.ui +92 -0
  33. dcscope/gui/compute/comp_lme4_results.py +120 -0
  34. dcscope/gui/compute/comp_lme4_results.ui +268 -0
  35. dcscope/gui/compute/comp_stats.py +223 -0
  36. dcscope/gui/compute/comp_stats.ui +187 -0
  37. dcscope/gui/dcor/__init__.py +304 -0
  38. dcscope/gui/dcor/dcor.ui +118 -0
  39. dcscope/gui/export/__init__.py +3 -0
  40. dcscope/gui/export/e2data.py +394 -0
  41. dcscope/gui/export/e2data.ui +367 -0
  42. dcscope/gui/export/e2filter.py +76 -0
  43. dcscope/gui/export/e2filter.ui +111 -0
  44. dcscope/gui/export/e2plot.py +94 -0
  45. dcscope/gui/export/e2plot.ui +175 -0
  46. dcscope/gui/main.py +1089 -0
  47. dcscope/gui/main.ui +579 -0
  48. dcscope/gui/matrix/__init__.py +4 -0
  49. dcscope/gui/matrix/block_matrix.py +141 -0
  50. dcscope/gui/matrix/block_matrix.ui +207 -0
  51. dcscope/gui/matrix/data_matrix.py +574 -0
  52. dcscope/gui/matrix/dm_dataset.py +116 -0
  53. dcscope/gui/matrix/dm_dataset.ui +348 -0
  54. dcscope/gui/matrix/dm_element.py +111 -0
  55. dcscope/gui/matrix/dm_element.ui +169 -0
  56. dcscope/gui/matrix/dm_filter.py +115 -0
  57. dcscope/gui/matrix/dm_filter.ui +287 -0
  58. dcscope/gui/matrix/plot_matrix.py +316 -0
  59. dcscope/gui/matrix/pm_element.py +39 -0
  60. dcscope/gui/matrix/pm_plot.py +86 -0
  61. dcscope/gui/matrix/pm_plot.ui +249 -0
  62. dcscope/gui/pipeline_plot.py +797 -0
  63. dcscope/gui/pipeline_plot.ui +66 -0
  64. dcscope/gui/preferences.py +380 -0
  65. dcscope/gui/preferences.ui +554 -0
  66. dcscope/gui/quick_view/__init__.py +1 -0
  67. dcscope/gui/quick_view/qv_main.py +1072 -0
  68. dcscope/gui/quick_view/qv_main.ui +1297 -0
  69. dcscope/gui/quick_view/qv_scatter.py +284 -0
  70. dcscope/gui/quick_view/qv_style.css +10 -0
  71. dcscope/gui/update.py +90 -0
  72. dcscope/gui/widgets/__init__.py +15 -0
  73. dcscope/gui/widgets/bg_thread.py +29 -0
  74. dcscope/gui/widgets/bulk_list.py +79 -0
  75. dcscope/gui/widgets/bulk_list.ui +95 -0
  76. dcscope/gui/widgets/double_spin_box_nan.py +75 -0
  77. dcscope/gui/widgets/feature_combobox.py +140 -0
  78. dcscope/gui/widgets/get_path.py +42 -0
  79. dcscope/gui/widgets/key_value_table_widget.css +12 -0
  80. dcscope/gui/widgets/key_value_table_widget.py +75 -0
  81. dcscope/gui/widgets/mdi_subwindow_wo_close.py +12 -0
  82. dcscope/gui/widgets/qrangeslider.py +262 -0
  83. dcscope/gui/widgets/rangecontrol.py +308 -0
  84. dcscope/gui/widgets/rangecontrol.ui +136 -0
  85. dcscope/gui/widgets/simple_image_view.py +55 -0
  86. dcscope/gui/widgets/simple_plot_widget.py +113 -0
  87. dcscope/gui/widgets/so_colorbaritem.py +29 -0
  88. dcscope/gui/widgets/wait_cursor.py +33 -0
  89. dcscope/idiom.py +26 -0
  90. dcscope/img/__init__.py +2 -0
  91. dcscope/img/icon-theme/breeze/COPYING-ICONS +209 -0
  92. dcscope/img/icon-theme/breeze/COPYING.LIB +510 -0
  93. dcscope/img/icon-theme/breeze/README +5 -0
  94. dcscope/img/icon-theme/breeze/actions/16/application-exit.svg +17 -0
  95. dcscope/img/icon-theme/breeze/actions/16/code-context.svg +13 -0
  96. dcscope/img/icon-theme/breeze/actions/16/dialog-cancel.svg +13 -0
  97. dcscope/img/icon-theme/breeze/actions/16/dialog-close.svg +17 -0
  98. dcscope/img/icon-theme/breeze/actions/16/dialog-messages.svg +13 -0
  99. dcscope/img/icon-theme/breeze/actions/16/dialog-ok-apply.svg +13 -0
  100. dcscope/img/icon-theme/breeze/actions/16/dialog-ok.svg +13 -0
  101. dcscope/img/icon-theme/breeze/actions/16/document-open-folder.svg +13 -0
  102. dcscope/img/icon-theme/breeze/actions/16/document-open.svg +13 -0
  103. dcscope/img/icon-theme/breeze/actions/16/document-save.svg +13 -0
  104. dcscope/img/icon-theme/breeze/actions/16/documentinfo.svg +12 -0
  105. dcscope/img/icon-theme/breeze/actions/16/draw-watercolor.svg +13 -0
  106. dcscope/img/icon-theme/breeze/actions/16/edit-clear-all.svg +13 -0
  107. dcscope/img/icon-theme/breeze/actions/16/edit-clear.svg +13 -0
  108. dcscope/img/icon-theme/breeze/actions/16/edit-paste.svg +13 -0
  109. dcscope/img/icon-theme/breeze/actions/16/globe.svg +16 -0
  110. dcscope/img/icon-theme/breeze/actions/16/gtk-preferences.svg +13 -0
  111. dcscope/img/icon-theme/breeze/actions/16/list-add.svg +13 -0
  112. dcscope/img/icon-theme/breeze/actions/16/messagebox_warning.svg +20 -0
  113. dcscope/img/icon-theme/breeze/actions/16/object-columns.svg +13 -0
  114. dcscope/img/icon-theme/breeze/actions/16/object-order-lower.svg +13 -0
  115. dcscope/img/icon-theme/breeze/actions/16/object-rows.svg +13 -0
  116. dcscope/img/icon-theme/breeze/actions/16/office-chart-line-stacked.svg +13 -0
  117. dcscope/img/icon-theme/breeze/actions/16/office-chart-ring.svg +13 -0
  118. dcscope/img/icon-theme/breeze/actions/16/office-chart-scatter.svg +13 -0
  119. dcscope/img/icon-theme/breeze/actions/16/path-mode-polyline.svg +13 -0
  120. dcscope/img/icon-theme/breeze/actions/16/preferences-activities.svg +13 -0
  121. dcscope/img/icon-theme/breeze/actions/16/remove.svg +10 -0
  122. dcscope/img/icon-theme/breeze/actions/16/search.svg +13 -0
  123. dcscope/img/icon-theme/breeze/actions/16/show-grid.svg +13 -0
  124. dcscope/img/icon-theme/breeze/actions/16/special_paste.svg +13 -0
  125. dcscope/img/icon-theme/breeze/actions/16/tools-wizard.svg +13 -0
  126. dcscope/img/icon-theme/breeze/actions/16/view-calendar-list.svg +13 -0
  127. dcscope/img/icon-theme/breeze/actions/16/view-filter.svg +13 -0
  128. dcscope/img/icon-theme/breeze/actions/16/view-list-tree.svg +13 -0
  129. dcscope/img/icon-theme/breeze/actions/16/view-statistics.svg +13 -0
  130. dcscope/img/icon-theme/breeze/actions/16/visibility.svg +21 -0
  131. dcscope/img/icon-theme/breeze/actions/22/application-exit.svg +13 -0
  132. dcscope/img/icon-theme/breeze/actions/22/code-context.svg +14 -0
  133. dcscope/img/icon-theme/breeze/actions/22/dialog-cancel.svg +14 -0
  134. dcscope/img/icon-theme/breeze/actions/22/dialog-close.svg +10 -0
  135. dcscope/img/icon-theme/breeze/actions/22/dialog-messages.svg +14 -0
  136. dcscope/img/icon-theme/breeze/actions/22/dialog-ok-apply.svg +14 -0
  137. dcscope/img/icon-theme/breeze/actions/22/dialog-ok.svg +14 -0
  138. dcscope/img/icon-theme/breeze/actions/22/document-open-folder.svg +14 -0
  139. dcscope/img/icon-theme/breeze/actions/22/document-open.svg +14 -0
  140. dcscope/img/icon-theme/breeze/actions/22/document-save.svg +14 -0
  141. dcscope/img/icon-theme/breeze/actions/22/documentinfo.svg +14 -0
  142. dcscope/img/icon-theme/breeze/actions/22/draw-watercolor.svg +14 -0
  143. dcscope/img/icon-theme/breeze/actions/22/edit-clear-all.svg +14 -0
  144. dcscope/img/icon-theme/breeze/actions/22/edit-clear.svg +14 -0
  145. dcscope/img/icon-theme/breeze/actions/22/edit-paste.svg +14 -0
  146. dcscope/img/icon-theme/breeze/actions/22/globe.svg +12 -0
  147. dcscope/img/icon-theme/breeze/actions/22/gtk-preferences.svg +13 -0
  148. dcscope/img/icon-theme/breeze/actions/22/list-add.svg +14 -0
  149. dcscope/img/icon-theme/breeze/actions/22/messagebox_warning.svg +17 -0
  150. dcscope/img/icon-theme/breeze/actions/22/object-columns.svg +14 -0
  151. dcscope/img/icon-theme/breeze/actions/22/object-order-lower.svg +17 -0
  152. dcscope/img/icon-theme/breeze/actions/22/object-rows.svg +17 -0
  153. dcscope/img/icon-theme/breeze/actions/22/office-chart-line-stacked.svg +17 -0
  154. dcscope/img/icon-theme/breeze/actions/22/office-chart-ring.svg +17 -0
  155. dcscope/img/icon-theme/breeze/actions/22/office-chart-scatter.svg +17 -0
  156. dcscope/img/icon-theme/breeze/actions/22/path-mode-polyline.svg +17 -0
  157. dcscope/img/icon-theme/breeze/actions/22/preferences-activities.svg +14 -0
  158. dcscope/img/icon-theme/breeze/actions/22/remove.svg +10 -0
  159. dcscope/img/icon-theme/breeze/actions/22/special_paste.svg +14 -0
  160. dcscope/img/icon-theme/breeze/actions/22/tools-wizard.svg +14 -0
  161. dcscope/img/icon-theme/breeze/actions/22/view-calendar-list.svg +14 -0
  162. dcscope/img/icon-theme/breeze/actions/22/view-filter.svg +14 -0
  163. dcscope/img/icon-theme/breeze/actions/22/view-list-tree.svg +14 -0
  164. dcscope/img/icon-theme/breeze/actions/22/view-statistics.svg +14 -0
  165. dcscope/img/icon-theme/breeze/actions/22/visibility.svg +14 -0
  166. dcscope/img/icon-theme/breeze/actions/24/application-exit.svg +12 -0
  167. dcscope/img/icon-theme/breeze/actions/24/code-context.svg +12 -0
  168. dcscope/img/icon-theme/breeze/actions/24/dialog-cancel.svg +12 -0
  169. dcscope/img/icon-theme/breeze/actions/24/dialog-close.svg +10 -0
  170. dcscope/img/icon-theme/breeze/actions/24/dialog-messages.svg +12 -0
  171. dcscope/img/icon-theme/breeze/actions/24/dialog-ok-apply.svg +12 -0
  172. dcscope/img/icon-theme/breeze/actions/24/dialog-ok.svg +14 -0
  173. dcscope/img/icon-theme/breeze/actions/24/document-open-folder.svg +12 -0
  174. dcscope/img/icon-theme/breeze/actions/24/document-open.svg +12 -0
  175. dcscope/img/icon-theme/breeze/actions/24/document-save.svg +12 -0
  176. dcscope/img/icon-theme/breeze/actions/24/documentinfo.svg +14 -0
  177. dcscope/img/icon-theme/breeze/actions/24/draw-watercolor.svg +12 -0
  178. dcscope/img/icon-theme/breeze/actions/24/edit-clear-all.svg +14 -0
  179. dcscope/img/icon-theme/breeze/actions/24/edit-clear.svg +12 -0
  180. dcscope/img/icon-theme/breeze/actions/24/edit-paste.svg +12 -0
  181. dcscope/img/icon-theme/breeze/actions/24/globe.svg +14 -0
  182. dcscope/img/icon-theme/breeze/actions/24/gtk-preferences.svg +13 -0
  183. dcscope/img/icon-theme/breeze/actions/24/list-add.svg +12 -0
  184. dcscope/img/icon-theme/breeze/actions/24/messagebox_warning.svg +13 -0
  185. dcscope/img/icon-theme/breeze/actions/24/object-columns.svg +12 -0
  186. dcscope/img/icon-theme/breeze/actions/24/object-order-lower.svg +15 -0
  187. dcscope/img/icon-theme/breeze/actions/24/object-rows.svg +15 -0
  188. dcscope/img/icon-theme/breeze/actions/24/office-chart-line-stacked.svg +15 -0
  189. dcscope/img/icon-theme/breeze/actions/24/office-chart-ring.svg +15 -0
  190. dcscope/img/icon-theme/breeze/actions/24/office-chart-scatter.svg +15 -0
  191. dcscope/img/icon-theme/breeze/actions/24/path-mode-polyline.svg +15 -0
  192. dcscope/img/icon-theme/breeze/actions/24/preferences-activities.svg +13 -0
  193. dcscope/img/icon-theme/breeze/actions/24/remove.svg +10 -0
  194. dcscope/img/icon-theme/breeze/actions/24/special_paste.svg +12 -0
  195. dcscope/img/icon-theme/breeze/actions/24/tools-wizard.svg +12 -0
  196. dcscope/img/icon-theme/breeze/actions/24/view-calendar-list.svg +12 -0
  197. dcscope/img/icon-theme/breeze/actions/24/view-filter.svg +12 -0
  198. dcscope/img/icon-theme/breeze/actions/24/view-list-tree.svg +12 -0
  199. dcscope/img/icon-theme/breeze/actions/24/view-statistics.svg +12 -0
  200. dcscope/img/icon-theme/breeze/actions/24/visibility.svg +14 -0
  201. dcscope/img/icon-theme/breeze/actions/32/application-exit.svg +8 -0
  202. dcscope/img/icon-theme/breeze/actions/32/dialog-cancel.svg +13 -0
  203. dcscope/img/icon-theme/breeze/actions/32/dialog-messages.svg +13 -0
  204. dcscope/img/icon-theme/breeze/actions/32/dialog-ok-apply.svg +1 -0
  205. dcscope/img/icon-theme/breeze/actions/32/dialog-ok.svg +1 -0
  206. dcscope/img/icon-theme/breeze/actions/32/document-open-folder.svg +13 -0
  207. dcscope/img/icon-theme/breeze/actions/32/document-open.svg +13 -0
  208. dcscope/img/icon-theme/breeze/actions/32/document-save.svg +18 -0
  209. dcscope/img/icon-theme/breeze/actions/32/gtk-preferences.svg +17 -0
  210. dcscope/img/icon-theme/breeze/actions/32/object-order-lower.svg +18 -0
  211. dcscope/img/icon-theme/breeze/actions/32/view-filter.svg +18 -0
  212. dcscope/img/icon-theme/breeze/actions/32/view-list-tree.svg +18 -0
  213. dcscope/img/icon-theme/breeze/places/16/folder-cloud.svg +13 -0
  214. dcscope/img/icon-theme/breeze/places/16/folder.svg +13 -0
  215. dcscope/img/icon-theme/breeze/places/22/folder-cloud.svg +13 -0
  216. dcscope/img/icon-theme/breeze/places/22/folder.svg +13 -0
  217. dcscope/img/icon-theme/breeze/places/24/folder-cloud.svg +12 -0
  218. dcscope/img/icon-theme/breeze/places/24/folder.svg +12 -0
  219. dcscope/img/icon-theme/breeze/places/32/folder-cloud.svg +35 -0
  220. dcscope/img/icon-theme/breeze/places/32/folder.svg +30 -0
  221. dcscope/img/icon-theme/breeze/places/64/folder-cloud.svg +35 -0
  222. dcscope/img/icon-theme/breeze/places/64/folder.svg +30 -0
  223. dcscope/img/icon-theme/breeze/status/16/dialog-error.svg +9 -0
  224. dcscope/img/icon-theme/breeze/status/16/dialog-information.svg +9 -0
  225. dcscope/img/icon-theme/breeze/status/16/dialog-question.svg +7 -0
  226. dcscope/img/icon-theme/breeze/status/16/dialog-warning.svg +9 -0
  227. dcscope/img/icon-theme/breeze/status/22/dialog-error.svg +9 -0
  228. dcscope/img/icon-theme/breeze/status/22/dialog-information.svg +9 -0
  229. dcscope/img/icon-theme/breeze/status/22/dialog-question.svg +7 -0
  230. dcscope/img/icon-theme/breeze/status/22/dialog-warning.svg +9 -0
  231. dcscope/img/icon-theme/breeze/status/24/dialog-error.svg +13 -0
  232. dcscope/img/icon-theme/breeze/status/24/dialog-information.svg +13 -0
  233. dcscope/img/icon-theme/breeze/status/24/dialog-question.svg +9 -0
  234. dcscope/img/icon-theme/breeze/status/24/dialog-warning.svg +1 -0
  235. dcscope/img/icon-theme/breeze/status/64/dialog-error.svg +25 -0
  236. dcscope/img/icon-theme/breeze/status/64/dialog-information.svg +25 -0
  237. dcscope/img/icon-theme/breeze/status/64/dialog-question.svg +25 -0
  238. dcscope/img/icon-theme/breeze/status/64/dialog-warning.svg +25 -0
  239. dcscope/img/icon-theme/collect_icons.py +124 -0
  240. dcscope/img/icon-theme/dcscope/dcor.png +0 -0
  241. dcscope/img/icon-theme/dcscope/edit-copy-anew.svg +13 -0
  242. dcscope/img/icon-theme/dcscope/emodulus.svg +69 -0
  243. dcscope/img/icon-theme/dcscope/filter_ray.svg +54 -0
  244. dcscope/img/icon-theme/dcscope/region_channel.svg +86 -0
  245. dcscope/img/icon-theme/dcscope/region_reservoir.svg +89 -0
  246. dcscope/img/icon-theme/dcscope/rlang.svg +108 -0
  247. dcscope/img/icon-theme/dcscope/statistical_significance.svg +106 -0
  248. dcscope/img/icon-theme/index.theme +81 -0
  249. dcscope/img/icon.png +0 -0
  250. dcscope/img/icon.svg +73 -0
  251. dcscope/img/splash.png +0 -0
  252. dcscope/meta_tool.py +143 -0
  253. dcscope/pipeline/__init__.py +5 -0
  254. dcscope/pipeline/core.py +632 -0
  255. dcscope/pipeline/dataslot.py +270 -0
  256. dcscope/pipeline/filter.py +161 -0
  257. dcscope/pipeline/filter_ray.py +170 -0
  258. dcscope/pipeline/plot.py +187 -0
  259. dcscope/plot_cache.py +79 -0
  260. dcscope/session.py +379 -0
  261. dcscope/util.py +34 -0
  262. dcscope-2.22.1.dist-info/METADATA +95 -0
  263. dcscope-2.22.1.dist-info/RECORD +267 -0
  264. dcscope-2.22.1.dist-info/WHEEL +5 -0
  265. dcscope-2.22.1.dist-info/entry_points.txt +2 -0
  266. dcscope-2.22.1.dist-info/licenses/LICENSE +621 -0
  267. dcscope-2.22.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,504 @@
1
+ import copy
2
+ import importlib.resources
3
+ import warnings
4
+
5
+ import dclab
6
+ from dclab.features.emodulus.viscosity import (
7
+ ALIAS_MEDIA, KNOWN_MEDIA, TemperatureOutOfRangeWarning
8
+ )
9
+ import numpy as np
10
+ from PyQt6 import uic, QtCore, QtWidgets
11
+
12
+ from ... import meta_tool
13
+ from ...pipeline import Dataslot
14
+
15
+ from .dlg_slot_reorder import DlgSlotReorder
16
+
17
+
18
+ class SlotPanel(QtWidgets.QWidget):
19
+ #: Emitted when a dcscope.pipeline.Dataslot is to be changed
20
+ slot_changed = QtCore.pyqtSignal(dict)
21
+ #: Emitted when the pipeline is to be changed
22
+ pipeline_changed = QtCore.pyqtSignal(dict)
23
+
24
+ def __init__(self, *args, **kwargs):
25
+ super(SlotPanel, self).__init__(*args, **kwargs)
26
+ ref = importlib.resources.files(
27
+ "dcscope.gui.analysis") / "ana_slot.ui"
28
+ with importlib.resources.as_file(ref) as path_ui:
29
+ uic.loadUi(path_ui, self)
30
+
31
+ # current DCscope pipeline
32
+ self._pipeline = None
33
+ # signals
34
+ self.toolButton_reorder.clicked.connect(self.on_reorder_slots)
35
+ self.toolButton_anew.clicked.connect(self.on_anew_slot)
36
+ self.toolButton_duplicate.clicked.connect(self.on_duplicate_slot)
37
+ self.toolButton_remove.clicked.connect(self.on_remove_slot)
38
+ self.pushButton_apply.clicked.connect(self.write_slot)
39
+ self.pushButton_reset.clicked.connect(self.update_content)
40
+ self.comboBox_slots.currentIndexChanged.connect(self.update_content)
41
+ self.comboBox_medium.currentIndexChanged.connect(self.on_ui_changed)
42
+ self.comboBox_temp.currentIndexChanged.connect(self.on_ui_changed)
43
+ self.comboBox_visc_model.currentIndexChanged.connect(
44
+ self.on_ui_changed)
45
+ self.doubleSpinBox_temp.valueChanged.connect(self.on_ui_changed)
46
+ # init
47
+ self._update_emodulus_medium_choices()
48
+ self._update_emodulus_temp_choices()
49
+ self._update_emodulus_lut_choices()
50
+ self._update_emodulus_visc_model_choices()
51
+
52
+ self.update_content()
53
+
54
+ def read_pipeline_state(self):
55
+ slot_state = self.current_slot_state
56
+ if self.comboBox_temp.currentData() in ["manual", "config"]:
57
+ emod_temp = self.doubleSpinBox_temp.value()
58
+ else:
59
+ emod_temp = np.nan
60
+ if self.comboBox_medium.currentData() in KNOWN_MEDIA:
61
+ emod_visc = np.nan # viscosity computed for known medium
62
+ scenario = self.comboBox_temp.currentData()
63
+ elif self.comboBox_medium.currentData() == "unknown":
64
+ emod_visc = np.nan # viscosity not defined
65
+ scenario = None
66
+ else: # "other", user-defined medium
67
+ emod_visc = self.doubleSpinBox_visc.value() # user input
68
+ scenario = None
69
+ emod_visc_model = self.comboBox_visc_model.currentData()
70
+ emod_select_lut = self.comboBox_lut.currentText()
71
+ state = {
72
+ "identifier": slot_state["identifier"],
73
+ "name": self.lineEdit_name.text(),
74
+ "path": slot_state["path"],
75
+ "color": self.pushButton_color.color().name(),
76
+ "slot used": self.checkBox_use.isChecked(),
77
+ "fl names": {"FL-1": self.lineEdit_fl1.text(),
78
+ "FL-2": self.lineEdit_fl2.text(),
79
+ "FL-3": self.lineEdit_fl3.text(),
80
+ },
81
+ "crosstalk": {
82
+ "crosstalk fl12": self.doubleSpinBox_ct12.value(),
83
+ "crosstalk fl13": self.doubleSpinBox_ct13.value(),
84
+ "crosstalk fl21": self.doubleSpinBox_ct21.value(),
85
+ "crosstalk fl23": self.doubleSpinBox_ct23.value(),
86
+ "crosstalk fl31": self.doubleSpinBox_ct31.value(),
87
+ "crosstalk fl32": self.doubleSpinBox_ct32.value(),
88
+ },
89
+ "emodulus": {
90
+ "emodulus enabled": slot_state["emodulus"]["emodulus enabled"],
91
+ "emodulus lut": emod_select_lut,
92
+ # It is ok if we have user-defined strings here, because
93
+ # only media in KNOWN_MEDIA are passed to dclab in the end.
94
+ "emodulus medium": self.comboBox_medium.currentData(),
95
+ "emodulus scenario": scenario,
96
+ "emodulus temperature": emod_temp,
97
+ "emodulus viscosity": emod_visc,
98
+ "emodulus viscosity model": emod_visc_model,
99
+ }
100
+ }
101
+ return state
102
+
103
+ def write_pipeline_state(self, state):
104
+ cur_state = self.current_slot_state
105
+ if cur_state["identifier"] != state["identifier"]:
106
+ raise ValueError("Slot identifier mismatch!")
107
+ self.lineEdit_name.setText(state["name"])
108
+ self.lineEdit_path.setText(str(state["path"]))
109
+ self.pushButton_color.setColor(state["color"])
110
+ self.lineEdit_fl1.setText(state["fl names"]["FL-1"])
111
+ self.lineEdit_fl2.setText(state["fl names"]["FL-2"])
112
+ self.lineEdit_fl3.setText(state["fl names"]["FL-3"])
113
+ self.checkBox_use.setChecked(state["slot used"])
114
+ # crosstalk
115
+ crosstalk = state["crosstalk"]
116
+ self.doubleSpinBox_ct12.setValue(crosstalk["crosstalk fl12"])
117
+ self.doubleSpinBox_ct13.setValue(crosstalk["crosstalk fl13"])
118
+ self.doubleSpinBox_ct21.setValue(crosstalk["crosstalk fl21"])
119
+ self.doubleSpinBox_ct23.setValue(crosstalk["crosstalk fl23"])
120
+ self.doubleSpinBox_ct31.setValue(crosstalk["crosstalk fl31"])
121
+ self.doubleSpinBox_ct32.setValue(crosstalk["crosstalk fl32"])
122
+ # emodulus
123
+ # updating the medium/temperature choices has to be done first,
124
+ # because self.comboBox_medium triggers the function on_ui_changed.
125
+ self._update_emodulus_medium_choices()
126
+ self._update_emodulus_temp_choices()
127
+ emodulus = state["emodulus"]
128
+ self.groupBox_emod.setVisible(emodulus["emodulus enabled"])
129
+ idx_med = self.comboBox_medium.findData(emodulus["emodulus medium"])
130
+ if idx_med == -1: # empty medium string
131
+ idx_med = self.comboBox_medium.findData("other")
132
+ self.comboBox_medium.setCurrentIndex(idx_med)
133
+ cfg = meta_tool.get_rtdc_config(state["path"])
134
+ if "medium" in cfg["setup"] and cfg["setup"]["medium"] in KNOWN_MEDIA:
135
+ self.comboBox_medium.setEnabled(False) # prevent modification
136
+ else:
137
+ self.comboBox_medium.setEnabled(True) # user-defined
138
+ # https://dclab.readthedocs.io/en/latest/sec_av_emodulus.html
139
+ scenario = emodulus.get("emodulus scenario", "manual")
140
+ if scenario:
141
+ idx_scen = self.comboBox_temp.findData(scenario)
142
+ self.comboBox_temp.blockSignals(True)
143
+ self.comboBox_temp.setCurrentIndex(idx_scen)
144
+ self.comboBox_temp.blockSignals(False)
145
+
146
+ idx_vm = self.comboBox_visc_model.findData(
147
+ # use defaults from previous session (Herold-2107)
148
+ emodulus.get("emodulus viscosity model", "herold-2017"))
149
+
150
+ self.comboBox_visc_model.setCurrentIndex(idx_vm)
151
+ # Set current state of the emodulus lut
152
+ idx_lut = self.comboBox_lut.findData(emodulus.get("emodulus lut", ""))
153
+ self.comboBox_lut.setCurrentIndex(idx_lut)
154
+ # This has to be done after setting the scenario
155
+ # (otherwise it might be overridden in the frontend)
156
+ self.doubleSpinBox_temp.setValue(emodulus["emodulus temperature"])
157
+ self.doubleSpinBox_visc.setValue(emodulus["emodulus viscosity"])
158
+
159
+ # Fluorescence data visibility
160
+ features = meta_tool.get_rtdc_features(state["path"])
161
+ hasfl1 = "fl1_max" in features
162
+ hasfl2 = "fl2_max" in features
163
+ hasfl3 = "fl3_max" in features
164
+
165
+ # labels
166
+ self.lineEdit_fl1.setVisible(hasfl1)
167
+ self.label_fl1.setVisible(hasfl1)
168
+ self.lineEdit_fl2.setVisible(hasfl2)
169
+ self.label_fl2.setVisible(hasfl2)
170
+ self.lineEdit_fl3.setVisible(hasfl3)
171
+ self.label_fl3.setVisible(hasfl3)
172
+
173
+ # crosstalk matrix
174
+ self.label_from_fl1.setVisible(hasfl1 & hasfl2 | hasfl1 & hasfl3)
175
+ self.label_from_fl2.setVisible(hasfl2 & hasfl1 | hasfl2 & hasfl3)
176
+ self.label_from_fl3.setVisible(hasfl3 & hasfl1 | hasfl3 & hasfl2)
177
+ self.label_to_fl1.setVisible(hasfl1 & hasfl2 | hasfl1 & hasfl3)
178
+ self.label_to_fl2.setVisible(hasfl2 & hasfl1 | hasfl2 & hasfl3)
179
+ self.label_to_fl3.setVisible(hasfl3 & hasfl1 | hasfl3 & hasfl2)
180
+ self.doubleSpinBox_ct12.setVisible(hasfl1 & hasfl2)
181
+ self.doubleSpinBox_ct13.setVisible(hasfl1 & hasfl3)
182
+ self.doubleSpinBox_ct21.setVisible(hasfl2 & hasfl1)
183
+ self.doubleSpinBox_ct23.setVisible(hasfl2 & hasfl3)
184
+ self.doubleSpinBox_ct31.setVisible(hasfl3 & hasfl1)
185
+ self.doubleSpinBox_ct32.setVisible(hasfl3 & hasfl2)
186
+
187
+ self.groupBox_fl_labels.setVisible(hasfl1 | hasfl2 | hasfl3)
188
+ self.groupBox_fl_cross.setVisible(hasfl1 | hasfl2 | hasfl3)
189
+
190
+ @staticmethod
191
+ def get_dataset_choices_medium(ds):
192
+ """Return the choices for the medium selection
193
+
194
+ Parameters
195
+ ----------
196
+ ds: RTDCBase
197
+ Dataset
198
+
199
+ Returns
200
+ -------
201
+ choices: list
202
+ List of [title, identifier]
203
+ """
204
+ if ds:
205
+ medium = ds.config.get("setup", {}).get("medium", "").strip()
206
+ if not medium: # empty medium string
207
+ medium = "other"
208
+ else:
209
+ medium = "undefined"
210
+ if medium in KNOWN_MEDIA:
211
+ valid_media = [medium]
212
+ else:
213
+ valid_media = KNOWN_MEDIA + [medium, "other", "undefined"]
214
+ choices = []
215
+ for vm in valid_media:
216
+ if vm == "CellCarrierB":
217
+ name = "CellCarrier B" # [sic]
218
+ else:
219
+ name = vm
220
+ choices.append([name, vm])
221
+ return choices
222
+
223
+ @staticmethod
224
+ def get_dataset_choices_temperature(ds):
225
+ """Return the choices for the temperature selection
226
+
227
+ Parameters
228
+ ----------
229
+ ds: RTDCBase
230
+ Dataset
231
+
232
+ Returns
233
+ -------
234
+ choices: list
235
+ List of [title, identifier]
236
+ """
237
+ choices = []
238
+ if ds is not None:
239
+ if "temp" in ds:
240
+ choices.append(["From feature", "feature"])
241
+ if "temperature" in ds.config["setup"]:
242
+ choices.append(["From meta data", "config"])
243
+ choices.append(["Manual", "manual"])
244
+ return choices
245
+
246
+ def _update_emodulus_medium_choices(self):
247
+ """update currently available medium choices for YM
248
+
249
+ Signals are blocked.
250
+ """
251
+ self.comboBox_medium.blockSignals(True)
252
+ self.comboBox_medium.clear()
253
+ ds = self.get_dataset()
254
+ choices = self.get_dataset_choices_medium(ds)
255
+ for name, data in choices:
256
+ self.comboBox_medium.addItem(name, data)
257
+ self.comboBox_medium.blockSignals(False)
258
+
259
+ def _update_emodulus_temp_choices(self):
260
+ """pupdate temperature choices for YM
261
+
262
+ The previous selection is preserved. Signals are blocked.
263
+ """
264
+ self.comboBox_temp.blockSignals(True)
265
+ cursel = self.comboBox_temp.currentData()
266
+ self.comboBox_temp.clear()
267
+ ds = self.get_dataset()
268
+ choices = self.get_dataset_choices_temperature(ds)
269
+ for name, data in choices:
270
+ self.comboBox_temp.addItem(name, data)
271
+ idx = self.comboBox_temp.findData(cursel)
272
+ self.comboBox_temp.setCurrentIndex(idx)
273
+ self.comboBox_temp.blockSignals(False)
274
+
275
+ def _update_emodulus_lut_choices(self):
276
+ """update currently available LUT choices for YM
277
+
278
+ The previous selection is preserved. Signals are blocked.
279
+ """
280
+ self.comboBox_lut.blockSignals(True)
281
+ cursel = self.comboBox_lut.currentData()
282
+ self.comboBox_lut.clear()
283
+ lut_dict = dclab.features.emodulus.load.get_internal_lut_names_dict()
284
+ for lut_id in lut_dict.keys():
285
+ self.comboBox_lut.addItem(lut_id, lut_id)
286
+ idx = self.comboBox_lut.findData(cursel)
287
+ self.comboBox_lut.setCurrentIndex(idx)
288
+ self.comboBox_lut.blockSignals(False)
289
+
290
+ def _update_emodulus_visc_model_choices(self):
291
+ """update currently available viscosity model choices for YM
292
+
293
+ Signals are blocked.
294
+ """
295
+ self.comboBox_visc_model.blockSignals(True)
296
+ self.comboBox_visc_model.clear()
297
+
298
+ choices = {"Herold (2017)": "herold-2017",
299
+ "Buyukurganci (2022)": "buyukurganci-2022"}
300
+ for name, data in choices.items():
301
+ self.comboBox_visc_model.addItem(name, data)
302
+ self.comboBox_visc_model.blockSignals(False)
303
+
304
+ @property
305
+ def current_slot_state(self):
306
+ if self.slot_ids:
307
+ slot_index = self.comboBox_slots.currentIndex()
308
+ slot_state = self.pipeline.slots[slot_index].__getstate__()
309
+ else:
310
+ slot_state = None
311
+ return slot_state
312
+
313
+ @property
314
+ def pipeline(self):
315
+ return self._pipeline
316
+
317
+ @property
318
+ def slot_ids(self):
319
+ """List of slot identifiers"""
320
+ if self.pipeline is None:
321
+ return []
322
+ else:
323
+ return [slot.identifier for slot in self.pipeline.slots]
324
+
325
+ @property
326
+ def slot_names(self):
327
+ """List of slot names"""
328
+ if self.pipeline is None:
329
+ return []
330
+ else:
331
+ return [slot.name for slot in self.pipeline.slots]
332
+
333
+ def get_dataset(self):
334
+ """Return dataset associated with the current slot index
335
+
336
+ Returns None if there is no dataset in the pipeline.
337
+ """
338
+ if self.pipeline is not None and self.pipeline.slots:
339
+ slot_index = self.comboBox_slots.currentIndex()
340
+ slot = self.pipeline.slots[slot_index]
341
+ return slot.get_dataset()
342
+ else:
343
+ return None
344
+
345
+ @QtCore.pyqtSlot()
346
+ def on_anew_slot(self):
347
+ slot_state = self.read_pipeline_state()
348
+ new_slot = Dataslot(slot_state["path"])
349
+ pos = self.pipeline.slot_ids.index(slot_state["identifier"])
350
+ self.pipeline.add_slot(new_slot, index=pos + 1)
351
+ state = self.pipeline.__getstate__()
352
+ self.pipeline_changed.emit(state)
353
+
354
+ @QtCore.pyqtSlot()
355
+ def on_duplicate_slot(self):
356
+ # determine the new filter state
357
+ slot_state = self.read_pipeline_state()
358
+ new_state = copy.deepcopy(slot_state)
359
+ new_slot = Dataslot(slot_state["path"])
360
+ new_state["identifier"] = new_slot.identifier
361
+ new_state["name"] = new_slot.name
362
+ new_slot.__setstate__(new_state)
363
+ # determine the filter position
364
+ pos = self.pipeline.slot_ids.index(slot_state["identifier"])
365
+ self.pipeline.add_slot(new_slot, index=pos + 1)
366
+ state = self.pipeline.__getstate__()
367
+ self.pipeline_changed.emit(state)
368
+
369
+ @QtCore.pyqtSlot()
370
+ def on_remove_slot(self):
371
+ slot_state = self.read_pipeline_state()
372
+ self.pipeline.remove_slot(slot_state["identifier"])
373
+ state = self.pipeline.__getstate__()
374
+ self.pipeline_changed.emit(state)
375
+
376
+ @QtCore.pyqtSlot()
377
+ def on_reorder_slots(self):
378
+ """Open dialog for reordering slots"""
379
+ dlg = DlgSlotReorder(self.pipeline, self)
380
+ dlg.pipeline_changed.connect(self.pipeline_changed)
381
+ dlg.exec()
382
+
383
+ @QtCore.pyqtSlot()
384
+ def on_ui_changed(self):
385
+ """Called when the user modifies the medium or temperature options"""
386
+ medium = self.comboBox_medium.currentData()
387
+ tselec = self.comboBox_temp.currentData()
388
+ medium_key = ALIAS_MEDIA.get(medium, medium)
389
+ visc_model = self.comboBox_visc_model.currentData()
390
+ # Only show model selection if we are dealing with MC-PBS
391
+ self.comboBox_visc_model.setVisible(medium_key.count("MC-PBS"))
392
+ self.doubleSpinBox_visc.setStyleSheet("")
393
+ if medium in KNOWN_MEDIA: # medium registered with dclab
394
+ self.label_temp.setVisible(True)
395
+ self.comboBox_temp.setVisible(True)
396
+ self.doubleSpinBox_temp.setVisible(True)
397
+ self.comboBox_temp.setEnabled(True)
398
+ self.doubleSpinBox_visc.setEnabled(True)
399
+ self.doubleSpinBox_visc.setReadOnly(True)
400
+ if tselec == "manual":
401
+ temperature = self.doubleSpinBox_temp.value()
402
+ self.doubleSpinBox_temp.setEnabled(True)
403
+ self.doubleSpinBox_temp.setReadOnly(False)
404
+ elif tselec == "config":
405
+ # get temperature from dataset
406
+ ds = self.get_dataset()
407
+ temperature = ds.config["setup"]["temperature"]
408
+ self.doubleSpinBox_temp.setEnabled(True)
409
+ self.doubleSpinBox_temp.setReadOnly(True)
410
+ self.doubleSpinBox_temp.setValue(temperature)
411
+ elif tselec == "feature":
412
+ temperature = np.nan
413
+ self.doubleSpinBox_temp.setEnabled(False)
414
+ self.doubleSpinBox_temp.setVisible(False)
415
+ self.doubleSpinBox_temp.setValue(temperature)
416
+ else:
417
+ assert tselec is None, "We should still be in init"
418
+ return
419
+ # For user convenience, also show the viscosity
420
+ if medium in KNOWN_MEDIA and not np.isnan(temperature):
421
+ # compute viscosity
422
+ state = self.read_pipeline_state()
423
+ cfg = meta_tool.get_rtdc_config(state["path"])
424
+ with warnings.catch_warnings(record=True) as w:
425
+ # Warn the user if the temperature is out-of-range
426
+ warnings.simplefilter("always")
427
+ visc = dclab.features.emodulus.viscosity.get_viscosity(
428
+ medium=medium,
429
+ channel_width=cfg["setup"]["channel width"],
430
+ flow_rate=cfg["setup"]["flow rate"],
431
+ temperature=temperature,
432
+ model=visc_model,
433
+ )
434
+ for wi in w:
435
+ if issubclass(wi.category,
436
+ TemperatureOutOfRangeWarning):
437
+ vstyle = "color: #950000; border-width: 2px"
438
+ break
439
+ else:
440
+ vstyle = "border-width: 2px"
441
+ self.doubleSpinBox_visc.setVisible(True)
442
+ self.doubleSpinBox_visc.setEnabled(True)
443
+ self.doubleSpinBox_visc.setReadOnly(True)
444
+ self.doubleSpinBox_visc.setValue(visc)
445
+ self.doubleSpinBox_visc.setStyleSheet(vstyle)
446
+ else:
447
+ self.doubleSpinBox_visc.setEnabled(False)
448
+ self.doubleSpinBox_visc.setVisible(False)
449
+ self.doubleSpinBox_visc.setReadOnly(True)
450
+ self.doubleSpinBox_visc.setValue(np.nan)
451
+ elif medium == "undefined":
452
+ self.label_temp.setVisible(False)
453
+ self.comboBox_temp.setVisible(False)
454
+ self.doubleSpinBox_temp.setVisible(False)
455
+ self.doubleSpinBox_temp.setEnabled(False)
456
+ self.doubleSpinBox_temp.setValue(np.nan)
457
+ self.doubleSpinBox_visc.setValue(np.nan)
458
+ self.doubleSpinBox_visc.setEnabled(False)
459
+ else: # "other" or user-defined
460
+ self.label_temp.setVisible(False)
461
+ self.comboBox_temp.setVisible(False)
462
+ self.doubleSpinBox_temp.setVisible(False)
463
+ self.doubleSpinBox_temp.setEnabled(False)
464
+ self.doubleSpinBox_temp.setValue(np.nan)
465
+ self.doubleSpinBox_visc.setEnabled(True)
466
+ self.doubleSpinBox_visc.setReadOnly(False)
467
+
468
+ def set_pipeline(self, pipeline):
469
+ self._pipeline = pipeline
470
+
471
+ def show_slot(self, slot_id):
472
+ self.update_content(slot_index=self.slot_ids.index(slot_id))
473
+
474
+ def update_content(self, slot_index=None, **kwargs):
475
+ if self.slot_ids:
476
+ # remember the previous slot index and make sure it is sane
477
+ prev_index = self.comboBox_slots.currentIndex()
478
+ if prev_index is None or prev_index < 0:
479
+ prev_index = len(self.slot_ids) - 1
480
+
481
+ self.setEnabled(True)
482
+ # update combobox
483
+ self.comboBox_slots.blockSignals(True)
484
+ if slot_index is None or slot_index < 0:
485
+ slot_index = prev_index
486
+ slot_index = min(slot_index, len(self.slot_ids) - 1)
487
+
488
+ self.comboBox_slots.clear()
489
+ self.comboBox_slots.addItems(self.slot_names)
490
+ self.comboBox_slots.setCurrentIndex(slot_index)
491
+ self.comboBox_slots.blockSignals(False)
492
+ # populate content
493
+ slot_state = self.pipeline.slots[slot_index].__getstate__()
494
+ self.write_pipeline_state(slot_state)
495
+ self.on_ui_changed()
496
+ else:
497
+ self.setEnabled(False)
498
+
499
+ def write_slot(self):
500
+ """Update the dcscope.pipeline.Dataslot instance"""
501
+ slot_state = self.read_pipeline_state()
502
+ # this signal will update the main pipeline which will trigger
503
+ # a call to `set_pipeline` and `update_content`.
504
+ self.slot_changed.emit(slot_state)