swcgeom 0.14.0__py3-none-any.whl → 0.15.0__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 swcgeom might be problematic. Click here for more details.

swcgeom/_version.py CHANGED
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '0.14.0'
16
- __version_tuple__ = version_tuple = (0, 14, 0)
15
+ __version__ = version = '0.15.0'
16
+ __version_tuple__ = version_tuple = (0, 15, 0)
@@ -5,7 +5,6 @@ from typing import Dict, List
5
5
 
6
6
  import numpy as np
7
7
  import pandas as pd
8
- from typing_extensions import Self
9
8
 
10
9
  from swcgeom.core.branch import Branch
11
10
  from swcgeom.core.swc_utils import to_sub_topology
@@ -31,7 +30,7 @@ class BranchTree(Tree):
31
30
  return self.branches[idx]
32
31
 
33
32
  @classmethod
34
- def from_tree(cls, tree: Tree) -> Self:
33
+ def from_tree(cls, tree: Tree) -> "BranchTree":
35
34
  """Generating a branch tree from tree."""
36
35
 
37
36
  branches = tree.get_branches()
@@ -56,6 +55,6 @@ class BranchTree(Tree):
56
55
  return branch_tree
57
56
 
58
57
  @classmethod
59
- def from_data_frame(cls, df: pd.DataFrame, *args, **kwargs) -> Self:
58
+ def from_data_frame(cls, df: pd.DataFrame, *args, **kwargs) -> "BranchTree":
60
59
  tree = super().from_data_frame(df, *args, **kwargs)
61
60
  return cls.from_tree(tree)
@@ -17,7 +17,6 @@ from typing import (
17
17
 
18
18
  import numpy as np
19
19
  import numpy.typing as npt
20
- from typing_extensions import Self
21
20
 
22
21
  from swcgeom.core.swc import eswc_cols
23
22
  from swcgeom.core.tree import Tree
@@ -155,7 +154,7 @@ class Population:
155
154
  return f"Neuron population in '{self.root}'"
156
155
 
157
156
  @classmethod
158
- def from_swc(cls, root: str, ext: str = ".swc", **kwargs) -> Self:
157
+ def from_swc(cls, root: str, ext: str = ".swc", **kwargs) -> "Population":
159
158
  if not os.path.exists(root):
160
159
  raise FileNotFoundError(
161
160
  f"the root does not refers to an existing directory: {root}"
@@ -171,7 +170,7 @@ class Population:
171
170
  ext: str = ".eswc",
172
171
  extra_cols: Optional[Iterable[str]] = None,
173
172
  **kwargs,
174
- ) -> Self:
173
+ ) -> "Population":
175
174
  extra_cols = list(extra_cols) if extra_cols is not None else []
176
175
  extra_cols.extend(k for k, t in eswc_cols)
177
176
  return cls.from_swc(root, ext, extra_cols=extra_cols, **kwargs)
@@ -244,7 +243,7 @@ class Populations:
244
243
  check_same: bool = False,
245
244
  labels: Optional[Iterable[str]] = None,
246
245
  **kwargs,
247
- ) -> Self:
246
+ ) -> "Populations":
248
247
  """Get population from dirs.
249
248
 
250
249
  Parameters
@@ -268,7 +267,7 @@ class Populations:
268
267
 
269
268
  fs = [inter for _ in roots]
270
269
  elif check_same:
271
- assert reduce(lambda a, b: a == b, fs), "not the same among populations"
270
+ assert [fs[0] == a for a in fs[1:]], "not the same among populations"
272
271
 
273
272
  populations = [
274
273
  Population(
@@ -276,7 +275,7 @@ class Populations:
276
275
  )
277
276
  for i, d in enumerate(roots)
278
277
  ]
279
- return cls(populations, labels=labels)
278
+ return Populations(populations, labels=labels)
280
279
 
281
280
  @classmethod
282
281
  def from_eswc(
@@ -286,7 +285,7 @@ class Populations:
286
285
  *,
287
286
  ext: str = ".eswc",
288
287
  **kwargs,
289
- ) -> Self:
288
+ ) -> "Populations":
290
289
  extra_cols = list(extra_cols) if extra_cols is not None else []
291
290
  extra_cols.extend(k for k, t in eswc_cols)
292
291
  return cls.from_swc(roots, extra_cols=extra_cols, ext=ext, **kwargs)
@@ -1,155 +1,26 @@
1
- """Assemble lines to swc."""
1
+ """Assemble lines to swc.
2
2
 
