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.

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,154 @@
1
+ """Split an .rtdc file into smaller .rtdc files"""
2
+ from __future__ import annotations
3
+
4
+ import argparse
5
+ import pathlib
6
+ import warnings
7
+
8
+ import hdf5plugin
9
+
10
+ from ..rtdc_dataset import fmt_tdms, new_dataset, RTDCWriter
11
+ from .._version import version
12
+
13
+ from . import common
14
+
15
+
16
+ def split(
17
+ path_in: str | pathlib.Path = None,
18
+ path_out: str | pathlib.Path = None,
19
+ split_events: int = 10000,
20
+ skip_initial_empty_image: bool = True,
21
+ skip_final_empty_image: bool = True,
22
+ ret_out_paths: bool = False,
23
+ verbose: bool = False):
24
+ """Split a measurement file
25
+
26
+ Parameters
27
+ ----------
28
+ path_in: str or pathlib.Path
29
+ path of input measurement file
30
+ path_out: str or pathlib.Path
31
+ path to output directory (optional)
32
+ split_events: int
33
+ maximum number of events in each output file
34
+ skip_initial_empty_image: bool
35
+ remove the first event of the dataset if the image is zero
36
+ skip_final_empty_image: bool
37
+ remove the final event of the dataset if the image is zero
38
+ ret_out_paths:
39
+ if True, return the list of output file paths
40
+ verbose: bool
41
+ if True, print messages to stdout
42
+
43
+ Returns
44
+ -------
45
+ [out_paths]: list of pathlib.Path
46
+ List of generated files (only if `ret_out_paths` is specified)
47
+ """
48
+ cmp_kw = hdf5plugin.Zstd(clevel=5)
49
+ if path_in is None:
50
+ parser = split_parser()
51
+ args = parser.parse_args()
52
+
53
+ path_in = pathlib.Path(args.path_in).resolve()
54
+ path_out = args.path_out
55
+ split_events = args.split_events
56
+ skip_initial_empty_image = not args.include_empty_boundary_images
57
+ skip_final_empty_image = not args.include_empty_boundary_images
58
+ verbose = True
59
+
60
+ if path_out in ["SAME", None]: # default to input directory
61
+ path_out = path_in.parent
62
+
63
+ path_in = pathlib.Path(path_in)
64
+ path_out = pathlib.Path(path_out)
65
+
66
+ logs = {"dclab-split": common.get_command_log(paths=[path_in])}
67
+
68
+ paths_gen = []
69
+ paths_temp = []
70
+ with warnings.catch_warnings(record=True) as w:
71
+ warnings.simplefilter("always")
72
+ # ignore ResourceWarning: unclosed file <_io.BufferedReader...>
73
+ warnings.simplefilter("ignore", ResourceWarning) # noqa: F821
74
+ if fmt_tdms.NPTDMS_AVAILABLE: # tdms-related warning filters
75
+ # ignore SlowVideoWarning
76
+ warnings.simplefilter("ignore",
77
+ fmt_tdms.event_image.SlowVideoWarning)
78
+ if skip_initial_empty_image:
79
+ # If the initial frame is skipped when empty,
80
+ # suppress any related warning messages.
81
+ warnings.simplefilter(
82
+ "ignore",
83
+ fmt_tdms.event_image.InitialFrameMissingWarning)
84
+
85
+ with new_dataset(path_in) as ds:
86
+ num_files = len(ds) // split_events
87
+ if len(ds) % split_events:
88
+ num_files += 1
89
+ for ii in range(num_files):
90
+ pp = path_out / f"{path_in.stem}_{ii+1:04d}.rtdc"
91
+ pt = pp.with_suffix(".rtdc~")
92
+ paths_gen.append(pp)
93
+ paths_temp.append(pt)
94
+ if verbose:
95
+ print(f"Generating {ii+1:d}/{num_files:d}: {pt}")
96
+ ds.filter.manual[:] = False # reset filter
97
+ ds.filter.manual[ii*split_events:(ii+1)*split_events] = True
98
+ common.skip_empty_image_events(
99
+ ds=ds,
100
+ initial=skip_initial_empty_image,
101
+ final=skip_final_empty_image)
102
+ ds.apply_filter()
103
+ ds.export.hdf5(path=pt,
104
+ features=ds.features_innate,
105
+ logs=True,
106
+ tables=True,
107
+ basins=True,
108
+ filtered=True,
109
+ compression_kwargs=cmp_kw,
110
+ )
111
+
112
+ if w:
113
+ logs["dclab-split-warnings"] = common.assemble_warnings(w)
114
+ sample_name = ds.config["experiment"]["sample"]
115
+
116
+ # Add the logs and update sample name
117
+ for ii, pt in enumerate(paths_temp):
118
+ meta = {"experiment": {"sample": f"{sample_name} {ii+1}/{num_files}"}}
119
+ with RTDCWriter(pt, compression_kwargs=cmp_kw) as hw:
120
+ for name in logs:
121
+ hw.store_log(name, logs[name])
122
+ hw.store_metadata(meta)
123
+
124
+ for pt, pp in zip(paths_temp, paths_gen):
125
+ pt.rename(pp)
126
+
127
+ if ret_out_paths:
128
+ return paths_gen
129
+
130
+
131
+ def split_parser():
132
+ descr = "Split an RT-DC measurement file (.tdms or .rtdc) into multiple " \
133
+ + "smaller .rtdc files."
134
+ parser = argparse.ArgumentParser(description=descr)
135
+ parser.add_argument('path_in', metavar="PATH_IN", type=str,
136
+ help='Input path (.tdms or .rtdc file)')
137
+ parser.add_argument('--path_out', metavar="PATH_OUT", type=str,
138
+ default="SAME",
139
+ help='Output directory (defaults to same directory)')
140
+ parser.add_argument('--split-events', type=int, default=10000,
141
+ help='Maximum number of events in each output file')
142
+ parser.add_argument('--include-empty-boundary-images',
143
+ dest='include_empty_boundary_images',
144
+ action='store_true',
145
+ help='In old versions of Shape-In, the first or last '
146
+ + 'images were sometimes not stored in the '
147
+ + 'resulting .avi file. In dclab, such images '
148
+ + 'are represented as zero-valued images. Set '
149
+ + 'this option, if you wish to include these '
150
+ + 'events with empty image data.')
151
+ parser.set_defaults(include_empty_boundary_images=False)
152
+ parser.add_argument('--version', action='version',
153
+ version=f'dclab-split {version}')
154
+ return parser
@@ -0,0 +1,186 @@
1
+ """Convert .tdms to .rtdc files"""
2
+ import argparse
3
+ import pathlib
4
+ import warnings
5
+
6
+ import hdf5plugin
7
+
8
+ from ..rtdc_dataset import fmt_tdms, new_dataset, RTDCWriter
9
+ from .._version import version
10
+
11
+ from . import common
12
+
13
+
14
+ def tdms2rtdc(path_tdms=None, path_rtdc=None, compute_features=False,
15
+ skip_initial_empty_image=True, skip_final_empty_image=True,
16
+ verbose=False):
17
+ """Convert .tdms datasets to the hdf5-based .rtdc file format
18
+
19
+ Parameters
20
+ ----------
21
+ path_tdms: str or pathlib.Path
22
+ Path to input .tdms file
23
+ path_rtdc: str or pathlib.Path
24
+ Path to output .rtdc file
25
+ compute_features: bool
26
+ If `True`, compute all ancillary features and store them in the
27
+ output file
28
+ skip_initial_empty_image: bool
29
+ In old versions of Shape-In, the first image was sometimes
30
+ not stored in the resulting .avi file. In dclab, such images
31
+ are represented as zero-valued images. If `True` (default),
32
+ this first image is not included in the resulting .rtdc file.
33
+ skip_final_empty_image: bool
34
+ In other versions of Shape-In, the final image is sometimes
35
+ also not stored in the .avi file. If `True` (default), this
36
+ final image is not included in the resulting .rtdc file.
37
+ verbose: bool
38
+ If `True`, print messages to stdout
39
+ """
40
+ cmp_kw = hdf5plugin.Zstd(clevel=5)
41
+ if path_tdms is None or path_rtdc is None:
42
+ parser = tdms2rtdc_parser()
43
+ args = parser.parse_args()
44
+
45
+ path_tdms = pathlib.Path(args.tdms_path).resolve()
46
+ path_rtdc = pathlib.Path(args.rtdc_path)
47
+ compute_features = args.compute_features
48
+ skip_initial_empty_image = not args.include_empty_boundary_images
49
+ skip_final_empty_image = not args.include_empty_boundary_images
50
+ verbose = True
51
+
52
+ # Determine whether input path is a tdms file or a directory
53
+ if path_tdms.is_dir():
54
+ # we have a directory to search
55
+ files_tdms = fmt_tdms.get_tdms_files(path_tdms)
56
+ if path_rtdc.is_file():
57
+ raise ValueError(
58
+ f"Output path is a file, expected folder: '{path_rtdc}'!")
59
+ files_rtdc = []
60
+ for path_in in files_tdms:
61
+ path_in = pathlib.Path(path_in)
62
+ rp = path_in.relative_to(path_tdms)
63
+ # determine output file name (same relative path)
64
+ rpr = path_rtdc / rp.with_suffix(".rtdc")
65
+ files_rtdc.append(rpr)
66
+ else:
67
+ # we have a single file or a non-existent path
68
+ files_tdms = [path_tdms]
69
+ files_rtdc = [path_rtdc]
70
+
71
+ files_tdms, files_rtdc, files_temp = common.setup_task_paths(
72
+ paths_in=files_tdms,
73
+ paths_out=files_rtdc,
74
+ allowed_input_suffixes=[".tdms"]
75
+ )
76
+
77
+ for ii in range(len(files_tdms)):
78
+ path_in = files_tdms[ii]
79
+ path_out = files_rtdc[ii]
80
+ path_temp = files_temp[ii]
81
+
82
+ if verbose:
83
+ common.print_info(
84
+ f"Converting {ii+1:d}/{len(files_tdms):d}: {path_in}")
85
+ # create directory
86
+ path_out.parent.mkdir(parents=True, exist_ok=True)
87
+ # load and export dataset
88
+ with warnings.catch_warnings(record=True) as w:
89
+ warnings.simplefilter("always")
90
+ # ignore ResourceWarning: unclosed file <_io.BufferedReader...>
91
+ warnings.simplefilter("ignore", ResourceWarning) # noqa: F821
92
+ # ignore SlowVideoWarning
93
+ warnings.simplefilter("ignore",
94
+ fmt_tdms.event_image.SlowVideoWarning)
95
+ if skip_initial_empty_image:
96
+ # If the initial frame is skipped when empty,
97
+ # suppress any related warning messages.
98
+ warnings.simplefilter(
99
+ "ignore",
100
+ fmt_tdms.event_image.InitialFrameMissingWarning)
101
+
102
+ with new_dataset(path_in) as ds:
103
+ # determine features to export
104
+ if compute_features:
105
+ features = ds.features
106
+ else:
107
+ # consider special case for "image", "trace", and "contour"
108
+ # (This will export both "mask" and "contour".
109
+ # The "mask" is computed from "contour" and it is needed
110
+ # by dclab for other ancillary features. We still keep
111
+ # "contour" because it is original data.
112
+ features = ds.features_innate
113
+
114
+ common.skip_empty_image_events(
115
+ ds=ds,
116
+ initial=skip_initial_empty_image,
117
+ final=skip_final_empty_image)
118
+ # export as hdf5
119
+ ds.export.hdf5(path=path_temp,
120
+ features=features,
121
+ filtered=True,
122
+ override=True,
123
+ compression_kwargs=cmp_kw)
124
+
125
+ # write logs
126
+ custom_dict = {}
127
+ # computed features
128
+ cfeats = list(set(features) - set(ds.features_innate))
129
+ if "mask" in features:
130
+ # Mask is always computed from contour data
131
+ cfeats.append("mask")
132
+ custom_dict["ancillary features"] = sorted(cfeats)
133
+
134
+ # command log
135
+ logs = {"dclab-tdms2rtdc": common.get_command_log(
136
+ paths=[path_in], custom_dict=custom_dict)}
137
+ # warnings log
138
+ if w:
139
+ logs["dclab-tdms2rtdc-warnings"] = \
140
+ common.assemble_warnings(w)
141
+ logs.update(ds.logs)
142
+ with RTDCWriter(path_temp, compression_kwargs=cmp_kw) as hw:
143
+ for name in logs:
144
+ hw.store_log(name, logs[name])
145
+
146
+ # Finally, rename temp to out
147
+ path_temp.rename(path_out)
148
+
149
+
150
+ def tdms2rtdc_parser():
151
+ descr = "Convert RT-DC .tdms files to the hdf5-based .rtdc file format. " \
152
+ + "Note: Do not delete original .tdms files after conversion. " \
153
+ + "The conversion might be incomplete."
154
+ parser = argparse.ArgumentParser(description=descr)
155
+ parser.add_argument('--compute-ancillary-features',
156
+ dest='compute_features',
157
+ action='store_true',
158
+ help='Compute features, such as volume or emodulus, '
159
+ + 'that are otherwise computed on-the-fly. '
160
+ + 'Use this if you want to minimize analysis '
161
+ + 'time in e.g. DCscope. CAUTION: ancillary '
162
+ + 'feature recipes might be subject to change '
163
+ + '(e.g. if an error is found in the recipe). '
164
+ + 'Disabling this option maximizes '
165
+ + 'compatibility with future versions and '
166
+ + 'allows to isolate the original data.')
167
+ parser.set_defaults(compute_features=False)
168
+ parser.add_argument('--include-empty-boundary-images',
169
+ dest='include_empty_boundary_images',
170
+ action='store_true',
171
+ help='In old versions of Shape-In, the first or last '
172
+ + 'images were sometimes not stored in the '
173
+ + 'resulting .avi file. In dclab, such images '
174
+ + 'are represented as zero-valued images. Set '
175
+ + 'this option, if you wish to include these '
176
+ + 'events with empty image data.')
177
+ parser.set_defaults(include_empty_boundary_images=False)
178
+ parser.add_argument('tdms_path', metavar="TDMS_PATH", type=str,
179
+ help='Input path (tdms file or folder containing '
180
+ + 'tdms files)')
181
+ parser.add_argument('rtdc_path', metavar="RTDC_PATH", type=str,
182
+ help='Output path (file or folder), existing data '
183
+ + 'will be overridden')
184
+ parser.add_argument('--version', action='version',
185
+ version=f'dclab-tdms2rtdc {version}')
186
+ return parser
@@ -0,0 +1,75 @@
1
+ """Verify dataset integrity"""
2
+ import argparse
3
+ import pathlib
4
+ import sys
5
+
6
+ from ..rtdc_dataset import check_dataset, fmt_tdms
7
+ from .._version import version
8
+
9
+ from . import common
10
+
11
+
12
+ def verify_dataset(path_in=None):
13
+ """Perform checks on experimental datasets"""
14
+ if path_in is None:
15
+ parser = verify_dataset_parser()
16
+ args = parser.parse_args()
17
+ path_in = pathlib.Path(args.path).resolve()
18
+ if not path_in.exists():
19
+ common.print_violation(f"File not found: {path_in}")
20
+ return sys.exit(4)
21
+ else:
22
+ common.print_info(f"Checking {path_in}")
23
+ # The exit status of this script. Non-zero exit status means:
24
+ # 1: alerts
25
+ # 2: violations
26
+ # 3: alerts and violations
27
+ # 4: other error
28
+ exit_status = 4
29
+ try:
30
+ viol, aler, info = check_dataset(path_in)
31
+ except fmt_tdms.InvalidTDMSFileFormatError:
32
+ common.print_violation("Invalid tdms file format!")
33
+ except fmt_tdms.IncompleteTDMSFileFormatError:
34
+ common.print_violation("Incomplete dataset!")
35
+ except fmt_tdms.ContourIndexingError:
36
+ common.print_violation("Invalid contour data!")
37
+ except fmt_tdms.InvalidVideoFileError:
38
+ common.print_violation("Invalid image data!")
39
+ except BaseException as e:
40
+ common.print_violation(f"{e.__class__.__name__}: {', '.join(e.args)}")
41
+ else:
42
+ for inf in info:
43
+ common.print_info(inf)
44
+ for ale in aler:
45
+ common.print_alert(ale)
46
+ for vio in viol:
47
+ common.print_violation(vio)
48
+ common.print_info(f"Check Complete: {len(viol)} violations and "
49
+ + f"{len(aler)} alerts")
50
+ if aler and viol:
51
+ exit_status = 3
52
+ elif aler:
53
+ exit_status = 1
54
+ elif viol:
55
+ exit_status = 2
56
+ else:
57
+ # everything is ok
58
+ exit_status = 0
59
+ finally:
60
+ # return sys.exit for testing (monkeypatched)
61
+ return sys.exit(exit_status)
62
+
63
+
64
+ def verify_dataset_parser():
65
+ descr = "Check experimental datasets for completeness. This command " \
66
+ + "is used e.g. to enforce data integrity with Shape-In. The " \
67
+ + "following exit codes are defined: ``0: valid dataset``, " \
68
+ + "``1: alerts encountered``, ``2: violations encountered``, " \
69
+ + "``3: alerts and violations``, ``4: other error``."
70
+ parser = argparse.ArgumentParser(description=descr)
71
+ parser.add_argument('path', metavar='PATH', type=str,
72
+ help='Path to experimental dataset')
73
+ parser.add_argument('--version', action='version',
74
+ version=f'dclab-verify-dataset {version}')
75
+ return parser
@@ -0,0 +1,79 @@
1
+ # flake8: noqa: F401
2
+ import warnings
3
+
4
+ from .feat_const import (
5
+ FEATURES_SCALAR, FEATURES_NON_SCALAR, FLUOR_TRACES,
6
+ # these should not be used
7
+ feature_names, feature_labels, feature_name2label,
8
+ # this one should also not be used, but we wait with deprecation,
9
+ # because DCscope heavily relies on it (it shouldn't)
10
+ scalar_feature_names
11
+ )
12
+ from .feat_logic import (
13
+ check_feature_shape, feature_exists, get_feature_label,
14
+ scalar_feature_exists
15
+ )
16
+ from .meta_const import (
17
+ CFG_ANALYSIS, CFG_METADATA, config_keys,
18
+ # these should not be used (in contrast, `config_keys` is quite
19
+ # important for iterating over all internal configuration keys)
20
+ config_descr, config_funcs, config_types,
21
+ )
22
+ from .meta_logic import (
23
+ config_key_exists,
24
+ get_config_value_descr, get_config_value_func, get_config_value_type
25
+ )
26
+
27
+
28
+ class DeprecatedObject:
29
+ def __init__(self, anobject, name, new):
30
+ self.anobject = anobject
31
+ self.message = f"dclab.dfn.{name} is deprecated, please use " \
32
+ + f"dclab.dfn.{new} instead."
33
+
34
+ def __getattr__(self, item):
35
+ warnings.warn(self.message, DeprecationWarning)
36
+ return self.anobject.__getattr__(item)
37
+
38
+ def __getitem__(self, item):
39
+ warnings.warn(self.message, DeprecationWarning)
40
+ return self.anobject.__getitem__(item)
41
+
42
+ def __iter__(self):
43
+ warnings.warn(self.message, DeprecationWarning)
44
+ return self.anobject.__iter__()
45
+
46
+ def __contains__(self, item):
47
+ warnings.warn(self.message, DeprecationWarning)
48
+ return self.anobject.__contains__(item)
49
+
50
+
51
+ config_descr = DeprecatedObject(config_descr,
52
+ "config_descr",
53
+ "get_config_value_descr",
54
+ )
55
+
56
+ config_funcs = DeprecatedObject(config_funcs,
57
+ "config_funcs",
58
+ "get_config_value_func",
59
+ )
60
+
61
+ config_types = DeprecatedObject(config_types,
62
+ "config_types",
63
+ "get_config_value_type",
64
+ )
65
+
66
+ feature_names = DeprecatedObject(feature_names,
67
+ "feature_names",
68
+ "feature_exists",
69
+ )
70
+
71
+ feature_labels = DeprecatedObject(feature_labels,
72
+ "feature_labels",
73
+ "get_feature_label",
74
+ )
75
+
76
+ feature_name2label = DeprecatedObject(feature_name2label,
77
+ "feature_name2label",
78
+ "get_feature_label",
79
+ )