# NeuronList math¶

`CatmaidNeuronList` implement some of the basic arithmetic and comparison operators that you might know from standard `lists` or `numpy.arrays`. Most this should be fairly intuitive (I hope) but there are a few things you should be aware of. The following examples will illustrate that:

As per usual, we need to get some neurons first (I’m assuming you’ve already imported and setup pymaid):

```nl = pymaid.get_neurons('annotation:glomerulus DA1 right')
```
neuron_name skeleton_id n_nodes n_connectors n_branch_nodes n_end_nodes open_ends cable_length review_status soma
0 PN glomerulus DA1 57316 ML 2863105 2863104 5222 439 149 157 63 1109.886700 NA True
1 PN glomerulus DA1 57382 ML 57381 7730 360 153 162 71 1215.920600 NA True
2 PN glomerulus DA1 61222 AJ 61221 7875 534 135 140 26 1182.642823 NA True
3 PN glomerulus DA1 57354 GA 57353 4898 327 90 95 52 1113.156682 NA True
4 PN glomerulus DA1 57324 LK JSL 57323 4585 438 120 127 59 1035.099284 NA True

## Comparisons¶

The `==` operator compares two elements:

```1 == 1
```
```True
```
```2 == 1
```
```False
```

For `CatmaidNeuron` this is done by comparing the neurons’ morphologies (somas, root nodes, cable length, …) and meta data (skeleton ID, name, …).

```n1 = nl
n2 = nl
n1 == n2
```
```True
```
```n1 = nl
n2 = nl
n1 == n2
```
```False
```

For `CatmaidNeuronList`, we do the same comparison pairwise between neurons in both neuronlists - so order matters!.

```nl == nl
```
```True
```
```nl == nl[:-1]
```
```False
```
```nl[[0, 1, 2]] == nl[[2, 1, 0]]
```
```False
```

This is safe against copying but making any changes to the neurons will cause inequality:

```n1 = nl
n2 = n1.copy()
n1 == n2
```
```True
```
```n1 = nl
n2 = n1.reroot(nl.tags['ends'], inplace=False)
n1 == n2
```
```False
```

You can also ask if a neuron is in a given `CatmaidNeuronList`:

```n1 = nl
n1 in nl
```
```True
```
```n1 in nl[1:]
```
```False
```

This also works with skeleton IDs

```n1.skeleton_id in nl
```
```True
```
```n1.skeleton_id in nl[1:]
```
```False
```

To merge two lists in Python, you can simply add them:

```a = 
b = 
a + b
```
```[1, 3]
```

`CatmaidNeuronList` works exactly the same:

```a = nl
b = nl[[1, 2]]
a + b
```
neuron_name skeleton_id n_nodes n_connectors n_branch_nodes n_end_nodes open_ends cable_length review_status soma
0 PN glomerulus DA1 57382 ML 57381 7729 360 153 162 71 1215.920599 NA True
1 AL.L(DA1) -{mALT}-> CAL.L-LH.L 2379518 PN022 D... 2379517 4657 411 86 90 31 836.067253 NA True
2 PN glomerulus DA1 57312 LK 57311 4882 429 157 164 105 1182.102458 NA True

This also works on with two single `CatmaidNeuron`! You can use that to combine them into a list:

```a = nl
b = nl
a + b
```
neuron_name skeleton_id n_nodes n_connectors n_branch_nodes n_end_nodes open_ends cable_length review_status soma
0 PN glomerulus DA1 57316 ML 2863105 2863104 5222 439 149 157 63 1109.88670 NA True
1 AL.L(DA1) -{mALT}-> CAL.L-LH.L 2319458 PN036 D... 2319457 10209 964 431 458 90 1747.51171 NA True

Note

If you want to combine two CatmaidNeurons into a single neuron instead of creating a neuronlist, check out `pymaid.stitch_neurons()`.

## Substraction¶

To remove an item from a Python list, you would call the `.pop()` method:

```a = [1, 2, 3]
b = 2
a.pop(b)
a
```
```[1, 2]
```

