swcgeom 0.18.3__tar.gz → 0.19.1__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 swcgeom might be problematic. Click here for more details.

Files changed (72) hide show
  1. {swcgeom-0.18.3/swcgeom.egg-info → swcgeom-0.19.1}/PKG-INFO +6 -5
  2. {swcgeom-0.18.3 → swcgeom-0.19.1}/pyproject.toml +15 -4
  3. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/analysis/feature_extractor.py +22 -24
  4. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/analysis/features.py +18 -40
  5. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/analysis/lmeasure.py +227 -323
  6. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/analysis/sholl.py +17 -23
  7. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/analysis/trunk.py +23 -28
  8. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/analysis/visualization.py +37 -44
  9. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/analysis/visualization3d.py +16 -25
  10. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/analysis/volume.py +33 -47
  11. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/core/__init__.py +1 -6
  12. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/core/branch.py +10 -17
  13. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/core/branch_tree.py +3 -2
  14. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/core/compartment.py +1 -1
  15. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/core/node.py +3 -6
  16. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/core/path.py +11 -16
  17. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/core/population.py +32 -51
  18. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/core/swc.py +25 -16
  19. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/core/swc_utils/__init__.py +4 -6
  20. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/core/swc_utils/assembler.py +5 -12
  21. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/core/swc_utils/base.py +40 -31
  22. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/core/swc_utils/checker.py +3 -8
  23. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/core/swc_utils/io.py +32 -47
  24. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/core/swc_utils/normalizer.py +17 -23
  25. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/core/swc_utils/subtree.py +13 -20
  26. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/core/tree.py +61 -51
  27. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/core/tree_utils.py +36 -49
  28. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/core/tree_utils_impl.py +4 -6
  29. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/images/augmentation.py +23 -39
  30. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/images/contrast.py +22 -46
  31. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/images/folder.py +32 -34
  32. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/images/io.py +108 -126
  33. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/transforms/base.py +28 -19
  34. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/transforms/branch.py +31 -41
  35. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/transforms/branch_tree.py +3 -1
  36. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/transforms/geometry.py +13 -4
  37. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/transforms/image_preprocess.py +2 -0
  38. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/transforms/image_stack.py +40 -35
  39. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/transforms/images.py +31 -24
  40. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/transforms/mst.py +27 -40
  41. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/transforms/neurolucida_asc.py +13 -13
  42. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/transforms/path.py +4 -0
  43. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/transforms/population.py +4 -0
  44. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/transforms/tree.py +16 -11
  45. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/transforms/tree_assembler.py +37 -54
  46. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/utils/download.py +7 -14
  47. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/utils/dsu.py +12 -0
  48. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/utils/ellipse.py +26 -14
  49. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/utils/file.py +8 -13
  50. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/utils/neuromorpho.py +78 -92
  51. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/utils/numpy_helper.py +15 -12
  52. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/utils/plotter_2d.py +10 -16
  53. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/utils/plotter_3d.py +7 -9
  54. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/utils/renderer.py +16 -8
  55. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/utils/sdf.py +12 -23
  56. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/utils/solid_geometry.py +58 -2
  57. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/utils/transforms.py +164 -100
  58. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/utils/volumetric_object.py +29 -53
  59. {swcgeom-0.18.3 → swcgeom-0.19.1/swcgeom.egg-info}/PKG-INFO +6 -5
  60. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom.egg-info/requires.txt +4 -2
  61. {swcgeom-0.18.3 → swcgeom-0.19.1}/LICENSE +0 -0
  62. {swcgeom-0.18.3 → swcgeom-0.19.1}/README.md +0 -0
  63. {swcgeom-0.18.3 → swcgeom-0.19.1}/setup.cfg +0 -0
  64. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/__init__.py +0 -0
  65. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/analysis/__init__.py +0 -0
  66. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/images/__init__.py +0 -0
  67. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/transforms/__init__.py +0 -0
  68. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/utils/__init__.py +0 -0
  69. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom/utils/debug.py +0 -0
  70. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom.egg-info/SOURCES.txt +0 -0
  71. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom.egg-info/dependency_links.txt +0 -0
  72. {swcgeom-0.18.3 → swcgeom-0.19.1}/swcgeom.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: swcgeom
