0
# Point Connection and Targeting
1
2
Functions for creating direct connections between specific points and converting synapse locations to skeleton targets. These capabilities are useful for precise path tracing and integrating external annotations into skeletonization workflows.
3
4
## Capabilities
5
6
### Direct Point Connection
7
8
Creates a skeleton path between two preselected points on a binary image, finding the optimal route through the object geometry.
9
10
```python { .api }
11
def connect_points(
12
labels,
13
start,
14
end,
15
anisotropy=(1,1,1),
16
fill_holes=False,
17
in_place=False,
18
pdrf_scale=100000,
19
pdrf_exponent=4
20
):
21
"""
22
Draw a centerline between preselected points on a binary image.
23
24
Extract a single centerline skeleton between two preselected points
25
from a binary image using a penalty distance field approach.
26
27
Parameters:
28
- labels (numpy.ndarray): Binary image (2D or 3D)
29
- start (tuple): Starting point coordinates (x, y, z) in voxel space
30
- end (tuple): Ending point coordinates (x, y, z) in voxel space
31
- anisotropy (tuple): Physical voxel dimensions (default: (1,1,1))
32
- fill_holes (bool): Fill holes in shapes before tracing (default: False)
33
- in_place (bool): Modify input array in place (default: False)
34
- pdrf_scale (float): Penalty field scale factor (default: 100000)
35
- pdrf_exponent (int): Penalty field exponent (default: 4)
36
37
Returns:
38
Skeleton: Single skeleton tracing the path between start and end points
39
40
Raises:
41
ValueError: If start and end points are in disconnected components
42
43
Notes:
44
- Input must be binary (True/False values)
45
- Coordinates are in voxel space (not physical units)
46
- Uses penalty distance field with Dijkstra's algorithm
47
- Start and end points must be in the same connected component
48
"""
49
```
50
51
#### Usage Example
52
53
```python
54
import kimimaro
55
import numpy as np
56
57
# Extract single neuron as binary image
58
neuron_binary = (labels == target_neuron_id)
59
60
# Connect soma to axon terminal
61
soma_center = (125, 200, 45) # Coordinates in voxels
62
axon_terminal = (890, 1240, 156) # Coordinates in voxels
63
64
# Trace direct connection
65
direct_path = kimimaro.connect_points(
66
neuron_binary,
67
start=soma_center,
68
end=axon_terminal,
69
anisotropy=(16, 16, 40) # nm per voxel
70
)
71
72
print(f"Direct path length: {direct_path.cable_length():.1f} nm")
73
print(f"Path vertices: {len(direct_path.vertices)}")
74
75
# Compare with full skeletonization
76
full_skeleton = kimimaro.skeletonize(
77
neuron_binary.astype(np.uint32),
78
anisotropy=(16, 16, 40)
79
)[1]
80
81
print(f"Full skeleton length: {full_skeleton.cable_length():.1f} nm")
82
print(f"Direct path is {direct_path.cable_length()/full_skeleton.cable_length()*100:.1f}% of full skeleton")
83
```
84
85
### Advanced Point Connection
86
87
```python
88
# Connect multiple points in sequence
89
connection_points = [
90
(100, 150, 30), # Start point
91
(200, 250, 45), # Intermediate point 1
92
(350, 400, 60), # Intermediate point 2
93
(500, 550, 75) # End point
94
]
95
96
# Create sequential connections
97
path_segments = []
98
for i in range(len(connection_points) - 1):
99
segment = kimimaro.connect_points(
100
neuron_binary,
101
start=connection_points[i],
102
end=connection_points[i + 1],
103
anisotropy=(16, 16, 40)
104
)
105
path_segments.append(segment)
106
107
# Combine segments (you would need to implement skeleton merging)
108
print(f"Created {len(path_segments)} path segments")
109
```
110
111
### Synapse Target Conversion
112
113
Converts synapse centroid locations to skeleton target points, enabling enhanced skeletonization around synaptic sites.
114
115
```python { .api }
116
def synapses_to_targets(labels, synapses, progress=False):
117
"""
118
Convert synapse centroids to skeleton targets.
119
120
Given synapse centroids (in voxels) and desired SWC integer labels,
121
finds the nearest voxel to each centroid for the corresponding label.
122
This enables targeted skeletonization that ensures skeleton paths
123
pass through or near synaptic sites.
124
125
Parameters:
126
- labels (numpy.ndarray): Labeled volume with neuron segments
127
- synapses (dict): Mapping of {label_id: [((x,y,z), swc_label), ...]}
128
- label_id: Which neuron label the synapse belongs to
129
- (x,y,z): Synapse centroid coordinates in voxel space
130
- swc_label: SWC node type for this synapse (e.g., 3=dendrite, 4=axon)
131
- progress (bool): Show progress bar (default: False)
132
133
Returns:
134
dict: Mapping of {(x,y,z): swc_label, ...} for use as extra_targets
135
136
Notes:
137
- Coordinates are in voxel space, not physical units
138
- SWC labels follow standard: 1=soma, 2=axon, 3=dendrite, 4=apical, etc.
139
- Targets can be used with extra_targets_before or extra_targets_after
140
"""
141
```
142
143
#### Usage Example
144
145
```python
146
import kimimaro
147
import numpy as np
148
149
# Define synapse locations for multiple neurons
150
synapses = {
151
# Neuron 1 has 3 synapses
152
1: [
153
((120, 200, 30), 3), # Dendrite synapse
154
((150, 220, 35), 3), # Another dendrite synapse
155
((180, 240, 40), 4), # Apical dendrite synapse
156
],
157
# Neuron 5 has 2 synapses
158
5: [
159
((80, 180, 25), 2), # Axon synapse
160
((90, 190, 28), 2), # Another axon synapse
161
],
162
# Neuron 12 has 1 soma synapse
163
12: [
164
((300, 400, 60), 1), # Soma synapse
165
]
166
}
167
168
# Convert synapses to target format
169
targets = kimimaro.synapses_to_targets(
170
labels,
171
synapses,
172
progress=True
173
)
174
175
print(f"Generated {len(targets)} target points")
176
print("Target locations:", list(targets.keys())[:5])
177
178
# Use targets in skeletonization to ensure paths hit synapses
179
skeletons = kimimaro.skeletonize(
180
labels,
181
anisotropy=(16, 16, 40),
182
extra_targets_after=list(targets.keys()), # Add as extra endpoints
183
teasar_params={
184
"scale": 1.5,
185
"const": 300,
186
"soma_detection_threshold": 750,
187
},
188
progress=True
189
)
190
191
# The resulting skeletons will have paths that pass through synapse locations
192
for label_id, skeleton in skeletons.items():
193
if label_id in synapses:
194
n_synapses = len(synapses[label_id])
195
print(f"Neuron {label_id}: {n_synapses} synapses, {len(skeleton.vertices)} skeleton vertices")
196
```
197
198
### Integration with Connectomics Annotations
199
200
```python
201
import kimimaro
202
import pandas as pd
203
import numpy as np
204
205
# Load connectomics annotations
206
def load_synapse_annotations(annotation_file):
207
"""Load synapse annotations from CSV or database."""
208
# Example format: neuron_id, x, y, z, synapse_type, confidence
209
df = pd.read_csv(annotation_file)
210
211
synapses = {}
212
for _, row in df.iterrows():
213
neuron_id = int(row['neuron_id'])
214
coords = (int(row['x']), int(row['y']), int(row['z']))
215
216
# Map synapse type to SWC label
217
swc_type_map = {
218
'presynaptic': 2, # Axon terminal
219
'postsynaptic': 3, # Dendrite
220
'soma_synapse': 1, # Soma
221
'apical': 4 # Apical dendrite
222
}
223
swc_label = swc_type_map.get(row['synapse_type'], 3)
224
225
if neuron_id not in synapses:
226
synapses[neuron_id] = []
227
synapses[neuron_id].append((coords, swc_label))
228
229
return synapses
230
231
# Load and process annotations
232
synapses = load_synapse_annotations("connectome_synapses.csv")
233
targets = kimimaro.synapses_to_targets(labels, synapses, progress=True)
234
235
# Skeletonize with synapse targets
236
skeletons = kimimaro.skeletonize(
237
labels,
238
anisotropy=(8, 8, 30), # High-resolution EM data
239
extra_targets_after=list(targets.keys()),
240
teasar_params={
241
"scale": 1.2, # Tighter invalidation for precise targeting
242
"const": 200, # Smaller minimum radius
243
"pdrf_scale": 150000, # Higher penalty field influence
244
},
245
parallel=8,
246
progress=True
247
)
248
249
print(f"Processed {len(skeletons)} neurons with {len(targets)} synapse targets")
250
```
251
252
### Validation and Quality Control
253
254
```python
255
def validate_synapse_targeting(skeletons, synapses, targets, max_distance=500):
256
"""Validate that skeletons actually reach synapse targets."""
257
258
validation_results = {}
259
260
for label_id, skeleton in skeletons.items():
261
if label_id not in synapses:
262
continue
263
264
results = {
265
'synapses_targeted': len(synapses[label_id]),
266
'distances': [],
267
'missed_synapses': []
268
}
269
270
# Check each synapse
271
for (synapse_coords, swc_label) in synapses[label_id]:
272
# Find closest skeleton vertex to synapse
273
skeleton_coords = skeleton.vertices
274
distances = np.sqrt(np.sum((skeleton_coords - np.array(synapse_coords))**2, axis=1))
275
min_distance = np.min(distances)
276
277
results['distances'].append(min_distance)
278
279
if min_distance > max_distance:
280
results['missed_synapses'].append({
281
'coords': synapse_coords,
282
'distance': min_distance,
283
'swc_label': swc_label
284
})
285
286
results['mean_distance'] = np.mean(results['distances'])
287
results['max_distance'] = np.max(results['distances'])
288
results['success_rate'] = 1 - len(results['missed_synapses']) / len(synapses[label_id])
289
290
validation_results[label_id] = results
291
292
return validation_results
293
294
# Run validation
295
validation = validate_synapse_targeting(skeletons, synapses, targets)
296
297
for label_id, results in validation.items():
298
print(f"Neuron {label_id}:")
299
print(f" Success rate: {results['success_rate']*100:.1f}%")
300
print(f" Mean distance to synapses: {results['mean_distance']:.1f} nm")
301
if results['missed_synapses']:
302
print(f" Missed {len(results['missed_synapses'])} synapses")
303
```
304
305
## Use Cases and Applications
306
307
### Axon Tracing
308
- Connect soma to axon terminals for long-range projection analysis
309
- Validate axonal continuity across image boundaries
310
- Measure axon length and branching patterns
311
312
### Dendritic Analysis
313
- Connect soma to dendritic tips for morphological analysis
314
- Trace specific dendritic branches identified in functional studies
315
- Validate dendritic spine connectivity
316
317
### Connectomics Integration
318
- Incorporate synapse annotations into skeleton generation
319
- Ensure skeleton paths pass through confirmed connection sites
320
- Generate skeletons optimized for connectivity analysis
321
322
### Quality Control
323
- Verify skeleton completeness by connecting known endpoints
324
- Test alternative paths through complex morphologies
325
- Validate automated skeletonization results with manual annotations
326
327
### Cross-scale Analysis
328
- Connect structures identified at different resolution scales
329
- Bridge between light microscopy and electron microscopy data
330
- Integrate multi-modal annotations into unified skeletons