swcgeom 0.19.4__cp312-cp312-win_amd64.whl → 0.20.0__cp312-cp312-win_amd64.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/core/population.py +53 -0
- swcgeom/core/swc_utils/checker.py +7 -2
- swcgeom/core/swc_utils/io.py +162 -31
- swcgeom/core/tree.py +13 -10
- swcgeom/images/loaders/pbd.cp312-win_amd64.pyd +0 -0
- swcgeom/images/loaders/raw.cp312-win_amd64.pyd +0 -0
- swcgeom/transforms/tree_assembler.py +4 -5
- {swcgeom-0.19.4.dist-info → swcgeom-0.20.0.dist-info}/METADATA +1 -1
- {swcgeom-0.19.4.dist-info → swcgeom-0.20.0.dist-info}/RECORD +12 -12
- {swcgeom-0.19.4.dist-info → swcgeom-0.20.0.dist-info}/WHEEL +1 -1
- {swcgeom-0.19.4.dist-info → swcgeom-0.20.0.dist-info}/licenses/LICENSE +0 -0
- {swcgeom-0.19.4.dist-info → swcgeom-0.20.0.dist-info}/top_level.txt +0 -0
swcgeom/core/population.py
CHANGED
|
@@ -15,10 +15,14 @@ from typing import Any, Protocol, TypeVar, cast, overload
|
|
|
15
15
|
import numpy as np
|
|
16
16
|
import numpy.typing as npt
|
|
17
17
|
from tqdm.contrib.concurrent import process_map
|
|
18
|
+
from typing import Literal
|
|
18
19
|
from typing_extensions import Self
|
|
19
20
|
|
|
20
21
|
from swcgeom.core.swc import eswc_cols
|
|
22
|
+
from swcgeom.core.swc_utils.base import SWCNames
|
|
23
|
+
from swcgeom.core.swc_utils.io import read_swc_components
|
|
21
24
|
from swcgeom.core.tree import Tree
|
|
25
|
+
from swcgeom.utils import PathOrIO
|
|
22
26
|
|
|
23
27
|
__all__ = ["LazyLoadingTrees", "ChainTrees", "Population", "Populations"]
|
|
24
28
|
|
|
@@ -226,6 +230,55 @@ class Population:
|
|
|
226
230
|
|
|
227
231
|
return swcs
|
|
228
232
|
|
|
233
|
+
@classmethod
|
|
234
|
+
def from_multi_roots_swc(
|
|
235
|
+
cls,
|
|
236
|
+
swc_file: PathOrIO,
|
|
237
|
+
*,
|
|
238
|
+
extra_cols: Iterable[str] | None = None,
|
|
239
|
+
encoding: Literal["detect"] | str = "utf-8",
|
|
240
|
+
names: SWCNames | None = None,
|
|
241
|
+
reset_index_per_subtree: bool = True,
|
|
242
|
+
**kwargs,
|
|
243
|
+
) -> Self:
|
|
244
|
+
"""Create a population from an SWC file containing multiple roots.
|
|
245
|
+
|
|
246
|
+
Each root in the SWC file will be treated as the start of a
|
|
247
|
+
separate tree in the resulting population.
|
|
248
|
+
|
|
249
|
+
Args:
|
|
250
|
+
swc_file: Path to the SWC file.
|
|
251
|
+
extra_cols: Read more cols in swc file. Passed to
|
|
252
|
+
`read_swc_components`.
|
|
253
|
+
encoding: The name of the encoding used to decode the file.
|
|
254
|
+
Passed to `read_swc_components`.
|
|
255
|
+
names: SWCNames configuration. Passed to `read_swc_components`.
|
|
256
|
+
reset_index_per_subtree: Reset node index for each subtree
|
|
257
|
+
to start with zero. Passed to `read_swc_components`.
|
|
258
|
+
**kwargs: Additional keyword arguments passed to `Tree.from_data_frame`
|
|
259
|
+
for each component tree.
|
|
260
|
+
|
|
261
|
+
Returns:
|
|
262
|
+
A Population object where each tree corresponds to a connected
|
|
263
|
+
component from the input SWC file.
|
|
264
|
+
"""
|
|
265
|
+
dfs, comments = read_swc_components(
|
|
266
|
+
swc_file,
|
|
267
|
+
extra_cols=extra_cols,
|
|
268
|
+
encoding=encoding,
|
|
269
|
+
names=names,
|
|
270
|
+
reset_index_per_subtree=reset_index_per_subtree,
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
trees = [
|
|
274
|
+
Tree.from_data_frame(df, source=f"{swc_file}#component_{i}", comments=comments, **kwargs)
|
|
275
|
+
for i, df in enumerate(dfs)
|
|
276
|
+
]
|
|
277
|
+
|
|
278
|
+
# Use the file path as the 'root' for the population representation
|
|
279
|
+
root_repr = str(swc_file) if not hasattr(swc_file, "name") else swc_file.name
|
|
280
|
+
return cls(trees, root=root_repr)
|
|
281
|
+
|
|
229
282
|
|
|
230
283
|
class Populations:
|
|
231
284
|
"""A set of population."""
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
# SPDX-FileCopyrightText: 2022 - 2025 Zexin Yuan <pypi@yzx9.xyz>
|
|
3
2
|
#
|
|
4
3
|
# SPDX-License-Identifier: Apache-2.0
|
|
@@ -15,6 +14,7 @@ from swcgeom.core.swc_utils.base import SWCNames, Topology, get_dsu, get_names,
|
|
|
15
14
|
from swcgeom.utils import DisjointSetUnion
|
|
16
15
|
|
|
17
16
|
__all__ = [
|
|
17
|
+
"get_num_of_roots",
|
|
18
18
|
"is_single_root",
|
|
19
19
|
"is_bifurcate",
|
|
20
20
|
"is_sorted",
|
|
@@ -25,9 +25,14 @@ __all__ = [
|
|
|
25
25
|
]
|
|
26
26
|
|
|
27
27
|
|
|
28
|
+
def get_num_of_roots(df: pd.DataFrame, *, names: SWCNames | None = None) -> int:
|
|
29
|
+
"""Get number of roots."""
|
|
30
|
+
return len(np.unique(get_dsu(df, names=names)))
|
|
31
|
+
|
|
32
|
+
|
|
28
33
|
def is_single_root(df: pd.DataFrame, *, names: SWCNames | None = None) -> bool:
|
|
29
34
|
"""Check is it only one root."""
|
|
30
|
-
return
|
|
35
|
+
return get_num_of_roots(df, names=names) == 1
|
|
31
36
|
|
|
32
37
|
|
|
33
38
|
def is_bifurcate(topology: Topology, *, exclude_root: bool = True) -> bool:
|
swcgeom/core/swc_utils/io.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
# SPDX-FileCopyrightText: 2022 - 2025 Zexin Yuan <pypi@yzx9.xyz>
|
|
3
2
|
#
|
|
4
3
|
# SPDX-License-Identifier: Apache-2.0
|
|
@@ -15,23 +14,23 @@ import numpy.typing as npt
|
|
|
15
14
|
import pandas as pd
|
|
16
15
|
|
|
17
16
|
from swcgeom.core.swc_utils.base import SWCNames, get_names
|
|
18
|
-
from swcgeom.core.swc_utils.checker import is_single_root
|
|
17
|
+
from swcgeom.core.swc_utils.checker import get_num_of_roots, is_single_root
|
|
19
18
|
from swcgeom.core.swc_utils.normalizer import (
|
|
20
19
|
link_roots_to_nearest_,
|
|
21
20
|
mark_roots_as_somas_,
|
|
22
21
|
reset_index_,
|
|
23
22
|
sort_nodes_,
|
|
24
23
|
)
|
|
25
|
-
from swcgeom.utils import FileReader, PathOrIO
|
|
24
|
+
from swcgeom.utils import DisjointSetUnion, FileReader, PathOrIO
|
|
26
25
|
|
|
27
|
-
__all__ = ["read_swc", "to_swc"]
|
|
26
|
+
__all__ = ["read_swc", "read_swc_components", "to_swc"]
|
|
28
27
|
|
|
29
28
|
|
|
30
29
|
def read_swc(
|
|
31
30
|
swc_file: PathOrIO,
|
|
32
31
|
extra_cols: Iterable[str] | None = None,
|
|
33
32
|
fix_roots: Literal["somas", "nearest", False] = False,
|
|
34
|
-
sort_nodes: bool =
|
|
33
|
+
sort_nodes: bool = True,
|
|
35
34
|
reset_index: bool = True,
|
|
36
35
|
*,
|
|
37
36
|
encoding: Literal["detect"] | str = "utf-8",
|
|
@@ -45,12 +44,12 @@ def read_swc(
|
|
|
45
44
|
extra_cols: Read more cols in swc file.
|
|
46
45
|
fix_roots: Fix multiple roots.
|
|
47
46
|
sort_nodes: Sort the indices of neuron tree.
|
|
48
|
-
After sorting the nodes, the index for each parent are always less than
|
|
49
|
-
|
|
47
|
+
After sorting the nodes, the index for each parent are always less than that of its children, default to
|
|
48
|
+
True.
|
|
50
49
|
reset_index: Reset node index to start with zero.
|
|
51
|
-
DO NOT set to false if you are not sure what will happened.
|
|
50
|
+
DO NOT set to false if you are not sure what will happened, default to True.
|
|
52
51
|
encoding: The name of the encoding used to decode the file.
|
|
53
|
-
If is `detect`, we will try to detect the character encoding.
|
|
52
|
+
If is `detect`, we will try to detect the character encoding, default to "utf-8".
|
|
54
53
|
|
|
55
54
|
Returns:
|
|
56
55
|
df: ~pandas.DataFrame
|
|
@@ -60,35 +59,148 @@ def read_swc(
|
|
|
60
59
|
df, comments = parse_swc(
|
|
61
60
|
swc_file, names=names, extra_cols=extra_cols, encoding=encoding
|
|
62
61
|
)
|
|
62
|
+
if df.empty:
|
|
63
|
+
raise ValueError(f"SWC file '{swc_file}' is empty or contains no valid nodes.")
|
|
63
64
|
|
|
64
65
|
# fix swc
|
|
65
|
-
if
|
|
66
|
+
if not is_single_root(df, names=names):
|
|
66
67
|
match fix_roots:
|
|
67
68
|
case "somas":
|
|
68
69
|
mark_roots_as_somas_(df)
|
|
69
70
|
case "nearest":
|
|
70
71
|
link_roots_to_nearest_(df)
|
|
72
|
+
case False:
|
|
73
|
+
warnings.warn(f"not a simple tree in `{swc_file}`")
|
|
71
74
|
case _:
|
|
72
75
|
raise ValueError(f"unknown fix type `{fix_roots}`")
|
|
73
76
|
|
|
74
|
-
if sort_nodes:
|
|
75
|
-
sort_nodes_(df)
|
|
76
|
-
elif reset_index:
|
|
77
|
-
reset_index_(df)
|
|
78
|
-
|
|
79
77
|
# check swc
|
|
80
|
-
if not is_single_root(df, names=names):
|
|
81
|
-
warnings.warn(f"not a simple tree in `{swc_file}`")
|
|
82
|
-
|
|
83
78
|
if (df[names.pid] == -1).argmax() != 0:
|
|
84
79
|
warnings.warn(f"root is not the first node in `{swc_file}`")
|
|
85
80
|
|
|
86
81
|
if (df[names.r] <= 0).any():
|
|
87
82
|
warnings.warn(f"non-positive radius in `{swc_file}`")
|
|
88
83
|
|
|
84
|
+
# post processing
|
|
85
|
+
if sort_nodes:
|
|
86
|
+
sort_nodes_(df)
|
|
87
|
+
elif reset_index:
|
|
88
|
+
reset_index_(df)
|
|
89
|
+
|
|
89
90
|
return df, comments
|
|
90
91
|
|
|
91
92
|
|
|
93
|
+
def read_swc_components(
|
|
94
|
+
swc_file: PathOrIO,
|
|
95
|
+
/,
|
|
96
|
+
*,
|
|
97
|
+
extra_cols: Iterable[str] | None = None,
|
|
98
|
+
encoding: Literal["detect"] | str = "utf-8",
|
|
99
|
+
names: SWCNames | None = None,
|
|
100
|
+
reset_index_per_subtree: bool = True,
|
|
101
|
+
) -> tuple[list[pd.DataFrame], list[str]]:
|
|
102
|
+
"""Read swc file, splitting multi-root files into separate DataFrames.
|
|
103
|
+
|
|
104
|
+
If the SWC file contains multiple roots (disconnected components),
|
|
105
|
+
each component is extracted into its own pandas DataFrame.
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
swc_file: Path to the SWC file.
|
|
109
|
+
extra_cols: Read more cols in swc file.
|
|
110
|
+
reset_index_per_subtree: Reset node index for each subtree
|
|
111
|
+
to start with zero. Defaults to True.
|
|
112
|
+
encoding: The name of the encoding used to decode the file.
|
|
113
|
+
If 'detect', attempts to detect the character encoding.
|
|
114
|
+
names: SWCNames configuration.
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
dfs: A list of pandas DataFrames, each representing a
|
|
118
|
+
connected component (potential tree) from the SWC file.
|
|
119
|
+
comments: List of comment lines from the SWC file.
|
|
120
|
+
"""
|
|
121
|
+
names = get_names(names)
|
|
122
|
+
df, comments = parse_swc(
|
|
123
|
+
swc_file, names=names, extra_cols=extra_cols, encoding=encoding
|
|
124
|
+
)
|
|
125
|
+
if df.empty:
|
|
126
|
+
warnings.warn(f"SWC file '{swc_file}' is empty or contains no valid nodes.")
|
|
127
|
+
return [], comments
|
|
128
|
+
|
|
129
|
+
num_roots = get_num_of_roots(df, names=names)
|
|
130
|
+
if num_roots == 0:
|
|
131
|
+
warnings.warn(f"SWC file '{swc_file}' contains no root nodes (pid = -1).")
|
|
132
|
+
return [], comments
|
|
133
|
+
|
|
134
|
+
elif num_roots == 1:
|
|
135
|
+
warnings.warn(
|
|
136
|
+
f"SWC file '{swc_file}' has only one root. Consider using `read_swc` for single trees."
|
|
137
|
+
)
|
|
138
|
+
# Return the original DataFrame wrapped in a list
|
|
139
|
+
return [df], comments
|
|
140
|
+
|
|
141
|
+
# Multiple roots: Split into components
|
|
142
|
+
sub_dfs = []
|
|
143
|
+
num_nodes = len(df)
|
|
144
|
+
dsu = DisjointSetUnion(num_nodes)
|
|
145
|
+
|
|
146
|
+
# Map original node IDs to 0..N-1 indices for DSU
|
|
147
|
+
id_to_idx = {node_id: i for i, node_id in enumerate(df[names.id])}
|
|
148
|
+
for i, row in df.iterrows():
|
|
149
|
+
parent_id = row[names.pid]
|
|
150
|
+
if parent_id == -1:
|
|
151
|
+
continue
|
|
152
|
+
|
|
153
|
+
child_idx = i # Use DataFrame index which is 0..N-1
|
|
154
|
+
parent_idx = id_to_idx.get(parent_id)
|
|
155
|
+
if parent_idx is None:
|
|
156
|
+
warnings.warn(
|
|
157
|
+
f"Parent ID {parent_id} for node ID {row[names.id]} not found "
|
|
158
|
+
f"in '{swc_file}'. Treating node as root of a component."
|
|
159
|
+
)
|
|
160
|
+
continue
|
|
161
|
+
|
|
162
|
+
# Ensure indices are valid before union (should always be if df is consistent)
|
|
163
|
+
if not dsu.validate_node(child_idx) or not dsu.validate_node(parent_idx):
|
|
164
|
+
# This case should ideally not happen with well-formed input
|
|
165
|
+
warnings.warn(
|
|
166
|
+
f"Internal error: Invalid node index for node id "
|
|
167
|
+
f"{row[names.id]} or parent id {parent_id} in '{swc_file}'.",
|
|
168
|
+
stacklevel=2,
|
|
169
|
+
)
|
|
170
|
+
continue
|
|
171
|
+
|
|
172
|
+
dsu.union_sets(child_idx, parent_idx)
|
|
173
|
+
|
|
174
|
+
# Group nodes by component representative index
|
|
175
|
+
components: dict[int, list[int]] = {}
|
|
176
|
+
for i in range(num_nodes):
|
|
177
|
+
parent_repr = dsu.find_parent(i)
|
|
178
|
+
if parent_repr not in components:
|
|
179
|
+
components[parent_repr] = []
|
|
180
|
+
components[parent_repr].append(i) # Store original DataFrame indices (0..N-1)
|
|
181
|
+
|
|
182
|
+
# Create a DataFrame for each component
|
|
183
|
+
for component_indices in components.values():
|
|
184
|
+
sub_df = df.iloc[component_indices].copy()
|
|
185
|
+
|
|
186
|
+
if reset_index_per_subtree:
|
|
187
|
+
# Remap IDs and PIDs for the subtree to be 0..M-1
|
|
188
|
+
old_id_to_new_id = {
|
|
189
|
+
old_id: new_id for new_id, old_id in enumerate(sub_df[names.id])
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
# Apply mapping, ensuring the root's PID becomes -1
|
|
193
|
+
sub_df[names.id] = sub_df[names.id].map(old_id_to_new_id)
|
|
194
|
+
sub_df[names.pid] = sub_df[names.pid].map(
|
|
195
|
+
lambda old_pid: old_id_to_new_id.get(old_pid, -1)
|
|
196
|
+
)
|
|
197
|
+
# else: IDs remain as they were in the original file subset.
|
|
198
|
+
|
|
199
|
+
sub_dfs.append(sub_df)
|
|
200
|
+
|
|
201
|
+
return sub_dfs, comments
|
|
202
|
+
|
|
203
|
+
|
|
92
204
|
def to_swc(
|
|
93
205
|
get_ndata: Callable[[str], npt.NDArray],
|
|
94
206
|
*,
|
|
@@ -180,21 +292,40 @@ def parse_swc(
|
|
|
180
292
|
with FileReader(fname, encoding=encoding) as f:
|
|
181
293
|
try:
|
|
182
294
|
for i, line in enumerate(f):
|
|
183
|
-
|
|
184
|
-
|
|
295
|
+
original_line = line # Keep for error messages/comments
|
|
296
|
+
line_content = original_line.split("#", 1)[0].strip() # Process content part
|
|
297
|
+
|
|
298
|
+
if not line_content: # Skip empty lines or lines that become empty
|
|
299
|
+
# Handle full comment lines using original_line
|
|
300
|
+
if match := RE_COMMENT.match(original_line):
|
|
301
|
+
comment = original_line[len(match.group(0)) :].removesuffix("\n").strip()
|
|
302
|
+
if comment and not comment.startswith(ignored_comment):
|
|
303
|
+
comments.append(comment)
|
|
304
|
+
continue # Move to next line
|
|
305
|
+
|
|
306
|
+
if (match := re_swc.search(line_content)) is not None:
|
|
307
|
+
# Check for extra numerical fields captured by the last group
|
|
308
|
+
# Warn if the captured group exists and contains non-whitespace
|
|
309
|
+
if flag and match.group(last_group) and match.group(last_group).strip():
|
|
185
310
|
warnings.warn(
|
|
186
|
-
f"
|
|
311
|
+
f"Extra fields detected and ignored in row {i + 1} of `{fname}`"
|
|
187
312
|
)
|
|
188
|
-
flag = False
|
|
189
|
-
|
|
190
|
-
for
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
313
|
+
flag = False # Only warn once
|
|
314
|
+
|
|
315
|
+
for j, trans in enumerate(transforms):
|
|
316
|
+
try:
|
|
317
|
+
vals[j].append(trans(match.group(j + 1)))
|
|
318
|
+
except ValueError as e:
|
|
319
|
+
raise ValueError(
|
|
320
|
+
f"Invalid data format in row {i + 1}, column {j+1} ('{keys[j]}') in `{fname}`: {match.group(j + 1)}"
|
|
321
|
+
) from e
|
|
322
|
+
|
|
323
|
+
else: # If re_swc didn't match the line_content
|
|
324
|
+
# It's not a valid SWC data line. We already handled empty/comment lines.
|
|
325
|
+
raise ValueError(
|
|
326
|
+
f"Invalid SWC data format in row {i + 1} in `{fname}`: {original_line.strip()}"
|
|
327
|
+
)
|
|
328
|
+
|
|
198
329
|
except UnicodeDecodeError as e:
|
|
199
330
|
raise ValueError(
|
|
200
331
|
"decode failed, try to enable auto detect `encoding='detect'`"
|
swcgeom/core/tree.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
# SPDX-FileCopyrightText: 2022 - 2025 Zexin Yuan <pypi@yzx9.xyz>
|
|
3
2
|
#
|
|
4
3
|
# SPDX-License-Identifier: Apache-2.0
|
|
@@ -233,22 +232,26 @@ class Tree(DictSWC):
|
|
|
233
232
|
node: "Tree.Node", pre: list[tuple[list[Tree.Branch], list[int]]]
|
|
234
233
|
) -> tuple[list[Tree.Branch], list[int]]:
|
|
235
234
|
if len(pre) == 1:
|
|
236
|
-
branches,
|
|
237
|
-
|
|
238
|
-
return branches,
|
|
235
|
+
branches, children = pre[0]
|
|
236
|
+
children.append(node.id)
|
|
237
|
+
return branches, children
|
|
239
238
|
|
|
240
239
|
branches: list[Tree.Branch] = []
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
240
|
+
for sub_branches, children in pre:
|
|
241
|
+
children.append(node.id)
|
|
242
|
+
children.reverse()
|
|
243
|
+
sub_branches.append(
|
|
244
|
+
Tree.Branch(self, np.array(children, dtype=np.int32))
|
|
245
|
+
)
|
|
246
246
|
sub_branches.reverse()
|
|
247
247
|
branches.extend(sub_branches)
|
|
248
248
|
|
|
249
249
|
return branches, [node.id]
|
|
250
250
|
|
|
251
|
-
branches,
|
|
251
|
+
branches, children = self.traverse(leave=collect_branches)
|
|
252
|
+
if len(children) > 0:
|
|
253
|
+
branches.append(Tree.Branch(self, np.array(children, dtype=np.int32)))
|
|
254
|
+
|
|
252
255
|
return branches
|
|
253
256
|
|
|
254
257
|
def get_paths(self) -> list[Path]:
|
|
Binary file
|
|
Binary file
|
|
@@ -11,7 +11,6 @@ import numpy as np
|
|
|
11
11
|
import pandas as pd
|
|
12
12
|
from typing_extensions import override
|
|
13
13
|
|
|
14
|
-
from swcgeom.core import Tree
|
|
15
14
|
from swcgeom.core.swc_utils import (
|
|
16
15
|
SWCNames,
|
|
17
16
|
get_names,
|
|
@@ -23,7 +22,7 @@ from swcgeom.transforms.base import Transform
|
|
|
23
22
|
EPS = 1e-5
|
|
24
23
|
|
|
25
24
|
|
|
26
|
-
class LinesToTree(Transform[
|
|
25
|
+
class LinesToTree(Transform[Iterable[pd.DataFrame], pd.DataFrame]):
|
|
27
26
|
"""Assemble lines to swc."""
|
|
28
27
|
|
|
29
28
|
def __init__(self, *, thre: float = 0.2, undirected: bool = True):
|
|
@@ -39,9 +38,9 @@ class LinesToTree(Transform[list[pd.DataFrame], Tree]):
|
|
|
39
38
|
|
|
40
39
|
@override
|
|
41
40
|
def __call__(
|
|
42
|
-
self,
|
|
43
|
-
)
|
|
44
|
-
return self.assemble(
|
|
41
|
+
self, x: Iterable[pd.DataFrame], *, names: SWCNames | None = None
|
|
42
|
+
) -> pd.DataFrame:
|
|
43
|
+
return self.assemble(x, names=names)
|
|
45
44
|
|
|
46
45
|
def assemble(
|
|
47
46
|
self,
|
|
@@ -14,16 +14,16 @@ swcgeom/core/branch_tree.py,sha256=6doQaarCB-nEcrMuNElwmPqgvE15yn5fxy3JePBcaTs,2
|
|
|
14
14
|
swcgeom/core/compartment.py,sha256=gWzklvRH9nXBPezr8QnIEKxta3uZHk3Um9hLC7DT_2I,3484
|
|
15
15
|
swcgeom/core/node.py,sha256=XkMjlQ-1E_WaCCK6ghArQ9lXKuxPvzylLJyf6hnSzAE,3958
|
|
16
16
|
swcgeom/core/path.py,sha256=5ZARke8KAnM2bO99OgDTvYDdsqxdJ6Oa2lZlfSI4Mco,4704
|
|
17
|
-
swcgeom/core/population.py,sha256=
|
|
17
|
+
swcgeom/core/population.py,sha256=EFsVNWD85W-fo-P5_bhWXzahYz4EdktRV22Ko37ZJso,12679
|
|
18
18
|
swcgeom/core/swc.py,sha256=Wlz4kV44dJpsYgiOEGTi8mL56KjvLAVuz_F_ip_JtaU,7189
|
|
19
|
-
swcgeom/core/tree.py,sha256=
|
|
19
|
+
swcgeom/core/tree.py,sha256=BNLA5tDMWI87IvoInbtJqBJlE8YXWvWt8TegpKrnlJk,13249
|
|
20
20
|
swcgeom/core/tree_utils.py,sha256=4eFHQ8EajJG4fGO3_in6LKLYW1e-dw1cP8ZhqBJA0b8,7662
|
|
21
21
|
swcgeom/core/tree_utils_impl.py,sha256=mhgQqrtnGwei8B2jY2JvVgPLM-KU6PsKy8t-thdxxh8,1740
|
|
22
22
|
swcgeom/core/swc_utils/__init__.py,sha256=afVBWtkRFqnZUZeHf194JiycdbvGi1TLP_jf6FN7XLw,778
|
|
23
23
|
swcgeom/core/swc_utils/assembler.py,sha256=_VlOPnJvmveB8jSnnOhqY0MchnYq7F1dXCWJdvbC44c,1001
|
|
24
24
|
swcgeom/core/swc_utils/base.py,sha256=TVT4e6XoKuyBWbu2sFyzslnTobIXSXLqAiHEbOILi_I,4979
|
|
25
|
-
swcgeom/core/swc_utils/checker.py,sha256=
|
|
26
|
-
swcgeom/core/swc_utils/io.py,sha256=
|
|
25
|
+
swcgeom/core/swc_utils/checker.py,sha256=ZcSSiprEnbgJiSCRm7cqc8eM0rQgNsdzFucR4bVTjdQ,2961
|
|
26
|
+
swcgeom/core/swc_utils/io.py,sha256=JRuNIq70xWFPSIMlBTZb7BUhvlnklswOTwZ_OKClINU,12062
|
|
27
27
|
swcgeom/core/swc_utils/normalizer.py,sha256=b0RxQroVyPmfKvV4x8FneEGgce8G4MI2xTsv34FADZA,5265
|
|
28
28
|
swcgeom/core/swc_utils/subtree.py,sha256=ri3Sh_uTi1mrfcA-rqTD88rW_L0cxZPRuON4zzADwNA,2126
|
|
29
29
|
swcgeom/images/__init__.py,sha256=3BLzhVKRbVtdsjaPTXX0SMO8JVxGwGvwVc4D0uyZ2nA,240
|
|
@@ -32,9 +32,9 @@ swcgeom/images/contrast.py,sha256=2Z38wV2laTCFAjZ3mT4vQlDtwHIZ-GmQQi81JDEzgO0,20
|
|
|
32
32
|
swcgeom/images/folder.py,sha256=veQnUP5W9eXtOsBB0YtwEs3GlsylREJt9yth1FMTyAA,6590
|
|
33
33
|
swcgeom/images/io.py,sha256=mY6rklHn3xuSNvd_g4YGwLHP8Y3u-hEb6bV2jFVraso,20424
|
|
34
34
|
swcgeom/images/loaders/__init__.py,sha256=a4XSH2Bn6v5YUGb_lKwdjAGD1i4SXBTXGVh08mct7pg,254
|
|
35
|
-
swcgeom/images/loaders/pbd.cp312-win_amd64.pyd,sha256=
|
|
35
|
+
swcgeom/images/loaders/pbd.cp312-win_amd64.pyd,sha256=4A0cVdlDvaKNIJJZGcah1goEDdIvaWl5IogHswY-kks,182272
|
|
36
36
|
swcgeom/images/loaders/pbd.pyx,sha256=14uWjLpdxLhdPVUoAjthEnRVbhV0AdKGBipXY_BZeWU,23092
|
|
37
|
-
swcgeom/images/loaders/raw.cp312-win_amd64.pyd,sha256=
|
|
37
|
+
swcgeom/images/loaders/raw.cp312-win_amd64.pyd,sha256=hS0nDfemawDGJ9Mdd12F8c7iDNMkW0ZbHxD2TaHH59Q,83968
|
|
38
38
|
swcgeom/images/loaders/raw.pyx,sha256=Zd6CIoy97aaGs6bxi9CzoraPp261dpuWMK_ZujElfYU,6947
|
|
39
39
|
swcgeom/transforms/__init__.py,sha256=DSE21HbgD6WczilWtONVq_m3zUgZXP-nsJjOCE_vKKU,916
|
|
40
40
|
swcgeom/transforms/base.py,sha256=oaOSZGrZKVbauypp9G-3G2f_WIx2gEJIft60jMg5rBc,4612
|
|
@@ -49,7 +49,7 @@ swcgeom/transforms/neurolucida_asc.py,sha256=QV9K6Q0lUandF0r2Fyd999VyiI8zdS4rYNZ
|
|
|
49
49
|
swcgeom/transforms/path.py,sha256=JMjPKm3eYB_nr6j2-BBF-zUqPRTTIDMInM8TkCoSafE,1319
|
|
50
50
|
swcgeom/transforms/population.py,sha256=305NHfplPu_VJvVNUm1_8-me0Cd6TsGXAQTi9AYfSTE,1019
|
|
51
51
|
swcgeom/transforms/tree.py,sha256=ykmEP9626z4SBAwl0Vgw3Z7VZwRqiO2GxPsWtTha5wQ,8028
|
|
52
|
-
swcgeom/transforms/tree_assembler.py,sha256=
|
|
52
|
+
swcgeom/transforms/tree_assembler.py,sha256=zYO_NwO8ES3IGnzhA9JhvK5PV42vDy1r8t5YgSeBuyI,5030
|
|
53
53
|
swcgeom/utils/__init__.py,sha256=k74fxbYGZfizmqHbWTqavtONOiqs5mndrBSC8SzDMQE,758
|
|
54
54
|
swcgeom/utils/debug.py,sha256=vURuhDf1Mx67-p8EMSoOTQbzZRAQd1Q5OQzD4OR6PaA,594
|
|
55
55
|
swcgeom/utils/download.py,sha256=bU2Be9fX_zNLaIe04fCaZFDHaLd_KoJMwnUvyUG_qUI,3789
|
|
@@ -65,8 +65,8 @@ swcgeom/utils/sdf.py,sha256=WxPwGd4DJRM8sIA2t8RP5_6fypom3PxMtg03sSNqKrM,10816
|
|
|
65
65
|
swcgeom/utils/solid_geometry.py,sha256=ma30775813e8bFC6ycGLNdY1N2v96iPmECeHZc2YnPA,4257
|
|
66
66
|
swcgeom/utils/transforms.py,sha256=hX6QgHKcaWmRwc5RlbKwVBGqCdXJbuQh-CPr02Lme0Q,9469
|
|
67
67
|
swcgeom/utils/volumetric_object.py,sha256=C6k73avzKJUIsvaP6Bb43K2oENjv0mRub2caNHz4qGI,15316
|
|
68
|
-
swcgeom-0.
|
|
69
|
-
swcgeom-0.
|
|
70
|
-
swcgeom-0.
|
|
71
|
-
swcgeom-0.
|
|
72
|
-
swcgeom-0.
|
|
68
|
+
swcgeom-0.20.0.dist-info/licenses/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
|
|
69
|
+
swcgeom-0.20.0.dist-info/METADATA,sha256=XW-JuO06KGOLekzXNpzm-sfWMe9XYRU2ldarUWCFHwk,2951
|
|
70
|
+
swcgeom-0.20.0.dist-info/WHEEL,sha256=8UP9x9puWI0P1V_d7K2oMTBqfeLNm21CTzZ_Ptr0NXU,101
|
|
71
|
+
swcgeom-0.20.0.dist-info/top_level.txt,sha256=hmLyUXWS61Gxl07haswFEKKefYPBVJYlUlol8ghNkjY,8
|
|
72
|
+
swcgeom-0.20.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|