3
- import warnings
4
- from copy import copy
5
- from typing import Iterable, List, Optional, Tuple
3
+ Notes
4
+ -----
5
+ This module is deprecated, please use `~.transforms.LinesToTree`
6
+ instead.
7
+ """
6
8
 
7
- import numpy as np
8
- import pandas as pd
9
-
10
- from swcgeom.core.swc_utils.base import SWCNames, get_names
11
- from swcgeom.core.swc_utils.normalizer import link_roots_to_nearest_, sort_nodes_
12
9
 
13
10
  __all__ = ["assemble_lines", "try_assemble_lines"]
14
11
 
15
12
 
16
- def assemble_lines(*args, **kwargs) -> pd.DataFrame:
17
- """Assemble lines to a tree.
18
-
19
- Assemble all the lines into a set of subtrees, and then connect
20
- them.
21
-
22
- Parameters
23
- ----------
24
- lines : List of ~pd.DataFrame
25
- An array of tables containing a line, columns should follwing
26
- the swc.
27
- **kwargs
28
- Forwarding to `try_assemble_lines`
29
-
30
- Returns
31
- -------
32
- tree : ~pd.DataFrame
33
-
34
- See Also
35
- --------
36
- ~swcgeom.core.swc_utils.try_assemble_lines
37
- """
38
- warnings.warn(
13
+ def assemble_lines(*args, **kwargs):
14
+ raise DeprecationWarning(
39
15
  "`assemble_lines` has been replaced by "
40
16
  "`~.transforms.LinesToTree` because it can be easy assemble "
41
- "with other tansformations, and this will be removed in next "
42
- "version.",
43
- DeprecationWarning,
17
+ "with other tansformations.",
44
18
  )
45
- return assemble_lines_impl(*args, **kwargs)
46
-
47
19
 
48
- def try_assemble_lines(*args, **kwargs) -> Tuple[pd.DataFrame, List[pd.DataFrame]]:
49
- """Trying assemble lines to a tree.
50
20
 
