Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/entitysdk/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@
from entitysdk.models.ion_channel_model import IonChannelModel, NeuronBlock, UseIon
from entitysdk.models.license import License
from entitysdk.models.memodel import MEModel
from entitysdk.models.memodelcalibrationresult import MEModelCalibrationResult
from entitysdk.models.morphology import ReconstructionMorphology
from entitysdk.models.mtype import MTypeClass
from entitysdk.models.taxonomy import Species, Strain, Taxonomy
from entitysdk.models.validation_result import ValidationResult

__all__ = [
"Asset",
Expand All @@ -24,6 +26,7 @@
"IonChannelModel",
"License",
"MEModel",
"MEModelCalibrationResult",
"MTypeClass",
"NeuronBlock",
"Organization",
Expand All @@ -34,4 +37,5 @@
"Strain",
"Taxonomy",
"UseIon",
"ValidationResult",
]
7 changes: 7 additions & 0 deletions src/entitysdk/models/memodel.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from entitysdk.models.emodel import EModel
from entitysdk.models.entity import Entity
from entitysdk.models.etype import ETypeClass
from entitysdk.models.memodelcalibrationresult import MEModelCalibrationResult
from entitysdk.models.morphology import (
BrainRegion,
License,
Expand Down Expand Up @@ -93,4 +94,10 @@ class MEModel(Entity):
description="The mtype classes of the memodel.",
),
] = None
calibration_result: Annotated[
MEModelCalibrationResult | None,
Field(
description="The calibration result of the memodel.",
),
] = None
legacy_id: list[str] | None = None
42 changes: 42 additions & 0 deletions src/entitysdk/models/memodelcalibrationresult.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"""ME-Model Calibration Result."""

from typing import Annotated

from pydantic import Field

from entitysdk.models.entity import Entity
from entitysdk.types import ID


class MEModelCalibrationResult(Entity):
"""ME-Model calibration result."""

holding_current: Annotated[
float,
Field(
description="The holding current to apply to the simulatable neuron, in nA.",
example=-0.016,
),
]
threshold_current: Annotated[
float,
Field(
description="The minimal amount of current needed to make "
"the simulatable neuron spike, in nA.",
example=0.1,
),
]
rin: Annotated[
float | None,
Field(
description="The input resistance of the simulatable neuron, in MOhm.",
example=0.1,
),
] = None
calibrated_entity_id: Annotated[
ID,
Field(
description="ID of the calibrated entity.",
example="85663316-a7ff-4107-9eb9-236de8868c5c",
),
]
34 changes: 34 additions & 0 deletions src/entitysdk/models/validation_result.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"""Validation result."""

from typing import Annotated

from pydantic import Field

from entitysdk.models.entity import Entity
from entitysdk.types import ID


class ValidationResult(Entity):
"""Validation result."""

passed: Annotated[
bool,
Field(
description="True if the validation passed, False otherwise.",
example=True,
),
]
name: Annotated[
str,
Field(
description="Name of the validation.",
example="Neuron spiking validation",
),
]
validated_entity_id: Annotated[
ID,
Field(
description="ID of the validated entity.",
example="85663316-a7ff-4107-9eb9-236de8868c5c",
),
]
10 changes: 6 additions & 4 deletions src/entitysdk/route.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,13 @@
"BrainRegion": "brain-region",
"Contribution": "contribution",
"ElectricalCellRecording": "electrical-cell-recording",
"EModel": "emodel",
"Entity": "entity",
"Ion": "ion",
"IonChannelModel": "ion-channel-model",
"License": "license",
"MEModel": "memodel",
"MEModelCalibrationResult": "memodel-calibration-result",
"MTypeClass": "mtype",
"Organization": "organization",
"Person": "person",
Expand All @@ -21,10 +26,7 @@
"Species": "species",
"Strain": "strain",
"Taxonomy": "taxonomy",
"IonChannelModel": "ion-channel-model",
"Ion": "ion",
"EModel": "emodel",
"MEModel": "memodel",
"ValidationResult": "validation-result",
}