3
- Version: 0.18.3
3
+ Version: 0.19.1
4
4
  Summary: Neuron geometry library for swc format
5
5
  Author-email: yzx9 <pypi@yzx9.xyz>
6
6
  License: Apache-2.0
@@ -15,12 +15,12 @@ Requires-Dist: numpy>=1.22.3
15
15
  Requires-Dist: pandas>=1.4.2
16
16
  Requires-Dist: pynrrd>=1.1.0
17
17
  Requires-Dist: scipy>=1.9.1
18
- Requires-Dist: sdflit>=0.2.1
18
+ Requires-Dist: sdflit>=0.2.6
19
19
  Requires-Dist: seaborn>=0.12.0
20
20
  Requires-Dist: tifffile>=2022.8.12
21
- Requires-Dist: typing_extensions>=4.4.0
21
+ Requires-Dist: typing-extensions>=4.4.0
22
22
  Requires-Dist: tqdm>=4.46.1
23
- Requires-Dist: v3d-py-helper>=0.4.1
23
+ Requires-Dist: v3d-py-helper>=0.4.1; python_version < "3.13"
24
24
  Provides-Extra: all
25
25
  Requires-Dist: beautifulsoup4>=4.11.1; extra == "all"
26
26
  Requires-Dist: certifi>=2023.5.7; extra == "all"
@@ -28,6 +28,7 @@ Requires-Dist: chardet>=5.2.0; extra == "all"
28
28
  Requires-Dist: lmdb>=1.4.1; extra == "all"
29
29
  Requires-Dist: requests>=2.0.0; extra == "all"
30
30
  Requires-Dist: urllib3>=1.26.0; extra == "all"
31
+ Dynamic: license-file
31
32
 
32
33
  # SWCGEOM
33
34
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "swcgeom"
3
- version = "0.18.3"
3
+ version = "0.19.1"
4
4
  description = "Neuron geometry library for swc format"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -14,12 +14,12 @@ dependencies = [
14
14
  "pandas>=1.4.2",
15
15
  "pynrrd>=1.1.0",
16
16
  "scipy>=1.9.1",
17
- "sdflit>=0.2.1",
17
+ "sdflit>=0.2.6",
18
18
  "seaborn>=0.12.0",
19
19
  "tifffile>=2022.8.12",
20
- "typing_extensions>=4.4.0",
20
+ "typing-extensions>=4.4.0",
21
21
  "tqdm>=4.46.1",
22
- "v3d-py-helper>=0.4.1",
22
+ "v3d-py-helper>=0.4.1; python_version < '3.13'",
23
23
  ]
24
24
 
25
25
  [project.optional-dependencies]
