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,270 @@
1
+ import copy
2
+ import functools
3
+
4
+ import dclab
5
+ from dclab.features.emodulus.viscosity import KNOWN_MEDIA
6
+ import numpy as np
7
+
8
+ from ..idiom import SLOPING_FEATURES
9
+ from .. import meta_tool
10
+ from ..util import hashobj
11
+
12
+
13
+ class Dataslot(object):
14
+ """Handles datasets in a pipeline"""
15
+ _instance_counter = 0
16
+ _instances = {}
17
+
18
+ def __init__(self, path, identifier=None, name=None):
19
+ Dataslot._instance_counter += 1
20
+ self.path = path
21
+ self._dataset = None
22
+ if identifier is None:
23
+ identifier = "Dataslot_{}".format(Dataslot._instance_counter)
24
+ while identifier in Dataslot._instances:
25
+ Dataslot._instance_counter += 1
26
+ identifier = "Dataslot_{}".format(Dataslot._instance_counter)
27
+ cfg = meta_tool.get_rtdc_config(path)
28
+ if name is None:
29
+ name = cfg["experiment"]["sample"]
30
+ #: session-unique identifier of the slot
31
+ self.identifier = identifier
32
+ #: user-defined name of the slot
33
+ self.name = name
34
+ #: whether to use this slot
35
+ self.slot_used = True
36
+ if identifier in Dataslot._instances:
37
+ raise ValueError("Dataslot with identifier "
38
+ + "'{}' already exists!".format(identifier))
39
+ Dataslot._instances[identifier] = self
40
+ self.color = random_color()
41
+ self.fl_name_dict = {"FL-1": "FL-1",
42
+ "FL-2": "FL-2",
43
+ "FL-3": "FL-3"}
44
+ is_channel = cfg["setup"]["chip region"] == "channel"
45
+ self.config = {
46
+ "crosstalk": {
47
+ # crosstalk
48
+ "crosstalk fl12": 0,
49
+ "crosstalk fl13": 0,
50
+ "crosstalk fl21": 0,
51
+ "crosstalk fl23": 0,
52
+ "crosstalk fl31": 0,
53
+ "crosstalk fl32": 0,
54
+ },
55
+ "emodulus": {
56
+ # emodulus
57
+ "emodulus enabled": is_channel, # False for reservoir
58
+ "emodulus lut": "LE-2D-FEM-19",
59
+ "emodulus medium": "undefined",
60
+ # https://dclab.readthedocs.io/en/latest/sec_av_emodulus.html
61
+ # possible values are:
62
+ # - "feature": scenario A
63
+ # - None: secnario B ("emodulus medium" is "other" or user-def)
64
+ # - "config": scenario C (temperature taken from config)
65
+ # - "manual": scenario C (temperature entered manually)
66
+ "emodulus scenario": "manual",
67
+ "emodulus temperature": np.nan,
68
+ "emodulus viscosity": np.nan,
69
+ "emodulus viscosity model": "buyukurganci-2022",
70
+ }
71
+ }
72
+
73
+ # use the emodulus medium and temperature values as defaults
74
+ ds = self.get_dataset()
75
+ calc = self.config["emodulus"]
76
+ if "medium" in ds.config["setup"]:
77
+ calc["emodulus medium"] = ds.config["setup"]["medium"]
78
+ if "temp" in ds:
79
+ # use the "temp" feature
80
+ calc["emodulus scenario"] = "feature"
81
+ elif "temperature" in ds.config["setup"]:
82
+ # use the average temperature
83
+ calc["emodulus temperature"] = ds.config["setup"]["temperature"]
84
+ calc["emodulus scenario"] = "config"
85
+
86
+ #: data file format
87
+ self.format = ds.format
88
+
89
+ def __getstate__(self):
90
+ state = {"color": self.color,
91
+ "crosstalk": self.config["crosstalk"],
92
+ "emodulus": self.config["emodulus"],
93
+ "fl names": self.fl_name_dict,
94
+ "identifier": self.identifier,
95
+ "name": self.name,
96
+ "path": self.path,
97
+ "slot used": self.slot_used,
98
+ }
99
+ return copy.deepcopy(state)
100
+
101
+ def __repr__(self):
102
+ repre = "<Pipeline Slot '{}' at {}>".format(self.identifier,
103
+ hex(id(self)))
104
+ return repre
105
+
106
+ def __setstate__(self, state):
107
+ if self.identifier != state["identifier"]:
108
+ raise ValueError("Identifier mismatch: '{}' vs. '{}'".format(
109
+ self.identifier, state["identifier"]))
110
+ self.color = state["color"]
111
+ self.config["crosstalk"].update(state["crosstalk"])
112
+ self.config["emodulus"].update(state["emodulus"])
113
+ self.fl_name_dict = state["fl names"]
114
+ self.name = state["name"]
115
+ self.path = state["path"]
116
+ self.slot_used = state["slot used"]
117
+
118
+ @staticmethod
119
+ def get_slot(slot_id):
120
+ """Get the slot with the given identifier"""
121
+ return Dataslot._instances[slot_id]
122
+
123
+ @staticmethod
124
+ def get_instances():
125
+ return Dataslot._instances
126
+
127
+ @staticmethod
128
+ def remove_slot(slot_id):
129
+ """Remove a slot taking care of closing any opened files"""
130
+ slot = Dataslot.get_slot(slot_id)
131
+ ds = slot._dataset
132
+ if ds is not None:
133
+ if isinstance(ds, dclab.rtdc_dataset.RTDC_HDF5):
134
+ ds.h5file.close()
135
+ Dataslot._instances.pop(slot_id)
136
+
137
+ @property
138
+ def hash(self):
139
+ """Return the hash of the slot"""
140
+ return hashobj(self.__getstate__())
141
+
142
+ def _set_emodulus_config(self, dataset):
143
+ """Set the Young's modulus data options
144
+
145
+ The three cases in the dclab docs apply:
146
+ https://dclab.readthedocs.io/en/latest/sec_av_emodulus.html
147
+ """
148
+ # remove any information
149
+ for key in self.config["emodulus"]:
150
+ if key in dataset.config["calculation"]:
151
+ dataset.config["calculation"].pop(key)
152
+
153
+ lut = self.config["emodulus"]["emodulus lut"]
154
+ medium = self.config["emodulus"]["emodulus medium"]
155
+ visc = self.config["emodulus"]["emodulus viscosity"]
156
+ visc_model = self.config["emodulus"]["emodulus viscosity model"]
157
+ scenario = self.config["emodulus"]["emodulus scenario"]
158
+ if scenario == "config":
159
+ # Force the temperature from the dataset metadata
160
+ # (this is a failsafe, the user/developer might not have set it)
161
+ temp = dataset.config["setup"]["temperature"]
162
+ elif scenario == "manual":
163
+ # Only here do we actually need the temperature stored
164
+ temp = self.config["emodulus"]["emodulus temperature"]
165
+ else:
166
+ # Temperature is not used in these scenarios.
167
+ temp = np.nan
168
+
169
+ dataset.config["calculation"]["emodulus lut"] = lut
170
+ # known media
171
+ if medium in dclab.features.emodulus.viscosity.KNOWN_MEDIA:
172
+ dataset.config["calculation"]["emodulus medium"] = medium
173
+ dataset.config["calculation"]["emodulus viscosity model"] = \
174
+ visc_model
175
+ # temperature
176
+ if not np.isnan(temp):
177
+ dataset.config["calculation"]["emodulus temperature"] = temp
178
+ # viscosity
179
+ if medium not in KNOWN_MEDIA and not np.isnan(visc):
180
+ dataset.config["calculation"]["emodulus viscosity"] = visc
181
+ if "emodulus viscosity model" in dataset.config["calculation"]:
182
+ dataset.config["calculation"].pop("emodulus viscosity model")
183
+
184
+ def get_dataset(self):
185
+ """Return the corresponding dataset
186
+
187
+ Returns
188
+ -------
189
+ ds: dclab.RTDCBase
190
+ Loaded dataset
191
+ """
192
+ if self._dataset is None:
193
+ ds = dclab.new_dataset(self.path)
194
+ self._dataset = ds
195
+ else:
196
+ ds = self._dataset
197
+ self.update_dataset(ds)
198
+ return ds
199
+
200
+ def get_sane_spacing_range(self, feat):
201
+ """Return sane contour spacing range for this dataset and feature"""
202
+ return get_sane_contour_spacing_range_for_slot_id(
203
+ self.identifier, feat)
204
+
205
+ def update_dataset(self, dataset):
206
+ """Update the configuration of an instance of RTDCBase
207
+
208
+ This is used to update the configuration for computing
209
+ the Young's modulus and fluorescence crosstalk.
210
+ """
211
+ # emodulus
212
+ self._set_emodulus_config(dataset)
213
+
214
+ # crosstalk
215
+ if np.sum(list(self.config["crosstalk"].values())):
216
+ dataset.config["calculation"].update(self.config["crosstalk"])
217
+ else:
218
+ # remove any information
219
+ for key in self.config["crosstalk"]:
220
+ if key in dataset.config["calculation"]:
221
+ dataset.config["calculation"].pop(key)
222
+
223
+
224
+ @functools.lru_cache(1000)
225
+ def get_sane_contour_spacing_range_for_slot_id(slot_id, feat):
226
+ slot = Dataslot.get_instances()[slot_id]
227
+ ds = slot.get_dataset()
228
+ sp_min, sp_max = get_sane_contour_spacing_range(feat, ds[feat][:])
229
+ return sp_min, sp_max
230
+
231
+
232
+ def get_sane_contour_spacing_range(feat, data):
233
+ """Return a sane range for contour spacing for a feature
234
+
235
+ Parameters
236
+ ----------
237
+ feat: str
238
+ Name of the feature; If this is in :const:`.SLOPING_FEATURES`,
239
+ then spacing takes into account first and last item in `data`.
240
+ Otherwise, the first 10000 elements of `data` are used to
241
+ guess a sane contour spacing.
242
+ data: 1d ndarray
243
+ feature data
244
+ """
245
+ if feat in SLOPING_FEATURES:
246
+ frange = np.abs(data[-1] - data[0])
247
+ if np.isnan(frange) or np.isinf(frange):
248
+ invalid = np.logical_or(np.isinf(data), np.isnan(data))
249
+ data_valid = data[~invalid]
250
+ frange = np.abs(data_valid[-1] - data_valid[0])
251
+ else:
252
+ frange = np.ptp(data[:10000])
253
+ if np.isnan(frange) or np.isinf(frange):
254
+ invalid = np.logical_or(np.isinf(data), np.isnan(data))
255
+ data_valid = data[~invalid]
256
+ frange = np.ptp(data_valid[:10000])
257
+ spmin = frange / 1000
258
+ spmax = frange / 5
259
+ return spmin, spmax
260
+
261
+
262
+ def random_color():
263
+ color = "#"
264
+ for _ in range(3):
265
+ # dark colors (until 200)
266
+ part = hex(np.random.randint(0, 200))[2:]
267
+ if len(part) == 1:
268
+ part += "0"
269
+ color += part
270
+ return color.upper()
@@ -0,0 +1,161 @@
1
+ """Keep record of all filters used"""
2
+ import copy
3
+
4
+ import dclab
5
+
6
+ from ..util import hashobj
7
+
8
+
9
+ class Filter(object):
10
+ """Handles filters in a pipeline"""
11
+ _instance_counter = 0
12
+ _instances = {}
13
+
14
+ def __init__(self, identifier=None, name=None):
15
+ Filter._instance_counter += 1
16
+ if identifier is None:
17
+ identifier = "Filter_{}".format(Filter._instance_counter)
18
+ while identifier in Filter._instances:
19
+ Filter._instance_counter += 1
20
+ identifier = "Filter_{}".format(Filter._instance_counter)
21
+
22
+ if name is None:
23
+ name = identifier
24
+ #: unique identifier of the filter
25
+ self.identifier = identifier
26
+ #: user-defined name of the filter
27
+ self.name = name
28
+ #: general filtering arguments are directly passed to
29
+ #: :class:`dclab.filter.Filter`
30
+ self.general = {"remove invalid events": False, # removes nan/inf
31
+ "enable filters": True, # whether to use the filter
32
+ }
33
+ #: filter for limiting number of events
34
+ self.limit_events = [False, 5000]
35
+ #: box filters with features as keys; each item is a
36
+ #: dictionary with the keys "start", "end", "active"
37
+ self.boxdict = {}
38
+ #: polygon filter list; each item is an identifier of
39
+ #: :class:`dclab.PolygonFilter`
40
+ self.polylist = []
41
+ if identifier in Filter._instances:
42
+ raise ValueError("Filter with identifier "
43
+ + "'{}' already exists!".format(identifier))
44
+ Filter._instances[identifier] = self
45
+
46
+ def __getstate__(self):
47
+ state = {
48
+ "filter used": self.filter_used,
49
+ "identifier": self.identifier,
50
+ "limit events bool": self.limit_events[0],
51
+ "limit events num": self.limit_events[1],
52
+ "name": self.name,
53
+ "remove invalid events": self.general["remove invalid events"],
54
+ "box filters": self.boxdict,
55
+ "polygon filters": sorted(self.polylist),
56
+ }
57
+ return copy.deepcopy(state)
58
+
59
+ def __repr__(self):
60
+ repre = "<Pipeline Filter '{}' at {}>".format(self.identifier,
61
+ hex(id(self)))
62
+ return repre
63
+
64
+ def __setstate__(self, state):
65
+ state = copy.deepcopy(state)
66
+ if self.identifier != state["identifier"]:
67
+ raise ValueError("Identifier mismatch: '{}' vs. '{}'".format(
68
+ self.identifier, state["identifier"]))
69
+ self.general["enable filters"] = state["filter used"]
70
+ self.limit_events = [state["limit events bool"],
71
+ state["limit events num"]]
72
+ self.name = state["name"]
73
+ self.general["remove invalid events"] = state["remove invalid events"]
74
+ self.boxdict = state["box filters"]
75
+ self.polylist = state["polygon filters"]
76
+
77
+ @staticmethod
78
+ def get_filter(identifier):
79
+ """Get the filter with the given identifier.
80
+
81
+ Notes
82
+ -----
83
+ Creates the filter if it does not exist.
84
+ """
85
+ if identifier in Filter._instances:
86
+ f = Filter._instances[identifier]
87
+ else:
88
+ f = Filter(identifier=identifier)
89
+ return f
90
+
91
+ @staticmethod
92
+ def get_instances():
93
+ return Filter._instances
94
+
95
+ @property
96
+ def filter_used(self):
97
+ return self.general["enable filters"]
98
+
99
+ @filter_used.setter
100
+ def filter_used(self, b):
101
+ self.general["enable filters"] = b
102
+
103
+ @property
104
+ def hash(self):
105
+ """Return the hash of the filter"""
106
+ return hashobj(self.__getstate__())
107
+
108
+ def add_box_filter(self, feature, start, end, active=True):
109
+ """Add a box filter"""
110
+ if not dclab.dfn.scalar_feature_exists(feature):
111
+ raise ValueError("Unknown scalar feature: {}".format(feature))
112
+ self.boxdict[feature] = {
113
+ "start": start,
114
+ "end": end,
115
+ "active": active}
116
+
117
+ def apply_to_dataset(self, dataset):
118
+ """Convenience function to apply this filter to a dataset
119
+
120
+ Parameters
121
+ ----------
122
+ dataset: :class:`dclab.RTDCBase`
123
+ Input dataset
124
+
125
+ Returns
126
+ -------
127
+ filtered_dataset: RTDCBase
128
+ Either the input dataset, or a hierarchy child.
129
+
130
+ Notes
131
+ -----
132
+
133
+ """
134
+ self.update_dataset(dataset)
135
+ dataset.apply_filter()
136
+
137
+ def update_dataset(self, dataset):
138
+ """Update the filtering configuration of a dataset
139
+
140
+ Notes
141
+ -----
142
+ Due to the design of the filtering pipeline, it is not
143
+ possible to use manual filters. If any are set, they
144
+ are removed from the filter.
145
+ """
146
+ # remove all previous filters
147
+ dataset.reset_filter()
148
+ cfgfilt = dataset.config["filtering"]
149
+
150
+ # set general options
151
+ cfgfilt.update(self.general)
152
+ cfgfilt["limit events"] = self.limit_events[0] * self.limit_events[1]
153
+ # set box filters
154
+ for feat in self.boxdict:
155
+ if self.boxdict[feat]["active"]:
156
+ cfgfilt["{} min".format(feat)] = self.boxdict[feat]["start"]
157
+ cfgfilt["{} max".format(feat)] = self.boxdict[feat]["end"]
158
+
159
+ # set polygon filters
160
+ for pid in self.polylist:
161
+ dataset.polygon_filter_add(pid)
@@ -0,0 +1,170 @@
1
+ import dclab
2
+
3
+
4
+ class FilterRay(object):
5
+ def __init__(self, slot):
6
+ """Manages filter-based dataset hierarchies
7
+
8
+ Filter rays are used to cache RTDCBase filter-hierarchy
9
+ children.
10
+ """
11
+ #: identifier of the ray (matches the slot)
12
+ self.identifier = slot.identifier
13
+ #: slot defining the ray
14
+ self.slot = slot
15
+ #: list of RTDCBase (hierarchy children)
16
+ self.steps = []
17
+ #: corresponds to hashes of the applied filters
18
+ self.step_hashes = []
19
+ # holds the filters (protected so that users use set_filters)
20
+ self._filters = []
21
+ # used for testing (incremented when the ray is cut)
22
+ self._generation = 0
23
+ # used for checking validity of the ray
24
+ self._slot_hash = "unset"
25
+ self._root_child = None
26
+
27
+ def __repr__(self):
28
+ repre = "<Pipeline Filter Ray '{}' at {}>".format(self.identifier,
29
+ hex(id(self)))
30
+ return repre
31
+
32
+ def _add_step(self, ds, filt):
33
+ """Add a filter step"""
34
+ self.step_hashes.append(filt.hash)
35
+ filt.update_dataset(ds)
36
+ self.steps.append(ds)
37
+ return self._new_child(ds, filt)
38
+
39
+ def _new_child(self, ds, filt=None, apply_filter=False):
40
+ identifier = self.slot.identifier
41
+ if filt is None:
42
+ identifier += "-root"
43
+ else:
44
+ identifier += "-" + filt.identifier + "-child"
45
+ ds = dclab.rtdc_dataset.RTDC_Hierarchy(
46
+ ds, apply_filter=apply_filter, identifier=identifier)
47
+ return ds
48
+
49
+ @property
50
+ def filters(self):
51
+ """filters currently used by the ray
52
+
53
+ Notes
54
+ -----
55
+ This list may not be up-to-date. If you would like to
56
+ get the current list of filters for a dataset, always
57
+ use :func:`.Pipeline.get_filters_for_slot`.
58
+ """
59
+ return self._filters
60
+
61
+ @property
62
+ def root_child(self):
63
+ """This is the first element in self.steps
64
+ (Will return a dataset even if self.steps is empty)
65
+ """
66
+ if self._slot_hash != self.slot.hash:
67
+ # reset everything (e.g. emodulus recipe might have changed)
68
+ self.steps = []
69
+ self.step_hashes = []
70
+ self._root_child = self._new_child(self.slot.get_dataset(),
71
+ apply_filter=True)
72
+ self._slot_hash = self.slot.hash
73
+ return self._root_child
74
+
75
+ def get_final_child(self, rtdc_ds=None, apply_filter=True):
76
+ """Return the final ray child of `rtdc_ds`
77
+
78
+ If `rtdc_ds` is None, then the dataset of the current
79
+ ray (self.slot) is used. If `rtdc_ds` is given, then
80
+ no ray caching is performed and the present ray is not
81
+ modified.
82
+
83
+ This is a convenience function used when the filter ray
84
+ must be applied to a different dataset (not the one in
85
+ `self.slot`). This is used in DCscope when a filter ray
86
+ is applied to other data on disk e.g. when computing
87
+ statistics. For regular use of the filter ray in a
88
+ pipeline, use :func:`get_dataset`.
89
+ """
90
+ filters = self.filters
91
+
92
+ if rtdc_ds is None:
93
+ # normal case
94
+ external = False
95
+ rtdc_ds = self.slot.get_dataset()
96
+ ds = self.root_child
97
+ else:
98
+ # ray is applied to other data
99
+ external = True
100
+ # do not modify rtdc_ds (create a child to work with)
101
+ ds = self._new_child(rtdc_ds, apply_filter=True)
102
+
103
+ # Dear future self,
104
+ #
105
+ # don't even think about filter ray branching.
106
+ #
107
+ # Sincerely,
108
+ # past self
109
+
110
+ if filters:
111
+ # apply all filters
112
+ for ii, filt in enumerate(filters):
113
+ # remember the previous hierarchy parent
114
+ # (ds is always used for the next iteration)
115
+ prev_ds = ds
116
+ if external:
117
+ # do not touch self.steps or self.step_hashes
118
+ filt.update_dataset(ds)
119
+ ds = self._new_child(ds, filt)
120
+ elif len(self.steps) < ii+1:
121
+ # just create a new step
122
+ ds = self._add_step(ds, filt)
123
+ elif filt.hash != self.step_hashes[ii]:
124
+ # the filter ray is changing here;
125
+ # cut it and add a new step
126
+ self.steps = self.steps[:ii]
127
+ self.step_hashes = self.step_hashes[:ii]
128
+ ds = self._add_step(ds, filt)
129
+ self._generation += 1 # for testing
130
+ else:
131
+ # the filters match so far
132
+ if len(self.steps) > ii + 1: # next child exists
133
+ ds = self.steps[ii + 1]
134
+ else: # next child does not exist
135
+ ds = self._new_child(ds, filt)
136
+ # we now have the entire filter pipeline in self.steps
137
+ final_ds = prev_ds
138
+ else:
139
+ final_ds = rtdc_ds
140
+ if apply_filter:
141
+ final_ds.apply_filter()
142
+ return final_ds
143
+
144
+ def get_dataset(self, filters=None, apply_filter=True):
145
+ """Return the dataset that corresponds to applying these filters
146
+
147
+ Parameters
148
+ ----------
149
+ filters: list of Filter or None
150
+ Filters used for computing the dataset hierarchy. If set
151
+ to None, the current filters in `self.filters` are used.
152
+ apply_filter: bool
153
+ Whether to apply all filters and update the metadata of
154
+ the requested dataset. This should be True if you are
155
+ intending to work with the resulting data. You can set
156
+ it to false if you would just like to fetch the dataset,
157
+ apply some more filters and then call `rejuvenate`
158
+ yourself.
159
+ """
160
+ if filters is not None:
161
+ # put the filters in place
162
+ self.set_filters(filters)
163
+ # compute the final hierarchy child
164
+ ds = self.get_final_child(apply_filter=apply_filter)
165
+ return ds
166
+
167
+ def set_filters(self, filters):
168
+ """Set the filters of the current ray"""
169
+ # only take into account active filters
170
+ self._filters = [f for f in filters if f.filter_used]