dclab 0.62.11__cp313-cp313-win_amd64.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 (137) hide show
  1. dclab/__init__.py +23 -0
  2. dclab/_version.py +16 -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 +183 -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.cp313-win_amd64.pyd +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.cp313-win_amd64.pyd +0 -0
  32. dclab/external/skimage/_find_contours_cy.pyx +188 -0
  33. dclab/external/skimage/_pnpoly.cp313-win_amd64.pyd +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.cp313-win_amd64.pyd +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 +256 -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_contours.py +222 -0
  73. dclab/kde_methods.py +303 -0
  74. dclab/lme4/__init__.py +5 -0
  75. dclab/lme4/lme4_template.R +94 -0
  76. dclab/lme4/rsetup.py +204 -0
  77. dclab/lme4/wrapr.py +386 -0
  78. dclab/polygon_filter.py +398 -0
  79. dclab/rtdc_dataset/__init__.py +15 -0
  80. dclab/rtdc_dataset/check.py +902 -0
  81. dclab/rtdc_dataset/config.py +533 -0
  82. dclab/rtdc_dataset/copier.py +353 -0
  83. dclab/rtdc_dataset/core.py +1001 -0
  84. dclab/rtdc_dataset/export.py +737 -0
  85. dclab/rtdc_dataset/feat_anc_core/__init__.py +24 -0
  86. dclab/rtdc_dataset/feat_anc_core/af_basic.py +75 -0
  87. dclab/rtdc_dataset/feat_anc_core/af_emodulus.py +160 -0
  88. dclab/rtdc_dataset/feat_anc_core/af_fl_max_ctc.py +133 -0
  89. dclab/rtdc_dataset/feat_anc_core/af_image_contour.py +113 -0
  90. dclab/rtdc_dataset/feat_anc_core/af_ml_class.py +102 -0
  91. dclab/rtdc_dataset/feat_anc_core/ancillary_feature.py +320 -0
  92. dclab/rtdc_dataset/feat_anc_ml/__init__.py +32 -0
  93. dclab/rtdc_dataset/feat_anc_plugin/__init__.py +3 -0
  94. dclab/rtdc_dataset/feat_anc_plugin/plugin_feature.py +329 -0
  95. dclab/rtdc_dataset/feat_basin.py +550 -0
  96. dclab/rtdc_dataset/feat_temp.py +102 -0
  97. dclab/rtdc_dataset/filter.py +263 -0
  98. dclab/rtdc_dataset/fmt_dcor/__init__.py +7 -0
  99. dclab/rtdc_dataset/fmt_dcor/access_token.py +52 -0
  100. dclab/rtdc_dataset/fmt_dcor/api.py +111 -0
  101. dclab/rtdc_dataset/fmt_dcor/base.py +200 -0
  102. dclab/rtdc_dataset/fmt_dcor/basin.py +73 -0
  103. dclab/rtdc_dataset/fmt_dcor/logs.py +26 -0
  104. dclab/rtdc_dataset/fmt_dcor/tables.py +42 -0
  105. dclab/rtdc_dataset/fmt_dict.py +103 -0
  106. dclab/rtdc_dataset/fmt_hdf5/__init__.py +6 -0
  107. dclab/rtdc_dataset/fmt_hdf5/base.py +192 -0
  108. dclab/rtdc_dataset/fmt_hdf5/basin.py +30 -0
  109. dclab/rtdc_dataset/fmt_hdf5/events.py +257 -0
  110. dclab/rtdc_dataset/fmt_hdf5/feat_defect.py +164 -0
  111. dclab/rtdc_dataset/fmt_hdf5/logs.py +33 -0
  112. dclab/rtdc_dataset/fmt_hdf5/tables.py +30 -0
  113. dclab/rtdc_dataset/fmt_hierarchy/__init__.py +11 -0
  114. dclab/rtdc_dataset/fmt_hierarchy/base.py +278 -0
  115. dclab/rtdc_dataset/fmt_hierarchy/events.py +146 -0
  116. dclab/rtdc_dataset/fmt_hierarchy/hfilter.py +140 -0
  117. dclab/rtdc_dataset/fmt_hierarchy/mapper.py +134 -0
  118. dclab/rtdc_dataset/fmt_http.py +102 -0
  119. dclab/rtdc_dataset/fmt_s3.py +320 -0
  120. dclab/rtdc_dataset/fmt_tdms/__init__.py +476 -0
  121. dclab/rtdc_dataset/fmt_tdms/event_contour.py +264 -0
  122. dclab/rtdc_dataset/fmt_tdms/event_image.py +220 -0
  123. dclab/rtdc_dataset/fmt_tdms/event_mask.py +62 -0
  124. dclab/rtdc_dataset/fmt_tdms/event_trace.py +146 -0
  125. dclab/rtdc_dataset/fmt_tdms/exc.py +37 -0
  126. dclab/rtdc_dataset/fmt_tdms/naming.py +151 -0
  127. dclab/rtdc_dataset/load.py +72 -0
  128. dclab/rtdc_dataset/writer.py +985 -0
  129. dclab/statistics.py +203 -0
  130. dclab/util.py +156 -0
  131. dclab/warn.py +15 -0
  132. dclab-0.62.11.dist-info/LICENSE +343 -0
  133. dclab-0.62.11.dist-info/METADATA +146 -0
  134. dclab-0.62.11.dist-info/RECORD +137 -0
  135. dclab-0.62.11.dist-info/WHEEL +5 -0
  136. dclab-0.62.11.dist-info/entry_points.txt +8 -0
  137. dclab-0.62.11.dist-info/top_level.txt +1 -0