@@ -34,3 +34,14 @@ all = [
34
34
 
35
35
  [project.urls]
36
36
  repository = "https://github.com/yzx9/swcgeom"
37
+
38
+ [dependency-groups]
39
+ dev = [
40
+ "pytest>=8.3.4",
41
+ ]
42
+
43
+ [tool.ruff]
44
+ target-version = "py310"
45
+ src = [ "tests", "swcgeom" ]
46
+ format.docstring-code-format = true
47
+ lint.pydocstyle.convention = "google"
@@ -15,10 +15,8 @@
15
15
 
16
16
  """Easy way to compute and visualize common features for feature.
17
17
 
18
- Notes
19
- -----
20
- For development, see method `Features.get_evaluator` to confirm the
21
- naming specification.
18
+ NOTE: For development, see method `Features.get_evaluator` to confirm the naming
19
+ specification.
22
20
  """
23
21
 
24
22
  from abc import ABC, abstractmethod
@@ -83,23 +81,31 @@ class Features:
83
81
 
84
82
  tree: Tree
85
83
 
86
- # fmt:off
87
84
  # Modules
88
85
  @cached_property
89
- def node_features(self) -> NodeFeatures: return NodeFeatures(self.tree)
86
+ def node_features(self) -> NodeFeatures:
87
+ return NodeFeatures(self.tree)
88
+
90
89
  @cached_property
91
- def furcation_features(self) -> FurcationFeatures: return FurcationFeatures(self.node_features)
90
+ def furcation_features(self) -> FurcationFeatures:
91
+ return FurcationFeatures(self.node_features)
92
+
92
93
  @cached_property
93
- def tip_features(self) -> TipFeatures: return TipFeatures(self.node_features)
94
+ def tip_features(self) -> TipFeatures:
95
+ return TipFeatures(self.node_features)
96
+
94
97
  @cached_property
95
- def branch_features(self) -> BranchFeatures: return BranchFeatures(self.tree)
98
+ def branch_features(self) -> BranchFeatures:
99
+ return BranchFeatures(self.tree)
100
+
96
101
  @cached_property
97
- def path_features(self) -> PathFeatures: return PathFeatures(self.tree)
102
+ def path_features(self) -> PathFeatures:
103
+ return PathFeatures(self.tree)
98
104
 
99
105
  # Caches
100
106
  @cached_property
101
- def sholl(self) -> Sholl: return Sholl(self.tree)
102
- # fmt:on
107
+ def sholl(self) -> Sholl:
108
+ return Sholl(self.tree)
103
109
 
104
110
  def __init__(self, tree: Tree) -> None:
105
111
  self.tree = tree
@@ -136,22 +142,17 @@ class Features:
136
142
  class FeatureExtractor(ABC):
137
143
  """Extract features from tree."""
138
144
 
139
- # fmt:off
140
145
  @overload
141
146
  def get(self, feature: Feature, **kwargs) -> NDArrayf32: ...
142
147
  @overload
143
148
  def get(self, feature: list[FeatAndKwargs]) -> list[NDArrayf32]: ...
144
149
  @overload
145
150
  def get(self, feature: dict[Feature, dict[str, Any]]) -> dict[str, NDArrayf32]: ...
146
- # fmt:on
147
151
  def get(self, feature, **kwargs):
148
152
  """Get feature.
149
153
 
150
- Notes
151
- -----
152
- Shape of returned array is not uniform, `TreeFeatureExtractor`
153
- returns array of shape (L, ), `PopulationFeatureExtracor`
154
- returns array of shape (N, L).
154
+ NOTE: Shape of returned array is not uniform, `TreeFeatureExtractor` returns
155
+ array of shape (L, ), `PopulationFeatureExtracor` returns array of shape (N, L).
155
156
  """
156
157
  if isinstance(feature, dict):
157
158
  return {k: self._get(k, **v) for k, v in feature.items()}
@@ -164,11 +165,8 @@ class FeatureExtractor(ABC):
164
165
  def plot(self, feature: FeatAndKwargs, title: str | bool = True, **kwargs) -> Axes:
165
166
  """Plot feature with appropriate way.
166
167
 
167
- Notes
168
- -----
169
- The drawing method is different in different classes, different
170
- in different features, and may different between versions,
171
- there are NO guarantees.
168
+ NOTE: The drawing method is different in different classes, different in
169
+ different features, and may different between versions, there are NO guarantees.
172
170
  """
173
171
  feat, feat_kwargs = _get_feat_and_kwargs(feature)
174
172
  if callable(custom_plot := getattr(self, f"plot_{feat}", None)):
@@ -13,7 +13,7 @@
13
13
  # limitations under the License.
14
14
 
15
15
 
16
- """Feature anlysis of tree."""
16
+ """Feature analysis of tree."""
17
17
 
18
18
  from abc import ABC, abstractmethod
19
19
  from functools import cached_property
@@ -53,22 +53,17 @@ class NodeFeatures:
53
53
  def get_count(self) -> npt.NDArray[np.float32]:
54
54
  """Get number of nodes.
55
55
 
56
- Returns
57
- -------
58
- count : array of shape (1,)
56
+ Args:
57
+ count: array of shape (1,)
59
58
  """
60
-
61
59
  return np.array([self.tree.number_of_nodes()], dtype=np.float32)
62
60
 
63
61
  def get_radial_distance(self) -> npt.NDArray[np.float32]:
64
62
  """Get the end-to-end straight-line distance to soma.
65
63
 
66
- Returns
67
- -------
68
- radial_distance : npt.NDArray[np.float32]
69
- Array of shape (N,).
64
+ Returns:
65
+ radial_distance: Array of shape (N,).
70
66
  """
71
-
72
67
  xyz = self.tree.xyz() - self.tree.soma().xyz()
73
68
  radial_distance = np.linalg.norm(xyz, axis=1)
74
69
  return radial_distance
@@ -81,12 +76,9 @@ class NodeFeatures:
81
76
 
82
77
  Criticle node means that soma, bifucation nodes, tips.
83
78
 
84
- Returns
85
- -------
86
- order : npt.NDArray[np.int32]
87
- Array of shape (N,), which k is the number of branchs.
79
+ Returns:
80
+ order: Array of shape (N,), which k is the number of branches.
88
81
  """
89
-
90
82
  order = np.zeros_like(self._branch_tree.id(), dtype=np.int32)
91
83
 
92
84
  def assign_depth(n: Tree.Node, pre_depth: int | None) -> int:
@@ -112,23 +104,17 @@ class _SubsetNodesFeatures(ABC):
112
104
  def get_count(self) -> npt.NDArray[np.float32]:
113
105
  """Get number of nodes.
114
106
 
115
- Returns
116
- -------
117
- count : npt.NDArray[np.float32]
118
- Array of shape (1,).
107
+ Returns:
108
+ count: Array of shape (1,).
119
109
  """
120
-
121
110
  return np.array([np.count_nonzero(self.nodes)], dtype=np.float32)
122
111
 
123
112
  def get_radial_distance(self) -> npt.NDArray[np.float32]:
124
113
  """Get the end-to-end straight-line distance to soma.
125
114
 
126
- Returns
127
- -------
128
- radial_distance : npt.NDArray[np.float32]
129
- Array of shape (N,).
115
+ Returns:
116
+ radial_distance: Array of shape (N,).
130
117
  """
131
-
132
118
  return self._features.get_radial_distance()[self.nodes]
133
119
 
134
120
  @classmethod
@@ -148,11 +134,9 @@ class FurcationFeatures(_SubsetNodesFeatures):
148
134
  class BifurcationFeatures(FurcationFeatures):
149
135
  """Evaluate bifurcation node feature of tree.
150
136
 
151
- Notes
152
- -----
153
- Deprecated due to the wrong spelling of furcation. For now, it
154
- is just an alias of `FurcationFeatures` and raise a warning. It
155
- will be change to raise an error in the future.
137
+ NOTE: Deprecated due to the wrong spelling of furcation. For now, it is just an
138
+ alias of `FurcationFeatures` and raise a warning. It will be change to raise an
139
+ error in the future.
156
140
  """
157
141
 
158
142
 
@@ -219,24 +203,18 @@ class BranchFeatures:
219
203
  def get_angle(self, eps: float = 1e-7) -> npt.NDArray[np.float32]:
220
204
  """Get agnle between branches.
221
205
 
222
- Returns
223
- -------
224
- angle : npt.NDArray[np.float32]
225
- An array of shape (N, N), which N is length of branches.
206
+ Returns:
207
+ angle: An array of shape (N, N), which N is length of branches.
226
208
  """
227
-
228
209
  return self.calc_angle(self._branches, eps=eps)
229
210
 
230
211
  @staticmethod
231
212
  def calc_angle(branches: list[T], eps: float = 1e-7) -> npt.NDArray[np.float32]:
232
213
  """Calc agnle between branches.
233
214
 
234
- Returns
235
- -------
236
- angle : npt.NDArray[np.float32]
237
- An array of shape (N, N), which N is length of branches.
215
+ Returns:
216
+ angle: An array of shape (N, N), which N is length of branches.
238
217
  """
239
-
240
218
  vector = np.array([br[-1].xyz() - br[0].xyz() for br in branches])
241
219
  vector_dot = np.matmul(vector, vector.T)
242
220
  vector_norm = np.linalg.norm(vector, ord=2, axis=1, keepdims=True)