dclab 0.67.0__cp314-cp314t-macosx_10_13_x86_64.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.
Potentially problematic release.
This version of dclab might be problematic. Click here for more details.
- dclab/__init__.py +41 -0
- dclab/_version.py +34 -0
- dclab/cached.py +97 -0
- dclab/cli/__init__.py +10 -0
- dclab/cli/common.py +237 -0
- dclab/cli/task_compress.py +126 -0
- dclab/cli/task_condense.py +223 -0
- dclab/cli/task_join.py +229 -0
- dclab/cli/task_repack.py +98 -0
- dclab/cli/task_split.py +154 -0
- dclab/cli/task_tdms2rtdc.py +186 -0
- dclab/cli/task_verify_dataset.py +75 -0
- dclab/definitions/__init__.py +79 -0
- dclab/definitions/feat_const.py +202 -0
- dclab/definitions/feat_logic.py +182 -0
- dclab/definitions/meta_const.py +252 -0
- dclab/definitions/meta_logic.py +111 -0
- dclab/definitions/meta_parse.py +94 -0
- dclab/downsampling.cpython-314t-darwin.so +0 -0
- dclab/downsampling.pyx +230 -0
- dclab/external/__init__.py +4 -0
- dclab/external/packaging/LICENSE +3 -0
- dclab/external/packaging/LICENSE.APACHE +177 -0
- dclab/external/packaging/LICENSE.BSD +23 -0
- dclab/external/packaging/__init__.py +6 -0
- dclab/external/packaging/_structures.py +61 -0
- dclab/external/packaging/version.py +505 -0
- dclab/external/skimage/LICENSE +28 -0
- dclab/external/skimage/__init__.py +2 -0
- dclab/external/skimage/_find_contours.py +216 -0
- dclab/external/skimage/_find_contours_cy.cpython-314t-darwin.so +0 -0
- dclab/external/skimage/_find_contours_cy.pyx +188 -0
- dclab/external/skimage/_pnpoly.cpython-314t-darwin.so +0 -0
- dclab/external/skimage/_pnpoly.pyx +99 -0
- dclab/external/skimage/_shared/__init__.py +1 -0
- dclab/external/skimage/_shared/geometry.cpython-314t-darwin.so +0 -0
- dclab/external/skimage/_shared/geometry.pxd +6 -0
- dclab/external/skimage/_shared/geometry.pyx +55 -0
- dclab/external/skimage/measure.py +7 -0
- dclab/external/skimage/pnpoly.py +53 -0
- dclab/external/statsmodels/LICENSE +35 -0
- dclab/external/statsmodels/__init__.py +6 -0
- dclab/external/statsmodels/nonparametric/__init__.py +1 -0
- dclab/external/statsmodels/nonparametric/_kernel_base.py +203 -0
- dclab/external/statsmodels/nonparametric/kernel_density.py +165 -0
- dclab/external/statsmodels/nonparametric/kernels.py +36 -0
- dclab/features/__init__.py +9 -0
- dclab/features/bright.py +81 -0
- dclab/features/bright_bc.py +93 -0
- dclab/features/bright_perc.py +63 -0
- dclab/features/contour.py +161 -0
- dclab/features/emodulus/__init__.py +339 -0
- dclab/features/emodulus/load.py +252 -0
- dclab/features/emodulus/lut_HE-2D-FEM-22.txt +16432 -0
- dclab/features/emodulus/lut_HE-3D-FEM-22.txt +1276 -0
- dclab/features/emodulus/lut_LE-2D-FEM-19.txt +13082 -0
- dclab/features/emodulus/pxcorr.py +135 -0
- dclab/features/emodulus/scale_linear.py +247 -0
- dclab/features/emodulus/viscosity.py +260 -0
- dclab/features/fl_crosstalk.py +95 -0
- dclab/features/inert_ratio.py +377 -0
- dclab/features/volume.py +242 -0
- dclab/http_utils.py +322 -0
- dclab/isoelastics/__init__.py +468 -0
- dclab/isoelastics/iso_HE-2D-FEM-22-area_um-deform.txt +2440 -0
- dclab/isoelastics/iso_HE-2D-FEM-22-volume-deform.txt +2635 -0
- dclab/isoelastics/iso_HE-3D-FEM-22-area_um-deform.txt +1930 -0
- dclab/isoelastics/iso_HE-3D-FEM-22-volume-deform.txt +2221 -0
- dclab/isoelastics/iso_LE-2D-FEM-19-area_um-deform.txt +2151 -0
- dclab/isoelastics/iso_LE-2D-FEM-19-volume-deform.txt +2250 -0
- dclab/isoelastics/iso_LE-2D-ana-18-area_um-deform.txt +1266 -0
- dclab/kde/__init__.py +1 -0
- dclab/kde/base.py +459 -0
- dclab/kde/contours.py +222 -0
- dclab/kde/methods.py +313 -0
- dclab/kde_contours.py +10 -0
- dclab/kde_methods.py +11 -0
- dclab/lme4/__init__.py +5 -0
- dclab/lme4/lme4_template.R +94 -0
- dclab/lme4/rsetup.py +204 -0
- dclab/lme4/wrapr.py +386 -0
- dclab/polygon_filter.py +398 -0
- dclab/rtdc_dataset/__init__.py +15 -0
- dclab/rtdc_dataset/check.py +902 -0
- dclab/rtdc_dataset/config.py +533 -0
- dclab/rtdc_dataset/copier.py +353 -0
- dclab/rtdc_dataset/core.py +896 -0
- dclab/rtdc_dataset/export.py +867 -0
- dclab/rtdc_dataset/feat_anc_core/__init__.py +24 -0
- dclab/rtdc_dataset/feat_anc_core/af_basic.py +75 -0
- dclab/rtdc_dataset/feat_anc_core/af_emodulus.py +160 -0
- dclab/rtdc_dataset/feat_anc_core/af_fl_max_ctc.py +133 -0
- dclab/rtdc_dataset/feat_anc_core/af_image_contour.py +113 -0
- dclab/rtdc_dataset/feat_anc_core/af_ml_class.py +102 -0
- dclab/rtdc_dataset/feat_anc_core/ancillary_feature.py +320 -0
- dclab/rtdc_dataset/feat_anc_ml/__init__.py +32 -0
- dclab/rtdc_dataset/feat_anc_plugin/__init__.py +3 -0
- dclab/rtdc_dataset/feat_anc_plugin/plugin_feature.py +329 -0
- dclab/rtdc_dataset/feat_basin.py +762 -0
- dclab/rtdc_dataset/feat_temp.py +102 -0
- dclab/rtdc_dataset/filter.py +263 -0
- dclab/rtdc_dataset/fmt_dcor/__init__.py +7 -0
- dclab/rtdc_dataset/fmt_dcor/access_token.py +52 -0
- dclab/rtdc_dataset/fmt_dcor/api.py +173 -0
- dclab/rtdc_dataset/fmt_dcor/base.py +299 -0
- dclab/rtdc_dataset/fmt_dcor/basin.py +73 -0
- dclab/rtdc_dataset/fmt_dcor/logs.py +26 -0
- dclab/rtdc_dataset/fmt_dcor/tables.py +66 -0
- dclab/rtdc_dataset/fmt_dict.py +103 -0
- dclab/rtdc_dataset/fmt_hdf5/__init__.py +6 -0
- dclab/rtdc_dataset/fmt_hdf5/base.py +192 -0
- dclab/rtdc_dataset/fmt_hdf5/basin.py +30 -0
- dclab/rtdc_dataset/fmt_hdf5/events.py +276 -0
- dclab/rtdc_dataset/fmt_hdf5/feat_defect.py +164 -0
- dclab/rtdc_dataset/fmt_hdf5/logs.py +33 -0
- dclab/rtdc_dataset/fmt_hdf5/tables.py +60 -0
- dclab/rtdc_dataset/fmt_hierarchy/__init__.py +11 -0
- dclab/rtdc_dataset/fmt_hierarchy/base.py +278 -0
- dclab/rtdc_dataset/fmt_hierarchy/events.py +146 -0
- dclab/rtdc_dataset/fmt_hierarchy/hfilter.py +140 -0
- dclab/rtdc_dataset/fmt_hierarchy/mapper.py +134 -0
- dclab/rtdc_dataset/fmt_http.py +102 -0
- dclab/rtdc_dataset/fmt_s3.py +354 -0
- dclab/rtdc_dataset/fmt_tdms/__init__.py +476 -0
- dclab/rtdc_dataset/fmt_tdms/event_contour.py +264 -0
- dclab/rtdc_dataset/fmt_tdms/event_image.py +220 -0
- dclab/rtdc_dataset/fmt_tdms/event_mask.py +62 -0
- dclab/rtdc_dataset/fmt_tdms/event_trace.py +146 -0
- dclab/rtdc_dataset/fmt_tdms/exc.py +37 -0
- dclab/rtdc_dataset/fmt_tdms/naming.py +151 -0
- dclab/rtdc_dataset/load.py +77 -0
- dclab/rtdc_dataset/meta_table.py +25 -0
- dclab/rtdc_dataset/writer.py +1019 -0
- dclab/statistics.py +226 -0
- dclab/util.py +176 -0
- dclab/warn.py +15 -0
- dclab-0.67.0.dist-info/METADATA +153 -0
- dclab-0.67.0.dist-info/RECORD +142 -0
- dclab-0.67.0.dist-info/WHEEL +6 -0
- dclab-0.67.0.dist-info/entry_points.txt +8 -0
- dclab-0.67.0.dist-info/licenses/LICENSE +283 -0
- dclab-0.67.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
#: List of scalar (one scalar value per event) features. This
|
|
2
|
+
#: list does not include the `ml_score_???` features. If you
|
|
3
|
+
#: need find out whether a feature name is valid, please use
|
|
4
|
+
#: :func:`is_valid_feature`.
|
|
5
|
+
FEATURES_SCALAR = [
|
|
6
|
+
["area_cvx", "Convex area [px]"],
|
|
7
|
+
# area_msd is the contour moment M00
|
|
8
|
+
["area_msd", "Measured area [px]"],
|
|
9
|
+
["area_ratio", "Porosity (convex to measured area ratio)"],
|
|
10
|
+
# area_um is computed from the convex contour
|
|
11
|
+
["area_um", "Area [µm²]"],
|
|
12
|
+
["area_um_raw", "Area [µm²] of raw contour"],
|
|
13
|
+
["aspect", "Aspect ratio of bounding box"],
|
|
14
|
+
# The background brightness of the frame (not of the mask)
|
|
15
|
+
["bg_med", "Median frame background brightness [a.u.]"],
|
|
16
|
+
# Background image offset which should be added to "image_bg" before
|
|
17
|
+
# performing background correction. This is used in cases where the
|
|
18
|
+
# background stored in "image_bg" is not accurate enough, e.g.
|
|
19
|
+
# because the image_bg is a median image for multiple events and
|
|
20
|
+
# the imaging system exhibits flickering.
|
|
21
|
+
["bg_off", "Background offset [a.u.]"],
|
|
22
|
+
# Brightness values are computed only for pixels inside the mask
|
|
23
|
+
["bright_avg", "Brightness average [a.u.]"],
|
|
24
|
+
["bright_sd", "Brightness SD [a.u.]"],
|
|
25
|
+
["bright_bc_avg", "Brightness average (bgc) [a.u.]"],
|
|
26
|
+
["bright_bc_sd", "Brightness SD (bgc) [a.u.]"],
|
|
27
|
+
["bright_perc_10", "10th Percentile of brightness (bgc)"],
|
|
28
|
+
["bright_perc_90", "90th Percentile of brightness (bgc)"],
|
|
29
|
+
["circ", "Circularity"],
|
|
30
|
+
# deform is computed from the convex contour
|
|
31
|
+
["deform", "Deformation"],
|
|
32
|
+
["deform_raw", "Deformation of raw contour"],
|
|
33
|
+
["eccentr_prnc", "Eccentricity of raw contour"],
|
|
34
|
+
["emodulus", "Young's modulus [kPa]"],
|
|
35
|
+
# fl*_area, fl*_pos, and fl*_width values correspond to the
|
|
36
|
+
# object for which the contour was found. For high concentrations,
|
|
37
|
+
# these values could be error-prone due to the assignment from
|
|
38
|
+
# false objects.
|
|
39
|
+
["fl1_area", "FL-1 area of peak [a.u.]"],
|
|
40
|
+
# fl1_dist is set to zero if there is only one peak
|
|
41
|
+
["fl1_dist", "FL-1 distance between two first peaks [µs]"],
|
|
42
|
+
["fl1_max", "FL-1 maximum [a.u.]"],
|
|
43
|
+
["fl1_max_ctc", "FL-1 maximum, crosstalk-corrected [a.u.]"],
|
|
44
|
+
["fl1_npeaks", "FL-1 number of peaks"],
|
|
45
|
+
["fl1_pos", "FL-1 position of peak [µs]"],
|
|
46
|
+
["fl1_width", "FL-1 width [µs]"],
|
|
47
|
+
["fl2_area", "FL-2 area of peak [a.u.]"],
|
|
48
|
+
["fl2_dist", "FL-2 distance between two first peaks [µs]"],
|
|
49
|
+
["fl2_max", "FL-2 maximum [a.u.]"],
|
|
50
|
+
["fl2_max_ctc", "FL-2 maximum, crosstalk-corrected [a.u.]"],
|
|
51
|
+
["fl2_npeaks", "FL-2 number of peaks"],
|
|
52
|
+
["fl2_pos", "FL-2 position of peak [µs]"],
|
|
53
|
+
["fl2_width", "FL-2 width [µs]"],
|
|
54
|
+
["fl3_area", "FL-3 area of peak [a.u.]"],
|
|
55
|
+
["fl3_dist", "FL-3 distance between two first peaks [µs]"],
|
|
56
|
+
["fl3_max", "FL-3 maximum [a.u.]"],
|
|
57
|
+
["fl3_max_ctc", "FL-3 maximum, crosstalk-corrected [a.u.]"],
|
|
58
|
+
["fl3_npeaks", "FL-3 number of peaks"],
|
|
59
|
+
["fl3_pos", "FL-3 position of peak [µs]"],
|
|
60
|
+
["fl3_width", "FL-3 width [µs]"],
|
|
61
|
+
# Sum of the flow rates for sample and sheath flow
|
|
62
|
+
["flow_rate", "Flow rate [µLs⁻¹]"],
|
|
63
|
+
["frame", "Video frame number"],
|
|
64
|
+
["g_force", "Gravitational force in multiples of g"],
|
|
65
|
+
# index starts with 1
|
|
66
|
+
["index", "Index (Dataset)"],
|
|
67
|
+
# index_online enumerates the events found by Shape-In and may have
|
|
68
|
+
# missing values in case of a writer-overrun with recovery (#71)
|
|
69
|
+
["index_online", "Index (Online)"],
|
|
70
|
+
# The inertia ratios of the event contours are defined by the
|
|
71
|
+
# central second order moments of area (sqrt(m20/m02).
|
|
72
|
+
["inert_ratio_cvx", "Inertia ratio of convex contour"],
|
|
73
|
+
["inert_ratio_prnc", "Principal inertia ratio of raw contour"],
|
|
74
|
+
["inert_ratio_raw", "Inertia ratio of raw contour"],
|
|
75
|
+
# This is an ancillary integer feature for visualizing the class
|
|
76
|
+
# membership of individual events based on the `ml_score_???`
|
|
77
|
+
# features.
|
|
78
|
+
["ml_class", "Most probable ML class"],
|
|
79
|
+
["nevents", "Number of events in the same image"],
|
|
80
|
+
["pc1", "Principal component 1"],
|
|
81
|
+
["pc2", "Principal component 2"],
|
|
82
|
+
# Convexity is defined by the ratio of convex contour length
|
|
83
|
+
# versus raw contour length. We use inverse convexity as it is
|
|
84
|
+
# more convenient to work with numbers >1.
|
|
85
|
+
["per_ratio", "Inverse Convexity (raw to convex perimeter ratio)"],
|
|
86
|
+
["per_um_raw", "Perimeter [µm] of raw contour"],
|
|
87
|
+
# pos_x and pos_y are computed from the contour moments
|
|
88
|
+
# "m10"/"m00" and "m01"/"m00" of the convex hull of "contour"
|
|
89
|
+
["pos_x", "Position along channel axis [µm]"],
|
|
90
|
+
["pos_y", "Position lateral in channel [µm]"],
|
|
91
|
+
# Sum of the pressures applied to sample and sheath flow
|
|
92
|
+
["pressure", "Pressure [mPa]"],
|
|
93
|
+
# QPI features computed from holographic data
|
|
94
|
+
["qpi_dm_avg", "Dry mass (average) [pg]"],
|
|
95
|
+
["qpi_dm_sd", "Dry mass (SD) [pg]"],
|
|
96
|
+
["qpi_pha_int", "Integrated phase [rad]"],
|
|
97
|
+
["qpi_ri_avg", "Refractive index (average)"],
|
|
98
|
+
["qpi_ri_sd", "Refractive index (SD)"],
|
|
99
|
+
# QPI features from refocused events
|
|
100
|
+
["qpi_focus", "Computed focus distance [µm]"],
|
|
101
|
+
# Size features
|
|
102
|
+
["size_x", "Bounding box size x [µm]"],
|
|
103
|
+
["size_y", "Bounding box size y [µm]"],
|
|
104
|
+
# Ratio between two halves of a mask
|
|
105
|
+
["sym_x", "Symmetry ratio left-right"],
|
|
106
|
+
["sym_y", "Symmetry ratio top-bottom"],
|
|
107
|
+
["temp", "Chip temperature [°C]"],
|
|
108
|
+
["temp_amb", "Ambient temperature [°C]"],
|
|
109
|
+
# Haralick texture features can be computed using the mahotas package
|
|
110
|
+
# from the background-corrected and masked image
|
|
111
|
+
["tex_asm_avg", "Texture angular second moment (avg)"], # H1
|
|
112
|
+
["tex_asm_ptp", "Texture angular second moment (ptp)"], # H1
|
|
113
|
+
["tex_con_avg", "Texture contrast (avg)"], # H2
|
|
114
|
+
["tex_con_ptp", "Texture contrast (ptp)"], # H2
|
|
115
|
+
["tex_cor_avg", "Texture correlation (avg)"], # H3
|
|
116
|
+
["tex_cor_ptp", "Texture correlation (ptp)"], # H3
|
|
117
|
+
["tex_den_avg", "Texture difference entropy (avg)"], # 11
|
|
118
|
+
["tex_den_ptp", "Texture difference entropy (ptp)"], # 11
|
|
119
|
+
["tex_ent_avg", "Texture entropy (avg)"], # H9
|
|
120
|
+
["tex_ent_ptp", "Texture entropy (ptp)"], # H9
|
|
121
|
+
["tex_f12_avg", "Texture First measure of correlation (avg)"], # 12
|
|
122
|
+
["tex_f12_ptp", "Texture First measure of correlation (ptp)"], # 12
|
|
123
|
+
["tex_f13_avg", "Texture Second measure of correlation (avg)"], # 13
|
|
124
|
+
["tex_f13_ptp", "Texture Second measure of correlation (ptp)"], # 13
|
|
125
|
+
["tex_idm_avg", "Texture inverse difference moment (avg)"], # H5
|
|
126
|
+
["tex_idm_ptp", "Texture inverse difference moment (ptp)"], # H5
|
|
127
|
+
["tex_sen_avg", "Texture sum entropy (avg)"], # H8
|
|
128
|
+
["tex_sen_ptp", "Texture sum entropy (ptp)"], # H8
|
|
129
|
+
["tex_sva_avg", "Texture sum variance (avg)"], # H7
|
|
130
|
+
["tex_sva_ptp", "Texture sum variance (ptp)"], # H7
|
|
131
|
+
["tex_var_avg", "Texture variance (avg)"], # H4
|
|
132
|
+
["tex_var_ptp", "Texture variance (ptp)"], # H4
|
|
133
|
+
["tilt", "Absolute tilt of raw contour"],
|
|
134
|
+
["time", "Time [s]"],
|
|
135
|
+
# Volume is computed from the raw contour (i.e. with exclusions).
|
|
136
|
+
# Fun fact: If we had decided to compute it from the convex contour,
|
|
137
|
+
# then we would have close to none pixelation effects ¯\_(ツ)_/¯.
|
|
138
|
+
["volume", "Volume [µm³]"],
|
|
139
|
+
]
|
|
140
|
+
|
|
141
|
+
#: User-defined features: They are not reserved for anything specific
|
|
142
|
+
#: and can be used by the user for e.g. prototyping.
|
|
143
|
+
for _i in range(10):
|
|
144
|
+
FEATURES_SCALAR.append([f"userdef{_i}", f"User-defined {_i}"])
|
|
145
|
+
|
|
146
|
+
#: Basin mapping features: These are used for datasets that are derived from a
|
|
147
|
+
#: subset of events of another dataset. For instance, if a dataset consists
|
|
148
|
+
#: of every second event from another dataset, the feature `basinmap1` would
|
|
149
|
+
#: consist of the integer array `[1, 3, 5, 7, ...]` (indexing starts at zero).
|
|
150
|
+
#: The `basinmap1` feature must then be referenced in the corresponding basin
|
|
151
|
+
#: definition. These features should not be presented explicitly to the
|
|
152
|
+
#: normal user (e.g. in DCscope) to avoid ambiguities, and they should
|
|
153
|
+
#: always be exported alongside basins that refer to them.
|
|
154
|
+
for _j in range(10):
|
|
155
|
+
FEATURES_SCALAR.append([f"basinmap{_j}", f"Basin mapping {_j}"])
|
|
156
|
+
|
|
157
|
+
#: list of non-scalar features
|
|
158
|
+
FEATURES_NON_SCALAR = [
|
|
159
|
+
# This is a (M, 2)-shaped array with integer contour coordinates
|
|
160
|
+
["contour", "Event contour"],
|
|
161
|
+
["image", "Gray scale event image"],
|
|
162
|
+
["image_bg", "Gray scale event background image"],
|
|
163
|
+
# This is the contour with holes filled
|
|
164
|
+
["mask", "Binary mask labeling the event in the image"],
|
|
165
|
+
# See FLUOR_TRACES for valid keys
|
|
166
|
+
["trace", "Dictionary of fluorescence traces"],
|
|
167
|
+
# QPI experimental holographic data
|
|
168
|
+
["qpi_oah", "Off-axis hologram"],
|
|
169
|
+
# QPI holographic background data (experimental or computed)
|
|
170
|
+
["qpi_oah_bg", "Off-axis hologram background"],
|
|
171
|
+
# QPI features computed from holographic data
|
|
172
|
+
["qpi_pha", "Hologram phase image [rad]"],
|
|
173
|
+
["qpi_amp", "Hologram amplitude image"],
|
|
174
|
+
]
|
|
175
|
+
|
|
176
|
+
#: List of fluorescence traces
|
|
177
|
+
FLUOR_TRACES = [
|
|
178
|
+
"fl1_median",
|
|
179
|
+
"fl1_raw",
|
|
180
|
+
"fl2_median",
|
|
181
|
+
"fl2_raw",
|
|
182
|
+
"fl3_median",
|
|
183
|
+
"fl3_raw",
|
|
184
|
+
]
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
# FEATURE convenience lists and dicts
|
|
188
|
+
|
|
189
|
+
#: list of feature names
|
|
190
|
+
feature_names = [_cc[0] for _cc in FEATURES_SCALAR + FEATURES_NON_SCALAR]
|
|
191
|
+
|
|
192
|
+
#: list of feature labels (same order as :const:`feature_names`
|
|
193
|
+
feature_labels = [_cc[1] for _cc in FEATURES_SCALAR + FEATURES_NON_SCALAR]
|
|
194
|
+
|
|
195
|
+
#: dict for converting feature names to labels
|
|
196
|
+
feature_name2label = {}
|
|
197
|
+
|
|
198
|
+
for _cc in FEATURES_SCALAR + FEATURES_NON_SCALAR:
|
|
199
|
+
feature_name2label[_cc[0]] = _cc[1]
|
|
200
|
+
|
|
201
|
+
#: list of scalar feature names
|
|
202
|
+
scalar_feature_names = [_cc[0] for _cc in FEATURES_SCALAR]
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import re
|
|
2
|
+
|
|
3
|
+
from . import feat_const
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
ML_SCORE_REGEX = re.compile(r"^ml_score_[a-z0-9]{3}$")
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def check_feature_shape(name, data):
|
|
10
|
+
"""Check if (non)-scalar feature matches with its data's dimensionality
|
|
11
|
+
|
|
12
|
+
Parameters
|
|
13
|
+
----------
|
|
14
|
+
name: str
|
|
15
|
+
name of the feature
|
|
16
|
+
data: array-like
|
|
17
|
+
data whose dimensionality will be checked
|
|
18
|
+
|
|
19
|
+
Raises
|
|
20
|
+
------
|
|
21
|
+
ValueError
|
|
22
|
+
If the data's shape does not match its scalar description
|
|
23
|
+
"""
|
|
24
|
+
if len(data.shape) == 1 and not scalar_feature_exists(name):
|
|
25
|
+
raise ValueError(
|
|
26
|
+
f"Feature '{name}' is not a scalar feature, but "
|
|
27
|
+
"a 1D array was given for `data`!"
|
|
28
|
+
)
|
|
29
|
+
elif len(data.shape) != 1 and scalar_feature_exists(name):
|
|
30
|
+
raise ValueError(
|
|
31
|
+
f"Feature '{name}' is a scalar feature, but the "
|
|
32
|
+
"`data` array is not 1D!"
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def feature_exists(name, scalar_only=False):
|
|
37
|
+
"""Return True if `name` is a valid feature name
|
|
38
|
+
|
|
39
|
+
This function not only checks whether `name` is in
|
|
40
|
+
:const:`feature_names`, but also validates against
|
|
41
|
+
the machine learning scores `ml_score_???` (where
|
|
42
|
+
`?` can be a digit or a lower-case letter in the
|
|
43
|
+
English alphabet).
|
|
44
|
+
|
|
45
|
+
Parameters
|
|
46
|
+
----------
|
|
47
|
+
name: str
|
|
48
|
+
name of a feature
|
|
49
|
+
scalar_only : bool
|
|
50
|
+
Specify whether the check should only search in scalar features
|
|
51
|
+
|
|
52
|
+
Returns
|
|
53
|
+
-------
|
|
54
|
+
valid: bool
|
|
55
|
+
True if name is a valid feature, False otherwise.
|
|
56
|
+
|
|
57
|
+
See Also
|
|
58
|
+
--------
|
|
59
|
+
scalar_feature_exists: Wraps `feature_exists` with `scalar_only=True`
|
|
60
|
+
"""
|
|
61
|
+
valid = False
|
|
62
|
+
if name in feat_const.scalar_feature_names:
|
|
63
|
+
# scalar feature
|
|
64
|
+
valid = True
|
|
65
|
+
elif not scalar_only and name in feat_const.feature_names:
|
|
66
|
+
# non-scalar feature
|
|
67
|
+
valid = True
|
|
68
|
+
elif ML_SCORE_REGEX.match(name):
|
|
69
|
+
# machine-learning score feature ml_score_???
|
|
70
|
+
valid = True
|
|
71
|
+
return valid
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def feature_register(name, label=None, is_scalar=True):
|
|
75
|
+
"""Register a new feature for usage in dclab
|
|
76
|
+
|
|
77
|
+
Used by temporary features and plugin features to add new feature
|
|
78
|
+
names and labels to `dclab.definitions`.
|
|
79
|
+
|
|
80
|
+
Parameters
|
|
81
|
+
----------
|
|
82
|
+
name: str
|
|
83
|
+
name of a feature
|
|
84
|
+
label: str, optional
|
|
85
|
+
feature label corresponding to the feature name. If set to None, then
|
|
86
|
+
a label is constructed for the feature name.
|
|
87
|
+
is_scalar: bool
|
|
88
|
+
Specify whether the feature of an event is a scalar (True)
|
|
89
|
+
or not (False)
|
|
90
|
+
|
|
91
|
+
Raises
|
|
92
|
+
------
|
|
93
|
+
ValueError
|
|
94
|
+
If the feature already exists.
|
|
95
|
+
"""
|
|
96
|
+
allowed_chars = "abcdefghijklmnopqrstuvwxyz_1234567890"
|
|
97
|
+
feat = "".join([f for f in name if f in allowed_chars])
|
|
98
|
+
if feat != name:
|
|
99
|
+
raise ValueError(
|
|
100
|
+
"`feature` must only contain lower-case characters, "
|
|
101
|
+
f"digits, and underscores; got '{name}'!"
|
|
102
|
+
)
|
|
103
|
+
if label is None:
|
|
104
|
+
label = f"User-defined feature {name}"
|
|
105
|
+
if feature_exists(name):
|
|
106
|
+
raise ValueError(f"Feature '{name}' already exists!")
|
|
107
|
+
|
|
108
|
+
# Populate the new feature in all dictionaries and lists
|
|
109
|
+
# (we don't need global here)
|
|
110
|
+
feat_const.feature_names.append(name)
|
|
111
|
+
feat_const.feature_labels.append(label)
|
|
112
|
+
feat_const.feature_name2label[name] = label
|
|
113
|
+
if is_scalar:
|
|
114
|
+
feat_const.scalar_feature_names.append(name)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def feature_deregister(name):
|
|
118
|
+
"""Unregister a feature from dclab
|
|
119
|
+
|
|
120
|
+
Used by temporary features and plugin features to
|
|
121
|
+
remove the feature names and labels from `dclab.definitions`.
|
|
122
|
+
|
|
123
|
+
Parameters
|
|
124
|
+
----------
|
|
125
|
+
name: str
|
|
126
|
+
name of a feature
|
|
127
|
+
|
|
128
|
+
Warnings
|
|
129
|
+
--------
|
|
130
|
+
This function should only be used internally, i.e., You should not use
|
|
131
|
+
this function. This function can break things.
|
|
132
|
+
"""
|
|
133
|
+
label = get_feature_label(name)
|
|
134
|
+
feat_const.feature_names.remove(name)
|
|
135
|
+
feat_const.feature_labels.remove(label)
|
|
136
|
+
feat_const.feature_name2label.pop(name)
|
|
137
|
+
if name in feat_const.scalar_feature_names:
|
|
138
|
+
feat_const.scalar_feature_names.remove(name)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def get_feature_label(name, rtdc_ds=None, with_unit=True):
|
|
142
|
+
"""Return the label corresponding to a feature name
|
|
143
|
+
|
|
144
|
+
This function not only checks :const:`feature_name2label`,
|
|
145
|
+
but also supports registered `ml_score_???` features.
|
|
146
|
+
|
|
147
|
+
Parameters
|
|
148
|
+
----------
|
|
149
|
+
name: str
|
|
150
|
+
name of a feature
|
|
151
|
+
with_unit: bool
|
|
152
|
+
set to False to remove units in square brackets
|
|
153
|
+
|
|
154
|
+
Returns
|
|
155
|
+
-------
|
|
156
|
+
label: str
|
|
157
|
+
feature label corresponding to the feature name
|
|
158
|
+
|
|
159
|
+
Notes
|
|
160
|
+
-----
|
|
161
|
+
TODO: extract feature label from ancillary information when an rtdc_ds is
|
|
162
|
+
given.
|
|
163
|
+
"""
|
|
164
|
+
if name in feat_const.feature_name2label:
|
|
165
|
+
label = feat_const.feature_name2label[name]
|
|
166
|
+
elif ML_SCORE_REGEX.match(name):
|
|
167
|
+
# use a generic name for machine-learning features
|
|
168
|
+
label = f"ML score {name[-3:].upper()}"
|
|
169
|
+
else:
|
|
170
|
+
exists = feature_exists(name)
|
|
171
|
+
msg = f"Could not find label for '{name}'"
|
|
172
|
+
msg += " (feature does not exist)" if not exists else ""
|
|
173
|
+
raise ValueError(msg)
|
|
174
|
+
if not with_unit:
|
|
175
|
+
if label.endswith("]") and label.count("["):
|
|
176
|
+
label = label.rsplit("[", 1)[0].strip()
|
|
177
|
+
return label
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def scalar_feature_exists(name):
|
|
181
|
+
"""Convenience method wrapping `feature_exists(..., scalar_only=True)`"""
|
|
182
|
+
return feature_exists(name, scalar_only=True)
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import copy
|
|
2
|
+
|
|
3
|
+
from .meta_parse import (
|
|
4
|
+
fbool, fint, fintlist, func_types, lcstr, f1dfloatduple, fboolorfloat
|
|
5
|
+
)
|
|
6
|
+
|
|
7
|
+
#: All configuration keywords editable by the user
|
|
8
|
+
CFG_ANALYSIS = {
|
|
9
|
+
# filtering parameters
|
|
10
|
+
"filtering": [
|
|
11
|
+
["hierarchy parent", str, "Hierarchy parent of the dataset"],
|
|
12
|
+
["remove invalid events", fbool, "Remove events with inf/nan values"],
|
|
13
|
+
["enable filters", fbool, "Enable filtering"],
|
|
14
|
+
["limit events", fint, "Upper limit for number of filtered events"],
|
|
15
|
+
["polygon filters", fintlist, "Polygon filter indices"],
|
|
16
|
+
],
|
|
17
|
+
# Addition user-defined data
|
|
18
|
+
"calculation": [
|
|
19
|
+
["emodulus lut", str, "Look-up table identifier"],
|
|
20
|
+
["emodulus medium", str, "Medium used (e.g. '0.49% MC-PBS')"],
|
|
21
|
+
["emodulus temperature", float, "Chip temperature [°C]"],
|
|
22
|
+
["emodulus viscosity", float, "Viscosity [Pa*s] if 'medium' unknown"],
|
|
23
|
+
["emodulus viscosity model", str, "Viscosity model for known media"],
|
|
24
|
+
["crosstalk fl21", float, "Fluorescence crosstalk, channel 2 to 1"],
|
|
25
|
+
["crosstalk fl31", float, "Fluorescence crosstalk, channel 3 to 1"],
|
|
26
|
+
["crosstalk fl12", float, "Fluorescence crosstalk, channel 1 to 2"],
|
|
27
|
+
["crosstalk fl32", float, "Fluorescence crosstalk, channel 3 to 2"],
|
|
28
|
+
["crosstalk fl13", float, "Fluorescence crosstalk, channel 1 to 3"],
|
|
29
|
+
["crosstalk fl23", float, "Fluorescence crosstalk, channel 2 to 3"],
|
|
30
|
+
]
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
#: All read-only configuration keywords for a measurement
|
|
34
|
+
CFG_METADATA = {
|
|
35
|
+
# All parameters related to the actual experiment
|
|
36
|
+
"experiment": [
|
|
37
|
+
["date", str, "Date of measurement ('YYYY-MM-DD')"],
|
|
38
|
+
["event count", fint, "Number of recorded events"],
|
|
39
|
+
["run index", fint, "Index of measurement run"],
|
|
40
|
+
["run identifier", str, "Unique measurement identifier"],
|
|
41
|
+
["sample", str, "Measured sample or user-defined reference"],
|
|
42
|
+
["time", str, "Start time of measurement ('HH:MM:SS[.S]')"],
|
|
43
|
+
["timestamp", float, "Start of measurement in unix time [s]"],
|
|
44
|
+
],
|
|
45
|
+
# All special keywords related to RT-FDC
|
|
46
|
+
# This section should not be present for regular RT-DC measurements.
|
|
47
|
+
"fluorescence": [
|
|
48
|
+
# The baseline offset was introduced in 0.33.0. It is added to
|
|
49
|
+
# the trace data to obtain the actual signal used for data
|
|
50
|
+
# processing (e.g. obtaining the fl1_max feature). This is more
|
|
51
|
+
# robust than adding the offset directly to the trace data, because
|
|
52
|
+
# of the possibility of integer overflows. Furthermore, DCKit can
|
|
53
|
+
# set this parameter without modifying the original trace data
|
|
54
|
+
# to correct/remove negative trace data
|
|
55
|
+
# (see https://github.com/DC-analysis/dclab/issues/101).
|
|
56
|
+
# Note that traces accessed from RTDCBase instances are never
|
|
57
|
+
# background-corrected!
|
|
58
|
+
["baseline 1 offset", fint, "Baseline offset channel 1"],
|
|
59
|
+
["baseline 2 offset", fint, "Baseline offset channel 2"],
|
|
60
|
+
["baseline 3 offset", fint, "Baseline offset channel 3"],
|
|
61
|
+
["bit depth", fint, "Trace bit depth"],
|
|
62
|
+
# If a fluorescence channel is used, a channel name *must* be
|
|
63
|
+
# present. If a channel is not used, the channel name *must not*
|
|
64
|
+
# be present. E.g. if only channels 1 and 2 are used, but there
|
|
65
|
+
# are three channels present, then `channel count` is two,
|
|
66
|
+
# `channels installed` is three, and `channel 3 name` is not set.
|
|
67
|
+
["channel 1 name", str, "FL1 description"],
|
|
68
|
+
["channel 2 name", str, "FL2 description"],
|
|
69
|
+
["channel 3 name", str, "FL3 description"],
|
|
70
|
+
["channel count", fint, "Number of active channels"],
|
|
71
|
+
["channels installed", fint, "Number of available channels"],
|
|
72
|
+
# In contrast to `channel ? name`, the laser power *may*
|
|
73
|
+
# be present (but must be set to 0), if a laser line is not used.
|
|
74
|
+
["laser 1 lambda", float, "Laser 1 wavelength [nm]"],
|
|
75
|
+
["laser 1 power", float, "Laser 1 output power [%]"],
|
|
76
|
+
["laser 2 lambda", float, "Laser 2 wavelength [nm]"],
|
|
77
|
+
["laser 2 power", float, "Laser 2 output power [%]"],
|
|
78
|
+
["laser 3 lambda", float, "Laser 3 wavelength [nm]"],
|
|
79
|
+
["laser 3 power", float, "Laser 3 output power [%]"],
|
|
80
|
+
["laser count", fint, "Number of active lasers"],
|
|
81
|
+
["lasers installed", fint, "Number of available lasers"],
|
|
82
|
+
["sample rate", fint, "Trace sample rate [Hz]"],
|
|
83
|
+
["samples per event", fint, "Samples per event"],
|
|
84
|
+
["signal max", float, "Upper voltage detection limit [V]"],
|
|
85
|
+
["signal min", float, "Lower voltage detection limit [V]"],
|
|
86
|
+
["trace median", fint, "Rolling median filter size for traces"],
|
|
87
|
+
],
|
|
88
|
+
# All tdms-related parameters
|
|
89
|
+
"fmt_tdms": [
|
|
90
|
+
["video frame offset", fint, "Missing events at beginning of video"],
|
|
91
|
+
],
|
|
92
|
+
# All imaging-related keywords
|
|
93
|
+
"imaging": [
|
|
94
|
+
["flash device", str, "Light source device type"], # e.g. green LED
|
|
95
|
+
["flash duration", float, "Light source flash duration [µs]"],
|
|
96
|
+
["frame rate", float, "Imaging frame rate [Hz]"],
|
|
97
|
+
["pixel size", float, "Pixel size [µm]"],
|
|
98
|
+
["roi position x", fint, "Image x coordinate on sensor [px]"],
|
|
99
|
+
["roi position y", fint, "Image y coordinate on sensor [px]"],
|
|
100
|
+
["roi size x", fint, "Image width [px]"],
|
|
101
|
+
["roi size y", fint, "Image height [px]"],
|
|
102
|
+
],
|
|
103
|
+
# All parameters for online contour extraction from the event images
|
|
104
|
+
"online_contour": [
|
|
105
|
+
# The option "bg empty" was introduced in dclab 0.34.0 and
|
|
106
|
+
# Shape-In 2.2.2.5.
|
|
107
|
+
# Shape-In writes to the "shapein-warning" log if there are
|
|
108
|
+
# frames with event images (non-empty frames) that had to be
|
|
109
|
+
# used for background correction.
|
|
110
|
+
["bg empty", fbool, "Background correction from empty frames only"],
|
|
111
|
+
["bin area min", fint, "Minium pixel area of binary image event"],
|
|
112
|
+
["bin kernel", fint, "Disk size for binary closing of mask image"],
|
|
113
|
+
["bin threshold", fint, "Threshold for mask from bg-corrected image"],
|
|
114
|
+
["image blur", fint, "Odd sigma for Gaussian blur (21x21 kernel)"],
|
|
115
|
+
["no absdiff", fbool, "Do not use OpenCV 'absdiff' for bg-correction"],
|
|
116
|
+
],
|
|
117
|
+
# All online-filter-related keywords (box filters, soft limit, and
|
|
118
|
+
# polygons are handled in `meta_logic`).
|
|
119
|
+
# Note that "soft limit" means that the event is still included in
|
|
120
|
+
# the dataset, but is not counted for "target event count". On the
|
|
121
|
+
# other hand, "hard limit" means that only those events that are
|
|
122
|
+
# within that filter are written to the dataset.
|
|
123
|
+
"online_filter": [
|
|
124
|
+
# "target*" is only set if measurement is stopped automatically.
|
|
125
|
+
# "target*" is not necessarily reached (e.g. user aborted).
|
|
126
|
+
["target duration", float, "Target measurement duration [min]"],
|
|
127
|
+
["target event count", fint, "Target event count for online gating"],
|
|
128
|
+
],
|
|
129
|
+
# Data processing pipeline
|
|
130
|
+
"pipeline": [
|
|
131
|
+
["dcnum background", str, "Background ID"],
|
|
132
|
+
["dcnum data", str, "Data ID"],
|
|
133
|
+
["dcnum feature", str, "Feature extractor ID"],
|
|
134
|
+
["dcnum gate", str, "Gating ID"],
|
|
135
|
+
["dcnum generation", str, "Generation ID"],
|
|
136
|
+
# The hash is computed by joining the other pipeline identifiers with
|
|
137
|
+
# the "|" character in this order: generation, data, background,
|
|
138
|
+
# segmenter, feature, gate.
|
|
139
|
+
["dcnum hash", str, "Hash"],
|
|
140
|
+
["dcnum mapping", str, "Event mapping from original dataset"],
|
|
141
|
+
["dcnum segmenter", str, "Segmenter ID"],
|
|
142
|
+
# The event yield the number of events the pipeline produced and
|
|
143
|
+
# helps identify files that were e.g. exported from original files.
|
|
144
|
+
["dcnum yield", fint, "Event yield"],
|
|
145
|
+
],
|
|
146
|
+
# All qpi-related keywords
|
|
147
|
+
"qpi": [
|
|
148
|
+
# experiment-related qpi metadata, see qpretrieve for details
|
|
149
|
+
["wavelength", float, "Imaging wavelength [nm]"],
|
|
150
|
+
["medium index", float, "Refractive index of medium"],
|
|
151
|
+
["pixel size raw", float, "Hologram pixel size [µm]."],
|
|
152
|
+
# post-analysis-related qpi metadata
|
|
153
|
+
["software version", str, "Software version(s)"],
|
|
154
|
+
# How background image was created 'experimental' or
|
|
155
|
+
# computation method e.g. 'sparsemed'
|
|
156
|
+
["bg method", str, "Background computation method"],
|
|
157
|
+
# calculation of pha and amp from hologram
|
|
158
|
+
# FFT preprocessing
|
|
159
|
+
# padding: 0 means no padding
|
|
160
|
+
["padding", fint, "Level of padding"],
|
|
161
|
+
["subtract mean", fbool, "Subtract mean before processing"],
|
|
162
|
+
# pipeline_kws
|
|
163
|
+
["filter name", str, "Fourier filter used"],
|
|
164
|
+
# qpretrieve defines the keyword argument `filter_size_interpretation`
|
|
165
|
+
# for determining the filter size in Fourier space. In DC, we
|
|
166
|
+
# need a well-defined value for the filter size. The most logical
|
|
167
|
+
# choice is to interpret the filter size as "frequency index", which
|
|
168
|
+
# is independent of the image shape and yields a good approximation
|
|
169
|
+
# of the actual resolution one can expect. The default value
|
|
170
|
+
# ("sideband distance") is a good choice for general QPI analysis,
|
|
171
|
+
# but there is no meaningful information one could extract from it
|
|
172
|
+
# by just looking at the number. Thus, the "filter size" that we
|
|
173
|
+
# see here corresponds to a filter size set in qpretrieve where
|
|
174
|
+
# `filter_size_interpretation="frequency index"`.
|
|
175
|
+
["filter size", float, "Fourier filter size [1/pix]"],
|
|
176
|
+
["scale to filter", fboolorfloat, "Scale QPI data to filter size"],
|
|
177
|
+
# x, y coordinates, don't set if you wish None to be the default
|
|
178
|
+
["sideband freq", f1dfloatduple, "Sideband coordinates [1/pix]"],
|
|
179
|
+
["invert phase", fbool, "Invert the phase data"],
|
|
180
|
+
# "pixel size proc" depends on `scale_to_filter`.
|
|
181
|
+
# If `scale_to_filter` is False, this is equal to "pixel size raw".
|
|
182
|
+
# If `scale_to_filter` is True or a float, this value will differ from
|
|
183
|
+
# "pixel size raw".
|
|
184
|
+
# RTDC "imaging:pixel size" equals "pixel size proc"
|
|
185
|
+
["pixel size proc", float, "QPI pixel size [µm]."],
|
|
186
|
+
# postprocessing of phase and amplitude
|
|
187
|
+
["amp fit offset", str, "Amplitude offset correction"],
|
|
188
|
+
["amp fit profile", str, "Amplitude profile correction"],
|
|
189
|
+
["pha fit offset", str, "Phase offset correction"],
|
|
190
|
+
["pha fit profile", str, "Phase profile correction"],
|
|
191
|
+
# QPImage background correction mask information
|
|
192
|
+
["amp border px", fint, "Width of border for amplitude [pix]"],
|
|
193
|
+
["pha border px", fint, "Width of border for phase [pix]"],
|
|
194
|
+
# Forward compatible QPImage background correction for trivial
|
|
195
|
+
# masks e.g. "tblr". "tb" useful for RTDC channel.
|
|
196
|
+
["amp border loc", str, "Border location specifier for amplitude"],
|
|
197
|
+
["pha border loc", str, "Border location specifier for phase"],
|
|
198
|
+
# refocusing metadata
|
|
199
|
+
["focus interval", f1dfloatduple, "Focus interval to search [µm]"],
|
|
200
|
+
["focus metric", str, "Metric used to calculate focus"],
|
|
201
|
+
["focus minimizer", str, "Minimizer used to calculate focus"],
|
|
202
|
+
["focus kernel", str, "Propagation kernel"],
|
|
203
|
+
["focus padding", fint, "Level of padding for refocus"],
|
|
204
|
+
],
|
|
205
|
+
# All setup-related keywords, except imaging
|
|
206
|
+
"setup": [
|
|
207
|
+
["channel width", float, "Width of microfluidic channel [µm]"],
|
|
208
|
+
["chip identifier", lcstr, "Unique identifier of the chip used"],
|
|
209
|
+
["chip region", lcstr, "Imaged chip region (channel or reservoir)"],
|
|
210
|
+
["flow rate", float, "Flow rate in channel [µL/s]"],
|
|
211
|
+
["flow rate sample", float, "Sample flow rate [µL/s]"],
|
|
212
|
+
["flow rate sheath", float, "Sheath flow rate [µL/s]"],
|
|
213
|
+
["identifier", str, "Unique setup identifier"],
|
|
214
|
+
# "medium" can have various values; it is used to calculate viscosity
|
|
215
|
+
["medium", str, "Medium used"],
|
|
216
|
+
["module composition", str, "Comma-separated list of modules used"],
|
|
217
|
+
["software version", str, "Acquisition software with version"],
|
|
218
|
+
["temperature", float, "Mean chip temperature [°C]"],
|
|
219
|
+
],
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
# CFG convenience lists and dicts
|
|
223
|
+
_cfg = copy.deepcopy(CFG_METADATA)
|
|
224
|
+
_cfg.update(CFG_ANALYSIS)
|
|
225
|
+
|
|
226
|
+
#: dict with metadata description
|
|
227
|
+
config_descr = {}
|
|
228
|
+
for _key in _cfg:
|
|
229
|
+
config_descr[_key] = {}
|
|
230
|
+
for _subkey, __, _descr in _cfg[_key]:
|
|
231
|
+
config_descr[_key][_subkey] = _descr
|
|
232
|
+
|
|
233
|
+
#: dict of dicts containing functions to convert input data
|
|
234
|
+
config_funcs = {}
|
|
235
|
+
for _key in _cfg:
|
|
236
|
+
config_funcs[_key] = {}
|
|
237
|
+
for _subkey, _type, __ in _cfg[_key]:
|
|
238
|
+
config_funcs[_key][_subkey] = _type
|
|
239
|
+
|
|
240
|
+
#: dict with section as keys and config parameter names as values
|
|
241
|
+
config_keys = {}
|
|
242
|
+
for _key in _cfg:
|
|
243
|
+
config_keys[_key] = [it[0] for it in _cfg[_key]]
|
|
244
|
+
|
|
245
|
+
#: dict of dicts containing the type of section parameters
|
|
246
|
+
config_types = {}
|
|
247
|
+
for _key in _cfg:
|
|
248
|
+
config_types[_key] = {}
|
|
249
|
+
for _subkey, _type, __ in _cfg[_key]:
|
|
250
|
+
if _type in func_types:
|
|
251
|
+
_type = func_types[_type]
|
|
252
|
+
config_types[_key][_subkey] = _type
|