dclab 0.67.0__cp314-cp314-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.
- 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-314-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-314-darwin.so +0 -0
- dclab/external/skimage/_find_contours_cy.pyx +188 -0
- dclab/external/skimage/_pnpoly.cpython-314-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-314-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
dclab/cli/task_split.py
ADDED
|
@@ -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
|
+
)
|