@@ -340,9 +340,9 @@ def _edge_count_to_root_old(x: 'core.TreeNeuron') -> dict:
340
340
341
341
@utils .map_neuronlist (desc = 'Classifying' , allow_parallel = True )
342
342
@utils .lock_neuron
343
- def classify_nodes (x : 'core.NeuronObject' ,
344
- inplace : bool = True
345
- ) -> Optional ['core.NeuronObject' ]:
343
+ def _classify_nodes_old (x : 'core.NeuronObject' ,
344
+ inplace : bool = True
345
+ ) -> Optional ['core.NeuronObject' ]:
346
346
"""Classify neuron's nodes into end nodes, branches, slabs or root.
347
347
348
348
Adds ``'type'`` column to ``x.nodes``.
@@ -414,6 +414,70 @@ def classify_nodes(x: 'core.NeuronObject',
414
414
return x
415
415
416
416
417
+
418
+ @utils .map_neuronlist (desc = 'Classifying' , allow_parallel = True )
419
+ @utils .lock_neuron
420
+ def classify_nodes (x : 'core.NeuronObject' ,
421
+ categorical = True ,
422
+ inplace : bool = True
423
+ ) -> Optional ['core.NeuronObject' ]:
424
+ """Classify neuron's nodes into end nodes, branches, slabs or root.
425
+
426
+ Adds ``'type'`` column to ``x.nodes`` table.
427
+
428
+ Parameters
429
+ ----------
430
+ x : TreeNeuron | NeuronList
431
+ Neuron(s) whose nodes to classify.
432
+ categorical : bool
433
+ If True (default), will use categorical data type which takes
434
+ up much less memory at a small run-time overhead.
435
+ inplace : bool, optional
436
+ If ``False``, nodes will be classified on a copy which is then
437
+ returned leaving the original neuron unchanged.
438
+
439
+ Returns
440
+ -------
441
+ TreeNeuron/List
442
+
443
+ Examples
444
+ --------
445
+ >>> import navis
446
+ >>> nl = navis.example_neurons(2)
447
+ >>> _ = navis.graph.classify_nodes(nl, inplace=True)
448
+
449
+ """
450
+ if not inplace :
451
+ x = x .copy ()
452
+
453
+ if not isinstance (x , core .TreeNeuron ):
454
+ raise TypeError (f'Expected TreeNeuron(s), got "{ type (x )} "' )
455
+
456
+ # At this point x is TreeNeuron
457
+ x : core .TreeNeuron
458
+
459
+ # Make sure there are nodes to classify
460
+ if not x .nodes .empty :
461
+ x .nodes ['type' ] = 'slab'
462
+ x .nodes .loc [~ x .nodes .node_id .isin (x .nodes .parent_id ), 'type' ] = 'end'
463
+ bp = x .nodes .parent_id .value_counts ()
464
+ bp = bp [bp > 1 ].index .values
465
+ x .nodes .loc [x .nodes .node_id .isin (bp ), 'type' ] = 'branch'
466
+ x .nodes .loc [x .nodes .parent_id < 0 , 'type' ] = 'root'
467
+ else :
468
+ x .nodes ['type' ] = None
469
+
470
+ # Turn into categorical data - saves tons of memory
471
+ # Note that we have to make sure all categories are set even if they
472
+ # don't exist (e.g. if a neuron has no branch points)
473
+ if categorical :
474
+ cat_types = CategoricalDtype (categories = ["end" , "branch" , "root" , "slab" ],
475
+ ordered = False )
476
+ x .nodes ['type' ] = x .nodes ['type' ].astype (cat_types )
477
+
478
+ return x
479
+
480
+
417
481
# only this combination will return a single bool
418
482
@overload
419
483
def distal_to (x : 'core.TreeNeuron' ,
0 commit comments