dcnum 0.16.6__tar.gz → 0.16.8__tar.gz

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.

Files changed (96) hide show
  1. {dcnum-0.16.6 → dcnum-0.16.8}/CHANGELOG +9 -1
  2. {dcnum-0.16.6 → dcnum-0.16.8}/PKG-INFO +1 -1
  3. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/_version.py +2 -2
  4. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/feat/event_extractor_manager_thread.py +16 -0
  5. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/logic/ctrl.py +11 -8
  6. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/write/deque_writer_thread.py +5 -3
  7. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/write/writer.py +6 -6
  8. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum.egg-info/PKG-INFO +1 -1
  9. {dcnum-0.16.6 → dcnum-0.16.8}/tests/test_feat_event_extractor_manager.py +2 -0
  10. {dcnum-0.16.6 → dcnum-0.16.8}/tests/test_read_basin.py +22 -1
  11. {dcnum-0.16.6 → dcnum-0.16.8}/.github/workflows/check.yml +0 -0
  12. {dcnum-0.16.6 → dcnum-0.16.8}/.github/workflows/deploy_pypi.yml +0 -0
  13. {dcnum-0.16.6 → dcnum-0.16.8}/.gitignore +0 -0
  14. {dcnum-0.16.6 → dcnum-0.16.8}/.readthedocs.yml +0 -0
  15. {dcnum-0.16.6 → dcnum-0.16.8}/LICENSE +0 -0
  16. {dcnum-0.16.6 → dcnum-0.16.8}/README.rst +0 -0
  17. {dcnum-0.16.6 → dcnum-0.16.8}/docs/conf.py +0 -0
  18. {dcnum-0.16.6 → dcnum-0.16.8}/docs/extensions/github_changelog.py +0 -0
  19. {dcnum-0.16.6 → dcnum-0.16.8}/docs/index.rst +0 -0
  20. {dcnum-0.16.6 → dcnum-0.16.8}/docs/requirements.txt +0 -0
  21. {dcnum-0.16.6 → dcnum-0.16.8}/pyproject.toml +0 -0
  22. {dcnum-0.16.6 → dcnum-0.16.8}/setup.cfg +0 -0
  23. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/__init__.py +0 -0
  24. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/feat/__init__.py +0 -0
  25. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/feat/feat_background/__init__.py +0 -0
  26. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/feat/feat_background/base.py +0 -0
  27. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/feat/feat_background/bg_copy.py +0 -0
  28. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/feat/feat_background/bg_roll_median.py +0 -0
  29. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/feat/feat_background/bg_sparse_median.py +0 -0
  30. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/feat/feat_brightness/__init__.py +0 -0
  31. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/feat/feat_brightness/bright_all.py +0 -0
  32. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/feat/feat_brightness/common.py +0 -0
  33. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/feat/feat_moments/__init__.py +0 -0
  34. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/feat/feat_moments/ct_opencv.py +0 -0
  35. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/feat/feat_moments/mt_legacy.py +0 -0
  36. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/feat/feat_texture/__init__.py +0 -0
  37. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/feat/feat_texture/common.py +0 -0
  38. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/feat/feat_texture/tex_all.py +0 -0
  39. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/feat/gate.py +0 -0
  40. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/feat/queue_event_extractor.py +0 -0
  41. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/logic/__init__.py +0 -0
  42. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/logic/job.py +0 -0
  43. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/logic/json_encoder.py +0 -0
  44. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/meta/__init__.py +0 -0
  45. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/meta/ppid.py +0 -0
  46. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/read/__init__.py +0 -0
  47. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/read/cache.py +0 -0
  48. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/read/const.py +0 -0
  49. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/read/hdf5_data.py +0 -0
  50. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/segm/__init__.py +0 -0
  51. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/segm/segm_thresh.py +0 -0
  52. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/segm/segmenter.py +0 -0
  53. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/segm/segmenter_cpu.py +0 -0
  54. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/segm/segmenter_gpu.py +0 -0
  55. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/segm/segmenter_manager_thread.py +0 -0
  56. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/write/__init__.py +0 -0
  57. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum/write/queue_collector_thread.py +0 -0
  58. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum.egg-info/SOURCES.txt +0 -0
  59. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum.egg-info/dependency_links.txt +0 -0
  60. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum.egg-info/requires.txt +0 -0
  61. {dcnum-0.16.6 → dcnum-0.16.8}/src/dcnum.egg-info/top_level.txt +0 -0
  62. {dcnum-0.16.6 → dcnum-0.16.8}/tests/conftest.py +0 -0
  63. {dcnum-0.16.6 → dcnum-0.16.8}/tests/data/fmt-hdf5_cytoshot_extended-moments-features.zip +0 -0
  64. {dcnum-0.16.6 → dcnum-0.16.8}/tests/data/fmt-hdf5_cytoshot_full-features_2023.zip +0 -0
  65. {dcnum-0.16.6 → dcnum-0.16.8}/tests/data/fmt-hdf5_cytoshot_full-features_legacy_allev_2023.zip +0 -0
  66. {dcnum-0.16.6 → dcnum-0.16.8}/tests/data/fmt-hdf5_shapein_empty.zip +0 -0
  67. {dcnum-0.16.6 → dcnum-0.16.8}/tests/data/fmt-hdf5_shapein_raw-with-variable-length-logs.zip +0 -0
  68. {dcnum-0.16.6 → dcnum-0.16.8}/tests/helper_methods.py +0 -0
  69. {dcnum-0.16.6 → dcnum-0.16.8}/tests/requirements.txt +0 -0
  70. {dcnum-0.16.6 → dcnum-0.16.8}/tests/test_feat_background_base.py +0 -0
  71. {dcnum-0.16.6 → dcnum-0.16.8}/tests/test_feat_background_bg_copy.py +0 -0
  72. {dcnum-0.16.6 → dcnum-0.16.8}/tests/test_feat_background_bg_roll_median.py +0 -0
  73. {dcnum-0.16.6 → dcnum-0.16.8}/tests/test_feat_background_bg_sparsemed.py +0 -0
  74. {dcnum-0.16.6 → dcnum-0.16.8}/tests/test_feat_brightness.py +0 -0
  75. {dcnum-0.16.6 → dcnum-0.16.8}/tests/test_feat_gate.py +0 -0
  76. {dcnum-0.16.6 → dcnum-0.16.8}/tests/test_feat_haralick.py +0 -0
  77. {dcnum-0.16.6 → dcnum-0.16.8}/tests/test_feat_moments_based.py +0 -0
  78. {dcnum-0.16.6 → dcnum-0.16.8}/tests/test_feat_moments_based_extended.py +0 -0
  79. {dcnum-0.16.6 → dcnum-0.16.8}/tests/test_init.py +0 -0
  80. {dcnum-0.16.6 → dcnum-0.16.8}/tests/test_logic_job.py +0 -0
  81. {dcnum-0.16.6 → dcnum-0.16.8}/tests/test_logic_join.py +0 -0
  82. {dcnum-0.16.6 → dcnum-0.16.8}/tests/test_logic_json.py +0 -0
  83. {dcnum-0.16.6 → dcnum-0.16.8}/tests/test_logic_pipeline.py +0 -0
  84. {dcnum-0.16.6 → dcnum-0.16.8}/tests/test_ppid.py +0 -0
  85. {dcnum-0.16.6 → dcnum-0.16.8}/tests/test_ppid_bg.py +0 -0
  86. {dcnum-0.16.6 → dcnum-0.16.8}/tests/test_ppid_data.py +0 -0
  87. {dcnum-0.16.6 → dcnum-0.16.8}/tests/test_ppid_feat.py +0 -0
  88. {dcnum-0.16.6 → dcnum-0.16.8}/tests/test_ppid_gate.py +0 -0
  89. {dcnum-0.16.6 → dcnum-0.16.8}/tests/test_ppid_segm.py +0 -0
  90. {dcnum-0.16.6 → dcnum-0.16.8}/tests/test_read_concat_hdf5.py +0 -0
  91. {dcnum-0.16.6 → dcnum-0.16.8}/tests/test_read_hdf5.py +0 -0
  92. {dcnum-0.16.6 → dcnum-0.16.8}/tests/test_segm_thresh.py +0 -0
  93. {dcnum-0.16.6 → dcnum-0.16.8}/tests/test_segmenter.py +0 -0
  94. {dcnum-0.16.6 → dcnum-0.16.8}/tests/test_write_deque_writer_thread.py +0 -0
  95. {dcnum-0.16.6 → dcnum-0.16.8}/tests/test_write_queue_collector_thread.py +0 -0
  96. {dcnum-0.16.6 → dcnum-0.16.8}/tests/test_write_writer.py +0 -0
