dcnum 0.25.9__py3-none-any.whl → 0.25.11__py3-none-any.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 dcnum might be problematic. Click here for more details.
- dcnum/_version.py +2 -2
- dcnum/logic/ctrl.py +3 -11
- dcnum/read/__init__.py +4 -1
- dcnum/read/hdf5_data.py +37 -0
- dcnum/segm/segm_torch/segm_torch_base.py +11 -4
- dcnum/write/writer.py +16 -1
- {dcnum-0.25.9.dist-info → dcnum-0.25.11.dist-info}/METADATA +3 -3
- {dcnum-0.25.9.dist-info → dcnum-0.25.11.dist-info}/RECORD +11 -11
- {dcnum-0.25.9.dist-info → dcnum-0.25.11.dist-info}/WHEEL +1 -1
- {dcnum-0.25.9.dist-info → dcnum-0.25.11.dist-info}/licenses/LICENSE +0 -0
- {dcnum-0.25.9.dist-info → dcnum-0.25.11.dist-info}/top_level.txt +0 -0
dcnum/_version.py
CHANGED
dcnum/logic/ctrl.py
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import collections
|
|
2
2
|
import datetime
|
|
3
|
-
import hashlib
|
|
4
3
|
import importlib
|
|
5
4
|
import json
|
|
6
5
|
import logging
|
|
@@ -24,7 +23,7 @@ from ..feat import gate
|
|
|
24
23
|
from ..feat import EventExtractorManagerThread
|
|
25
24
|
from ..segm import SegmenterManagerThread, get_available_segmenters
|
|
26
25
|
from ..meta import ppid
|
|
27
|
-
from ..read import HDF5Data, get_mapping_indices
|
|
26
|
+
from ..read import HDF5Data, get_measurement_identifier, get_mapping_indices
|
|
28
27
|
from .._version import version, version_tuple
|
|
29
28
|
from ..write import (
|
|
30
29
|
DequeWriterThread, HDF5Writer, QueueCollectorThread, copy_features,
|
|
@@ -453,15 +452,7 @@ class DCNumJobRunner(threading.Thread):
|
|
|
453
452
|
# segmentation did actually take place.
|
|
454
453
|
mid_ap = f"dcn-{self.pphash[:7]}"
|
|
455
454
|
# This is the current measurement identifier
|
|
456
|
-
mid_cur = hw.h5
|
|
457
|
-
if not mid_cur:
|
|
458
|
-
# Compute a measurement identifier from the metadata
|
|
459
|
-
m_time = hw.h5.attrs.get("experiment:time", "none")
|
|
460
|
-
m_date = hw.h5.attrs.get("experiment:date", "none")
|
|
461
|
-
m_sid = hw.h5.attrs.get("setup:identifier", "none")
|
|
462
|
-
hasher = hashlib.md5(
|
|
463
|
-
f"{m_time}_{m_date}_{m_sid}".encode("utf-8"))
|
|
464
|
-
mid_cur = str(uuid.UUID(hex=hasher.hexdigest()))
|
|
455
|
+
mid_cur = get_measurement_identifier(hw.h5)
|
|
465
456
|
# The new measurement identifier is a combination of both.
|
|
466
457
|
mid_new = f"{mid_cur}_{mid_ap}" if mid_cur else mid_ap
|
|
467
458
|
hw.h5.attrs["experiment:run identifier"] = mid_new
|
|
@@ -666,6 +657,7 @@ class DCNumJobRunner(threading.Thread):
|
|
|
666
657
|
mapping=basinmap0,
|
|
667
658
|
paths=paths,
|
|
668
659
|
description=f"Created with dcnum {version}",
|
|
660
|
+
identifier=get_measurement_identifier(hin),
|
|
669
661
|
)
|
|
670
662
|
self._progress_bn += 1 / len(feats_raw)
|
|
671
663
|
t_tot = time.perf_counter() - t0
|
dcnum/read/__init__.py
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
from .cache import md5sum
|
|
3
3
|
from .const import PROTECTED_FEATURES
|
|
4
4
|
from .detect_flicker import detect_flickering
|
|
5
|
-
from .hdf5_data import
|
|
5
|
+
from .hdf5_data import (
|
|
6
|
+
HDF5Data, HDF5ImageCache, get_measurement_identifier,
|
|
7
|
+
BasinIdentifierMismatchError
|
|
8
|
+
)
|
|
6
9
|
from .hdf5_concat import concatenated_hdf5_data
|
|
7
10
|
from .mapped import get_mapping_indices, get_mapped_object
|
dcnum/read/hdf5_data.py
CHANGED
|
@@ -16,6 +16,10 @@ from .const import PROTECTED_FEATURES
|
|
|
16
16
|
from .mapped import get_mapped_object, get_mapping_indices
|
|
17
17
|
|
|
18
18
|
|
|
19
|
+
class BasinIdentifierMismatchError(BaseException):
|
|
20
|
+
"""Used when basin identifiers do not match"""
|
|
21
|
+
|
|
22
|
+
|
|
19
23
|
class HDF5Data:
|
|
20
24
|
"""HDF5 (.rtdc) input file data instance"""
|
|
21
25
|
def __init__(self,
|
|
@@ -473,6 +477,12 @@ class HDF5Data:
|
|
|
473
477
|
features = []
|
|
474
478
|
else:
|
|
475
479
|
h5 = h5py.File(path, "r")
|
|
480
|
+
# verify that the basin was identified correctly
|
|
481
|
+
if ((id_exp := bn_dict.get("identifier")) is not None
|
|
482
|
+
and (id_act := get_measurement_identifier(h5)) != id_exp):
|
|
483
|
+
raise BasinIdentifierMismatchError(
|
|
484
|
+
f"The basin '{path}' with identifier '{id_act}' "
|
|
485
|
+
f"does not match the expected identifier '{id_exp}'")
|
|
476
486
|
h5group = h5["events"]
|
|
477
487
|
# features defined in the basin
|
|
478
488
|
features = bn_dict.get("features")
|
|
@@ -560,3 +570,30 @@ def concatenated_hdf5_data(*args, **kwargs):
|
|
|
560
570
|
DeprecationWarning)
|
|
561
571
|
from . import hdf5_concat
|
|
562
572
|
return hdf5_concat.concatenated_hdf5_data(*args, **kwargs)
|
|
573
|
+
|
|
574
|
+
|
|
575
|
+
def get_measurement_identifier(h5: h5py.Group) -> str | None:
|
|
576
|
+
"""Return the measurement identifier for the given H5File object
|
|
577
|
+
|
|
578
|
+
The basin identifier is taken from the HDF5 attributes. If the
|
|
579
|
+
"experiment:run identifier" attribute is not set, it is
|
|
580
|
+
computed from the HDF5 attributes "experiment:time",
|
|
581
|
+
"experiment:date", and "setup:identifier".
|
|
582
|
+
|
|
583
|
+
If the measurement identifier cannot be found or computed,
|
|
584
|
+
return None.
|
|
585
|
+
"""
|
|
586
|
+
# This is the current measurement identifier
|
|
587
|
+
mid = h5.attrs.get("experiment:run identifier")
|
|
588
|
+
if not mid:
|
|
589
|
+
# Compute a measurement identifier from the metadata
|
|
590
|
+
m_time = h5.attrs.get("experiment:time", None) or None
|
|
591
|
+
m_date = h5.attrs.get("experiment:date", None) or None
|
|
592
|
+
m_sid = h5.attrs.get("setup:identifier", None) or None
|
|
593
|
+
if None not in [m_time, m_date, m_sid]:
|
|
594
|
+
# Only compute an identifier if all of the above
|
|
595
|
+
# are defined.
|
|
596
|
+
hasher = hashlib.md5(
|
|
597
|
+
f"{m_time}_{m_date}_{m_sid}".encode("utf-8"))
|
|
598
|
+
mid = str(uuid.UUID(hex=hasher.hexdigest()))
|
|
599
|
+
return mid
|
|
@@ -3,6 +3,8 @@ import pathlib
|
|
|
3
3
|
import re
|
|
4
4
|
from typing import Dict
|
|
5
5
|
|
|
6
|
+
import numpy as np
|
|
7
|
+
|
|
6
8
|
from ...meta import paths
|
|
7
9
|
|
|
8
10
|
from ..segmenter import Segmenter, SegmenterNotApplicableError
|
|
@@ -116,10 +118,15 @@ class TorchSegmenterBase(Segmenter):
|
|
|
116
118
|
"""
|
|
117
119
|
key = item["key"]
|
|
118
120
|
if key in data_dict:
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
121
|
+
valid = True
|
|
122
|
+
if "regexp" in item:
|
|
123
|
+
re_match = bool(re.search(item["regexp"], data_dict[key],
|
|
124
|
+
re.MULTILINE))
|
|
125
|
+
negate = item.get("regexp-negate", False)
|
|
126
|
+
valid = valid and (re_match if not negate else not re_match)
|
|
127
|
+
if "value" in item:
|
|
128
|
+
valid = valid and np.allclose(item["value"], data_dict[key],
|
|
129
|
+
atol=0, rtol=0.01)
|
|
123
130
|
if not valid:
|
|
124
131
|
reasons_list.append(item.get("reason", "unknown reason"))
|
|
125
132
|
elif not item.get("allow-missing-key", False):
|
dcnum/write/writer.py
CHANGED
|
@@ -8,7 +8,7 @@ import h5py
|
|
|
8
8
|
import hdf5plugin
|
|
9
9
|
import numpy as np
|
|
10
10
|
|
|
11
|
-
from ..read import HDF5Data
|
|
11
|
+
from ..read import HDF5Data, get_measurement_identifier
|
|
12
12
|
from .._version import version
|
|
13
13
|
|
|
14
14
|
|
|
@@ -157,6 +157,7 @@ class HDF5Writer:
|
|
|
157
157
|
description: str | None = None,
|
|
158
158
|
mapping: np.ndarray = None,
|
|
159
159
|
internal_data: Dict | None = None,
|
|
160
|
+
identifier: str | None = None,
|
|
160
161
|
):
|
|
161
162
|
"""Write an HDF5-based file basin
|
|
162
163
|
|
|
@@ -177,6 +178,10 @@ class HDF5Writer:
|
|
|
177
178
|
internal_data: dict of ndarrays
|
|
178
179
|
internal basin data to store; If this is set, then `features`
|
|
179
180
|
and `paths` must be set to `None`.
|
|
181
|
+
identifier: str
|
|
182
|
+
the measurement identifier of the basin as computed by
|
|
183
|
+
the :func:`~dcnum.read.hdf5_data.get_measurement_identifier`
|
|
184
|
+
function.
|
|
180
185
|
"""
|
|
181
186
|
bdat = {
|
|
182
187
|
"description": description,
|
|
@@ -190,6 +195,9 @@ class HDF5Writer:
|
|
|
190
195
|
if paths is not None:
|
|
191
196
|
raise ValueError("`paths` must be set to None when storing "
|
|
192
197
|
"internal basin features")
|
|
198
|
+
if identifier is not None:
|
|
199
|
+
warnings.warn(f"Not storing identifier for internal "
|
|
200
|
+
f"basin '{name}' (got '{identifier}')")
|
|
193
201
|
# store the internal basin information
|
|
194
202
|
for feat in internal_data:
|
|
195
203
|
if feat in self.h5.require_group("basin_events"):
|
|
@@ -206,6 +214,8 @@ class HDF5Writer:
|
|
|
206
214
|
bdat["format"] = "hdf5"
|
|
207
215
|
bdat["paths"] = [str(pp) for pp in paths]
|
|
208
216
|
bdat["type"] = "file"
|
|
217
|
+
# identifier only makes sense here (not for internal basins)
|
|
218
|
+
bdat["identifier"] = identifier
|
|
209
219
|
|
|
210
220
|
# Explicit features stored in basin file
|
|
211
221
|
if features is not None and len(features):
|
|
@@ -322,6 +332,7 @@ def create_with_basins(
|
|
|
322
332
|
warnings.warn(f"Creating basin-based file '{path_out}' without any "
|
|
323
333
|
f"basins, since the list `basin_paths' is empty!",
|
|
324
334
|
CreatingFileWithoutBasinWarning)
|
|
335
|
+
basin_paths = []
|
|
325
336
|
with HDF5Writer(path_out, mode="w") as hw:
|
|
326
337
|
# Get the metadata from the first available basin path
|
|
327
338
|
|
|
@@ -359,16 +370,19 @@ def create_with_basins(
|
|
|
359
370
|
features = sorted(h5["events"].keys())
|
|
360
371
|
features = [f for f in features if
|
|
361
372
|
not f.startswith("basinmap")]
|
|
373
|
+
basin_identifier = get_measurement_identifier(h5)
|
|
362
374
|
name = prep.name
|
|
363
375
|
else:
|
|
364
376
|
features = None
|
|
365
377
|
name = bps[0]
|
|
378
|
+
basin_identifier = None
|
|
366
379
|
|
|
367
380
|
# Write the basin data
|
|
368
381
|
hw.store_basin(name=name,
|
|
369
382
|
paths=bps,
|
|
370
383
|
features=features,
|
|
371
384
|
description=f"Created by dcnum {version}",
|
|
385
|
+
identifier=basin_identifier,
|
|
372
386
|
)
|
|
373
387
|
|
|
374
388
|
|
|
@@ -404,6 +418,7 @@ def copy_basins(h5_src: h5py.File,
|
|
|
404
418
|
paths=bn_dict["paths"],
|
|
405
419
|
features=bn_dict["features"],
|
|
406
420
|
mapping=mapping,
|
|
421
|
+
identifier=bn_dict.get("identifier"),
|
|
407
422
|
)
|
|
408
423
|
else:
|
|
409
424
|
warnings.warn(f"Ignored basin of type '{bn_dict['type']}'",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dcnum
|
|
3
|
-
Version: 0.25.
|
|
3
|
+
Version: 0.25.11
|
|
4
4
|
Summary: numerics toolbox for imaging deformability cytometry
|
|
5
5
|
Author: Maximilian Schlögel, Paul Müller, Raghava Alajangi
|
|
6
6
|
Maintainer-email: Paul Müller <dev@craban.de>
|
|
@@ -55,12 +55,12 @@ For more options, please check out the `documentation
|
|
|
55
55
|
|
|
56
56
|
|
|
57
57
|
|
|
58
|
-
.. |dcnum| image:: https://raw.github.com/DC-analysis/dcnum/
|
|
58
|
+
.. |dcnum| image:: https://raw.github.com/DC-analysis/dcnum/main/docs/logo/dcnum.png
|
|
59
59
|
.. |PyPI Version| image:: https://img.shields.io/pypi/v/dcnum.svg
|
|
60
60
|
:target: https://pypi.python.org/pypi/dcnum
|
|
61
61
|
.. |Build Status| image:: https://img.shields.io/github/actions/workflow/status/DC-analysis/dcnum/check.yml
|
|
62
62
|
:target: https://github.com/DC-analysis/dcnum/actions?query=workflow%3AChecks
|
|
63
|
-
.. |Coverage Status| image:: https://img.shields.io/codecov/c/github/DC-analysis/dcnum
|
|
63
|
+
.. |Coverage Status| image:: https://img.shields.io/codecov/c/github/DC-analysis/dcnum
|
|
64
64
|
:target: https://codecov.io/gh/DC-analysis/dcnum
|
|
65
65
|
.. |Docs Status| image:: https://readthedocs.org/projects/dcnum/badge/?version=latest
|
|
66
66
|
:target: https://readthedocs.org/projects/dcnum/builds/
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
dcnum/__init__.py,sha256=p0mYg01FQ6nsERYmx_FfVxqqHvYcSMEyIAMBIivAmO8,1206
|
|
2
|
-
dcnum/_version.py,sha256=
|
|
2
|
+
dcnum/_version.py,sha256=G2RU878iZqAjfDOQZYI6kgCV8us1Ipc26TtDUjv56s0,515
|
|
3
3
|
dcnum/os_env_st.py,sha256=4psq-gPuWTTQ118kCiTx0Mhoyads4Irn6JSUzZk8gyc,3052
|
|
4
4
|
dcnum/feat/__init__.py,sha256=jUJYWTD3VIoDNKrmryXbjHb1rGwYtK4b7VPWihYgUoo,325
|
|
5
5
|
dcnum/feat/event_extractor_manager_thread.py,sha256=6D3RVYBuH7gOoGZ4Kz74n6fhq7MtlTY26kpSwZRqg3M,7972
|
|
@@ -21,18 +21,18 @@ dcnum/feat/feat_texture/__init__.py,sha256=6StM9S540UVtdFFR3bHa7nfCTomeVdoo7Uy9C
|
|
|
21
21
|
dcnum/feat/feat_texture/common.py,sha256=COXHpXS-7DMouGu3WF83I76L02Sr7P9re4lxajh6g0E,439
|
|
22
22
|
dcnum/feat/feat_texture/tex_all.py,sha256=_5H3sXYRN0Uq2eUHn3XUyEHkU_tncEqbqJTC-HZcnGY,5198
|
|
23
23
|
dcnum/logic/__init__.py,sha256=7J3GrwJInNQbrLk61HRIV7X7p69TAIbMYpR34hh6u14,177
|
|
24
|
-
dcnum/logic/ctrl.py,sha256=
|
|
24
|
+
dcnum/logic/ctrl.py,sha256=4r5N4WlqJW1f61zpaWFBJofEgMsD7H2APeiqOu9Li08,37099
|
|
25
25
|
dcnum/logic/job.py,sha256=MprDL6DwXWmvtGgy7W9A7s2rVRx68ObdJB8mvGFwVcw,7718
|
|
26
26
|
dcnum/logic/json_encoder.py,sha256=wb6uk6EeTkXyrvwtLm9uWe0cfmiBannzcsKLsDLHuQo,843
|
|
27
27
|
dcnum/meta/__init__.py,sha256=AVqRgyKXO1orKnE305h88IBvoZ1oz6X11HN1WP5nGvg,60
|
|
28
28
|
dcnum/meta/paths.py,sha256=aIG39JYbZpOlCbPQIlp0SqGumjbGINYhL2AAoznJt5o,1113
|
|
29
29
|
dcnum/meta/ppid.py,sha256=JInGtwSCsO9nr1E1aishm0k9iQIFB-essBKvv5aBE98,8510
|
|
30
|
-
dcnum/read/__init__.py,sha256=
|
|
30
|
+
dcnum/read/__init__.py,sha256=EzH-a_RHnUdG32ws-UgU5tc_je972G3pYgn48ai8PFc,356
|
|
31
31
|
dcnum/read/cache.py,sha256=ChxokVuMaTfi6N6ZbOTWpNYkPgAAYi1lR8nD7JbzjPQ,6497
|
|
32
32
|
dcnum/read/const.py,sha256=x6LfRwWvIxm6nDWlSADVWqDuzMX6bLzy5kQprwLPzA4,496
|
|
33
33
|
dcnum/read/detect_flicker.py,sha256=XVf7nqaHx6weRTtS7KPa5_WRU2flDQIZTbKspeguqdU,1829
|
|
34
34
|
dcnum/read/hdf5_concat.py,sha256=A4Ah_NLxa1ESapEWJcUhdglzi7_E3qKNd81ES7A-_2o,5589
|
|
35
|
-
dcnum/read/hdf5_data.py,sha256=
|
|
35
|
+
dcnum/read/hdf5_data.py,sha256=Hp1nzEe4EYaIFw22-VLFYbzvwFzctMYrtjoHAwdhDI8,22924
|
|
36
36
|
dcnum/read/mapped.py,sha256=zU2fYdZfLNHn0rKHxDzBhNFMu4--WWa8nSeE2likyZA,3637
|
|
37
37
|
dcnum/segm/__init__.py,sha256=9cLEAd3JWE8IGqDHV-eSDIYOGBfOepd8OcebtNs8Omk,309
|
|
38
38
|
dcnum/segm/segm_thresh.py,sha256=iVhvIhzO0Gw0t3rXOgH71rOI0CNjJJQq4Gg6BulUhK8,948
|
|
@@ -41,7 +41,7 @@ dcnum/segm/segmenter_manager_thread.py,sha256=vMZFBa18oO8OyVB3niy_mtEfKkGOWHEga4
|
|
|
41
41
|
dcnum/segm/segmenter_mpo.py,sha256=O6G4xzHKNMSmyX9HDXTfl-3f9Fk2filxvVrRIO2D9hg,14117
|
|
42
42
|
dcnum/segm/segmenter_sto.py,sha256=C55orEAZtMowNwtAT_WdSv46n5CzgLFuGq9kwdHc97I,3963
|
|
43
43
|
dcnum/segm/segm_torch/__init__.py,sha256=DtUqJTbj7ybrTbXlwHq1Y4SCzi22rMW9Cus6wX-iU-A,822
|
|
44
|
-
dcnum/segm/segm_torch/segm_torch_base.py,sha256=
|
|
44
|
+
dcnum/segm/segm_torch/segm_torch_base.py,sha256=wPt5QAmBDQxAA3Zxrdj3l9di0nIQmlUmKVJWtEpahH8,4814
|
|
45
45
|
dcnum/segm/segm_torch/segm_torch_mpo.py,sha256=GOva6o-6_SppxWD4BeBB3ap1TR-6rIYHavtfIstaYvc,2643
|
|
46
46
|
dcnum/segm/segm_torch/segm_torch_sto.py,sha256=PTOJrP_FkaxZZul8lM4VA2HL3KyxrheDDWWdJbmJdiw,3393
|
|
47
47
|
dcnum/segm/segm_torch/torch_model.py,sha256=5aL6SwSvg1N2gATEGBhP3aA4WTHlvGzQVYuizmh0LrU,3187
|
|
@@ -50,9 +50,9 @@ dcnum/segm/segm_torch/torch_preproc.py,sha256=m4Dd2URdvS7ifA1MkbEkc9d9T30lA_1qbE
|
|
|
50
50
|
dcnum/write/__init__.py,sha256=sK79IlvCFIqf2oFABVeyYedMnHOsEIQpxAauEeNO-Tw,273
|
|
51
51
|
dcnum/write/deque_writer_thread.py,sha256=ao7F1yrVKyufgC4rC0Y2_Vt7snuT6KpI7W2qVxcjdhk,1994
|
|
52
52
|
dcnum/write/queue_collector_thread.py,sha256=-p5vrk9cDhtaIMFIu_cCmvlZJafrFkW68uONonMURYo,11617
|
|
53
|
-
dcnum/write/writer.py,sha256=
|
|
54
|
-
dcnum-0.25.
|
|
55
|
-
dcnum-0.25.
|
|
56
|
-
dcnum-0.25.
|
|
57
|
-
dcnum-0.25.
|
|
58
|
-
dcnum-0.25.
|
|
53
|
+
dcnum/write/writer.py,sha256=WZLuetH7ZIvK-lhXjmyskHczAWFa9EfHXZWBUf9w1UE,21394
|
|
54
|
+
dcnum-0.25.11.dist-info/licenses/LICENSE,sha256=rX7tNSxP-EhLz-yYUyoBGwjJheA2fiZpT1Iw0LXnJ2M,1069
|
|
55
|
+
dcnum-0.25.11.dist-info/METADATA,sha256=N1T08nz_vUPVx7WzJ6aT45yfVfLu4VdM5EcUm7CfROY,2342
|
|
56
|
+
dcnum-0.25.11.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
57
|
+
dcnum-0.25.11.dist-info/top_level.txt,sha256=Hmh38rgG_MFTVDpUDGuO2HWTSq80P585Het4COQzFTg,6
|
|
58
|
+
dcnum-0.25.11.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|