Skip to content

Commit

Permalink
Use actual acronym to generate ID of barrel regions (#13)
Browse files Browse the repository at this point in the history
Use actual region acronym to generate ID of barrel regions

---------

Co-authored-by: Zisis Eleftherios <eleftherios.zisis@epfl.ch>
  • Loading branch information
lecriste and eleftherioszisis authored Mar 14, 2024
1 parent 67867d7 commit 645bc62
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 48 deletions.
53 changes: 34 additions & 19 deletions atlas_splitter/barrel_splitter/somatosensory_barrels.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
The code relays on pd.DataFrame containing the annotated positions of each barrel voxel
in x,y,z coordinates.
"""

import copy
import logging
from typing import Any, Dict, List
Expand All @@ -26,12 +27,12 @@


def layer_ids(
region_map: RegionMap, names: List[str], layers: List[str]
region: str, names: List[str], layers: List[str], region_map
) -> Dict[str, Dict[str, int]]:
"""Create a dictionary of ids for the new regions with layer subregions.
Args:
region_map: region map object from voxcell
region: Base barrel region acronym. Example: SSp-bfd
names: A list of names of the new regions.
layers: A list of names of the new layer regions.
Expand All @@ -41,17 +42,16 @@ def layer_ids(
new_ids: Dict[str, Dict[str, int]] = {}
for name in names:
new_ids[name] = {}
new_ids[name][name] = id_from_acronym(region_map, name)

new_ids[name][name] = id_from_acronym(region_map, _acronym(region, name))
for layer_name in layers:
new_ids[name][layer_name] = id_from_acronym(region_map, name + layer_name)
new_ids[name][layer_name] = id_from_acronym(
region_map, _acronym(region, name, layer_name)
)

return dict(new_ids)
return new_ids


def get_hierarchy_by_acronym(
hierarchy: HierarchyDict, region_map: RegionMap, start_acronym="SSp-bfd"
):
def get_hierarchy_by_acronym(hierarchy: HierarchyDict, region_map: RegionMap, start_acronym):
"""Find and return child with a matching acronym from the next level
of the hierarchy.
Expand Down Expand Up @@ -129,7 +129,7 @@ def add_hierarchy_child(
Args:
parent: The parent structure to which the child is being added.
id: The unique identifier for the child.
id_: The unique identifier for the child.
name: The name of the child.
acronym: The acronym for the child.
Expand All @@ -147,13 +147,14 @@ def add_hierarchy_child(


def edit_hierarchy( # pylint: disable=too-many-arguments
region: str,
hierarchy: HierarchyDict,
new_ids: Dict[str, Dict[str, int]],
region_map: RegionMap,
layers: List[str],
) -> None:
"""Edit in place the hierarchy to include new children volumes of a given
region. Implemented to integrated the barrel columns into [SSp-bfd]
region. Implemented to integrate the barrel columns into [SSp-bfd]
Barrel cortex in Primary Somatosensory cortex.
Note:
Expand All @@ -170,22 +171,23 @@ def edit_hierarchy( # pylint: disable=too-many-arguments
unchanged.
Args:
region (str): Barrel region acronym. Example: SSp-bdf2
hierarchy (HierarchyDict): brain regions hierarchy dict
new_ids (Dict[int, Dict[str, int]]): set of new ids
region_map (RegionMap): region map object from voxcell
layers (list): list of layers to be integrated
"""
# pylint: disable=too-many-locals
children_names = new_ids.keys()
hierarchy_ = get_hierarchy_by_acronym(hierarchy, region_map)
hierarchy_ = get_hierarchy_by_acronym(hierarchy, region_map, start_acronym=region)

new_children = hierarchy_["children"]
for name in children_names:
new_barrel = add_hierarchy_child(
hierarchy_,
new_ids[name][name],
f"{hierarchy_['name']}, {name} barrel",
f"{hierarchy_['acronym']}-{name}",
_acronym(region, name),
)
assert new_barrel["acronym"].endswith(name)

Expand All @@ -195,7 +197,7 @@ def edit_hierarchy( # pylint: disable=too-many-arguments
new_barrel,
new_ids[name][layer],
f"{new_barrel['name']} layer {layer}",
f"{new_barrel['acronym']}-{layer}",
_acronym(region, name, layer),
)
assert new_barrel_layer["acronym"].endswith(layer)

Expand All @@ -207,7 +209,7 @@ def edit_hierarchy( # pylint: disable=too-many-arguments
new_barrel_layer,
new_ids[name][sublayer],
f"{new_barrel['name']} layer {sublayer}",
f"{new_barrel['acronym']}-{sublayer}",
_acronym(region, name, sublayer),
)
layer23_child["children"] = []
_assert_is_leaf_node(layer23_child)
Expand All @@ -226,6 +228,18 @@ def edit_hierarchy( # pylint: disable=too-many-arguments
hierarchy_["children"] = new_children


def _acronym(region_acronym, layer=None, sublayer=None):
final_acronym = region_acronym
if layer:
final_acronym += f"-{layer}"

if sublayer:
assert layer is not None, "Sublayer name needs a layer name too, but None passed."
final_acronym += f"-{sublayer}"

return final_acronym


def edit_volume(
annotation: VoxelData,
region_map: RegionMap,
Expand All @@ -234,7 +248,7 @@ def edit_volume(
new_ids: Dict[str, Dict[str, int]],
) -> None:
"""Edit in place the volume of the barrel cortex to include the barrel columns as
separate ids. Implemented to integrated the barrel columns into [SSp-bfd] Barrel
separate ids. Implemented to integrate the barrel columns into [SSp-bfd] Barrel
cortex in Primary Somatosensory cortex. The columns are also subdivided into layers.
Args:
Expand Down Expand Up @@ -274,17 +288,18 @@ def split_barrels(
annotation (VoxelData): whole brain annotation
barrel_positions (pd.DataFrame): x,y,z voxel positions
"""
region = "SSp-bfd"
assert "msg" in hierarchy, "Wrong hierarchy input. The AIBS 1.json file is expected."

region_map = RegionMap.from_dict(hierarchy["msg"][0])
barrel_names = list(np.sort(barrel_positions.barrel.unique()))
barrel_names = sorted(barrel_positions.barrel.unique())

layers = ["1", "2/3", "2", "3", "4", "5", "6a", "6b"]
new_ids = layer_ids(region_map, barrel_names, layers)
new_ids = layer_ids(region, barrel_names, layers, region_map)

layers = ["1", "2/3", "4", "5", "6a", "6b"]
L.info("Editing hierarchy: barrel columns...")
edit_hierarchy(hierarchy, new_ids, region_map, layers)
edit_hierarchy(region, hierarchy, new_ids, region_map, layers)

layers = ["1", "2", "3", "4", "5", "6a", "6b"]
L.info("Editing annotation: barrel columns...")
Expand Down
42 changes: 31 additions & 11 deletions tests/barrel_splitter/test_somatosensory_barrels.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

TEST_PATH = Path(__file__).parent

new_ids = {
NEW_IDS = {
"C1": {
"C1": 2010,
"1": 2011,
Expand All @@ -41,16 +41,16 @@
}


def test_layer_ids():
region_map = RegionMap.load_json(str(Path(TEST_PATH, "../1.json", encoding="utf-8")))
def test_layer_ids(region_map):
region = "my-region"
names = ["region1", "region2", "region3"]
layers = ["layer1", "layer2"]
result = tested.layer_ids(region_map, names, layers)
result = tested.layer_ids(region, names, layers, region_map)

expected = {
"region1": {"region1": 3631290122, "layer1": 2267454475, "layer2": 1012379119},
"region2": {"region2": 1722831506, "layer1": 3787876483, "layer2": 1416363748},
"region3": {"region3": 1193141608, "layer1": 3031486657, "layer2": 3890489924},
"region1": {"region1": 3100903567, "layer1": 3343828692, "layer2": 2819474802},
"region2": {"region2": 2741980671, "layer1": 3212473027, "layer2": 1147204648},
"region3": {"region3": 3227521405, "layer1": 3371952578, "layer2": 1691103868},
}
assert result == expected

Expand Down Expand Up @@ -139,19 +139,21 @@ def test_get_hierarchy_by_acronym():
assert hierarchy_test == hierarchy["msg"][0]["children"][0]


def test_edit_hierarchy():
def test_edit_hierarchy(region_map):
layers = ["1", "2/3", "4", "5", "6a", "6b"]
hierarchy = get_barrel_cortex_excerpt()
expected_hierarchy = get_barrel_cortex_excerpt_edited()
region_map = RegionMap.from_dict(hierarchy["msg"][0])

# tested.edit_hierarchy(hierarchy, new_ids, region_map, 329, layers)
tested.edit_hierarchy(hierarchy, new_ids, region_map, layers)
region = "SSp-bfd"
# tested.edit_hierarchy(hierarchy, NEW_IDS, region_map, 329, layers)
tested.edit_hierarchy(region, hierarchy, NEW_IDS, region_map, layers)
region_map_test = RegionMap.from_dict(hierarchy["msg"][0])

assert hierarchy == expected_hierarchy

bc_hierarchy = hierarchy["msg"][0]["children"][0]

assert np.size(bc_hierarchy["children"]) == 8 # barrel cortex children
assert np.size(bc_hierarchy["children"][-1]["children"]) == 6 # barrel children
assert (
Expand All @@ -175,13 +177,31 @@ def test_edit_hierarchy():
]


@pytest.mark.parametrize(
"region,layer,sublayer, expected",
[
("SSp-bfd3", None, None, "SSp-bfd3"),
("SSp-bfd", "C2", None, "SSp-bfd-C2"),
("SSp-bfd", "C2", 3, "SSp-bfd-C2-3"),
],
)
def test_acronym(region, layer, sublayer, expected):
res = tested._acronym(region, layer, sublayer)
assert res == expected


def test_acronym__raises():
with pytest.raises(AssertionError):
tested._acronym("SSp-bfd", None, "foo")


def test_edit_volume():
layers = ["1", "2", "3", "4", "5", "6a", "6b"]
annotation_test, positions = get_barrel_splitter_input_data()
hierarchy = get_barrel_cortex_excerpt_edited()
region_map = RegionMap.from_dict(hierarchy["msg"][0])

tested.edit_volume(annotation_test, region_map, positions, layers, new_ids)
tested.edit_volume(annotation_test, region_map, positions, layers, NEW_IDS)
test = annotation_test.raw
assert test.shape == (3, 57, 57)
assert np.all(test[0, :, :] == 0)
Expand Down
36 changes: 18 additions & 18 deletions tests/test_app_barrel_splitter.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,24 @@
1070,
1998,
1999,
1050271831,
1419828837,
1541598958,
1561898146,
1669999094,
1742227897,
1779524838,
1914058509,
1941812702,
2061835172,
2112620658,
2190770412,
2321675771,
2491030215,
3335143301,
3364575989,
3625413550,
3951617891,
1013068637,
1082141991,
1337935688,
1420546517,
1558550786,
1667660763,
1714311201,
1843338795,
1945434117,
2072239244,
2157537321,
2525505631,
2563782304,
2866280389,
2930307508,
3188993656,
3219108088,
3291535006,
}


Expand Down

0 comments on commit 645bc62

Please sign in to comment.