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.
- dcscope/__init__.py +17 -0
- dcscope/__main__.py +44 -0
- dcscope/_version.py +21 -0
- dcscope/extensions.py +250 -0
- dcscope/gui/__init__.py +2 -0
- dcscope/gui/analysis/__init__.py +10 -0
- dcscope/gui/analysis/ana_basins.py +110 -0
- dcscope/gui/analysis/ana_basins.ui +143 -0
- dcscope/gui/analysis/ana_filter.py +341 -0
- dcscope/gui/analysis/ana_filter.ui +364 -0
- dcscope/gui/analysis/ana_log.py +122 -0
- dcscope/gui/analysis/ana_log.ui +100 -0
- dcscope/gui/analysis/ana_meta.py +207 -0
- dcscope/gui/analysis/ana_meta.ui +141 -0
- dcscope/gui/analysis/ana_plot.py +638 -0
- dcscope/gui/analysis/ana_plot.ui +1060 -0
- dcscope/gui/analysis/ana_slot.py +504 -0
- dcscope/gui/analysis/ana_slot.ui +684 -0
- dcscope/gui/analysis/ana_tables.py +227 -0
- dcscope/gui/analysis/ana_tables.ui +195 -0
- dcscope/gui/analysis/ana_view.py +69 -0
- dcscope/gui/analysis/ana_view.ui +269 -0
- dcscope/gui/analysis/dlg_slot_reorder.py +55 -0
- dcscope/gui/analysis/dlg_slot_reorder.ui +138 -0
- dcscope/gui/bulk/__init__.py +2 -0
- dcscope/gui/bulk/bulk_emodulus.py +200 -0
- dcscope/gui/bulk/bulk_emodulus.ui +245 -0
- dcscope/gui/compute/__init__.py +3 -0
- dcscope/gui/compute/comp_lme4.py +115 -0
- dcscope/gui/compute/comp_lme4.ui +194 -0
- dcscope/gui/compute/comp_lme4_dataset.py +51 -0
- dcscope/gui/compute/comp_lme4_dataset.ui +92 -0
- dcscope/gui/compute/comp_lme4_results.py +120 -0
- dcscope/gui/compute/comp_lme4_results.ui +268 -0
- dcscope/gui/compute/comp_stats.py +223 -0
- dcscope/gui/compute/comp_stats.ui +187 -0
- dcscope/gui/dcor/__init__.py +304 -0
- dcscope/gui/dcor/dcor.ui +118 -0
- dcscope/gui/export/__init__.py +3 -0
- dcscope/gui/export/e2data.py +394 -0
- dcscope/gui/export/e2data.ui +367 -0
- dcscope/gui/export/e2filter.py +76 -0
- dcscope/gui/export/e2filter.ui +111 -0
- dcscope/gui/export/e2plot.py +94 -0
- dcscope/gui/export/e2plot.ui +175 -0
- dcscope/gui/main.py +1089 -0
- dcscope/gui/main.ui +579 -0
- dcscope/gui/matrix/__init__.py +4 -0
- dcscope/gui/matrix/block_matrix.py +141 -0
- dcscope/gui/matrix/block_matrix.ui +207 -0
- dcscope/gui/matrix/data_matrix.py +574 -0
- dcscope/gui/matrix/dm_dataset.py +116 -0
- dcscope/gui/matrix/dm_dataset.ui +348 -0
- dcscope/gui/matrix/dm_element.py +111 -0
- dcscope/gui/matrix/dm_element.ui +169 -0
- dcscope/gui/matrix/dm_filter.py +115 -0
- dcscope/gui/matrix/dm_filter.ui +287 -0
- dcscope/gui/matrix/plot_matrix.py +316 -0
- dcscope/gui/matrix/pm_element.py +39 -0
- dcscope/gui/matrix/pm_plot.py +86 -0
- dcscope/gui/matrix/pm_plot.ui +249 -0
- dcscope/gui/pipeline_plot.py +797 -0
- dcscope/gui/pipeline_plot.ui +66 -0
- dcscope/gui/preferences.py +380 -0
- dcscope/gui/preferences.ui +554 -0
- dcscope/gui/quick_view/__init__.py +1 -0
- dcscope/gui/quick_view/qv_main.py +1072 -0
- dcscope/gui/quick_view/qv_main.ui +1297 -0
- dcscope/gui/quick_view/qv_scatter.py +284 -0
- dcscope/gui/quick_view/qv_style.css +10 -0
- dcscope/gui/update.py +90 -0
- dcscope/gui/widgets/__init__.py +15 -0
- dcscope/gui/widgets/bg_thread.py +29 -0
- dcscope/gui/widgets/bulk_list.py +79 -0
- dcscope/gui/widgets/bulk_list.ui +95 -0
- dcscope/gui/widgets/double_spin_box_nan.py +75 -0
- dcscope/gui/widgets/feature_combobox.py +140 -0
- dcscope/gui/widgets/get_path.py +42 -0
- dcscope/gui/widgets/key_value_table_widget.css +12 -0
- dcscope/gui/widgets/key_value_table_widget.py +75 -0
- dcscope/gui/widgets/mdi_subwindow_wo_close.py +12 -0
- dcscope/gui/widgets/qrangeslider.py +262 -0
- dcscope/gui/widgets/rangecontrol.py +308 -0
- dcscope/gui/widgets/rangecontrol.ui +136 -0
- dcscope/gui/widgets/simple_image_view.py +55 -0
- dcscope/gui/widgets/simple_plot_widget.py +113 -0
- dcscope/gui/widgets/so_colorbaritem.py +29 -0
- dcscope/gui/widgets/wait_cursor.py +33 -0
- dcscope/idiom.py +26 -0
- dcscope/img/__init__.py +2 -0
- dcscope/img/icon-theme/breeze/COPYING-ICONS +209 -0
- dcscope/img/icon-theme/breeze/COPYING.LIB +510 -0
- dcscope/img/icon-theme/breeze/README +5 -0
- dcscope/img/icon-theme/breeze/actions/16/application-exit.svg +17 -0
- dcscope/img/icon-theme/breeze/actions/16/code-context.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/dialog-cancel.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/dialog-close.svg +17 -0
- dcscope/img/icon-theme/breeze/actions/16/dialog-messages.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/dialog-ok-apply.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/dialog-ok.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/document-open-folder.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/document-open.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/document-save.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/documentinfo.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/16/draw-watercolor.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/edit-clear-all.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/edit-clear.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/edit-paste.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/globe.svg +16 -0
- dcscope/img/icon-theme/breeze/actions/16/gtk-preferences.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/list-add.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/messagebox_warning.svg +20 -0
- dcscope/img/icon-theme/breeze/actions/16/object-columns.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/object-order-lower.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/object-rows.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/office-chart-line-stacked.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/office-chart-ring.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/office-chart-scatter.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/path-mode-polyline.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/preferences-activities.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/remove.svg +10 -0
- dcscope/img/icon-theme/breeze/actions/16/search.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/show-grid.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/special_paste.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/tools-wizard.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/view-calendar-list.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/view-filter.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/view-list-tree.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/view-statistics.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/visibility.svg +21 -0
- dcscope/img/icon-theme/breeze/actions/22/application-exit.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/22/code-context.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/dialog-cancel.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/dialog-close.svg +10 -0
- dcscope/img/icon-theme/breeze/actions/22/dialog-messages.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/dialog-ok-apply.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/dialog-ok.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/document-open-folder.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/document-open.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/document-save.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/documentinfo.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/draw-watercolor.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/edit-clear-all.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/edit-clear.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/edit-paste.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/globe.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/22/gtk-preferences.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/22/list-add.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/messagebox_warning.svg +17 -0
- dcscope/img/icon-theme/breeze/actions/22/object-columns.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/object-order-lower.svg +17 -0
- dcscope/img/icon-theme/breeze/actions/22/object-rows.svg +17 -0
- dcscope/img/icon-theme/breeze/actions/22/office-chart-line-stacked.svg +17 -0
- dcscope/img/icon-theme/breeze/actions/22/office-chart-ring.svg +17 -0
- dcscope/img/icon-theme/breeze/actions/22/office-chart-scatter.svg +17 -0
- dcscope/img/icon-theme/breeze/actions/22/path-mode-polyline.svg +17 -0
- dcscope/img/icon-theme/breeze/actions/22/preferences-activities.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/remove.svg +10 -0
- dcscope/img/icon-theme/breeze/actions/22/special_paste.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/tools-wizard.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/view-calendar-list.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/view-filter.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/view-list-tree.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/view-statistics.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/visibility.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/24/application-exit.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/code-context.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/dialog-cancel.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/dialog-close.svg +10 -0
- dcscope/img/icon-theme/breeze/actions/24/dialog-messages.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/dialog-ok-apply.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/dialog-ok.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/24/document-open-folder.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/document-open.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/document-save.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/documentinfo.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/24/draw-watercolor.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/edit-clear-all.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/24/edit-clear.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/edit-paste.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/globe.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/24/gtk-preferences.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/24/list-add.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/messagebox_warning.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/24/object-columns.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/object-order-lower.svg +15 -0
- dcscope/img/icon-theme/breeze/actions/24/object-rows.svg +15 -0
- dcscope/img/icon-theme/breeze/actions/24/office-chart-line-stacked.svg +15 -0
- dcscope/img/icon-theme/breeze/actions/24/office-chart-ring.svg +15 -0
- dcscope/img/icon-theme/breeze/actions/24/office-chart-scatter.svg +15 -0
- dcscope/img/icon-theme/breeze/actions/24/path-mode-polyline.svg +15 -0
- dcscope/img/icon-theme/breeze/actions/24/preferences-activities.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/24/remove.svg +10 -0
- dcscope/img/icon-theme/breeze/actions/24/special_paste.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/tools-wizard.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/view-calendar-list.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/view-filter.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/view-list-tree.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/view-statistics.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/visibility.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/32/application-exit.svg +8 -0
- dcscope/img/icon-theme/breeze/actions/32/dialog-cancel.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/32/dialog-messages.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/32/dialog-ok-apply.svg +1 -0
- dcscope/img/icon-theme/breeze/actions/32/dialog-ok.svg +1 -0
- dcscope/img/icon-theme/breeze/actions/32/document-open-folder.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/32/document-open.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/32/document-save.svg +18 -0
- dcscope/img/icon-theme/breeze/actions/32/gtk-preferences.svg +17 -0
- dcscope/img/icon-theme/breeze/actions/32/object-order-lower.svg +18 -0
- dcscope/img/icon-theme/breeze/actions/32/view-filter.svg +18 -0
- dcscope/img/icon-theme/breeze/actions/32/view-list-tree.svg +18 -0
- dcscope/img/icon-theme/breeze/places/16/folder-cloud.svg +13 -0
- dcscope/img/icon-theme/breeze/places/16/folder.svg +13 -0
- dcscope/img/icon-theme/breeze/places/22/folder-cloud.svg +13 -0
- dcscope/img/icon-theme/breeze/places/22/folder.svg +13 -0
- dcscope/img/icon-theme/breeze/places/24/folder-cloud.svg +12 -0
- dcscope/img/icon-theme/breeze/places/24/folder.svg +12 -0
- dcscope/img/icon-theme/breeze/places/32/folder-cloud.svg +35 -0
- dcscope/img/icon-theme/breeze/places/32/folder.svg +30 -0
- dcscope/img/icon-theme/breeze/places/64/folder-cloud.svg +35 -0
- dcscope/img/icon-theme/breeze/places/64/folder.svg +30 -0
- dcscope/img/icon-theme/breeze/status/16/dialog-error.svg +9 -0
- dcscope/img/icon-theme/breeze/status/16/dialog-information.svg +9 -0
- dcscope/img/icon-theme/breeze/status/16/dialog-question.svg +7 -0
- dcscope/img/icon-theme/breeze/status/16/dialog-warning.svg +9 -0
- dcscope/img/icon-theme/breeze/status/22/dialog-error.svg +9 -0
- dcscope/img/icon-theme/breeze/status/22/dialog-information.svg +9 -0
- dcscope/img/icon-theme/breeze/status/22/dialog-question.svg +7 -0
- dcscope/img/icon-theme/breeze/status/22/dialog-warning.svg +9 -0
- dcscope/img/icon-theme/breeze/status/24/dialog-error.svg +13 -0
- dcscope/img/icon-theme/breeze/status/24/dialog-information.svg +13 -0
- dcscope/img/icon-theme/breeze/status/24/dialog-question.svg +9 -0
- dcscope/img/icon-theme/breeze/status/24/dialog-warning.svg +1 -0
- dcscope/img/icon-theme/breeze/status/64/dialog-error.svg +25 -0
- dcscope/img/icon-theme/breeze/status/64/dialog-information.svg +25 -0
- dcscope/img/icon-theme/breeze/status/64/dialog-question.svg +25 -0
- dcscope/img/icon-theme/breeze/status/64/dialog-warning.svg +25 -0
- dcscope/img/icon-theme/collect_icons.py +124 -0
- dcscope/img/icon-theme/dcscope/dcor.png +0 -0
- dcscope/img/icon-theme/dcscope/edit-copy-anew.svg +13 -0
- dcscope/img/icon-theme/dcscope/emodulus.svg +69 -0
- dcscope/img/icon-theme/dcscope/filter_ray.svg +54 -0
- dcscope/img/icon-theme/dcscope/region_channel.svg +86 -0
- dcscope/img/icon-theme/dcscope/region_reservoir.svg +89 -0
- dcscope/img/icon-theme/dcscope/rlang.svg +108 -0
- dcscope/img/icon-theme/dcscope/statistical_significance.svg +106 -0
- dcscope/img/icon-theme/index.theme +81 -0
- dcscope/img/icon.png +0 -0
- dcscope/img/icon.svg +73 -0
- dcscope/img/splash.png +0 -0
- dcscope/meta_tool.py +143 -0
- dcscope/pipeline/__init__.py +5 -0
- dcscope/pipeline/core.py +632 -0
- dcscope/pipeline/dataslot.py +270 -0
- dcscope/pipeline/filter.py +161 -0
- dcscope/pipeline/filter_ray.py +170 -0
- dcscope/pipeline/plot.py +187 -0
- dcscope/plot_cache.py +79 -0
- dcscope/session.py +379 -0
- dcscope/util.py +34 -0
- dcscope-2.22.1.dist-info/METADATA +95 -0
- dcscope-2.22.1.dist-info/RECORD +267 -0
- dcscope-2.22.1.dist-info/WHEEL +5 -0
- dcscope-2.22.1.dist-info/entry_points.txt +2 -0
- dcscope-2.22.1.dist-info/licenses/LICENSE +621 -0
- 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]
|