51
- Treat the first line as a tree, find a line whose shortest distance
52
- between the tree and the line is less than threshold, merge it into
53
- the tree, repeat until there are no line to merge, return tree and
54
- the remaining lines.
55
-
56
- Parameters
57
- ----------
58
- lines : List of ~pd.DataFrame
59
- An array of tables containing a line, columns should follwing
60
- the swc.
61
- undirected : bool, default `True`
62
- Both ends of a line can be considered connection point. If
63
- `False`, only the starting point.
64
- thre : float, default `0.2`
65
- Connection threshold.
66
- id_offset : int, default `0`
67
- The offset of the line node id.
68
- sort_nodes : bool, default `True`
69
- sort nodes of subtree
70
- names : SWCNames, optional
71
-
72
- Returns
73
- -------
74
- tree : ~pd.DataFrame
75
- remaining_lines : List of ~pd.DataFrame
76
- """
77
- warnings.warn(
21
+ def try_assemble_lines(*args, **kwargs):
22
+ raise DeprecationWarning(
78
23
  "`try_assemble_lines` has been replaced by "
79
24
  "`~.transforms.LinesToTree` because it can be easy assemble "
80
- "with other tansformations, and this will be removed in next "
81
- "version.",
82
- DeprecationWarning,
25
+ "with other tansformations.",
83
26
  )
84
- return try_assemble_lines_impl(*args, **kwargs)
85
-
86
-
87
- # TODO: move the following codes to `transforms` module
88
-
89
- EPS = 1e-5
90
-
91
-
92
- def assemble_lines_impl(lines: Iterable[pd.DataFrame], **kwargs) -> pd.DataFrame:
93
- tree, lines = try_assemble_lines_impl(lines, sort_nodes=False, **kwargs)
94
- while len(lines) > 0:
95
- t, lines = try_assemble_lines_impl(
96
- lines, id_offset=len(tree), sort_nodes=False, **kwargs
97
- )
98
- tree = pd.concat([tree, t])
99
-
100
- tree = tree.reset_index()
101
- link_roots_to_nearest_(tree)
102
- sort_nodes_(tree)
103
- return tree
104
-
105
-
106
- def try_assemble_lines_impl( # pylint: disable=too-many-arguments
107
- lines: Iterable[pd.DataFrame],
108
- undirected: bool = True,
109
- thre: float = 0.2,
110
- id_offset: int = 0,
111
- sort_nodes: bool = True,
112
- *,
113
- names: Optional[SWCNames] = None,
114
- ) -> Tuple[pd.DataFrame, List[pd.DataFrame]]:
115
- names = get_names(names)
116
- lines = copy(list(lines))
117
-
118
- tree = lines[0]
119
- tree[names.id] = id_offset + np.arange(len(tree))
120
- tree[names.pid] = tree[names.id] - 1
121
- tree.at[0, names.pid] = -1
122
- del lines[0]
123
-
124
- while True:
125
- for i, line in enumerate(lines):
126
- for p in [0, -1] if undirected else [0]:
127
- xyz = [names.x, names.y, names.z]
128
- vs = tree[xyz] - line.iloc[p][xyz]
129
- dis = np.linalg.norm(vs, axis=1)
130
- ind = np.argmin(dis)
131
- if dis[ind] > thre:
132
- continue
133
-
134
- if dis[ind] < EPS:
135
- line = line.drop((p + len(line)) % len(line)).reset_index(drop=True)
136
-
137
- line[names.id] = id_offset + len(tree) + np.arange(len(line))
138
- line[names.pid] = line[names.id] + (-1 if p == 0 else 1)
139
- line.at[(p + len(line)) % len(line), names.pid] = tree.iloc[ind][
140
- names.id
141
- ]
142
- tree = pd.concat([tree, line])
143
- del lines[i]
144
- break
145
- else:
146
- continue
147
-
148
- break
149
- else:
150
- break
151
-
152
- if sort_nodes:
153
- sort_nodes_(tree)
154
-
155
- return tree, lines
@@ -27,8 +27,8 @@ def to_sub_topology(sub: Topology) -> Tuple[Topology, npt.NDArray[np.int32]]:
27
27
  Returns
28
28
  -------
29
29
  sub_topology : Topology
30
- id_map : List of int
31
- Map from new id to original id.
30
+ mapping : List of int
31
+ Map from new id to old id.
32
32
 
33
33
  See Also
34
34
  --------
swcgeom/core/tree.py CHANGED
@@ -20,7 +20,6 @@ from typing import (
20
20
  import numpy as np
21
21
  import numpy.typing as npt
22
22
  import pandas as pd
23
- from typing_extensions import Self
24
23
 
25
24
  from swcgeom.core.branch import Branch
26
25
  from swcgeom.core.node import Node
@@ -28,7 +27,7 @@ from swcgeom.core.path import Path
28
27
  from swcgeom.core.segment import Segment, Segments
29
28
  from swcgeom.core.swc import DictSWC, eswc_cols
30
29
  from swcgeom.core.swc_utils import SWCNames, get_names, read_swc, traverse
31
- from swcgeom.core.tree_utils_impl import get_subtree_impl
30
+ from swcgeom.core.tree_utils_impl import Mapping, get_subtree_impl
32
31
  from swcgeom.utils import PathOrIO, padding1d
33
32
 
34
33
  __all__ = ["Tree"]
@@ -73,9 +72,18 @@ class Tree(DictSWC):
73
72
  """The end-to-end straight-line distance to soma."""
74
73
  return self.distance(self.attach.soma())
75
74
 
76
- def subtree(self) -> "Tree":
77
- """Get subtree from node."""
78
- n_nodes, ndata, source, names = get_subtree_impl(self.attach, self.id)
75
+ def subtree(self, *, out_mapping: Optional[Mapping] = None) -> "Tree":
76
+ """Get subtree from node.
77
+
78
+ Parameters
79
+ ----------
80
+ out_mapping : List of int or Dict[int, int], optional
81
+ Map from new id to old id.
82
+ """
83
+
84
+ n_nodes, ndata, source, names = get_subtree_impl(
85
+ self.attach, self.id, out_mapping=out_mapping
86
+ )
79
87
  return Tree(n_nodes, **ndata, source=source, names=names)
80
88
 
81
89
  def is_root(self) -> bool:
@@ -260,11 +268,11 @@ class Tree(DictSWC):
260
268
  paths = self.traverse(enter=assign_path, leave=collect_path)
261
269
  return [self.Path(self, idx) for idx in paths]
262
270
 
263
- def get_neurites(self, type_check: bool = True) -> Iterable[Self]:
271
+ def get_neurites(self, type_check: bool = True) -> Iterable["Tree"]:
264
272
  """Get neurites from soma."""
265
273
  return (n.subtree() for n in self.soma(type_check).children())
266
274
 
267
- def get_dendrites(self, type_check: bool = True) -> Iterable[Self]:
275
+ def get_dendrites(self, type_check: bool = True) -> Iterable["Tree"]:
268
276
  """Get dendrites."""
269
277
  types = [self.types.apical_dendrite, self.types.basal_dendrite]
270
278
  children = self.soma(type_check).children()
@@ -312,15 +320,14 @@ class Tree(DictSWC):
312
320
  """Get length of tree."""
313
321
  return sum(s.length() for s in self.get_segments())
314
322
 
315
- @classmethod
323
+ @staticmethod
316
324
  def from_data_frame(
317
- cls,
318
325
  df: pd.DataFrame,
319
326
  source: str = "",
320
327
  *,
321
328
  comments: Optional[Iterable[str]] = None,
322
329
  names: Optional[SWCNames] = None,
323
- ) -> Self:
330
+ ) -> "Tree":
324
331
  """Read neuron tree from data frame."""
325
332
  names = get_names(names)
326
333
  tree = Tree(
@@ -333,7 +340,7 @@ class Tree(DictSWC):
333
340
  return tree
334
341
 
335
342
  @classmethod
336
- def from_swc(cls, swc_file: PathOrIO, **kwargs) -> Self:
343
+ def from_swc(cls, swc_file: PathOrIO, **kwargs) -> "Tree":
337
344
  """Read neuron tree from swc file.
