dcnum 0.25.6__py3-none-any.whl → 0.25.8__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.

@@ -7,6 +7,15 @@ import numpy as np
7
7
 
8
8
  class ExtendedJSONEncoder(json.JSONEncoder):
9
9
  def default(self, obj):
10
+ """Extended JSON encoder for the **dcnum** logic
11
+
12
+ This JSON encoder can handle the following additional objects:
13
+
14
+ - ``pathlib.Path``
15
+ - integer numbers
16
+ - ``numpy`` boolean
17
+ - slices (via "PYTHON-SLICE" identifier)
18
+ """
10
19
  if isinstance(obj, pathlib.Path):
11
20
  return str(obj)
12
21
  elif isinstance(obj, numbers.Integral):
dcnum/meta/paths.py CHANGED
@@ -1,6 +1,7 @@
1
1
  import pathlib
2
2
 
3
3
  search_path_registry = {}
4
+ """Dictionary keeping track of user-defined search paths"""
4
5
 
5
6
 
6
7
  def register_search_path(topic: str,
dcnum/meta/ppid.py CHANGED
@@ -9,9 +9,11 @@ import warnings
9
9
 
10
10
  import numpy as np
11
11
 
12
- #: Increment this string if there are breaking changes that make
13
- #: previous pipelines unreproducible.
14
12
  DCNUM_PPID_GENERATION = "11"
13
+ """The dcnum pipeline generation.
14
+ Increment this string if there are breaking changes that make
15
+ previous pipelines unreproducible.
16
+ """
15
17
 
16
18
 
17
19
  class ClassWithPPIDCapabilities(Protocol):
dcnum/os_env_st.py CHANGED
@@ -4,7 +4,6 @@ import os
4
4
 
5
5
  logger = logging.getLogger(__name__)
6
6
 
7
- #: environment variables that set number of threads
8
7
  os_env_threading = [
9
8
  "MKL_NUM_THREADS",
10
9
  "NUMBA_NUM_THREADS",
@@ -14,13 +13,14 @@ os_env_threading = [
14
13
  "OPENBLAS_NUM_THREADS",
15
14
  "VECLIB_MAXIMUM_THREADS",
16
15
  ]
16
+ """environment variables that define number of threads libraries will use"""
17
17
 
18
18
 
19
19
  class RequestSingleThreaded:
20
20
  """Context manager for starting a process with specific environment
21
21
 
22
22
  When entering the context, the environment variables defined in
23
- `os_env_threading` are all set to "1", telling the relevant libraries
23
+ ``os_env_threading`` are all set to "1", telling the relevant libraries
24
24
  that they should work in single-threaded mode.
25
25
  When exiting the context, these environment variables are reset to
26
26
  their original values (or unset if applicable).
dcnum/read/__init__.py CHANGED
@@ -2,5 +2,6 @@
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 HDF5Data, HDF5ImageCache, concatenated_hdf5_data
5
+ from .hdf5_data import HDF5Data, HDF5ImageCache
6
+ from .hdf5_concat import concatenated_hdf5_data
6
7
  from .mapped import get_mapping_indices, get_mapped_object
dcnum/read/cache.py CHANGED
@@ -25,8 +25,10 @@ class BaseImageChunkCache(abc.ABC):
25
25
  self._dtype = None
26
26
  chunk_size = min(shape[0], chunk_size)
27
27
  self._len = self.shape[0]
28
- #: This is a FILO cache for the chunks
28
+
29
29
  self.cache = collections.OrderedDict()
30
+ """This is a FILO cache for the chunks"""
31
+
30
32
  self.image_shape = self.shape[1:]
31
33
  self.chunk_shape = (chunk_size,) + self.shape[1:]
32
34
  self.chunk_size = chunk_size
dcnum/read/const.py CHANGED
@@ -1,5 +1,3 @@
1
- #: Scalar features that apply to all events in a frame and which are
2
- #: not computed for individual events.
3
1
  PROTECTED_FEATURES = [
4
2
  "bg_off",
5
3
  "flow_rate",
@@ -10,6 +8,11 @@ PROTECTED_FEATURES = [
10
8
  "temp_amb",
11
9
  "time",
12
10
  ]
11
+ """Frame-defined scalar features.
12
+ Scalar features that apply to all events in a frame and which are
13
+ not computed for individual events
14
+ """
15
+
13
16
 
14
17
  # User-defined features may be anything, but if the user needs something
15
18
  # very specific for the pipeline, having them protected is a nice feature.
@@ -17,7 +17,7 @@ def detect_flickering(image_data: np.ndarray | HDF5Data,
17
17
  triggering signal.
18
18
 
19
19
  If flickering is detected, you should use the "sparsemed" background
20
- computation with `offset_correction` set to True.
20
+ computation with ``offset_correction`` set to True.
21
21
 
22
22
  Parameters
23
23
  ----------
@@ -0,0 +1,145 @@
1
+ import io
2
+ import pathlib
3
+ import tempfile
4
+ import warnings
5
+
6
+ import h5py
7
+ import numpy as np
8
+
9
+
10
+ from .hdf5_data import HDF5Data
11
+
12
+
13
+ def concatenated_hdf5_data(paths: list[pathlib.Path],
14
+ path_out: bool | pathlib.Path | None = True,
15
+ compute_frame: bool = True,
16
+ features: list[str] | None = None):
17
+ """Return a virtual dataset concatenating all the input paths
18
+
19
+ Parameters
20
+ ----------
21
+ paths:
22
+ Path of the input HDF5 files that will be concatenated along
23
+ the feature axis. The metadata will be taken from the first
24
+ file.
25
+ path_out:
26
+ If `None`, then the dataset is created in memory. If `True`
27
+ (default), create a file on disk. If a pathlib.Path is specified,
28
+ the dataset is written to that file. Note that datasets in memory
29
+ are likely not pickable (so don't use them for multiprocessing).
30
+ compute_frame:
31
+ Whether to compute the "events/frame" feature, taking the frame
32
+ data from the input files and properly incrementing them along
33
+ the file index.
34
+ features:
35
+ List of features to take from the input files.
36
+
37
+ Notes
38
+ -----
39
+ - If one of the input files does not contain a feature from the first
40
+ input `paths`, then a `ValueError` is raised. Use the `features`
41
+ argument to specify which features you need instead.
42
+ - Basins are not considered.
43
+ """
44
+ h5kwargs = {"mode": "w", "libver": "latest"}
45
+ if isinstance(path_out, (pathlib.Path, str)):
46
+ h5kwargs["name"] = path_out
47
+ elif path_out is True:
48
+ tf = tempfile.NamedTemporaryFile(prefix="dcnum_vc_",
49
+ suffix=".hdf5",
50
+ delete=False)
51
+ tf.write(b"dummy")
52
+ h5kwargs["name"] = tf.name
53
+ tf.close()
54
+ elif path_out is None:
55
+ h5kwargs["name"] = io.BytesIO()
56
+ else:
57
+ raise ValueError(
58
+ f"Invalid type for `path_out`: {type(path_out)} ({path_out}")
59
+
60
+ if len(paths) == 0:
61
+ raise ValueError("Please specify at least one file in `paths`!")
62
+ elif len(paths) == 1:
63
+ warnings.warn("Only one file passed to `concatenated_hdf5_data`; this "
64
+ "is equivalent to using `HDF5Data`, but slower.")
65
+
66
+ frames = []
67
+
68
+ with h5py.File(**h5kwargs) as hv:
69
+ # determine the sizes of the input files
70
+ shapes = {}
71
+ dtypes = {}
72
+ size = 0
73
+ for ii, pp in enumerate(paths):
74
+ pp = pathlib.Path(pp).resolve()
75
+ with h5py.File(pp, libver="latest") as h5:
76
+ # get all feature keys
77
+ featsi = sorted(h5["events"].keys())
78
+ # get metadata
79
+ if ii == 0:
80
+ meta = dict(h5.attrs)
81
+ if not features:
82
+ features = featsi
83
+ # make sure number of features are consistent
84
+ if not set(features) <= set(featsi):
85
+ raise ValueError(
86
+ f"File {pp} contains more features than {paths[0]}!")
87
+ # populate shapes for all features
88
+ for feat in features:
89
+ if not isinstance(h5["events"][feat], h5py.Dataset):
90
+ warnings.warn(
91
+ f"Ignoring {feat}; not implemented yet!")
92
+ continue
93
+ if feat in ["frame", "time"]:
94
+ continue
95
+ shapes.setdefault(feat, []).append(
96
+ h5["events"][feat].shape)
97
+ if ii == 0:
98
+ dtypes[feat] = h5["events"][feat].dtype
99
+ # increment size
100
+ size += h5["events"][features[0]].shape[0]
101
+ # remember the frame feature if requested
102
+ if compute_frame:
103
+ frames.append(h5["events/frame"][:])
104
+
105
+ # write metadata
106
+ hv.attrs.update(meta)
107
+
108
+ # Create the virtual datasets
109
+ for feat in shapes:
110
+ if len(shapes[feat][0]) == 1:
111
+ # scalar feature
112
+ shape = (sum([sh[0] for sh in shapes[feat]]))
113
+ else:
114
+ # non-scalar feature
115
+ length = (sum([sh[0] for sh in shapes[feat]]))
116
+ shape = list(shapes[feat][0])
117
+ shape[0] = length
118
+ shape = tuple(shape)
119
+ layout = h5py.VirtualLayout(shape=shape, dtype=dtypes[feat])
120
+ loc = 0
121
+ for jj, pp in enumerate(paths):
122
+ vsource = h5py.VirtualSource(pp, f"events/{feat}",
123
+ shape=shapes[feat][jj])
124
+ cursize = shapes[feat][jj][0]
125
+ layout[loc:loc+cursize] = vsource
126
+ loc += cursize
127
+ hv.create_virtual_dataset(f"/events/{feat}", layout, fillvalue=0)
128
+
129
+ if compute_frame:
130
+ # concatenate frames and store in dataset
131
+ frame_concat = np.zeros(size, dtype=np.uint64)
132
+ locf = 0 # indexing location
133
+ prevmax = 0 # maximum frame number stored so far in array
134
+ for fr in frames:
135
+ offset = prevmax + 1 - fr[0]
136
+ frame_concat[locf:locf+fr.size] = fr + offset
137
+ locf += fr.size
138
+ prevmax = fr[-1] + offset
139
+ hv.create_dataset("/events/frame", data=frame_concat)
140
+
141
+ # write metadata
142
+ hv.attrs["experiment:event count"] = size
143
+
144
+ data = HDF5Data(h5kwargs["name"])
145
+ return data
dcnum/read/hdf5_data.py CHANGED
@@ -1,11 +1,9 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import hashlib
4
- import io
5
4
  import json
6
5
  import numbers
7
6
  import pathlib
8
- import tempfile
9
7
  from typing import Dict, BinaryIO, List
10
8
  import uuid
11
9
  import warnings
@@ -160,7 +158,10 @@ class HDF5Data:
160
158
  if not hasattr(self, "h5"):
161
159
  self.h5 = None
162
160
 
163
- self.path = state["path"]
161
+ path = state["path"]
162
+ if isinstance(path, str):
163
+ path = pathlib.Path(path)
164
+ self.path = path
164
165
 
165
166
  self.md5_5m = state["md5_5m"]
166
167
  if self.md5_5m is None:
@@ -552,136 +553,10 @@ class HDF5Data:
552
553
  return self._keys
553
554
 
554
555
 
555
- def concatenated_hdf5_data(paths: List[pathlib.Path],
556
- path_out: True | pathlib.Path | None = True,
557
- compute_frame: bool = True,
558
- features: List[str] | None = None):
559
- """Return a virtual dataset concatenating all the input paths
560
-
561
- Parameters
562
- ----------
563
- paths:
564
- Path of the input HDF5 files that will be concatenated along
565
- the feature axis. The metadata will be taken from the first
566
- file.
567
- path_out:
568
- If `None`, then the dataset is created in memory. If `True`
569
- (default), create a file on disk. If a pathlib.Path is specified,
570
- the dataset is written to that file. Note that datasets in memory
571
- are likely not pickable (so don't use them for multiprocessing).
572
- compute_frame:
573
- Whether to compute the "events/frame" feature, taking the frame
574
- data from the input files and properly incrementing them along
575
- the file index.
576
- features:
577
- List of features to take from the input files.
578
-
579
- Notes
580
- -----
581
- - If one of the input files does not contain a feature from the first
582
- input `paths`, then a `ValueError` is raised. Use the `features`
583
- argument to specify which features you need instead.
584
- - Basins are not considered.
585
- """
586
- h5kwargs = {"mode": "w", "libver": "latest"}
587
- if isinstance(path_out, (pathlib.Path, str)):
588
- h5kwargs["name"] = path_out
589
- elif path_out is True:
590
- tf = tempfile.NamedTemporaryFile(prefix="dcnum_vc_",
591
- suffix=".hdf5",
592
- delete=False)
593
- tf.write(b"dummy")
594
- h5kwargs["name"] = tf.name
595
- tf.close()
596
- elif path_out is None:
597
- h5kwargs["name"] = io.BytesIO()
598
- else:
599
- raise ValueError(
600
- f"Invalid type for `path_out`: {type(path_out)} ({path_out}")
601
-
602
- if len(paths) == 0:
603
- raise ValueError("Please specify at least one file in `paths`!")
604
- elif len(paths) == 1:
605
- warnings.warn("Only one file passed to `concatenated_hdf5_data`; this "
606
- "is equivalent to using `HDF5Data`, but slower.")
607
-
608
- frames = []
609
-
610
- with h5py.File(**h5kwargs) as hv:
611
- # determine the sizes of the input files
612
- shapes = {}
613
- dtypes = {}
614
- size = 0
615
- for ii, pp in enumerate(paths):
616
- pp = pathlib.Path(pp).resolve()
617
- with h5py.File(pp, libver="latest") as h5:
618
- # get all feature keys
619
- featsi = sorted(h5["events"].keys())
620
- # get metadata
621
- if ii == 0:
622
- meta = dict(h5.attrs)
623
- if not features:
624
- features = featsi
625
- # make sure number of features are consistent
626
- if not set(features) <= set(featsi):
627
- raise ValueError(
628
- f"File {pp} contains more features than {paths[0]}!")
629
- # populate shapes for all features
630
- for feat in features:
631
- if not isinstance(h5["events"][feat], h5py.Dataset):
632
- warnings.warn(
633
- f"Ignoring {feat}; not implemented yet!")
634
- continue
635
- if feat in ["frame", "time"]:
636
- continue
637
- shapes.setdefault(feat, []).append(
638
- h5["events"][feat].shape)
639
- if ii == 0:
640
- dtypes[feat] = h5["events"][feat].dtype
641
- # increment size
642
- size += h5["events"][features[0]].shape[0]
643
- # remember the frame feature if requested
644
- if compute_frame:
645
- frames.append(h5["events/frame"][:])
646
-
647
- # write metadata
648
- hv.attrs.update(meta)
649
-
650
- # Create the virtual datasets
651
- for feat in shapes:
652
- if len(shapes[feat][0]) == 1:
653
- # scalar feature
654
- shape = (sum([sh[0] for sh in shapes[feat]]))
655
- else:
656
- # non-scalar feature
657
- length = (sum([sh[0] for sh in shapes[feat]]))
658
- shape = list(shapes[feat][0])
659
- shape[0] = length
660
- shape = tuple(shape)
661
- layout = h5py.VirtualLayout(shape=shape, dtype=dtypes[feat])
662
- loc = 0
663
- for jj, pp in enumerate(paths):
664
- vsource = h5py.VirtualSource(pp, f"events/{feat}",
665
- shape=shapes[feat][jj])
666
- cursize = shapes[feat][jj][0]
667
- layout[loc:loc+cursize] = vsource
668
- loc += cursize
669
- hv.create_virtual_dataset(f"/events/{feat}", layout, fillvalue=0)
670
-
671
- if compute_frame:
672
- # concatenate frames and store in dataset
673
- frame_concat = np.zeros(size, dtype=np.uint64)
674
- locf = 0 # indexing location
675
- prevmax = 0 # maximum frame number stored so far in array
676
- for fr in frames:
677
- offset = prevmax + 1 - fr[0]
678
- frame_concat[locf:locf+fr.size] = fr + offset
679
- locf += fr.size
680
- prevmax = fr[-1] + offset
681
- hv.create_dataset("/events/frame", data=frame_concat)
682
-
683
- # write metadata
684
- hv.attrs["experiment:event count"] = size
685
-
686
- data = HDF5Data(h5kwargs["name"])
687
- return data
556
+ def concatenated_hdf5_data(*args, **kwargs):
557
+ warnings.warn(
558
+ "Please use `dcnum.read.hdf5_concat.concatenated_hdf5_data`. "
559
+ "Accessing this method via `dcnum.read.hdf5_data` is deprecated.",
560
+ DeprecationWarning)
561
+ from . import hdf5_concat
562
+ return hdf5_concat.concatenated_hdf5_data(*args, **kwargs)
@@ -52,9 +52,10 @@ class TorchSegmenterBase(Segmenter):
52
52
  segmenter_kwargs: dict
53
53
  Keyword arguments for the segmenter
54
54
  meta: dict
55
- Dictionary of metadata from an :class:`HDF5Data` instance
55
+ Dictionary of metadata from an :class:`.hdf5_data.HDF5Data`
56
+ instance
56
57
  logs: dict
57
- Dictionary of logs from an :class:`HDF5Data` instance
58
+ Dictionary of logs from an :class:`.hdf5_data.HDF5Data` instance
58
59
 
59
60
  Returns
60
61
  -------
@@ -11,6 +11,7 @@ def postprocess_masks(masks,
11
11
  """Postprocess mask images from ML segmenters
12
12
 
13
13
  The transformation includes:
14
+
14
15
  - Revert the cropping and padding operations done in
15
16
  :func:`.preprocess_images` by padding with zeros and cropping.
16
17
  - If the original image shape is larger than the mask image shape,
@@ -11,6 +11,7 @@ def preprocess_images(images: np.ndarray,
11
11
  """Transform image data to something torch models expect
12
12
 
13
13
  The transformation includes:
14
+
14
15
  - normalization (division by 255, subtraction of mean, division by std)
15
16
  - cropping and padding of the input images to `image_shape`. For padding,
16
17
  the median of each *individual* image is used.
dcnum/segm/segmenter.py CHANGED
@@ -26,17 +26,23 @@ class SegmenterNotApplicableError(BaseException):
26
26
 
27
27
 
28
28
  class Segmenter(abc.ABC):
29
- #: Required hardware ("cpu" or "gpu") defined in first-level subclass.
30
29
  hardware_processor = "none"
31
- #: Whether to enable mask post-processing. If disabled, you should
32
- #: make sure that your mask is properly defined and cleaned or you
33
- #: have to call `process_mask` in your `segment_algorithm` implementation.
30
+ """Required hardware ("cpu" or "gpu") defined in first-level subclass."""
31
+
34
32
  mask_postprocessing = True
35
- #: Default keyword arguments for mask post-processing. See `process_mask`
36
- #: for available options.
33
+ """Whether to enable mask post-processing.
34
+ If disabled, you should make sure that your mask is properly defined
35
+ and cleaned or you have to call `process_mask` in your
36
+ ``segment_algorithm`` implementation.
37
+ """
38
+
37
39
  mask_default_kwargs = {}
38
- #: If the segmenter requires a background-corrected image, set this to True
40
+ """Default keyword arguments for mask post-processing.
41
+ See `process_mask` for available options.
42
+ """
43
+
39
44
  requires_background_correction = False
45
+ """Whether the segmenter requires a background-corrected image"""
40
46
 
41
47
  def __init__(self,
42
48
  *,
@@ -46,10 +52,11 @@ class Segmenter(abc.ABC):
46
52
  """Base segmenter class
47
53
 
48
54
  This is the base segmenter class for the multiprocessing operation
49
- segmenter :class:`.MPOSegmenter` (multiple subprocesses are spawned
50
- and each of them works on a queue of images) and the single-threaded
51
- operation segmenter :class:`.STOSegmenter` (e.g. for batch
52
- segmentation on a GPU).
55
+ segmenter :class:`.segmenter_mpo.MPOSegmenter` (multiple
56
+ subprocesses are spawned and each of them works on a queue of images)
57
+ and the single-threaded operation segmenter
58
+ :class:`.segmenter_sto.STOSegmenter` (e.g. for batch segmentation on
59
+ a GPU).
53
60
 
54
61
  Parameters
55
62
  ----------
@@ -64,12 +71,15 @@ class Segmenter(abc.ABC):
64
71
  self.logger = logging.getLogger(__name__).getChild(
65
72
  self.__class__.__name__)
66
73
  spec = inspect.getfullargspec(self.segment_algorithm)
67
- #: custom keyword arguments for the subclassing segmenter
74
+
68
75
  self.kwargs = spec.kwonlydefaults or {}
76
+ """custom keyword arguments for the subclassing segmenter"""
77
+
69
78
  self.kwargs.update(kwargs)
70
79
 
71
- #: keyword arguments for mask post-processing
72
80
  self.kwargs_mask = {}
81
+ """keyword arguments for mask post-processing"""
82
+
73
83
  if self.mask_postprocessing:
74
84
  spec_mask = inspect.getfullargspec(self.process_mask)
75
85
  self.kwargs_mask.update(spec_mask.kwonlydefaults or {})
@@ -108,7 +118,7 @@ class Segmenter(abc.ABC):
108
118
  KEY:KW_APPROACH:KW_MASK
109
119
 
110
120
  Where KEY is e.g. "legacy" or "watershed", and KW_APPROACH is a
111
- list of keyword arguments for `segment_algorithm`, e.g.::
121
+ list of keyword arguments for ``segment_algorithm``, e.g.::
112
122
 
113
123
  thresh=-6^blur=0
114
124
 
@@ -296,10 +306,10 @@ class Segmenter(abc.ABC):
296
306
 
297
307
  @functools.cache
298
308
  def segment_algorithm_wrapper(self):
299
- """Wraps `self.segment_algorithm` to only accept an image
309
+ """Wraps ``self.segment_algorithm`` to only accept an image
300
310
 
301
- The static method `self.segment_algorithm` may optionally accept
302
- keyword arguments `self.kwargs`. This wrapper returns the
311
+ The static method ``self.segment_algorithm`` may optionally accept
312
+ keyword arguments ``self.kwargs``. This wrapper returns the
303
313
  wrapped method that only accepts the image as an argument. This
304
314
  makes sense if you want to unify
305
315
  """
@@ -336,7 +346,7 @@ class Segmenter(abc.ABC):
336
346
  additional background offset values that should be subtracted
337
347
  from the image data before segmentation. Should only be
338
348
  used in combination with segmenters that have
339
- `requires_background_correction` set to True.
349
+ ``requires_background_correction`` set to True.
340
350
  """
341
351
  images = image_data.get_chunk(chunk)
342
352
  if bg_off is not None:
@@ -364,9 +374,10 @@ class Segmenter(abc.ABC):
364
374
  segmenter_kwargs: dict
365
375
  Keyword arguments for the segmenter
366
376
  meta: dict
367
- Dictionary of metadata from an :class:`HDF5Data` instance
377
+ Dictionary of metadata from an :class:`.hdf5_data.HDF5Data`
378
+ instance
368
379
  logs: dict
369
- Dictionary of logs from an :class:`HDF5Data` instance
380
+ Dictionary of logs from an :class:`.hdf5_data.HDF5Data` instance
370
381
 
371
382
  Returns
372
383
  -------
@@ -36,8 +36,8 @@ class SegmenterManagerThread(threading.Thread):
36
36
  its job for a slot, the slot value will be set to "e" (for
37
37
  "task is with feature extractor").
38
38
  slot_chunks:
39
- For each slot in `slot_states`, this shared array defines
40
- on which chunk in `image_data` the segmentation took place.
39
+ For each slot in ``slot_states``, this shared array defines
40
+ on which chunk in ``image_data`` the segmentation took place.
41
41
  bg_off:
42
42
  1d array containing additional background image offset values
43
43
  that are added to each background image before subtraction
@@ -45,10 +45,10 @@ class SegmenterManagerThread(threading.Thread):
45
45
 
46
46
  Notes
47
47
  -----
48
- This manager keeps a list `labels_list` which enumerates the
49
- slots just like `slot_states` and `slot_chunks` do. For each
48
+ This manager keeps a list ``labels_list`` which enumerates the
49
+ slots just like ``slot_states` and ``slot_chunks`` do. For each
50
50
  slot, this list contains the labeled image data (integer-valued)
51
- for the input `image_data` chunks.
51
+ for the input ``image_data`` chunks.
52
52
 
53
53
  The working principle of this `SegmenterManagerThread` allows
54
54
  the user to define a fixed number of slots on which the segmenter
@@ -61,21 +61,28 @@ class SegmenterManagerThread(threading.Thread):
61
61
  super(SegmenterManagerThread, self).__init__(
62
62
  name="SegmenterManager", *args, **kwargs)
63
63
  self.logger = logging.getLogger("dcnum.segm.SegmenterManagerThread")
64
- #: Segmenter instance
64
+
65
65
  self.segmenter = segmenter
66
- #: Image data which is being segmented
66
+ """Segmenter instance"""
67
+
67
68
  self.image_data = image_data
68
- #: Additional, optional background offset
69
+ """Image data which is being segmented"""
70
+
69
71
  self.bg_off = (
70
72
  bg_off if self.segmenter.requires_background_correction else None)
71
- #: Slot states
73
+ """Additional, optional background offset"""
74
+
72
75
  self.slot_states = slot_states
73
- #: Current slot chunk index for the slot states
76
+ """Slot states"""
77
+
74
78
  self.slot_chunks = slot_chunks
75
- #: List containing the segmented labels of each slot
79
+ """Current slot chunk index for the slot states"""
80
+
76
81
  self.labels_list = [None] * len(self.slot_states)
77
- #: Time counter for segmentation
82
+ """List containing the segmented labels of each slot"""
83
+
78
84
  self.t_count = 0
85
+ """Time counter for segmentation"""
79
86
 
80
87
  def run(self):
81
88
  num_slots = len(self.slot_states)
@@ -35,7 +35,7 @@ class MPOSegmenter(Segmenter, abc.ABC):
35
35
  debug: bool
36
36
  Debugging parameters
37
37
  kwargs:
38
- Additional, optional keyword arguments for `segment_algorithm`
38
+ Additional, optional keyword arguments for ``segment_algorithm``
39
39
  defined in the subclass.
40
40
  """
41
41
  super(MPOSegmenter, self).__init__(kwargs_mask=kwargs_mask,
@@ -145,7 +145,7 @@ class MPOSegmenter(Segmenter, abc.ABC):
145
145
  """Perform batch segmentation of `images`
146
146
 
147
147
  Before segmentation, an optional background offset correction with
148
- `bg_off` is performed. After segmentation, mask postprocessing is
148
+ ``bg_off`` is performed. After segmentation, mask postprocessing is
149
149
  performed according to the class definition.
150
150
 
151
151
  Parameters
@@ -264,7 +264,7 @@ class MPOSegmenter(Segmenter, abc.ABC):
264
264
  """Return the integer label image for an input image
265
265
 
266
266
  Before segmentation, an optional background offset correction with
267
- `bg_off` is performed. After segmentation, mask postprocessing is
267
+ ``bg_off`` is performed. After segmentation, mask postprocessing is
268
268
  performed according to the class definition.
269
269
  """
270
270
  segm_wrap = self.segment_algorithm_wrapper()
@@ -296,7 +296,7 @@ class MPOSegmenterWorker:
296
296
 
297
297
  Parameters
298
298
  ----------
299
- segmenter: MPOSegmenter
299
+ segmenter: .segmenter_mpo.MPOSegmenter
300
300
  The segmentation instance
301
301
  sl_start: int
302
302
  Start of slice of input array to process