@@ -0,0 +1,73 @@
1
+ import re
2
+
3
+ from ..feat_basin import Basin
4
+
5
+ from .api import REQUESTS_AVAILABLE, APIHandler, DCORAccessError
6
+ from .base import RTDC_DCOR
7
+
8
+
9
+ REGEXP_FULL_DCOR_URL = re.compile(
10
+ r"^https?:\/\/" # scheme
11
+ r"[a-z0-9-\.]*\.[a-z0-9-\.]*\/?api\/3\/action\/dcserv\?id=" # host and API
12
+ r"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$") # id
13
+
14
+
15
+ class DCORBasin(Basin):
16
+ basin_format = "dcor"
17
+ basin_type = "remote"
18
+
19
+ def __init__(self, *args, **kwargs):
20
+ """Access to private and public DCOR resources
21
+
22
+ Since version 2 of the DCOR data API, all feature data are
23
+ accessed via :class:`.HTTPBasin`s on S3. The DCOR basin is just
24
+ a wrapper around those `HTTPBasin`s.
25
+
26
+ For private resources, the DCOR format facilitates authentication
27
+ via access tokens. Behind the scenes, DCOR creates a pre-signed
28
+ URL to access private data on an S3 object storage provider.
29
+ Note that you must let dclab know your DCOR access
30
+ token via :func:`.APIHandler.add_api_key` for this to work.
31
+
32
+ The `location` must be a full DCOR URL, including the scheme
33
+ and netloc, e.g:
34
+
35
+ https://dcor.mpl.mpg.de/api/3/action/dcserv?
36
+ id=b1404eb5-f661-4920-be79-5ff4e85915d5
37
+ """
38
+ self._available_verified = None
39
+ super(DCORBasin, self).__init__(*args, **kwargs)
40
+
41
+ def _load_dataset(self, location, **kwargs):
42
+ return RTDC_DCOR(location, **kwargs)
43
+
44
+ def is_available(self):
45
+ """Check whether a DCOR resource is available
46
+
47
+ Notes
48
+ -----
49
+ - Make sure that your DCOR access token is stored in
50
+ :class:`.APIHandler`. You can add tokens with
51
+ :func:`.APIHandler.add_api_key`.
52
+ """
53
+ with self._av_check_lock:
54
+ if not REQUESTS_AVAILABLE:
55
+ # don't even bother
56
+ self._available_verified = False
57
+ elif not is_full_dcor_url(self.location):
58
+ # not a full DCOR URL
59
+ self._available_verified = False
60
+ if self._available_verified is None:
61
+ api = APIHandler(self.location)
62
+ try:
63
+ self._available_verified = api.get("valid")
64
+ except DCORAccessError:
65
+ self._available_verified = False
66
+ return self._available_verified
67
+
68
+
69
+ def is_full_dcor_url(string):
70
+ if not isinstance(string, str):
71
+ return False
72
+ else:
73
+ return REGEXP_FULL_DCOR_URL.match(string.strip())
@@ -0,0 +1,26 @@
1
+ class DCORLogs:
2
+ def __init__(self, api):
3
+ self.api = api
4
+ self._logs_cache = None
5
+
6
+ def __contains__(self, key):
7
+ return key in self.keys()
8
+
9
+ def __getitem__(self, key):
10
+ return self._logs[key]
11
+
12
+ def __iter__(self):
13
+ for key in self.keys():
14
+ yield key
15
+
16
+ def __len__(self):
17
+ return len(self._logs)
18
+
19
+ def keys(self):
20
+ return self._logs.keys()
21
+
22
+ @property
23
+ def _logs(self):
24
+ if self._logs_cache is None:
25
+ self._logs_cache = self.api.get(query="logs")
26
+ return self._logs_cache
@@ -0,0 +1,42 @@
1
+ import numpy as np
2
+
3
+
4
+ class DCORTables:
5
+ def __init__(self, api):
6
+ self.api = api
7
+ self._tables_cache = None
8
+
9
+ def __contains__(self, key):
10
+ return key in self.keys()
11
+
12
+ def __getitem__(self, key):
13
+ return self._tables[key]
14
+
15
+ def __iter__(self):
16
+ for key in self.keys():
17
+ yield key
18
+
19
+ def __len__(self):
20
+ return len(self._tables)
21
+
22
+ def keys(self):
23
+ return self._tables.keys()
24
+
25
+ @property
26
+ def _tables(self):
27
+ if self._tables_cache is None:
28
+ table_data = self.api.get(query="tables")
29
+ # assemble the tables
30
+ tables = {}
31
+ for key in table_data:
32
+ columns, data = table_data[key]
33
+ tab_data = np.asarray(data)
34
+ if columns is not None:
35
+ # We have a rec-array (named columns)
36
+ ds_dt = np.dtype({'names': columns,
37
+ 'formats': [np.float64] * len(columns)})
38
+ tab_data = np.rec.array(tab_data, dtype=ds_dt)
39
+ tables[key] = tab_data
40
+
41
+ self._tables_cache = tables
42
+ return self._tables_cache
@@ -0,0 +1,103 @@
1
+ """RT-DC dictionary format"""
2
+ import collections
3
+ import time
4
+
5
+ import numpy as np
6
+
7
+ from .. import definitions as dfn
8
+ from ..util import hashobj
9
+
10
+ from .config import Configuration
11
+ from .core import RTDCBase
12
+
13
+
14
+ class DictContourEvent:
15
+ def __init__(self, contours):
16
+ assert contours[0].shape[1] == 2
17
+ self.shape = (len(contours), np.nan, 2)
18
+ self.contours = contours
19
+
20
+ def __iter__(self):
21
+ return iter(self.contours)
22
+
23
+ def __getitem__(self, item):
24
+ return self.contours[item]
25
+
26
+ def __len__(self):
27
+ return len(self.contours)
28
+
29
+
30
+ class DictTraceEvent(collections.UserDict):
31
+
32
+ @property
33
+ def shape(self):
34
+ key0 = sorted(self.keys())[0]
35
+ return len(self), len(self[key0]), len(self[key0][0])
36
+
37
+
38
+ class RTDC_Dict(RTDCBase):
39
+ _local_basins_allowed = True
40
+
41
+ def __init__(self, ddict, *args, **kwargs):
42
+ """Dictionary-based RT-DC dataset
43
+
44
+ Parameters
45
+ ----------
46
+ ddict: dict
47
+ Dictionary with features as keys (valid features like
48
+ "area_cvx", "deform", "image" are defined by
49
+ `dclab.definitions.feature_exists`) with which the class
50
+ will be instantiated. The configuration is set to the
51
+ default configuration of dclab.
52
+
53
+ .. versionchanged:: 0.27.0
54
+ Scalar features are automatically converted to arrays.
55
+ *args:
56
+ Arguments for `RTDCBase`
57
+ **kwargs:
58
+ Keyword arguments for `RTDCBase`
59
+ """
60
+ assert ddict
61
+
62
+ super(RTDC_Dict, self).__init__(*args, **kwargs)
63
+
64
+ t = time.localtime()
65
+
66
+ # Get an identifying string
67
+ keys = list(ddict.keys())
68
+ keys.sort()
69
+ ids = hashobj(ddict[keys[0]])
70
+ self._ids = ids
71
+ self.path = "none"
72
+ self.title = "{}_{:02d}_{:02d}/{}.dict".format(t[0], t[1], t[2], ids)
73
+
74
+ # Populate events
75
+ for feat in ddict:
76
+ if dfn.feature_exists(feat):
77
+ if dfn.scalar_feature_exists(feat):
78
+ data = np.array(ddict[feat])
79
+ elif feat == "contour":
80
+ data = DictContourEvent(ddict[feat])
81
+ elif feat == "trace":
82
+ data = DictTraceEvent(ddict[feat])
83
+ elif isinstance(ddict[feat], list):
84
+ # convert e.g. image data to arrays
85
+ data = np.array(ddict[feat])
86
+ else:
87
+ data = ddict[feat]
88
+ else:
89
+ raise ValueError("Invalid feature name '{}'".format(feat))
90
+ if isinstance(data, np.ndarray):
91
+ # Convert numpy array to read-only array
92
+ data = data.view()
93
+ data.setflags(write=False)
94
+ self._events[feat] = data
95
+
96
+ event_count = len(ddict[list(ddict.keys())[0]])
97
+
98
+ self.config = Configuration()
99
+ self.config["experiment"]["event count"] = event_count
100
+
101
+ @property
102
+ def hash(self):
103
+ return self._ids
@@ -0,0 +1,6 @@
1
+ # flake8: noqa: F401
2
+ from .base import RTDC_HDF5, MIN_DCLAB_EXPORT_VERSION
3
+ from .basin import HDF5Basin # import means registering
4
+ from .events import (
5
+ H5Events, H5MaskEvent, H5TraceEvent, H5ScalarEvent, H5ContourEvent)
6
+ from .feat_defect import DEFECTIVE_FEATURES
@@ -0,0 +1,192 @@
1
+ """RT-DC hdf5 format"""
2
+ from __future__ import annotations
3
+
4
+ import io
5
+ import json
6
+ import pathlib
7
+ from typing import Any, BinaryIO, Dict
8
+ import warnings
9
+
10
+ import h5py
11
+
12
+ from ...external.packaging import parse as parse_version
13
+ from ...util import hashobj, hashfile
14
+
15
+ from ..config import Configuration
16
+ from ..core import RTDCBase
17
+
18
+ from . import events
19
+ from . import logs
20
+ from . import tables
21
+
22
+ #: rtdc files exported with dclab prior to this version are not supported
23
+ MIN_DCLAB_EXPORT_VERSION = "0.3.3.dev2"
24
+
25
+
26
+ class OldFormatNotSupportedError(BaseException):
27
+ pass
28
+
29
+
30
+ class UnknownKeyWarning(UserWarning):
31
+ pass
32
+
33
+
34
+ class RTDC_HDF5(RTDCBase):
35
+ def __init__(self,
36
+ h5path: str | pathlib.Path | BinaryIO | io.IOBase,
37
+ h5kwargs: Dict[str, Any] = None,
38
+ *args,
39
+ **kwargs):
40
+ """HDF5 file format for RT-DC measurements
41
+
42
+ Parameters
43
+ ----------
44
+ h5path: str or pathlib.Path or file-like object
45
+ Path to an '.rtdc' measurement file or a file-like object
46
+ h5kwargs: dict
47
+ Additional keyword arguments given to :class:`h5py.File`
48
+ *args:
49
+ Arguments for `RTDCBase`
50
+ **kwargs:
51
+ Keyword arguments for `RTDCBase`
52
+
53
+ Attributes
54
+ ----------
55
+ path: pathlib.Path
56
+ Path to the experimental HDF5 (.rtdc) file
57
+ """
58
+ super(RTDC_HDF5, self).__init__(*args, **kwargs)
59
+
60
+ # Any subclass from RTDC_HDF5 is probably a remote-type and should
61
+ # not be able to access local basins. If you do not agree, please
62
+ # enable this in the definition of the subclass.
63
+ self._local_basins_allowed = True if self.format == "hdf5" else False
64
+
65
+ if isinstance(h5path, (str, pathlib.Path)):
66
+ h5path = pathlib.Path(h5path)
67
+ else:
68
+ h5path = h5path
69
+
70
+ self._hash = None
71
+ self.path = h5path
72
+
73
+ # Increase the read cache (which defaults to 1MiB), since
74
+ # normally we have around 2.5MiB image chunks.
75
+ if h5kwargs is None:
76
+ h5kwargs = {}
77
+ h5kwargs.setdefault("rdcc_nbytes", 10 * 1024 ** 2)
78
+ h5kwargs.setdefault("rdcc_w0", 0)
79
+
80
+ self.h5kwargs = h5kwargs
81
+ self.h5file = h5py.File(h5path, **h5kwargs)
82
+
83
+ self._events = events.H5Events(self.h5file)
84
+
85
+ # Parse configuration
86
+ self.config = RTDC_HDF5.parse_config(self.h5file)
87
+
88
+ # Override logs property with HDF5 data
89
+ self.logs = logs.H5Logs(self.h5file)
90
+
91
+ # Override the tables property with HDF5 data
92
+ self.tables = tables.H5Tables(self.h5file)
93
+
94
+ # check version
95
+ rtdc_soft = self.config["setup"].get("software version", "unknown")
96
+ if rtdc_soft.startswith("dclab "):
97
+ rtdc_ver = parse_version(rtdc_soft.split(" ")[1])
98
+ if rtdc_ver < parse_version(MIN_DCLAB_EXPORT_VERSION):
99
+ msg = "The file {} was created ".format(self.path) \
100
+ + "with dclab {} which is ".format(rtdc_ver) \
101
+ + "not supported anymore! Please rerun " \
102
+ + "dclab-tdms2rtdc / export the data again."
103
+ raise OldFormatNotSupportedError(msg)
104
+
105
+ self.title = "{} - M{}".format(
106
+ self.config["experiment"].get("sample", "undefined sample"),
107
+ self.config["experiment"].get("run index", "0"))
108
+
109
+ def close(self):
110
+ """Close the underlying HDF5 file"""
111
+ super(RTDC_HDF5, self).close()
112
+ self.h5file.close()
113
+
114
+ @property
115
+ def _h5(self):
116
+ warnings.warn("Access to the underlying HDF5 file is now public. "
117
+ "Please use the `h5file` attribute instead of `_h5`!",
118
+ DeprecationWarning)
119
+ return self.h5file
120
+
121
+ @staticmethod
122
+ def can_open(h5path):
123
+ """Check whether a given file is in the .rtdc file format"""
124
+ h5path = pathlib.Path(h5path)
125
+ if h5path.suffix == ".rtdc":
126
+ return True
127
+ else:
128
+ # we don't know the extension; check for the "events" group
129
+ canopen = False
130
+ try:
131
+ # This is a workaround for Python2 where h5py cannot handle
132
+ # unicode file names.
133
+ with h5path.open("rb") as fd:
134
+ h5 = h5py.File(fd, "r")
135
+ if "events" in h5:
136
+ canopen = True
137
+ except IOError:
138
+ # not an HDF5 file
139
+ pass
140
+ return canopen
141
+
142
+ @staticmethod
143
+ def parse_config(h5path):
144
+ """Parse the RT-DC configuration of an HDF5 file
145
+
146
+ `h5path` may be a h5py.File object or an actual path
147
+ """
148
+ if not isinstance(h5path, h5py.File):
149
+ with h5py.File(h5path, mode="r") as fh5:
150
+ h5attrs = dict(fh5.attrs)
151
+ else:
152
+ h5attrs = dict(h5path.attrs)
153
+
154
+ # Convert byte strings to unicode strings
155
+ # https://github.com/h5py/h5py/issues/379
156
+ for key in h5attrs:
157
+ if isinstance(h5attrs[key], bytes):
158
+ h5attrs[key] = h5attrs[key].decode("utf-8")
159
+
160
+ config = Configuration()
161
+ for key in h5attrs:
162
+ section, pname = key.split(":")
163
+ config[section][pname] = h5attrs[key]
164
+ return config
165
+
166
+ @property
167
+ def hash(self):
168
+ """Hash value based on file name and content"""
169
+ if self._hash is None:
170
+ tohash = [self.path.name,
171
+ # Hash a maximum of ~1MB of the hdf5 file
172
+ hashfile(self.path, blocksize=65536, count=20)]
173
+ self._hash = hashobj(tohash)
174
+ return self._hash
175
+
176
+ def basins_get_dicts(self):
177
+ """Return list of dicts for all basins defined in `self.h5file`"""
178
+ return self.basin_get_dicts_from_h5file(self.h5file)
179
+
180
+ @staticmethod
181
+ def basin_get_dicts_from_h5file(h5file):
182
+ """Return list of dicts for all basins defined in `h5file`"""
183
+ basins = []
184
+ # Do not sort anything here, sorting is done in `RTDCBase`.
185
+ for bk in h5file.get("basins", []):
186
+ bdat = list(h5file["basins"][bk])
187
+ if isinstance(bdat[0], bytes):
188
+ bdat = [bi.decode("utf") for bi in bdat]
189
+ bdict = json.loads(" ".join(bdat))
190
+ bdict["key"] = bk
191
+ basins.append(bdict)
192
+ return basins
@@ -0,0 +1,30 @@
1
+ """RT-DC hdf5 format"""
2
+ from __future__ import annotations
3
+
4
+ import pathlib
5
+
6
+ from .. import feat_basin
7
+
8
+ from .base import RTDC_HDF5
9
+
10
+
11
+ class HDF5Basin(feat_basin.Basin):
12
+ basin_format = "hdf5"
13
+ basin_type = "file"
14
+
15
+ def __init__(self, *args, **kwargs):
16
+ self._available_verified = None
17
+ super(HDF5Basin, self).__init__(*args, **kwargs)
18
+
19
+ def _load_dataset(self, location, **kwargs):
20
+ return RTDC_HDF5(location, **kwargs)
21
+
22
+ def is_available(self):
23
+ if self._available_verified is None:
24
+ with self._av_check_lock:
25
+ try:
26
+ self._available_verified = \
27
+ pathlib.Path(self.location).exists()
28
+ except OSError:
29
+ pass
30
+ return self._available_verified