@@ -1,3 +1,11 @@
1
+ 0.16.8
2
+ - fix: correctly set number of workers for CPUSegmenter
3
+ - enh: update list of environment variables that should be set to
4
+ disable multithreading in subprocesses
5
+ 0.16.7
6
+ - fix: if the writer dequeue fills up, stall the feature extractor
7
+ - enh: optimize DequeWriterThread loop
8
+ - enh: minor optimization in HDF5Writer.require_feature
1
9
  0.16.6
2
10
  - fix: correctly handle mask images with no background on border
3
11
  - fix: enforce user-defined features in concatenated_hdf5_data
@@ -19,7 +27,7 @@
19
27
  - enh: define valid DCNumJobRunner state
20
28
  - enh: more robust computation of progress
21
29
  - enh: use HDF5Data when loading input data for background computation
22
- - enh: automatically split segmenters and axtractors equally
30
+ - enh: automatically split segmenters and extractors equally
23
31
  - ref: reduce default image cache size from 5 to 2
24
32
  - ref: move dataset generation default kwargs to writer submodule
25
33
  - ref: warn above 0.5% of discarded events in EventExtractorManagerThread
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dcnum
3
- Version: 0.16.6
3
+ Version: 0.16.8
4
4
  Summary: numerics toolbox for imaging deformability cytometry