338
345
 
339
346
  See Also
@@ -352,7 +359,7 @@ class Tree(DictSWC):
352
359
  @classmethod
353
360
  def from_eswc(
354
361
  cls, swc_file: str, extra_cols: Optional[List[str]] = None, **kwargs
355
- ) -> Self:
362
+ ) -> "Tree":
356
363
  """Read neuron tree from eswc file.
357
364
 
358
365
  See Also
@@ -17,7 +17,7 @@ from swcgeom.core.swc_utils import (
17
17
  to_sub_topology,
18
18
  )
19
19
  from swcgeom.core.tree import Tree
20
- from swcgeom.core.tree_utils_impl import get_subtree_impl, to_subtree_impl
20
+ from swcgeom.core.tree_utils_impl import Mapping, get_subtree_impl, to_subtree_impl
21
21
 
22
22
  __all__ = [
23
23
  "sort_tree",
@@ -128,7 +128,12 @@ def to_sub_tree(swc_like: SWCLike, sub: Topology) -> Tuple[Tree, Dict[int, int]]
128
128
  return subtree, id_map
129
129
 
130
130
 
131
- def to_subtree(swc_like: SWCLike, removals: Iterable[int]) -> Tree:
131
+ def to_subtree(
132
+ swc_like: SWCLike,
133
+ removals: Iterable[int],
134
+ *,
135
+ out_mapping: Optional[Mapping] = None,
136
+ ) -> Tree:
132
137
  """Create subtree from origin tree.
133
138
 
134
139
  Parameters
@@ -136,17 +141,24 @@ def to_subtree(swc_like: SWCLike, removals: Iterable[int]) -> Tree:
136
141
  swc_like : SWCLike
137
142
  removals : List of int
138
143
  A list of id of nodes to be removed.
144
+ out_mapping: List of int or Dict[int, int], optional
145
+ Map new id to old id.
139
146
  """
147
+
140
148
  new_ids = swc_like.id().copy()
141
149
  for i in removals:
142
150
  new_ids[i] = REMOVAL
143
151
 
144
152
  sub = propagate_removal((new_ids, swc_like.pid()))
145
- n_nodes, ndata, source, names = to_subtree_impl(swc_like, sub)
153
+ n_nodes, ndata, source, names = to_subtree_impl(
154
+ swc_like, sub, out_mapping=out_mapping
155
+ )
146
156
  return Tree(n_nodes, **ndata, source=source, names=names)
147
157
 
148
158
 
149
- def get_subtree(swc_like: SWCLike, n: int) -> Tree:
159
+ def get_subtree(
160
+ swc_like: SWCLike, n: int, *, out_mapping: Optional[Mapping] = None
161
+ ) -> Tree:
150
162
  """Get subtree rooted at n.
151
163
 
152
164
  Parameters
@@ -154,8 +166,13 @@ def get_subtree(swc_like: SWCLike, n: int) -> Tree:
154
166
  swc_like : SWCLike
155
167
  n : int
156
168
  Id of the root of the subtree.
