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.

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-314-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-314-darwin.so +0 -0
  32. dclab/external/skimage/_find_contours_cy.pyx +188 -0
  33. dclab/external/skimage/_pnpoly.cpython-314-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-314-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,299 @@
1
+ """DCOR client interface"""
2
+ import logging
3
+ import pathlib
4
+ import re
5
+ import time
6
+
7
+ from ...util import hashobj
8
+
9
+ from ..config import Configuration
10
+ from ..core import RTDCBase
11
+ from ..feat_basin import PerishableRecord
12
+
13
+ from . import api
14
+ from .logs import DCORLogs
15
+ from .tables import DCORTables
16
+
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+
21
+ #: Append directories here where dclab should look for certificate bundles
22
+ #: for a specific host. The directory should contain files named after the
23
+ #: hostname, e.g. "dcor.mpl.mpg.de.cert".
24
+ DCOR_CERTS_SEARCH_PATHS = []
25
+
26
+ #: Regular expression for matching a DCOR resource URL
27
+ REGEXP_DCOR_URL = re.compile(
28
+ r"^(https?:\/\/)?" # scheme
29
+ r"([a-z0-9-\.]*\/?api\/3\/action\/dcserv\?id=)?" # host with API
30
+ r"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$") # id
31
+
32
+
33
+ class RTDC_DCOR(RTDCBase):
34
+ def __init__(self, url, host="dcor.mpl.mpg.de", api_key="",
35
+ use_ssl=None, cert_path=None, dcserv_api_version=2,
36
+ *args, **kwargs):
37
+ """Wrap around the DCOR API
38
+
39
+ Parameters
40
+ ----------
41
+ url: str
42
+ Full URL or resource identifier; valid values are
43
+
44
+ - `<https://dcor.mpl.mpg.de/api/3/action/dcserv?id=
45
+ b1404eb5-f661-4920-be79-5ff4e85915d5>`_
46
+ - dcor.mpl.mpg.de/api/3/action/dcserv?id=b1404eb5-f
47
+ 661-4920-be79-5ff4e85915d5
48
+ - b1404eb5-f661-4920-be79-5ff4e85915d5
49
+ host: str
50
+ The default host machine used if the host is not given in `url`
51
+ api_key: str
52
+ API key to access private resources
53
+ use_ssl: bool
54
+ Set this to False to disable SSL (should only be used for
55
+ testing). Defaults to None (does not force SSL if the URL
56
+ starts with "http://").
57
+ cert_path: pathlib.Path
58
+ The (optional) path to a server CA bundle; this should only
59
+ be necessary for DCOR instances in the intranet with a custom
60
+ CA or for certificate pinning.
61
+ dcserv_api_version: int
62
+ Version of the dcserv API to use. In version 0.13.2 of
63
+ ckanext-dc_serve, version 2 was introduced which entails
64
+ serving an S3-basin-only dataset.
65
+ *args:
66
+ Arguments for `RTDCBase`
67
+ **kwargs:
68
+ Keyword arguments for `RTDCBase`
69
+
70
+ Attributes
71
+ ----------
72
+ path: str
73
+ Full URL to the DCOR resource
74
+ """
75
+ if not api.REQUESTS_AVAILABLE:
76
+ raise ModuleNotFoundError(
77
+ "Package `requests` required for DCOR format!")
78
+
79
+ super(RTDC_DCOR, self).__init__(*args, **kwargs)
80
+
81
+ self._hash = None
82
+ self._cache_basin_dict = None
83
+ self.cache_basin_dict_time = 600
84
+ self.path = RTDC_DCOR.get_full_url(url, use_ssl, host)
85
+
86
+ if cert_path is None:
87
+ cert_path = get_server_cert_path(get_host_from_url(self.path))
88
+
89
+ self.api = api.APIHandler(url=self.path,
90
+ api_key=api_key,
91
+ cert_path=cert_path,
92
+ dcserv_api_version=dcserv_api_version)
93
+
94
+ # Parse configuration
95
+ self.config = Configuration(cfg=self.api.get(query="metadata"))
96
+
97
+ # Lazy logs
98
+ self.logs = DCORLogs(self.api)
99
+
100
+ # Lazy tables
101
+ self.tables = DCORTables(self.api)
102
+
103
+ # Get size
104
+ size = self.config["experiment"].get("event count")
105
+ if size is None:
106
+ size = int(self.api.get(query="size"))
107
+ self._size = size
108
+
109
+ self.title = f"{self.config['experiment']['sample']} - " \
110
+ + f"M{self.config['experiment']['run index']}"
111
+
112
+ def __len__(self):
113
+ return self._size
114
+
115
+ @property
116
+ def hash(self):
117
+ """Hash value based on file name and content"""
118
+ if self._hash is None:
119
+ tohash = [self.path]
120
+ self._hash = hashobj(tohash)
121
+ return self._hash
122
+
123
+ @staticmethod
124
+ def get_full_url(url, use_ssl, host=None):
125
+ """Return the full URL to a DCOR resource
126
+
127
+ Parameters
128
+ ----------
129
+ url: str
130
+ Full URL or resource identifier; valid values are
131
+
132
+ - https://dcor.mpl.mpg.de/api/3/action/dcserv?id=caab96f6-
133
+ df12-4299-aa2e-089e390aafd5'
134
+ - dcor.mpl.mpg.de/api/3/action/dcserv?id=caab96f6-df12-
135
+ 4299-aa2e-089e390aafd5
136
+ - caab96f6-df12-4299-aa2e-089e390aafd5
137
+ use_ssl: bool or None
138
+ Set this to False to disable SSL (should only be used for
139
+ testing). Defaults to None (does not force SSL if the URL
140
+ starts with "http://").
141
+ host: str
142
+ Use this host if it is not specified in `url`
143
+ """
144
+ if use_ssl is None:
145
+ if url.startswith("http://"):
146
+ # user wanted it that way
147
+ scheme = "http"
148
+ else:
149
+ scheme = "https"
150
+ elif use_ssl:
151
+ scheme = "https"
152
+ else:
153
+ scheme = "http"
154
+ if url.count("://"):
155
+ base = url.split("://", 1)[1]
156
+ else:
157
+ base = url
158
+ # determine the api_path and the netloc
159
+ if base.count("/"):
160
+ netloc, api_path = base.split("/", 1)
161
+ else:
162
+ netloc = None # default to `host`
163
+ api_path = "api/3/action/dcserv?id=" + base
164
+ # remove https from host string (user convenience)
165
+ if host is not None:
166
+ host = host.split("://")[-1]
167
+
168
+ netloc = host if netloc is None else netloc
169
+ new_url = f"{scheme}://{netloc}/{api_path}"
170
+ return new_url
171
+
172
+ def _basin_refresh(self, basin):
173
+ """Refresh the specified basin"""
174
+ # Retrieve the basin dictionary from DCOR
175
+ basin_dicts = self.basins_get_dicts()
176
+ for bn_dict in basin_dicts:
177
+ if bn_dict.get("name") == basin.name:
178
+ break
179
+ else:
180
+ raise ValueError(f"Basin '{basin.name}' not found in {self}")
181
+
182
+ tre = bn_dict["time_request"]
183
+ ttl = bn_dict["time_expiration"]
184
+ # remember time relative to time.time, subtract 30s to be on safe side
185
+ tex = bn_dict["time_local_request"] + (ttl - tre) - 30
186
+
187
+ if isinstance(basin.perishable, bool):
188
+ logger.debug("Initializing basin perishable %s", basin.name)
189
+ # create a perishable record
190
+ basin.perishable = PerishableRecord(
191
+ basin=basin,
192
+ expiration_func=self._basin_expiration,
193
+ expiration_kwargs={"time_local_expiration": tex},
194
+ refresh_func=self._basin_refresh,
195
+ )
196
+ else:
197
+ logger.debug("Refreshing basin perishable %s", basin.name)
198
+ # only update (this also works with weakref.ProxyType)
199
+ basin.perishable.expiration_kwargs = {"time_local_expiration": tex}
200
+
201
+ if len(bn_dict["urls"]) > 1:
202
+ logger.warning(f"Basin {basin.name} has multiple URLs. I am not "
203
+ f"checking their availability: {bn_dict}")
204
+ basin.location = bn_dict["urls"][0]
205
+
206
+ def _basin_expiration(self, basin, time_local_expiration):
207
+ """Check whether the basin has perished"""
208
+ return time_local_expiration < time.time()
209
+
210
+ def _basins_get_dicts(self):
211
+ try:
212
+ basin_dicts = self.api.get(query="basins")
213
+ # Fill in missing timing information
214
+ for bn_dict in basin_dicts:
215
+ if (bn_dict.get("format") == "http"
216
+ and "perishable" not in bn_dict):
217
+ # We are communicating with an older version of
218
+ # ckanext-dc_serve. Take a look at the URL and check
219
+ # whether we have a perishable (~1 hour) URL or whether
220
+ # this is a public resource.
221
+ expires_regexp = re.compile(".*expires=([0-9]*)$")
222
+ for url in bn_dict.get("urls", []):
223
+ if match := expires_regexp.match(url.lower()):
224
+ logger.debug("Detected perishable basin: %s",
225
+ bn_dict["name"])
226
+ bn_dict["perishable"] = True
227
+ bn_dict["time_request"] = time.time()
228
+ bn_dict["time_expiration"] = int(match.group(1))
229
+ # add part of the resource ID to the name
230
+ infourl = url.split(bn_dict["name"], 1)[-1]
231
+ infourl = infourl.replace("/", "")
232
+ bn_dict["name"] += f"-{infourl[:5]}"
233
+ break
234
+ else:
235
+ bn_dict["perishable"] = False
236
+ # If we have a perishable basin, add the local request time
237
+ if bn_dict.get("perishable"):
238
+ bn_dict["time_local_request"] = time.time()
239
+ except api.DCORAccessError:
240
+ # TODO: Do not catch this exception when all DCOR instances
241
+ # implement the 'basins' query.
242
+ # This means that the server does not implement the 'basins' query.
243
+ basin_dicts = []
244
+ return basin_dicts
245
+
246
+ def basins_get_dicts(self):
247
+ """Return list of dicts for all basins defined on DCOR
248
+
249
+ The return value of this method is cached for 10 minutes
250
+ (cache time defined in the `cache_basin_dict_time` [s] property).
251
+ """
252
+ if (self._cache_basin_dict is None
253
+ or time.time() > (self._cache_basin_dict[1]
254
+ + self.cache_basin_dict_time)):
255
+ self._cache_basin_dict = (self._basins_get_dicts(), time.time())
256
+ return self._cache_basin_dict[0]
257
+
258
+ def basins_retrieve(self):
259
+ """Same as superclass, but add perishable information"""
260
+ basin_dicts = self.basins_get_dicts()
261
+ basins = super(RTDC_DCOR, self).basins_retrieve()
262
+ for bn in basins:
263
+ for bn_dict in basin_dicts:
264
+ if bn.name == bn_dict.get("name"):
265
+ # Determine whether we have to set a perishable record.
266
+ if bn_dict.get("perishable"):
267
+ # required for `_basin_refresh` to create a record
268
+ bn.perishable = True
269
+ # create the actual record
270
+ self._basin_refresh(bn)
271
+ break
272
+ return basins
273
+
274
+
275
+ def get_host_from_url(url):
276
+ """Extract the hostname from a URL"""
277
+ return url.split("://")[1].split("/")[0]
278
+
279
+
280
+ def get_server_cert_path(host):
281
+ """Return server certificate bundle for DCOR `host`"""
282
+
283
+ for path in DCOR_CERTS_SEARCH_PATHS:
284
+ path = pathlib.Path(path)
285
+ cert_path = path / f"{host}.cert"
286
+ if cert_path.exists():
287
+ break
288
+ else:
289
+ # use default certificate bundle
290
+ cert_path = api.requests.certs.where()
291
+
292
+ return cert_path
293
+
294
+
295
+ def is_dcor_url(string):
296
+ if not isinstance(string, str):
297
+ return False
298
+ else:
299
+ return REGEXP_DCOR_URL.match(string.strip())
@@ -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", timeout=5)
26
+ return self._logs_cache
@@ -0,0 +1,66 @@
1
+ import numpy as np
2
+
3
+ from ..meta_table import MetaTable
4
+
5
+
6
+ class DCORTables:
7
+ def __init__(self, api):
8
+ self.api = api
9
+ self._tables_cache = None
10
+
11
+ def __contains__(self, key):
12
+ return key in self.keys()
13
+
14
+ def __getitem__(self, key):
15
+ return self._tables[key]
16
+
17
+ def __iter__(self):
18
+ for key in self.keys():
19
+ yield key
20
+
21
+ def __len__(self):
22
+ return len(self._tables)
23
+
24
+ def keys(self):
25
+ return self._tables.keys()
26
+
27
+ @property
28
+ def _tables(self):
29
+ if self._tables_cache is None:
30
+ table_data = self.api.get(query="tables", timeout=13)
31
+ # assemble the tables
32
+ tables = {}
33
+ for key in table_data:
34
+ tables[key] = DCORTable(table_data[key])
35
+
36
+ self._tables_cache = tables
37
+ return self._tables_cache
38
+
39
+
40
+ class DCORTable(MetaTable):
41
+ def __init__(self, table_content):
42
+ self._columns, data = table_content
43
+ self._tab_data = np.asarray(data)
44
+ if self._columns is not None:
45
+ # We have a rec-array (named columns)
46
+
47
+ ds_dt = np.dtype({'names': self._columns,
48
+ 'formats': [np.float64] * len(self._columns)})
49
+ self._tab_data = np.rec.array(self._tab_data, dtype=ds_dt)
50
+
51
+ def __array__(self, *args, **kwargs):
52
+ return self._tab_data.__array__(*args, **kwargs)
53
+
54
+ @property
55
+ def meta(self):
56
+ # TODO: Implement metadata sending from DCOR.
57
+ return {}
58
+
59
+ def has_graphs(self):
60
+ return self._columns is not None
61
+
62
+ def keys(self):
63
+ return self._columns
64
+
65
+ def __getitem__(self, key):
66
+ return self._tab_data[key]
@@ -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