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,341 @@
1
+ import copy
2
+ import importlib.resources
3
+
4
+ from PyQt6 import uic, QtCore, QtWidgets
5
+
6
+ import dclab
7
+
8
+ from ...pipeline import Filter
9
+
10
+ from ..widgets import RangeControl
11
+ from ... import idiom
12
+
13
+
14
+ class FilterPanel(QtWidgets.QWidget):
15
+ """Filter panel widget
16
+
17
+ The filtering panel visualizes the properties of a
18
+ :class:`dcscope.pipeline.filter.Filter` instance,
19
+ i.e. box filters, list of polygon filters, filter
20
+ name, etc. Their `__getstate__` and `__setstate__`
21
+ functions are compatible.
22
+ """
23
+ #: Emitted when a dcscope.pipeline.Filter is to be changed
24
+ filter_changed = QtCore.pyqtSignal(dict)
25
+ #: Emitted when the pipeline is to be changed
26
+ pipeline_changed = QtCore.pyqtSignal(dict)
27
+ #: Emitted when the user wants to create a new polygon filter
28
+ request_new_polygon_filter = QtCore.pyqtSignal()
29
+
30
+ def __init__(self, *args, **kwargs):
31
+ super(FilterPanel, self).__init__(*args, **kwargs)
32
+ ref = importlib.resources.files(
33
+ "dcscope.gui.analysis") / "ana_filter.ui"
34
+ with importlib.resources.as_file(ref) as path_ui:
35
+ uic.loadUi(path_ui, self)
36
+ # current DCscope pipeline
37
+ self._pipeline = None
38
+ self.setUpdatesEnabled(False)
39
+ #: contains the range widgets for the box filters
40
+ self._box_range_controls = {}
41
+ self._populate_box_filters()
42
+ self._polygon_checkboxes = {}
43
+ self.update_polygon_filters()
44
+ self.toolButton_duplicate.clicked.connect(self.on_duplicate_filter)
45
+ self.toolButton_remove.clicked.connect(self.on_remove_filter)
46
+ self.pushButton_apply.clicked.connect(self.write_filter)
47
+ self.pushButton_reset.clicked.connect(self.update_content)
48
+
49
+ self.comboBox_filters.currentIndexChanged.connect(self.update_content)
50
+ self.toolButton_moreless.clicked.connect(self.on_moreless)
51
+ self.label_box_edit.setVisible(False)
52
+ self._box_edit_view = False
53
+ self.update_content()
54
+ self.setUpdatesEnabled(True)
55
+
56
+ def read_pipeline_state(self):
57
+ state = {
58
+ "filter used": self.checkBox_enable.isChecked(),
59
+ "identifier": self.current_filter.identifier,
60
+ "limit events bool": self.checkBox_limit.isChecked(),
61
+ "limit events num": self.spinBox_limit.value(),
62
+ "name": self.lineEdit_name.text(),
63
+ "remove invalid events": self.checkBox_invalid.isChecked(),
64
+ }
65
+ # box filters
66
+ box = {}
67
+ for feat in self.active_box_features:
68
+ rc = self._box_range_controls[feat]
69
+ box[feat] = rc.read_pipeline_state()
70
+ state["box filters"] = box
71
+ # polygon filters
72
+ pflist = []
73
+ for key in self._polygon_checkboxes:
74
+ if self._polygon_checkboxes[key].isChecked():
75
+ pflist.append(key)
76
+ state["polygon filters"] = pflist
77
+ return state
78
+
79
+ def write_pipeline_state(self, state):
80
+ if self.current_filter.identifier != state["identifier"]:
81
+ raise ValueError("Filter identifier mismatch!")
82
+ self.checkBox_enable.setChecked(state["filter used"])
83
+ self.lineEdit_name.setText(state["name"])
84
+ self.checkBox_limit.setChecked(state["limit events bool"])
85
+ self.spinBox_limit.setValue(state["limit events num"])
86
+ self.checkBox_invalid.setChecked(state["remove invalid events"])
87
+ # box filters
88
+ box = state["box filters"]
89
+ for feat in self._box_range_controls:
90
+ rc = self._box_range_controls[feat]
91
+ if feat in box:
92
+ rc.show()
93
+ rc.write_pipeline_state(box[feat])
94
+ else:
95
+ rc.setActive(False) # uncheck range control (#67)
96
+ rc.hide()
97
+ rc.reset_range()
98
+
99
+ # polygon filters
100
+ pflist = state["polygon filters"]
101
+ for key in self._polygon_checkboxes:
102
+ if key in pflist:
103
+ self._polygon_checkboxes[key].setChecked(True)
104
+ else:
105
+ self._polygon_checkboxes[key].setChecked(False)
106
+
107
+ def _populate_box_filters(self):
108
+ """Dynamically update available pipeline box filters
109
+
110
+ This method can be called multiple times. If called multiple
111
+ times, additional features that were not there before
112
+ (e.g. `ml_score_???`) are added.
113
+ """
114
+ feats, labs = self.get_features_labels()
115
+
116
+ self.verticalLayout_box.setAlignment(QtCore.Qt.AlignmentFlag.AlignTop)
117
+
118
+ for lab, feat in sorted(zip(labs, feats)):
119
+ integer = True if feat in idiom.INTEGER_FEATURES else False
120
+ if feat not in self._box_range_controls:
121
+ # Create the control
122
+ rc = RangeControl(
123
+ self,
124
+ checkbox=False, # checkbox is used in on_moreless
125
+ integer=integer,
126
+ label=lab,
127
+ data=feat)
128
+ rc.setActive(False)
129
+ rc.setVisible(False)
130
+ # Insert the control at the correct position (label-sorted)
131
+ rcf = list(self._box_range_controls.keys())
132
+ rcl = [dclab.dfn.get_feature_label(ft) for ft in rcf]
133
+ index = sorted(rcl + [lab]).index(lab)
134
+ self.verticalLayout_box.insertWidget(index, rc)
135
+ self._box_range_controls[feat] = rc
136
+
137
+ @property
138
+ def active_box_features(self):
139
+ """List of box-filtered features that are active"""
140
+ act = []
141
+ for feat, item in self._box_range_controls.items():
142
+ if item.is_active():
143
+ act.append(feat)
144
+ return act
145
+
146
+ @property
147
+ def current_filter(self):
148
+ if self.filter_ids:
149
+ filt_index = self.comboBox_filters.currentIndex()
150
+ filt_id = self.filter_ids[filt_index]
151
+ filt = Filter.get_instances()[filt_id]
152
+ else:
153
+ filt = None
154
+ return filt
155
+
156
+ @property
157
+ def filter_ids(self):
158
+ """List of filter identifiers"""
159
+ if self.pipeline is not None:
160
+ ids = [filt.identifier for filt in self.pipeline.filters]
161
+ else:
162
+ ids = []
163
+ return ids
164
+
165
+ @property
166
+ def filter_names(self):
167
+ """List of filter names"""
168
+ if self.pipeline is not None:
169
+ nms = [filt.name for filt in self.pipeline.filters]
170
+ else:
171
+ nms = []
172
+ return nms
173
+
174
+ @property
175
+ def pipeline(self):
176
+ return self._pipeline
177
+
178
+ def get_features_labels(self):
179
+ """Wrapper around pipeline with default features if empty"""
180
+ if self.pipeline is not None and self.pipeline.num_slots != 0:
181
+ feats, labs = self.pipeline.get_features(scalar=True,
182
+ label_sort=True,
183
+ ret_labels=True,
184
+ union=True)
185
+ else:
186
+ # fallback (nothing in the pipeline or no pipeline)
187
+ features = dclab.dfn.scalar_feature_names
188
+ labs = [dclab.dfn.get_feature_label(f) for f in features]
189
+ lf = sorted(zip(labs, features))
190
+ feats = [it[1] for it in lf]
191
+ labs = [it[0] for it in lf]
192
+ return feats, labs
193
+
194
+ def on_duplicate_filter(self):
195
+ # determine the new filter state
196
+ filt_state = self.read_pipeline_state()
197
+ new_state = copy.deepcopy(filt_state)
198
+ new_filt = Filter()
199
+ new_state["identifier"] = new_filt.identifier
200
+ new_state["name"] = new_filt.name
201
+ new_filt.__setstate__(new_state)
202
+ # determine the filter position
203
+ pos = self.pipeline.filter_ids.index(filt_state["identifier"])
204
+ self.pipeline.add_filter(new_filt, index=pos+1)
205
+ state = self.pipeline.__getstate__()
206
+ self.pipeline_changed.emit(state)
207
+
208
+ def on_remove_filter(self):
209
+ filt_state = self.read_pipeline_state()
210
+ self.pipeline.remove_filter(filt_state["identifier"])
211
+ state = self.pipeline.__getstate__()
212
+ self.pipeline_changed.emit(state)
213
+
214
+ def on_moreless(self):
215
+ """User wants to choose box filters"""
216
+ if not self._box_edit_view:
217
+ # get available features to show
218
+ features, _ = self.get_features_labels()
219
+ # create missing range controls if applicable (e.g. ml_score_???)
220
+ self._populate_box_filters()
221
+ # Show all filters shared by all datasets to the user
222
+ for feat, rc in self._box_range_controls.items():
223
+ if feat in features:
224
+ rc.setVisible(True)
225
+ rc.checkBox.setVisible(True)
226
+ rc.doubleSpinBox_min.setEnabled(False)
227
+ rc.doubleSpinBox_max.setEnabled(False)
228
+ rc.range_slider.setEnabled(False)
229
+ self.toolButton_moreless.setText("...Finish editing")
230
+ self.label_box_edit.setVisible(True)
231
+ self._box_edit_view = True
232
+ else:
233
+ # Hide all filters that are not active
234
+ for _, rc in self._box_range_controls.items():
235
+ if not rc.is_active():
236
+ rc.setVisible(False)
237
+ rc.checkBox.setVisible(False)
238
+ rc.doubleSpinBox_min.setEnabled(True)
239
+ rc.doubleSpinBox_max.setEnabled(True)
240
+ rc.range_slider.setEnabled(True)
241
+ self.toolButton_moreless.setText("Choose filters...")
242
+ self.label_box_edit.setVisible(False)
243
+ self._box_edit_view = False
244
+ # Update box filter ranges
245
+ self.update_box_ranges()
246
+
247
+ def set_pipeline(self, pipeline):
248
+ self._pipeline = pipeline
249
+
250
+ def show_filter(self, filt_id):
251
+ self.update_content(filt_index=self.filter_ids.index(filt_id))
252
+
253
+ def update_content(self, filt_index=None, **kwargs):
254
+ if self.filter_ids:
255
+ # remember the previous filter index and make sure it is sane
256
+ prev_index = self.comboBox_filters.currentIndex()
257
+ if prev_index is None or prev_index < 0:
258
+ prev_index = len(self.filter_ids) - 1
259
+
260
+ self.setEnabled(True)
261
+ self.update_polygon_filters(update_state=False)
262
+ # update combobox
263
+ self.comboBox_filters.blockSignals(True)
264
+ if filt_index is None or filt_index < 0:
265
+ # fallback to previous filter index
266
+ filt_index = prev_index
267
+ filt_index = min(filt_index, len(self.filter_ids) - 1)
268
+
269
+ self.comboBox_filters.clear()
270
+ self.comboBox_filters.addItems(self.filter_names)
271
+ self.comboBox_filters.setCurrentIndex(filt_index)
272
+ self.comboBox_filters.blockSignals(False)
273
+ # populate content
274
+ filt = Filter.get_filter(identifier=self.filter_ids[filt_index])
275
+ state = filt.__getstate__()
276
+ self.write_pipeline_state(state)
277
+ self.update_box_ranges()
278
+ else:
279
+ self.setEnabled(False)
280
+
281
+ def update_box_ranges(self):
282
+ """Update the box plot filter ranges
283
+
284
+ Feature information is taken from the current pipeline.
285
+ """
286
+ if self.pipeline is not None and self.pipeline.num_slots:
287
+ # compute min/max values
288
+ mmdict = {}
289
+ for feat in self.active_box_features:
290
+ mmdict[feat] = self.pipeline.get_min_max(feat=feat)
291
+ # update used features
292
+ for feat in self._box_range_controls:
293
+ rc = self._box_range_controls[feat]
294
+ if feat in mmdict:
295
+ rc.setLimits(*mmdict[feat])
296
+ if self.current_filter is not None:
297
+ state = self.current_filter.__getstate__()
298
+ if feat not in state["box filters"]:
299
+ # reset range to limits
300
+ rc.reset_range()
301
+
302
+ def update_polygon_filters(self, update_state=True):
303
+ """Update the layout containing the polygon filters"""
304
+ self.verticalLayout_poly.setAlignment(QtCore.Qt.AlignmentFlag.AlignTop)
305
+ # clear layout
306
+ for ii in reversed(range(self.verticalLayout_poly.count())):
307
+ item = self.verticalLayout_poly.itemAt(ii).widget()
308
+ if item is not None:
309
+ item.hide()
310
+ item.deleteLater()
311
+ self._polygon_checkboxes = {} # must come after getting the state
312
+ if dclab.PolygonFilter.instances:
313
+ for pf in dclab.PolygonFilter.instances:
314
+ widget = QtWidgets.QWidget()
315
+ hbox = QtWidgets.QHBoxLayout()
316
+ hbox.setAlignment(QtCore.Qt.AlignmentFlag.AlignLeft)
317
+ hbox.setContentsMargins(0, 0, 0, 0)
318
+ chb = QtWidgets.QCheckBox()
319
+ hbox.addWidget(chb)
320
+ hbox.addWidget(QtWidgets.QLabel(pf.name))
321
+ widget.setLayout(hbox)
322
+ self.verticalLayout_poly.addWidget(widget)
323
+ self._polygon_checkboxes[pf.unique_id] = chb
324
+ else:
325
+ label = QtWidgets.QLabel("No polygon filters have been created "
326
+ + "yet.")
327
+ button = QtWidgets.QPushButton("Create polygon filter")
328
+ button.clicked.connect(self.request_new_polygon_filter)
329
+ self.verticalLayout_poly.addWidget(label)
330
+ self.verticalLayout_poly.addWidget(button)
331
+ # update current filters
332
+ if update_state and self.current_filter is not None:
333
+ self.write_pipeline_state(self.current_filter.__getstate__())
334
+
335
+ def write_filter(self):
336
+ """Update the dcscope.pipeline.Filter instance"""
337
+ # get current index
338
+ filter_state = self.read_pipeline_state()
339
+ # this signal will update the main pipeline which will trigger
340
+ # a call to `set_pipeline` and `update_content`.
341
+ self.filter_changed.emit(filter_state)