169
+ out_mapping: List of int or Dict[int, int], optional
170
+ Map new id to old id.
157
171
  """
158
- n_nodes, ndata, source, names = get_subtree_impl(swc_like, n)
172
+
173
+ n_nodes, ndata, source, names = get_subtree_impl(
174
+ swc_like, n, out_mapping=out_mapping
175
+ )
159
176
  return Tree(n_nodes, **ndata, source=source, names=names)
160
177
 
161
178
 
@@ -171,6 +188,7 @@ def redirect_tree(tree: Tree, new_root: int, sort: bool = True) -> Tree:
171
188
  sort : bool, default `True`
172
189
  If true, sort indices of nodes after redirect.
173
190
  """
191
+
174
192
  tree = tree.copy()
175
193
  path = [tree.node(new_root)]
176
194
  while (p := path[-1].parent()) is not None:
@@ -5,7 +5,7 @@ Notes
5
5
  Do not import `Tree` and keep this file minimized.
6
6
  """
7
7
 
8
- from typing import Any, Dict, Tuple
8
+ from typing import Any, Dict, List, Optional, Tuple
9
9
 
10
10
  import numpy as np
11
11
  import numpy.typing as npt
@@ -15,10 +15,13 @@ from swcgeom.core.swc_utils import Topology, to_sub_topology, traverse
15
15
 
16
16
  __all__ = ["get_subtree_impl", "to_subtree_impl"]
17
17
 
18
+ Mapping = Dict[int, int] | List[int]
18
19
  TreeArgs = Tuple[int, Dict[str, npt.NDArray[Any]], str, SWCNames]
19
20
 
20
21
 
21
- def get_subtree_impl(swc_like: SWCLike, n: int) -> TreeArgs:
22
+ def get_subtree_impl(
23
+ swc_like: SWCLike, n: int, *, out_mapping: Optional[Mapping] = None
24
+ ) -> TreeArgs:
22
25
  ids = []
23
26
  topo = (swc_like.id(), swc_like.pid())
24
27
  traverse(topo, enter=lambda n, _: ids.append(n), root=n)
@@ -26,14 +29,27 @@ def get_subtree_impl(swc_like: SWCLike, n: int) -> TreeArgs:
26
29
  sub_ids = np.array(ids, dtype=np.int32)
27
30
  sub_pid = swc_like.pid()[sub_ids]
28
31
  sub_pid[0] = -1
29
- return to_subtree_impl(swc_like, (sub_ids, sub_pid))
32
+ return to_subtree_impl(swc_like, (sub_ids, sub_pid), out_mapping=out_mapping)
30
33
 
31
34
 
32
- def to_subtree_impl(swc_like: SWCLike, sub: Topology) -> TreeArgs:
33
- (new_id, new_pid), id_map = to_sub_topology(sub)
35
+ def to_subtree_impl(
36
+ swc_like: SWCLike,
37
+ sub: Topology,
38
+ *,
39
+ out_mapping: Optional[Mapping] = None,
40
+ ) -> TreeArgs:
41
+ (new_id, new_pid), mapping = to_sub_topology(sub)
34
42
 
35
43
  n_nodes = new_id.shape[0]
36
- ndata = {k: swc_like.get_ndata(k)[id_map].copy() for k in swc_like.keys()}
44
+ ndata = {k: swc_like.get_ndata(k)[mapping].copy() for k in swc_like.keys()}
37
45
  ndata.update(id=new_id, pid=new_pid)
38
46
 
47
+ if isinstance(out_mapping, list):
48
+ out_mapping.clear()
49
+ out_mapping.extend(mapping)
50
+ elif isinstance(out_mapping, dict):
51
+ out_mapping.clear()
52
+ for new_id, old_id in enumerate(mapping):
53
+ out_mapping[new_id] = old_id # returning a dict may leads to bad perf
54
+
39
55
  return n_nodes, ndata, swc_like.source, swc_like.names
swcgeom/images/folder.py CHANGED
@@ -2,14 +2,25 @@
2
2
 
3
3
  import os
4
4
  import re
5
+ import warnings
5
6
  from abc import ABC, abstractmethod
6
- from typing import Callable, Generic, Iterable, List, Literal, Optional, Tuple, TypeVar
7
+ from typing import (
8
+ Callable,
9
+ Generic,
10
+ Iterable,
11
+ List,
12
+ Literal,
13
+ Optional,
14
+ Tuple,
15
+ TypeVar,
16
+ overload,
17
+ )
7
18
 
8
19
  import numpy as np
9
20
  import numpy.typing as npt
10
21
  from typing_extensions import Self
11
22
 
12
- from swcgeom.images.io import read_imgs
23
+ from swcgeom.images.io import ScalarType, read_imgs
13
24
  from swcgeom.transforms import Identity, Transform
14
25
 
15
26
  __all__ = [
@@ -21,20 +32,23 @@ __all__ = [
21
32
  T = TypeVar("T")
22
33
 
23
34
 
24
- class ImageStackFolderBase(Generic[T], ABC):
35
+ class ImageStackFolderBase(Generic[ScalarType, T], ABC):
25
36
  """Image stack folder base."""
26
37
 
27
38
  files: List[str]
28
- transform: Transform[npt.NDArray[np.float32], T]
39
+ transform: Transform[npt.NDArray[ScalarType], T]
29
40
 
30
- def __init__(
31
- self,
32
- files: Iterable[str],
33
- *,
34
- transform: Optional[Transform[npt.NDArray[np.float32], T]] = None,
35
- ) -> None:
41
+ # fmt: off
42
+ @overload
43
+ def __init__(self, files: Iterable[str], *, dtype: None = ..., transform: Optional[Transform[npt.NDArray[np.float32], T]] = None) -> None: ...
44
+ @overload
45
+ def __init__(self, files: Iterable[str], *, dtype: ScalarType, transform: Optional[Transform[npt.NDArray[ScalarType], T]] = None) -> None: ...
46
+ # fmt: on
47
+
48
+ def __init__(self, files: Iterable[str], *, dtype=None, transform=None) -> None:
36
49
  super().__init__()
37
50
  self.files = list(files)
51
+ self.dtype = dtype or np.float32
38
52
  self.transform = transform or Identity() # type: ignore
39
53
 
40
54
  @abstractmethod
@@ -45,13 +59,12 @@ class ImageStackFolderBase(Generic[T], ABC):
45
59
  return len(self.files)
46
60
 
47
61
  def _get(self, fname: str) -> T:
48
- imgs = self.read_imgs(fname)
62
+ imgs = self._read(fname)
49
63
  imgs = self.transform(imgs)
50
64
  return imgs
51
65
 
52
- @staticmethod
53
- def read_imgs(fname: str) -> npt.NDArray[np.float32]:
54
- return read_imgs(fname).get_full()
66
+ def _read(self, fname: str) -> npt.NDArray[ScalarType]:
67
+ return read_imgs(fname, dtype=self.dtype).get_full() # type: ignore
55
68
 
56
69
  @staticmethod
57
70
  def scan(root: str, *, pattern: Optional[str] = None) -> List[str]:
@@ -63,8 +76,20 @@ class ImageStackFolderBase(Generic[T], ABC):
63
76
 
64
77
  return fs
65
78
 
79
+ @staticmethod
80
+ def read_imgs(fname: str) -> npt.NDArray[np.float32]:
81
+ warnings.warn(
82
+ "`ImageStackFolderBase.read_imgs` serves as a "
83
+ "straightforward wrapper for `~swcgeom.images.io.read_imgs(fname).get_full()`. "
84
+ "However, as it is not utilized within our internal "
85
+ "processes, it is scheduled for removal in the "
86
+ "forthcoming version.",
87
+ DeprecationWarning,
88
+ )
89
+ return read_imgs(fname).get_full()
90
+
66
91
 
67
- class ImageStackFolder(Generic[T], ImageStackFolderBase[T]):
92
+ class ImageStackFolder(ImageStackFolderBase[ScalarType, T]):
68
93
  """Image stack folder."""
69
94
 
70
95
  def __getitem__(self, idx: int, /) -> T:
@@ -84,7 +109,7 @@ class ImageStackFolder(Generic[T], ImageStackFolderBase[T]):
84
109
  return cls(cls.scan(root, pattern=pattern), **kwargs)
85
110
 
86
111
 
87
- class LabeledImageStackFolder(Generic[T], ImageStackFolderBase[T]):
112
+ class LabeledImageStackFolder(ImageStackFolderBase[ScalarType, T]):
88
113
  """Image stack folder with label."""
89
114
 
90
115
  labels: List[int]
@@ -115,7 +140,7 @@ class LabeledImageStackFolder(Generic[T], ImageStackFolderBase[T]):
115
140
  return cls(files, labels, **kwargs)
116
141
 
117
142
 
118
- class PathImageStackFolder(Generic[T], ImageStackFolder[T]):
143
+ class PathImageStackFolder(ImageStackFolder[ScalarType, T]):
119
144
  """Image stack folder with relpath."""
120
145
 
121
146
  root: str