Skip to content

Commit

Permalink
Cell types and other tests (#56)
Browse files Browse the repository at this point in the history
* Added cell types and other tests

* changelog

* New cell types unittests

* Fix fixture

* Test merging utilities

* Added missing test resolving tests

* Added missing utils tests

---------

Co-authored-by: kanesoban <[email protected]>
Co-authored-by: Nicolas Frank <[email protected]>
  • Loading branch information
3 people authored Dec 18, 2024
1 parent 35cbca5 commit 56a81ea
Show file tree
Hide file tree
Showing 7 changed files with 1,199 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Tool implementations without langchain or langgraph dependencies
- CRUDs.
- BlueNaas CRUD tools
- Cell types, resolving and utils tests
- app unit tests
- Tests of AgentsRoutine.
- Unit tests for database
Expand Down
165 changes: 165 additions & 0 deletions swarm_copy_tests/data/KG_brain_regions_hierarchy_test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
{
"@context": "https://neuroshapes.org",
"@id": "http://bbp.epfl.ch/neurosciencegraph/ontologies/core/brainregion",
"@type": "Ontology",
"versionInfo": "R103",
"hasHierarchyView": [
{
"@id": "https://bbp.epfl.ch/ontologies/core/bmo/BrainLayer",
"label": "Layer",
"description": "Layer based hierarchy",
"hasParentHierarchyProperty": "isLayerPartOf",
"hasChildrenHierarchyProperty": "hasLayerPart",
"hasLeafHierarchyProperty": "hasLayerLeafRegionPart"
},
{
"@id": "https://neuroshapes.org/BrainRegion",
"label": "BrainRegion",
"description": "Atlas default brain region hierarchy",
"hasParentHierarchyProperty": "isPartOf",
"hasChildrenHierarchyProperty": "hasPart",
"hasLeafHierarchyProperty": "hasLeafRegionPart"
}
],
"atlasRelease": {
"@id": "https://bbp.epfl.ch/neurosciencegraph/data/4906ab85-694f-469d-962f-c0174e901885",
"@type": "BrainAtlasRelease",
"_rev": 8
},
"defines": [
{
"@id": "http://api.brain-map.org/api/v2/data/Structure/1",
"@type": "Class",
"atlas_id": 424,
"color_hex_triplet": "FF4C3E",
"graph_order": 775,
"hemisphere_id": 3,
"st_level": 9,
"identifier": "1",
"isPartOf": [
"http://api.brain-map.org/api/v2/data/Structure/2"
],
"isDefinedBy": "http://bbp.epfl.ch/neurosciencegraph/ontologies/core/brainregion",
"subClassOf": [
"https://neuroshapes.org/BrainRegion"
],
"delineates": [
"http://purl.obolibrary.org/obo/UBERON_0014594"
],
"regionVolume": {
"unitCode": "cubic micrometer",
"value": 108296875.0
},
"regionVolumeRatioToWholeBrain": {
"unitCode": "cubic micrometer",
"value": 0.00021400307558019888
},
"representedInAnnotation": true,
"hasHierarchyView": [
"https://neuroshapes.org/BrainRegion"
],
"prefLabel": "Tuberomammillary nucleus, ventral part",
"label": "Tuberomammillary nucleus, ventral part",
"notation": "TMv",
"altLabel": "TMv",
"atlasRelease": {
"@id": "https://bbp.epfl.ch/neurosciencegraph/data/4906ab85-694f-469d-962f-c0174e901885",
"@type": "BrainAtlasRelease",
"_rev": 8
}
},
{
"@id": "http://api.brain-map.org/api/v2/data/Structure/2",
"@type": "Class",
"atlas_id": 425,
"color_hex_triplet": "FF90FF",
"graph_order": 834,
"hemisphere_id": 3,
"st_level": 9,
"hasPart": [
"http://api.brain-map.org/api/v2/data/Structure/503",
"http://api.brain-map.org/api/v2/data/Structure/511",
"http://api.brain-map.org/api/v2/data/Structure/614454425",
"http://api.brain-map.org/api/v2/data/Structure/494"
],
"identifier": "2",
"isDefinedBy": "http://bbp.epfl.ch/neurosciencegraph/ontologies/core/brainregion",
"subClassOf": [
"https://neuroshapes.org/BrainRegion"
],
"regionVolume": {
"unitCode": "cubic micrometer",
"value": 2036828125.0
},
"regionVolumeRatioToWholeBrain": {
"unitCode": "cubic micrometer",
"value": 0.004024931311990765
},
"representedInAnnotation": true,
"hasLeafRegionPart": [
"http://api.brain-map.org/api/v2/data/Structure/494",
"http://api.brain-map.org/api/v2/data/Structure/614454425",
"http://api.brain-map.org/api/v2/data/Structure/511",
"http://api.brain-map.org/api/v2/data/Structure/503"
],
"hasHierarchyView": [
"https://neuroshapes.org/BrainRegion"
],
"prefLabel": "Superior colliculus, motor related, intermediate gray layer",
"label": "Superior colliculus, motor related, intermediate gray layer",
"notation": "SCig",
"altLabel": "SCig",
"atlasRelease": {
"@id": "https://bbp.epfl.ch/neurosciencegraph/data/4906ab85-694f-469d-962f-c0174e901885",
"@type": "BrainAtlasRelease",
"_rev": 8
}
},
{
"@id": "http://api.brain-map.org/api/v2/data/Structure/3",
"@type": "Class",
"atlas_id": 424,
"color_hex_triplet": "FF4C3E",
"graph_order": 775,
"hemisphere_id": 3,
"st_level": 9,
"identifier": "3",
"isPartOf": [
"http://api.brain-map.org/api/v2/data/Structure/2"
],
"isDefinedBy": "http://bbp.epfl.ch/neurosciencegraph/ontologies/core/brainregion",
"subClassOf": [
"https://neuroshapes.org/BrainRegion"
],
"delineates": [
"http://purl.obolibrary.org/obo/UBERON_0014594"
],
"regionVolume": {
"unitCode": "cubic micrometer",
"value": 108296875.0
},
"regionVolumeRatioToWholeBrain": {
"unitCode": "cubic micrometer",
"value": 0.00021400307558019888
},
"representedInAnnotation": true,
"hasHierarchyView": [
"https://neuroshapes.org/BrainRegion"
],
"prefLabel": "Tuberomammillary nucleus, ventral part",
"label": "Primary Motor Cortex",
"notation": "TMv",
"altLabel": "TMv",
"atlasRelease": {
"@id": "https://bbp.epfl.ch/neurosciencegraph/data/4906ab85-694f-469d-962f-c0174e901885",
"@type": "BrainAtlasRelease",
"_rev": 8
}
}
],
"derivation": [
{},
{}
],
"label": "Brain Region Ontology"
}
1 change: 1 addition & 0 deletions swarm_copy_tests/data/brainregion_hierarchy.json

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions swarm_copy_tests/data/kg_cell_types_hierarchy_test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"@context": "https://neuroshapes.org",
"@id": "http://bbp.epfl.ch/neurosciencegraph/ontologies/core/celltypes",
"@type": "Ontology",
"preferredNamespacePrefix": "celltypes",
"versionInfo": "R1660",
"defines": [
{"@id": "http://bbp.epfl.ch/neurosciencegraph/ontologies/etypes/cACint", "@type": "Class", "label": "cACint", "subClassOf": ["https://bbp.epfl.ch/ontologies/core/bmo/NeuronElectricalType", "https://neuroshapes.org/EType", "https://bbp.epfl.ch/ontologies/core/bmo/BrainCellType"], "definition": "Continuous accommodating interneuron electrical type", "color": "#108b8b", "prefLabel": "Continuous accommodating interneuron electrical type", "notation": "cACint", "atlasRelease": {"@id": "https://bbp.epfl.ch/neurosciencegraph/data/brainatlasrelease/c96c71a8-4c0d-4bc1-8a1a-141d9ed6693d", "@type": "BrainAtlasRelease", "_rev": 45}},
{"@id": "http://bbp.epfl.ch/neurosciencegraph/ontologies/mtypes/GCL_GC", "@type": "Class", "label": "GCL_GC", "subClassOf": ["https://bbp.epfl.ch/ontologies/core/mtypes/HippocampusMType", "https://bbp.epfl.ch/ontologies/core/bmo/NeuronMorphologicalType", "https://neuroshapes.org/MType", "https://bbp.epfl.ch/ontologies/core/bmo/BrainCellType"], "atlasRelease": {"@id": "https://bbp.epfl.ch/neurosciencegraph/data/brainatlasrelease/c96c71a8-4c0d-4bc1-8a1a-141d9ed6693d", "@type": "BrainAtlasRelease", "_rev": 45}},
{"@id": "http://bbp.epfl.ch/neurosciencegraph/ontologies/mtypes/L23_PTPC", "@type": "Class", "label": "L23_PTPC", "subClassOf": ["https://bbp.epfl.ch/ontologies/core/bmo/HumanNeocortexMType", "https://neuroshapes.org/PyramidalNeuron", "https://bbp.epfl.ch/ontologies/core/bmo/NeuronMorphologicalType", "https://neuroshapes.org/MType", "https://bbp.epfl.ch/ontologies/core/bmo/BrainCellType"], "notation": "L2_MC", "atlasRelease": {"@id": "https://bbp.epfl.ch/neurosciencegraph/data/brainatlasrelease/c96c71a8-4c0d-4bc1-8a1a-141d9ed6693d", "@type": "BrainAtlasRelease", "_rev": 45}}
],
"label": "Cell Types Ontology"
}
190 changes: 190 additions & 0 deletions swarm_copy_tests/test_cell_types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
"""Test cell types meta functions."""
import logging
from pathlib import Path

