diff --git a/emannotationschemas/__init__.py b/emannotationschemas/__init__.py index de8e3be..971c383 100644 --- a/emannotationschemas/__init__.py +++ b/emannotationschemas/__init__.py @@ -48,14 +48,22 @@ V1DDFunctionalUnitCoregistration, ) from emannotationschemas.schemas.functional_props import ( - FunctionalPropertiesBCM, DigitalTwinPropertiesBCM, + FunctionalPropertiesBCM, ) from emannotationschemas.schemas.glia_contact import GliaContact from emannotationschemas.schemas.groups import SimpleGroup, SimpleGroupIndexed +from emannotationschemas.schemas.matching import ( + CellMatch, + CellMatchReference, + CellSimilarity, +) from emannotationschemas.schemas.neuropil import FlyNeuropil from emannotationschemas.schemas.nucleus_detection import NucleusDetection -from emannotationschemas.schemas.postsynaptic_compartment import PostsynapticCompartment +from emannotationschemas.schemas.postsynaptic_compartment import ( + PostsynapticCompartment, + SpineWithInfo, +) from emannotationschemas.schemas.presynaptic_bouton_type import PresynapticBoutonType from emannotationschemas.schemas.proofreading import ( CompartmentProofreadStatus, @@ -66,11 +74,6 @@ from emannotationschemas.schemas.reference_text_float import ( ReferenceTagFloat, ) -from emannotationschemas.schemas.matching import ( - CellMatch, - CellSimilarity, - CellMatchReference, -) from emannotationschemas.schemas.synapse import ( BuhmannEcksteinSynapseSchema, BuhmannSynapseSchema, @@ -92,6 +95,7 @@ "bouton_shape": BoutonShape, "presynaptic_bouton_type": PresynapticBoutonType, "postsynaptic_compartment": PostsynapticCompartment, + "spine_with_info": SpineWithInfo, "microns_func_coreg": FunctionalCoregistration, "microns_func_unit_coreg": FunctionalUnitCoregistration, "v1dd_func_unit_coreg": V1DDFunctionalUnitCoregistration, diff --git a/emannotationschemas/schemas/postsynaptic_compartment.py b/emannotationschemas/schemas/postsynaptic_compartment.py index a7abc0a..97168af 100644 --- a/emannotationschemas/schemas/postsynaptic_compartment.py +++ b/emannotationschemas/schemas/postsynaptic_compartment.py @@ -1,7 +1,8 @@ import marshmallow as mm -from emannotationschemas.schemas.base import ReferenceAnnotation from marshmallow.validate import OneOf +from emannotationschemas.schemas.base import BoundSpatialPoint, ReferenceAnnotation + allowed_compartments = [ "soma", "dendrite", @@ -12,7 +13,6 @@ class PostsynapticCompartment(ReferenceAnnotation): - compartment = mm.fields.Str( required=True, validate=OneOf(allowed_compartments), @@ -30,3 +30,14 @@ class PostsynapticCompartment(ReferenceAnnotation): validate=OneOf(allowed_dendrite_classes), description="Type of dendritic branch, e.g. basal or apical", ) + + +class SpineWithInfo(BoundSpatialPoint): + volume = mm.fields.Float( + required=False, description="Estimated volume of the spine" + ) + + n_inputs = mm.fields.Int( + required=False, + description="Number of synaptic inputs (unique root IDs) onto the spine", + ) diff --git a/tests/test_spine.py b/tests/test_spine.py new file mode 100644 index 0000000..c5b445b --- /dev/null +++ b/tests/test_spine.py @@ -0,0 +1,35 @@ +from emannotationschemas.schemas.postsynaptic_compartment import SpineWithInfo + +good_spine_with_info = { + "position": [100, 200, 300], + "supervoxel_id": 50, + "root_id": 10, + "volume": 1.5, + "n_inputs": 3, +} + + +def test_spine_with_info_schema(): + schema = SpineWithInfo() + result = schema.load(good_spine_with_info) + assert result["position"] == [100, 200, 300] + assert result["supervoxel_id"] == 50 + assert result["root_id"] == 10 + assert result["volume"] == 1.5 + assert result["n_inputs"] == 3 + + +def test_spine_with_info_optional(): + schema = SpineWithInfo() + result = schema.load( + { + "position": [100, 200, 300], + "supervoxel_id": 50, + "root_id": 10, + } + ) + assert result["position"] == [100, 200, 300] + assert result["supervoxel_id"] == 50 + assert result["root_id"] == 10 + assert "volume" not in result + assert "n_inputs" not in result