`CatmaidNeuronList` lets you simply use substraction:

```a = nl[[0, 1, 2]]
b = nl
a - b
```
neuron_name skeleton_id n_nodes n_connectors n_branch_nodes n_end_nodes open_ends cable_length review_status soma
0 PN glomerulus DA1 57382 ML 57381 7729 360 153 162 71 1215.920599 NA True
1 AL.L(DA1) -{mALT}-> CAL.L-LH.L 2379518 PN022 D... 2379517 4657 411 86 90 31 836.067253 NA True

## Bitwise AND¶

To find the intersection between two lists, you would use `sets` and the `&` operator:

```a = set([0, 1, 2])
b = set([2, 3, 4])
a & b
```
```{2}
```

`CatmaidNeuronList` work similarly:

```a = nl[[0, 1, 2]]
b = nl[[2, 3, 4]]
a & b
```
neuron_name skeleton_id n_nodes n_connectors n_branch_nodes n_end_nodes open_ends cable_length review_status soma
0 PN glomerulus DA1 57312 LK 57311 4882 429 157 164 105 1182.102458 NA True

All of the above also work with skeleton IDs as one of the operators

```a = nl[[0, 1, 2]]
b = nl[[2, 3, 4]]
a & b.skeleton_id
```
neuron_name skeleton_id n_nodes n_connectors n_branch_nodes n_end_nodes open_ends cable_length review_status soma
0 PN glomerulus DA1 57312 LK 57311 4882 429 157 164 105 1182.102458 NA True

## Multiplication and Division¶

So far, all operations have led to changes in the structure of the `CatmaidNeuronList`. Multiplication and division are different! If you multiply/divide a `CatmaidNeuron` or `CatmaidNeuronList` by a number, you will change the coordinates of nodes and connectors (plus node radii):

```n = nl
```
treenode_id parent_id creator_id x y z radius confidence type
0 3046710 32963981 53 442883 212802 44240 -1 5 slab
1 32963981 3046707 150 442931 212892 44040 -1 5 slab
2 652935 652934 22 444126 151826 216240 -1 5 slab
3 3245741 3245737 61 414617 243177 52400 3451 5 end
4 3042776 27298300 53 436753 225519 38000 -1 5 slab
```n2 = n / 1000
```
treenode_id parent_id creator_id x y z radius confidence type
0 3046710 32963981 53 442.883 212.802 44.24 -0.001 5 slab
1 32963981 3046707 150 442.931 212.892 44.04 -0.001 5 slab
2 652935 652934 22 444.126 151.826 216.24 -0.001 5 slab
3 3245741 3245737 61 414.617 243.177 52.40 3.451 5 end
4 3042776 27298300 53 436.753 225.519 38.00 -0.001 5 slab

The main use of this is to convert units from e.g. nm to um.

## Dealing with unequal neuron objects¶

As we demonstrated earlier, making changes to `CatmaidNeuron/Lists` will cause comparisons to fail. This also propagates into substractions and bitwise comparisons:

```n1 = nl
n1 in nl
```
```True
```
```n2 = n1.reroot(nl.tags['ends'], inplace=False)
n2 in nl
```
```False
```
```nl & n1
```
neuron_name skeleton_id n_nodes n_connectors n_branch_nodes n_end_nodes open_ends cable_length review_status soma
0 PN glomerulus DA1 57316 ML 2863105 2863104 5222 439 149 157 63 1109.8867 NA True
```nl & n2
```
```WARNING : Skeleton IDs overlap but neuron not identical! Bitwise cancelled! Try using .skeleton_id instead. (pymaid)
```

See how the comparison fails because we’ve made changes? The same happens if you tried `nl - n2`.

As mentioned in the warning, the workaround is to use the skeleton ID instead:

```n2.skeleton_id in nl
```
```True
```
```nl & n2.skeleton_id
```
neuron_name skeleton_id n_nodes n_connectors n_branch_nodes n_end_nodes open_ends cable_length review_status soma
0 PN glomerulus DA1 57316 ML 2863105 2863104 5222 439 149 157 63 1109.8867 NA True