import pytest

from swarm_copy.cell_types import CellTypesMeta, get_celltypes_descendants

CELL_TYPES_FILE = Path(__file__).parent / "data" / "kg_cell_types_hierarchy_test.json"


@pytest.mark.parametrize(
"cell_type_id,expected_descendants",
[
(
"https://bbp.epfl.ch/ontologies/core/bmo/BrainCellType",
{
"http://bbp.epfl.ch/neurosciencegraph/ontologies/mtypes/L23_PTPC",
"http://bbp.epfl.ch/neurosciencegraph/ontologies/etypes/cACint",
"http://bbp.epfl.ch/neurosciencegraph/ontologies/mtypes/GCL_GC",
"https://bbp.epfl.ch/ontologies/core/bmo/BrainCellType",
},
),
(
"https://bbp.epfl.ch/ontologies/core/bmo/NeuronElectricalType",
{
"https://bbp.epfl.ch/ontologies/core/bmo/NeuronElectricalType",
"http://bbp.epfl.ch/neurosciencegraph/ontologies/etypes/cACint",
},
),
(
"http://bbp.epfl.ch/neurosciencegraph/ontologies/etypes/cACint",
{
"http://bbp.epfl.ch/neurosciencegraph/ontologies/etypes/cACint",
},
),
],
)
def test_get_celltypes_descendants(cell_type_id, expected_descendants, tmp_path):
cell_types_meta = CellTypesMeta.from_json(CELL_TYPES_FILE)
save_file = tmp_path / "tmp_config_cell_types_meta.json"
cell_types_meta.save_config(save_file)