5
5
  Author: Maximilian Schlögel, Paul Müller
6
6
  Maintainer-email: Paul Müller <dev@craban.de>
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '0.16.6'
16
- __version_tuple__ = version_tuple = (0, 16, 6)
15
+ __version__ = version = '0.16.8'
16
+ __version_tuple__ = version_tuple = (0, 16, 8)
@@ -1,4 +1,5 @@
1
1
  """Feature computation: managing event extraction threads"""
2
+ import collections
2
3
  import logging
3
4
  import multiprocessing as mp
4
5
  import threading
@@ -17,6 +18,7 @@ class EventExtractorManagerThread(threading.Thread):
17
18
  labels_list: List,
18
19
  fe_kwargs: Dict,
19
20
  num_workers: int,
21
+ writer_dq: collections.deque,
20
22
  debug: bool = False,
21
23
  *args, **kwargs):
22
24
  """Manage event extraction threads or precesses
@@ -40,6 +42,9 @@ class EventExtractorManagerThread(threading.Thread):
40
42
  :func:`.EventExtractor.get_init_kwargs` for more information.
41
43
  num_workers:
42
44
  Number of child threads or worker processes to use.
45
+ writer_dq:
46
+ The queue the writer uses. We monitor this queue. If it
47
+ fills up, we take a break.
43
48
  debug:
44
49
  Whether to run in debugging mode which means more log
45
50
  messages and only one thread (`num_workers` has no effect).
@@ -66,6 +71,8 @@ class EventExtractorManagerThread(threading.Thread):
66
71
  self.label_array = np.ctypeslib.as_array(
67
72
  self.fe_kwargs["label_array"]).reshape(
68
73
  self.data.image.chunk_shape)
74
+ #: Writer deque to monitor
75
+ self.writer_dq = writer_dq
69
76
  #: Time counter for feature extraction
70
77
  self.t_count = 0
71
78
  #: Whether debugging is enabled
@@ -86,6 +93,15 @@ class EventExtractorManagerThread(threading.Thread):
86
93
  chunks_processed = 0
87
94
  frames_processed = 0
88
95
  while True:
96
+ # If the writer_dq starts filling up, then this could lead to
97
+ # an oom-kill signal. Stall for the writer to prevent this.
98
+ ldq = len(self.writer_dq)
99
+ if ldq > 100:
100
+ stallsec = ldq / 100
101
+ self.logger.warning(
102
+ f"Stalling {stallsec:.1f}s for slow writer")
103
+ time.sleep(stallsec)
104
+
89
105
  cur_slot = 0
90
106
  unavailable_slots = 0
91
107
  # Check all slots for segmented labels
@@ -124,21 +124,23 @@ class DCNumJobRunner(threading.Thread):
124
124
  self.logger = logging.getLogger(f"dcnum.Runner-{self.pphash[:2]}")
125
125
 
126
126
  # Sanity checks
127
- for os_env in [
128
- "OMP_NUM_THREADS",
129
- "MKL_NUM_THREADS",
130
- "NUMEXPR_NUM_THREADS",
131
- "NUMBA_NUM_THREADS"]:
127
+ for os_env in ["MKL_NUM_THREADS", "NUMBA_NUM_THREADS",
128
+ "NUMEXPR_NUM_THREADS", "NUMPY_NUM_THREADS",
129
+ "OPENBLAS_NUM_THREADS", "OMP_NUM_THREADS",
130
+ "VECLIB_MAXIMUM_THREADS"]:
132
131
  # You should disable multithreading for all major tools that
133
132
  # use dcnum.logic. We don't want multithreading, because dcnum
134
133
  # uses linear code and relies on multiprocessing for
135
134
  # parallelization. This has to be done before importing numpy
136
135
  # or any other library affected. In your scripts, you can use:
137
136
  #
138
- # os.environ.setdefault("OMP_NUM_THREADS", "1")
139
137
  # os.environ.setdefault("MKL_NUM_THREADS", "1")
140
- # os.environ.setdefault("NUMEXPR_NUM_THREADS", "1")
141
138
  # os.environ.setdefault("NUMBA_NUM_THREADS", "1")
139
+ # os.environ.setdefault("NUMEXPR_NUM_THREADS", "1")
140
+ # os.environ.setdefault("NUMPY_NUM_THREADS", "1")
141
+ # os.environ.setdefault("OPENBLAS_NUM_THREADS", "1")
142
+ # os.environ.setdefault("OMP_NUM_THREADS", "1")
143
+ # os.environ.setdefault("VECLIB_MAXIMUM_THREADS", "1")
142
144
  #
143
145
  val_act = os.environ.get(os_env)
144
146
  if val_act != "1":
@@ -515,7 +517,7 @@ class DCNumJobRunner(threading.Thread):
515
517
  num_segmenters = 1
516
518
  num_extractors = max(1, num_extractors)
517
519
  num_segmenters = max(1, num_segmenters)
518
- self.job["segmenter_kwargs"]["num_workers"] = num_segmenters
520
+ self.job.kwargs["segmenter_kwargs"]["num_workers"] = num_segmenters
519
521
 
520
522
  slot_chunks = mp_spawn.Array("i", num_slots)
521
523
  slot_states = mp_spawn.Array("u", num_slots)
@@ -546,6 +548,7 @@ class DCNumJobRunner(threading.Thread):
546
548
  fe_kwargs=fe_kwargs,
547
549
  num_workers=num_extractors,
548
550
  labels_list=thr_segm.labels_list,
551
+ writer_dq=writer_dq,
549
552
  debug=self.job["debug"])
550
553
  thr_feat.start()
551
554
 
@@ -41,11 +41,13 @@ class DequeWriterThread(threading.Thread):
41
41
 
42
42
  def run(self):
43
43
  while True:
44
+ ldq = len(self.dq)
44
45
  if self.must_stop_loop:
45
46
  break
46
- elif len(self.dq):
47
- feat, data = self.dq.popleft()
48
- self.writer.store_feature_chunk(feat=feat, data=data)
47
+ elif ldq:
48
+ for _ in range(ldq):
49
+ feat, data = self.dq.popleft()
50
+ self.writer.store_feature_chunk(feat=feat, data=data)
49
51
  elif self.may_stop_loop:
50
52
  break
51
53
  else:
@@ -35,7 +35,7 @@ class HDF5Writer:
35
35
 
36
36
  @staticmethod
37
37
  def get_best_nd_chunks(item_shape, feat_dtype=np.float64):
38
- """Return best chunks for image data
38
+ """Return best chunks for HDF5 datasets
39
39
 
40
40
  Chunking has performance implications. It’s recommended to keep the
41
41
  total size of dataset chunks between 10 KiB and 1 MiB. This number
@@ -44,6 +44,7 @@ class HDF5Writer:
44
44
  """