Expand Down
4 changes: 4 additions & 0 deletions tests/integration/test_searching.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@
IonChannelModel,
License,
MEModel,
MEModelCalibrationResult,
MTypeClass,
Organization,
Person,
ReconstructionMorphology,
Role,
Species,
Strain,
ValidationResult,
)


Expand All @@ -33,6 +35,8 @@
EModel,
MEModel,
ElectricalCellRecording,
ValidationResult,
MEModelCalibrationResult,
],
)
def test_is_searchable(entity_type, client):
Expand Down
8 changes: 8 additions & 0 deletions tests/unit/models/data/memodel_calibration_result.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"authorized_public": false,
"id" : "cfecab84-b37c-4fa0-adaa-86457d660061",
"holding_current" : 0.0,
"threshold_current" : 0.06554153953301577,
"rin" : 100.03205800593804,
"calibrated_entity_id" : "54004e96-cef0-4f1c-8c89-d9cdf7b94e43"
}
7 changes: 7 additions & 0 deletions tests/unit/models/data/validation_result.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"authorized_public": false,
"id" : "6fa52c8b-e9df-4f10-bdee-07c9af59a5ba",
"passed" : true,
"name" : "Simulatable Neuron Spiking Validation",
"validated_entity_id" : "54004e96-cef0-4f1c-8c89-d9cdf7b94e43"
}
42 changes: 42 additions & 0 deletions tests/unit/models/test_memodel_calibration_result.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import json
from pathlib import Path

import pytest

from entitysdk.models import MEModelCalibrationResult

from ..util import MOCK_UUID

DATA_DIR = Path(__file__).parent / "data"

Model = MEModelCalibrationResult


@pytest.fixture
def json_data():
return json.loads(Path(DATA_DIR / "memodel_calibration_result.json").read_bytes())


@pytest.fixture
def model(json_data):
return Model.model_validate(json_data)


def test_read(client, httpx_mock, auth_token, json_data):
httpx_mock.add_response(method="GET", json=json_data)
entity = client.get_entity(
entity_id=MOCK_UUID,
entity_type=Model,
token=auth_token,
with_assets=False,
)
assert entity.model_dump(mode="json", exclude_none=True) == json_data


def test_register(client, httpx_mock, auth_token, model, json_data):
httpx_mock.add_response(
method="POST", json=model.model_dump(mode="json") | {"id": str(MOCK_UUID)}
)
registered = client.register_entity(entity=model, token=auth_token)
expected_json = json_data | {"id": str(MOCK_UUID)}
assert registered.model_dump(mode="json", exclude_none=True) == expected_json
42 changes: 42 additions & 0 deletions tests/unit/models/test_validation_result.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import json
from pathlib import Path

import pytest

from entitysdk.models import ValidationResult

from ..util import MOCK_UUID

DATA_DIR = Path(__file__).parent / "data"

Model = ValidationResult


@pytest.fixture
def json_data():
return json.loads(Path(DATA_DIR / "validation_result.json").read_bytes())


@pytest.fixture
def model(json_data):
return Model.model_validate(json_data)


def test_read(client, httpx_mock, auth_token, json_data):
httpx_mock.add_response(method="GET", json=json_data)
entity = client.get_entity(
entity_id=MOCK_UUID,
entity_type=Model,
token=auth_token,
with_assets=False,
)
assert entity.model_dump(mode="json", exclude_none=True) == json_data


def test_register(client, httpx_mock, auth_token, model, json_data):
httpx_mock.add_response(
method="POST", json=model.model_dump(mode="json") | {"id": str(MOCK_UUID)}
)
registered = client.register_entity(entity=model, token=auth_token)
expected_json = json_data | {"id": str(MOCK_UUID)}
assert registered.model_dump(mode="json", exclude_none=True) == expected_json