descendants = get_celltypes_descendants(cell_type_id, json_path=save_file)
assert expected_descendants == descendants


class TestCellTypesMeta:
def test_from_json(self):
ct_meta = CellTypesMeta.from_json(CELL_TYPES_FILE)
assert isinstance(ct_meta.name_, dict)
assert isinstance(ct_meta.descendants_ids, dict)

expected_names = {
"http://bbp.epfl.ch/neurosciencegraph/ontologies/etypes/cACint": "cACint",
"http://bbp.epfl.ch/neurosciencegraph/ontologies/mtypes/GCL_GC": "GCL_GC",
"http://bbp.epfl.ch/neurosciencegraph/ontologies/mtypes/L23_PTPC": (
"L23_PTPC"
),
}

assert ct_meta.name_ == expected_names
assert ct_meta.descendants_ids[
"https://bbp.epfl.ch/ontologies/core/mtypes/HippocampusMType"
] == {"http://bbp.epfl.ch/neurosciencegraph/ontologies/mtypes/GCL_GC"}
assert ct_meta.descendants_ids[
"https://bbp.epfl.ch/ontologies/core/bmo/BrainCellType"
] == {
"http://bbp.epfl.ch/neurosciencegraph/ontologies/mtypes/L23_PTPC",
"http://bbp.epfl.ch/neurosciencegraph/ontologies/etypes/cACint",
"http://bbp.epfl.ch/neurosciencegraph/ontologies/mtypes/GCL_GC",
}

