Skip to content

Commit

Permalink
Merge pull request #13 from AllenNeuralDynamics/10-helper-function-to…
Browse files Browse the repository at this point in the history
…-directly-access-leaf-nodes

feat: add direct access to leaf nodes from atlas.leaf_nodes
  • Loading branch information
dbirman authored Aug 16, 2024
2 parents 06ac41a + 5d31c85 commit 4afe54f
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 9 deletions.
6 changes: 5 additions & 1 deletion brainglobe_atlasapi/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
STRUCTURES_FILENAME,
)
from brainglobe_atlasapi.structure_class import StructuresDict
from brainglobe_atlasapi.utils import read_json, read_tiff
from brainglobe_atlasapi.utils import read_json, read_tiff, get_leaves_from_tree

LEFT_HEMI_VAL = 1
RIGHT_HEMI_VAL = 2
Expand Down Expand Up @@ -47,6 +47,10 @@ def __init__(self, path):

self.structures = StructuresDict(structures_list)

# Parse the structure list to find leaf nodes
self.leaf_nodes = get_leaves_from_tree(self.structures_list)


# Instantiate SpaceConvention object describing the current atlas:
self.space = AnatomicalSpace(
origin=self.orientation,
Expand Down
37 changes: 37 additions & 0 deletions brainglobe_atlasapi/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,3 +317,40 @@ def read_tiff(path):
"""
return tifffile.imread(str(path))


def get_leaves_from_tree(structures_list):
"""Parse a structure tree (in list format) to find leaf nodes
We'll do this by going through the list once to create a dictionary mapping ID->node
A second time to map nodes to their parents (as children)
And a third time to pull all the nodes with no children
Parameters
----------
structures_list : list
List of structures from BrainGlobeAtlas.structures_list
"""

id_map = {}

# Get a map of id -> structure
for structure in structures_list:
structure['children'] = []
id_map[structure['id']] = structure

# Map each node to it's parent.children list
for structure in structures_list:
if len(structure['structure_id_path']) > 1:
parent_id = structure['structure_id_path'][-2]

if not parent_id == structure['id']:
id_map[parent_id]['children'].append(structure['id'])

# Get leaf nodes
leaf_nodes = []
for id in id_map.keys():
if not id_map[id]['children']:
leaf_nodes.append(id)

return leaf_nodes
21 changes: 16 additions & 5 deletions tests/atlasapi/test_core_atlas.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import pytest
import tifffile

import brainglobe_atlasapi.core as core
from brainglobe_atlasapi.core import AdditionalRefDict


Expand Down Expand Up @@ -92,7 +93,7 @@ def test_data_from_coords(atlas, coords):
)
== "root"
)
assert atlas.hemisphere_from_coords(coords) == atlas.right_hemisphere_value
assert atlas.hemisphere_from_coords(coords) == core.RIGHT_HEMI_VAL
assert atlas.hemisphere_from_coords(coords, as_string=True) == "right"
assert (
atlas.hemisphere_from_coords(
Expand Down Expand Up @@ -177,8 +178,18 @@ def test_descendants(atlas):


def test_mask(atlas):
mask = atlas.get_structure_mask('VISp')
mask_left = atlas.get_structure_mask('VISp', hemisphere=-1)
mask = atlas.get_structure_mask('root')
mask_left = atlas.get_structure_mask('root', hemisphere=-1)

assert np.sum(mask > 0) == 7113
assert np.sum((mask > 0) & (mask_left > 0)) == 3548
assert np.sum(mask > 0) == 3589
assert np.sum((mask > 0) & (mask_left > 0)) == 1709


def test_leaf(atlas):
leaf_nodes = atlas.leaf_nodes

known_leaves = [567]

print(leaf_nodes)
print(known_leaves)
assert all(item in leaf_nodes for item in known_leaves)
11 changes: 11 additions & 0 deletions tests/atlasapi/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,14 @@ def test_get_download_size_HTTPError():

with pytest.raises(HTTPError):
utils.get_download_size(test_url)


def test_get_leaves():
structures_list = [
{'acronym': 'root', 'id': 997, 'name': 'root', 'structure_id_path': [997], 'rgb_triplet': [255, 255, 255], 'children': [8, 1009, 73]},
{'acronym': 'grey', 'id': 8, 'name': 'Basic cell groups and regions', 'structure_id_path': [997, 8], 'rgb_triplet': [191, 218, 227], 'children': [567, 343, 512]}
]

leaf_nodes = utils.get_leaves_from_tree(structures_list)

assert leaf_nodes == [8]
17 changes: 14 additions & 3 deletions tutorials/Atlas API usage.ipynb

Large diffs are not rendered by default.

0 comments on commit 4afe54f

Please sign in to comment.