dclab 0.67.0__cp314-cp314t-macosx_11_0_arm64.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.

Files changed (142) hide show
  1. dclab/__init__.py +41 -0
  2. dclab/_version.py +34 -0
  3. dclab/cached.py +97 -0
  4. dclab/cli/__init__.py +10 -0
  5. dclab/cli/common.py +237 -0
  6. dclab/cli/task_compress.py +126 -0
  7. dclab/cli/task_condense.py +223 -0
  8. dclab/cli/task_join.py +229 -0
  9. dclab/cli/task_repack.py +98 -0
  10. dclab/cli/task_split.py +154 -0
  11. dclab/cli/task_tdms2rtdc.py +186 -0
  12. dclab/cli/task_verify_dataset.py +75 -0
  13. dclab/definitions/__init__.py +79 -0
  14. dclab/definitions/feat_const.py +202 -0
  15. dclab/definitions/feat_logic.py +182 -0
  16. dclab/definitions/meta_const.py +252 -0
  17. dclab/definitions/meta_logic.py +111 -0
  18. dclab/definitions/meta_parse.py +94 -0
  19. dclab/downsampling.cpython-314t-darwin.so +0 -0
  20. dclab/downsampling.pyx +230 -0
  21. dclab/external/__init__.py +4 -0
  22. dclab/external/packaging/LICENSE +3 -0
  23. dclab/external/packaging/LICENSE.APACHE +177 -0
  24. dclab/external/packaging/LICENSE.BSD +23 -0
  25. dclab/external/packaging/__init__.py +6 -0
  26. dclab/external/packaging/_structures.py +61 -0
  27. dclab/external/packaging/version.py +505 -0
  28. dclab/external/skimage/LICENSE +28 -0
  29. dclab/external/skimage/__init__.py +2 -0
  30. dclab/external/skimage/_find_contours.py +216 -0
  31. dclab/external/skimage/_find_contours_cy.cpython-314t-darwin.so +0 -0
  32. dclab/external/skimage/_find_contours_cy.pyx +188 -0
  33. dclab/external/skimage/_pnpoly.cpython-314t-darwin.so +0 -0
  34. dclab/external/skimage/_pnpoly.pyx +99 -0
  35. dclab/external/skimage/_shared/__init__.py +1 -0
  36. dclab/external/skimage/_shared/geometry.cpython-314t-darwin.so +0 -0
  37. dclab/external/skimage/_shared/geometry.pxd +6 -0
  38. dclab/external/skimage/_shared/geometry.pyx +55 -0
  39. dclab/external/skimage/measure.py +7 -0
  40. dclab/external/skimage/pnpoly.py +53 -0
  41. dclab/external/statsmodels/LICENSE +35 -0
  42. dclab/external/statsmodels/__init__.py +6 -0
  43. dclab/external/statsmodels/nonparametric/__init__.py +1 -0
  44. dclab/external/statsmodels/nonparametric/_kernel_base.py +203 -0
  45. dclab/external/statsmodels/nonparametric/kernel_density.py +165 -0
  46. dclab/external/statsmodels/nonparametric/kernels.py +36 -0
  47. dclab/features/__init__.py +9 -0
  48. dclab/features/bright.py +81 -0
  49. dclab/features/bright_bc.py +93 -0
  50. dclab/features/bright_perc.py +63 -0
  51. dclab/features/contour.py +161 -0
  52. dclab/features/emodulus/__init__.py +339 -0
  53. dclab/features/emodulus/load.py +252 -0
  54. dclab/features/emodulus/lut_HE-2D-FEM-22.txt +16432 -0
  55. dclab/features/emodulus/lut_HE-3D-FEM-22.txt +1276 -0
  56. dclab/features/emodulus/lut_LE-2D-FEM-19.txt +13082 -0
  57. dclab/features/emodulus/pxcorr.py +135 -0
  58. dclab/features/emodulus/scale_linear.py +247 -0
  59. dclab/features/emodulus/viscosity.py +260 -0
  60. dclab/features/fl_crosstalk.py +95 -0
  61. dclab/features/inert_ratio.py +377 -0
  62. dclab/features/volume.py +242 -0
  63. dclab/http_utils.py +322 -0
  64. dclab/isoelastics/__init__.py +468 -0
  65. dclab/isoelastics/iso_HE-2D-FEM-22-area_um-deform.txt +2440 -0
  66. dclab/isoelastics/iso_HE-2D-FEM-22-volume-deform.txt +2635 -0
  67. dclab/isoelastics/iso_HE-3D-FEM-22-area_um-deform.txt +1930 -0
  68. dclab/isoelastics/iso_HE-3D-FEM-22-volume-deform.txt +2221 -0
  69. dclab/isoelastics/iso_LE-2D-FEM-19-area_um-deform.txt +2151 -0
  70. dclab/isoelastics/iso_LE-2D-FEM-19-volume-deform.txt +2250 -0
  71. dclab/isoelastics/iso_LE-2D-ana-18-area_um-deform.txt +1266 -0
  72. dclab/kde/__init__.py +1 -0
  73. dclab/kde/base.py +459 -0
  74. dclab/kde/contours.py +222 -0
  75. dclab/kde/methods.py +313 -0
  76. dclab/kde_contours.py +10 -0
  77. dclab/kde_methods.py +11 -0
  78. dclab/lme4/__init__.py +5 -0
  79. dclab/lme4/lme4_template.R +94 -0
  80. dclab/lme4/rsetup.py +204 -0
  81. dclab/lme4/wrapr.py +386 -0
  82. dclab/polygon_filter.py +398 -0
  83. dclab/rtdc_dataset/__init__.py +15 -0
  84. dclab/rtdc_dataset/check.py +902 -0
  85. dclab/rtdc_dataset/config.py +533 -0
  86. dclab/rtdc_dataset/copier.py +353 -0
  87. dclab/rtdc_dataset/core.py +896 -0
  88. dclab/rtdc_dataset/export.py +867 -0
  89. dclab/rtdc_dataset/feat_anc_core/__init__.py +24 -0
  90. dclab/rtdc_dataset/feat_anc_core/af_basic.py +75 -0
  91. dclab/rtdc_dataset/feat_anc_core/af_emodulus.py +160 -0
  92. dclab/rtdc_dataset/feat_anc_core/af_fl_max_ctc.py +133 -0
  93. dclab/rtdc_dataset/feat_anc_core/af_image_contour.py +113 -0
  94. dclab/rtdc_dataset/feat_anc_core/af_ml_class.py +102 -0
  95. dclab/rtdc_dataset/feat_anc_core/ancillary_feature.py +320 -0
  96. dclab/rtdc_dataset/feat_anc_ml/__init__.py +32 -0
  97. dclab/rtdc_dataset/feat_anc_plugin/__init__.py +3 -0
  98. dclab/rtdc_dataset/feat_anc_plugin/plugin_feature.py +329 -0
  99. dclab/rtdc_dataset/feat_basin.py +762 -0
  100. dclab/rtdc_dataset/feat_temp.py +102 -0
  101. dclab/rtdc_dataset/filter.py +263 -0
  102. dclab/rtdc_dataset/fmt_dcor/__init__.py +7 -0
  103. dclab/rtdc_dataset/fmt_dcor/access_token.py +52 -0
  104. dclab/rtdc_dataset/fmt_dcor/api.py +173 -0
  105. dclab/rtdc_dataset/fmt_dcor/base.py +299 -0
  106. dclab/rtdc_dataset/fmt_dcor/basin.py +73 -0
  107. dclab/rtdc_dataset/fmt_dcor/logs.py +26 -0
  108. dclab/rtdc_dataset/fmt_dcor/tables.py +66 -0
  109. dclab/rtdc_dataset/fmt_dict.py +103 -0
  110. dclab/rtdc_dataset/fmt_hdf5/__init__.py +6 -0
  111. dclab/rtdc_dataset/fmt_hdf5/base.py +192 -0
  112. dclab/rtdc_dataset/fmt_hdf5/basin.py +30 -0
  113. dclab/rtdc_dataset/fmt_hdf5/events.py +276 -0
  114. dclab/rtdc_dataset/fmt_hdf5/feat_defect.py +164 -0
  115. dclab/rtdc_dataset/fmt_hdf5/logs.py +33 -0
  116. dclab/rtdc_dataset/fmt_hdf5/tables.py +60 -0
  117. dclab/rtdc_dataset/fmt_hierarchy/__init__.py +11 -0
  118. dclab/rtdc_dataset/fmt_hierarchy/base.py +278 -0
  119. dclab/rtdc_dataset/fmt_hierarchy/events.py +146 -0
  120. dclab/rtdc_dataset/fmt_hierarchy/hfilter.py +140 -0
  121. dclab/rtdc_dataset/fmt_hierarchy/mapper.py +134 -0
  122. dclab/rtdc_dataset/fmt_http.py +102 -0
  123. dclab/rtdc_dataset/fmt_s3.py +354 -0
  124. dclab/rtdc_dataset/fmt_tdms/__init__.py +476 -0
  125. dclab/rtdc_dataset/fmt_tdms/event_contour.py +264 -0
  126. dclab/rtdc_dataset/fmt_tdms/event_image.py +220 -0
  127. dclab/rtdc_dataset/fmt_tdms/event_mask.py +62 -0
  128. dclab/rtdc_dataset/fmt_tdms/event_trace.py +146 -0
  129. dclab/rtdc_dataset/fmt_tdms/exc.py +37 -0
  130. dclab/rtdc_dataset/fmt_tdms/naming.py +151 -0
  131. dclab/rtdc_dataset/load.py +77 -0
  132. dclab/rtdc_dataset/meta_table.py +25 -0
  133. dclab/rtdc_dataset/writer.py +1019 -0
  134. dclab/statistics.py +226 -0
  135. dclab/util.py +176 -0
  136. dclab/warn.py +15 -0
  137. dclab-0.67.0.dist-info/METADATA +153 -0
  138. dclab-0.67.0.dist-info/RECORD +142 -0
  139. dclab-0.67.0.dist-info/WHEEL +6 -0
  140. dclab-0.67.0.dist-info/entry_points.txt +8 -0
  141. dclab-0.67.0.dist-info/licenses/LICENSE +283 -0
  142. 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