def test_from_dict(self):
test_dict = {
"defines": [
{
"@id": "id1",
"label": "cell1",
"subClassOf": []
},
{
"@id": "id2",
"label": "cell2",
"subClassOf": ["id1"]
},
{
"@id": "id3",
"subClassOf": ["id2"]
}
]
}
cell_meta = CellTypesMeta.from_dict(test_dict)
assert isinstance(cell_meta, CellTypesMeta)
assert cell_meta.name_ == {"id1": "cell1", "id2": "cell2", "id3": None}
assert cell_meta.descendants_ids == {"id1": {"id2", "id3"}, "id2": {"id3"}}

def test_from_dict_missing_label(self):
test_dict = {
"defines": [
{
"@id": "id1",
"subClassOf": []
},
{
"@id": "id2",
"subClassOf": ["id1"]
}
]
}
cell_meta = CellTypesMeta.from_dict(test_dict)
assert cell_meta.name_ == {"id1": None, "id2": None}
assert cell_meta.descendants_ids == {"id1": {"id2"}}

def test_from_dict_missing_subClassOf(self):
test_dict = {
"defines": [
{
"@id": "id1",
"label": "cell1",
},
{
"@id": "id2",
"label": "cell2",
"subClassOf": ["id1"]
}
]
}
cell_meta = CellTypesMeta.from_dict(test_dict)
assert cell_meta.name_ == {"id1": "cell1", "id2": "cell2"}
assert cell_meta.descendants_ids == {"id1": {"id2"}}

@pytest.mark.parametrize(
"cell_type_id,expected_descendants",
[
(
"https://bbp.epfl.ch/ontologies/core/bmo/BrainCellType",
{
"http://bbp.epfl.ch/neurosciencegraph/ontologies/mtypes/L23_PTPC",
"http://bbp.epfl.ch/neurosciencegraph/ontologies/etypes/cACint",
"http://bbp.epfl.ch/neurosciencegraph/ontologies/mtypes/GCL_GC",
"https://bbp.epfl.ch/ontologies/core/bmo/BrainCellType",
},
),
(
"https://bbp.epfl.ch/ontologies/core/bmo/NeuronElectricalType",
{
"https://bbp.epfl.ch/ontologies/core/bmo/NeuronElectricalType",
"http://bbp.epfl.ch/neurosciencegraph/ontologies/etypes/cACint",
},
),
(
[
"https://bbp.epfl.ch/ontologies/core/bmo/BrainCellType",
"https://bbp.epfl.ch/ontologies/core/bmo/NeuronElectricalType",
],
{
"http://bbp.epfl.ch/neurosciencegraph/ontologies/mtypes/L23_PTPC",
"http://bbp.epfl.ch/neurosciencegraph/ontologies/etypes/cACint",
"http://bbp.epfl.ch/neurosciencegraph/ontologies/mtypes/GCL_GC",
"https://bbp.epfl.ch/ontologies/core/bmo/BrainCellType",
"https://bbp.epfl.ch/ontologies/core/bmo/NeuronElectricalType",
},
),
(
"https://bbp.epfl.ch/ontologies/core/bmo/NeuronElectricalType",
{
"https://bbp.epfl.ch/ontologies/core/bmo/NeuronElectricalType",
"http://bbp.epfl.ch/neurosciencegraph/ontologies/etypes/cACint",
},
),
(
"http://bbp.epfl.ch/neurosciencegraph/ontologies/etypes/cACint",
{
"http://bbp.epfl.ch/neurosciencegraph/ontologies/etypes/cACint",
},
),
],
)
def test_descendants(self, cell_type_id, expected_descendants):
ct_meta = CellTypesMeta.from_json(CELL_TYPES_FILE)
assert ct_meta.descendants(cell_type_id) == expected_descendants

def test_load_and_save_config(self, tmp_path):
ct_meta = CellTypesMeta.from_json(CELL_TYPES_FILE)
file_path = tmp_path / "ct_meta_tmp.json"
ct_meta.save_config(file_path)
ct_meta2 = CellTypesMeta.load_config(file_path)
assert ct_meta.name_ == ct_meta2.name_
assert ct_meta.descendants_ids == ct_meta2.descendants_ids
Loading

0 comments on commit 56a81ea

Please sign in to comment.