45
45
  # set image feature chunk size to approximately 1MiB
46
46
  num_bytes = 1024 ** 2
47
+ # Note that `np.prod(()) == 1`
47
48
  event_size = np.prod(item_shape) * np.dtype(feat_dtype).itemsize
48
49
  chunk_size = num_bytes / event_size
49
50
  # Set minimum chunk size to 10 so that we can have at least some
@@ -53,12 +54,11 @@ class HDF5Writer:
53
54
 
54
55
  def require_feature(self, feat, item_shape, feat_dtype, ds_kwds=None):
55
56
  """Create a new feature in the "events" group"""
56
-
57
- if ds_kwds is None:
58
- ds_kwds = {}
59
- for key in self.ds_kwds:
60
- ds_kwds.setdefault(key, self.ds_kwds[key])
61
57
  if feat not in self.events:
58
+ if ds_kwds is None:
59
+ ds_kwds = {}
60
+ for key in self.ds_kwds:
61
+ ds_kwds.setdefault(key, self.ds_kwds[key])
62
62
  dset = self.events.create_dataset(
63
63
  feat,
64
64
  shape=tuple([0] + list(item_shape)),
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dcnum
3
- Version: 0.16.6
3
+ Version: 0.16.8
4
4
  Summary: numerics toolbox for imaging deformability cytometry
5
5
  Author: Maximilian Schlögel, Paul Müller
6
6
  Maintainer-email: Paul Müller <dev@craban.de>
@@ -1,3 +1,4 @@
1
+ import collections
1
2
  import logging
2
3
  import multiprocessing as mp
3
4
  import queue
@@ -48,6 +49,7 @@ def test_event_extractor_manager_thread():
48
49
  fe_kwargs=fe_kwargs,
49
50
  num_workers=1,
50
51
  labels_list=thr_segm.labels_list,
52
+ writer_dq=collections.deque(),
51
53
  debug=True)
52
54
  thr_feat.run()
53
55
  thr_segm.join()
@@ -4,7 +4,6 @@ import numpy as np
4
4
  from dcnum.write import HDF5Writer, create_with_basins
5
5
  from dcnum.read import HDF5Data
6
6
 
7
-
8
7
  from helper_methods import retrieve_data
9
8
 
10
9
 
@@ -184,3 +183,25 @@ def test_basin_scalar_features():
184
183
  assert np.allclose(hd["deform"][0], 0.0740563677588885)
185
184
  assert np.allclose(hd["area_um"][0], 0.559682)
186
185
  assert np.allclose(hd["area_um"][1], 91.193185875)
186
+
187
+
188
+ def test_basin_self_reference():
189
+ """Paths can self-reference in basins, no recursion errors"""
190
+ h5path = retrieve_data("fmt-hdf5_cytoshot_full-features_2023.zip")
191
+
192
+ # Dataset creation
193
+ with HDF5Writer(h5path, "a") as hw:
194
+ # Next, store the basin information in the new dataset
195
+ hw.store_basin(name="test",
196
+ paths=[h5path])
197
+
198
+ # Now open the scalar dataset and check whether basins are defined
199
+ with HDF5Data(h5path) as hd:
200
+ assert "image" in hd.get_basin_data(0)[1]
201
+ assert "image" in hd.keys()
202
+ assert np.median(hd["image"][0]) == 187
203
+ assert np.median(hd.image[0]) == 187
204
+ assert np.median(hd.image_corr[0]) == 1
205
+ assert np.allclose(np.mean(hd["deform"]),
206
+ 0.23354564471483724,
207
+ atol=0, rtol=1e-7)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes