entitysdk 0.4.0__tar.gz → 0.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {entitysdk-0.4.0/src/entitysdk.egg-info → entitysdk-0.5.0}/PKG-INFO +3 -4
- {entitysdk-0.4.0 → entitysdk-0.5.0}/README.md +2 -3
- entitysdk-0.5.0/src/entitysdk/downloaders/__init__.py +1 -0
- entitysdk-0.5.0/src/entitysdk/downloaders/emodel.py +29 -0
- entitysdk-0.5.0/src/entitysdk/downloaders/ion_channel_model.py +29 -0
- entitysdk-0.5.0/src/entitysdk/downloaders/memodel.py +42 -0
- entitysdk-0.5.0/src/entitysdk/downloaders/morphology.py +36 -0
- entitysdk-0.5.0/src/entitysdk/schemas/memodel.py +13 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/types.py +2 -0
- entitysdk-0.5.0/src/entitysdk/utils/filesystem.py +12 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0/src/entitysdk.egg-info}/PKG-INFO +3 -4
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk.egg-info/SOURCES.txt +13 -1
- entitysdk-0.5.0/tests/unit/downloaders/test_emodel.py +70 -0
- entitysdk-0.5.0/tests/unit/downloaders/test_ion_channel_model.py +72 -0
- entitysdk-0.5.0/tests/unit/downloaders/test_memodel.py +199 -0
- entitysdk-0.5.0/tests/unit/downloaders/test_morphology.py +68 -0
- entitysdk-0.5.0/tests/unit/utils/test_filesystem.py +6 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/.github/workflows/sdist.yml +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/.github/workflows/tox.yml +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/.gitignore +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/CHANGELOG.rst +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/CONTRIBUTING.md +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/LICENSE.txt +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/examples/01_searching.ipynb +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/examples/02_morphology.ipynb +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/examples/03_contribution.ipynb +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/examples/04_circuit.ipynb +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/examples/05_simulation_campaign.ipynb +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/pyproject.toml +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/setup.cfg +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/__init__.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/client.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/common.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/config.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/core.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/exception.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/mixin.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/models/__init__.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/models/agent.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/models/asset.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/models/base.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/models/brain_location.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/models/brain_region.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/models/circuit.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/models/contribution.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/models/core.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/models/electrical_cell_recording.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/models/emodel.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/models/entity.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/models/etype.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/models/ion_channel_model.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/models/license.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/models/memodel.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/models/memodelcalibrationresult.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/models/morphology.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/models/mtype.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/models/response.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/models/scientific_artifact.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/models/simulation.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/models/simulation_campaign.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/models/subject.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/models/taxonomy.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/models/validation_result.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/result.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/route.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/schemas/__init__.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/schemas/asset.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/schemas/base.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/serdes.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/token_manager.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/util.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/utils/__init__.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk/utils/asset.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk.egg-info/dependency_links.txt +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk.egg-info/requires.txt +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/src/entitysdk.egg-info/top_level.txt +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/__init__.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/integration/__init__.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/integration/conftest.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/integration/test_searching.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/unit/__init__.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/unit/conftest.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/unit/models/__init__.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/unit/models/data/.gitignore +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/unit/models/data/circuit.json +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/unit/models/data/electrical_cell_recording.json +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/unit/models/data/ion_channel_model.json +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/unit/models/data/memodel_calibration_result.json +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/unit/models/data/reconstruction_morphology.json +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/unit/models/data/simulation_campaign.json +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/unit/models/data/validation_result.json +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/unit/models/test_agent.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/unit/models/test_asset.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/unit/models/test_brain_region.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/unit/models/test_circuit.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/unit/models/test_contribution.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/unit/models/test_electrical_cell_recording.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/unit/models/test_init.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/unit/models/test_ion_channel_model.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/unit/models/test_memodel_calibration_result.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/unit/models/test_morphology.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/unit/models/test_simulation_campaign.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/unit/models/test_validation_result.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/unit/test_base.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/unit/test_client.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/unit/test_common.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/unit/test_config.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/unit/test_result.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/unit/test_route.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/unit/test_serdes.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/unit/test_token_manager.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/unit/test_util.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/unit/util.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tests/unit/utils/test_asset.py +0 -0
- {entitysdk-0.4.0 → entitysdk-0.5.0}/tox.ini +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: entitysdk
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.5.0
|
4
4
|
Summary: Python library for interacting with the entitycore service
|
5
5
|
Author-email: Open Brain Institute <info@openbraininstitute.org>
|
6
6
|
Maintainer-email: Open Brain Institute <info@openbraininstitute.org>
|
@@ -66,14 +66,14 @@ client = Client(
|
|
66
66
|
project_id=UUID("your-project-id"),
|
67
67
|
virtual_lab_id=UUID("your-lab-id")
|
68
68
|
),
|
69
|
-
environment="staging"
|
69
|
+
environment="staging",
|
70
|
+
token_manager=token
|
70
71
|
)
|
71
72
|
|
72
73
|
# Search for morphologies
|
73
74
|
iterator = client.search_entity(
|
74
75
|
entity_type=models.ReconstructionMorphology,
|
75
76
|
query={"mtype__pref_label": "L5_TPC:A"},
|
76
|
-
token=token,
|
77
77
|
limit=1,
|
78
78
|
)
|
79
79
|
morphology = next(iterator)
|
@@ -84,7 +84,6 @@ client.upload_file(
|
|
84
84
|
entity_type=models.ReconstructionMorphology,
|
85
85
|
file_path="path/to/file.swc",
|
86
86
|
file_content_type="application/swc",
|
87
|
-
token="your-token"
|
88
87
|
)
|
89
88
|
```
|
90
89
|
|
@@ -45,14 +45,14 @@ client = Client(
|
|
45
45
|
project_id=UUID("your-project-id"),
|
46
46
|
virtual_lab_id=UUID("your-lab-id")
|
47
47
|
),
|
48
|
-
environment="staging"
|
48
|
+
environment="staging",
|
49
|
+
token_manager=token
|
49
50
|
)
|
50
51
|
|
51
52
|
# Search for morphologies
|
52
53
|
iterator = client.search_entity(
|
53
54
|
entity_type=models.ReconstructionMorphology,
|
54
55
|
query={"mtype__pref_label": "L5_TPC:A"},
|
55
|
-
token=token,
|
56
56
|
limit=1,
|
57
57
|
)
|
58
58
|
morphology = next(iterator)
|
@@ -63,7 +63,6 @@ client.upload_file(
|
|
63
63
|
entity_type=models.ReconstructionMorphology,
|
64
64
|
file_path="path/to/file.swc",
|
65
65
|
file_content_type="application/swc",
|
66
|
-
token="your-token"
|
67
66
|
)
|
68
67
|
```
|
69
68
|
|
@@ -0,0 +1 @@
|
|
1
|
+
"""Downloaders module."""
|
@@ -0,0 +1,29 @@
|
|
1
|
+
"""Download functions for EModel entities."""
|
2
|
+
|
3
|
+
from pathlib import Path
|
4
|
+
|
5
|
+
from entitysdk.client import Client
|
6
|
+
from entitysdk.models.emodel import EModel
|
7
|
+
from entitysdk.utils.filesystem import create_dir
|
8
|
+
|
9
|
+
|
10
|
+
def download_hoc(
|
11
|
+
client: Client,
|
12
|
+
emodel: EModel,
|
13
|
+
output_dir: str | Path,
|
14
|
+
) -> Path:
|
15
|
+
"""Download hoc file.
|
16
|
+
|
17
|
+
Args:
|
18
|
+
client (Client): EntitySDK client
|
19
|
+
emodel (EModel): EModel entitysdk object
|
20
|
+
output_dir (str or Path): directory to save the hoc file
|
21
|
+
"""
|
22
|
+
output_dir = create_dir(output_dir)
|
23
|
+
asset = client.download_assets(
|
24
|
+
emodel,
|
25
|
+
selection={"content_type": "application/hoc"},
|
26
|
+
output_path=output_dir,
|
27
|
+
).one()
|
28
|
+
|
29
|
+
return asset.output_path
|
@@ -0,0 +1,29 @@
|
|
1
|
+
"""Download functions for IonChannelModel entities."""
|
2
|
+
|
3
|
+
from pathlib import Path
|
4
|
+
|
5
|
+
from entitysdk.client import Client
|
6
|
+
from entitysdk.models.ion_channel_model import IonChannelModel
|
7
|
+
from entitysdk.utils.filesystem import create_dir
|
8
|
+
|
9
|
+
|
10
|
+
def download_ion_channel_mechanism(
|
11
|
+
client: Client,
|
12
|
+
ion_channel_model: IonChannelModel,
|
13
|
+
output_dir: str | Path,
|
14
|
+
) -> Path:
|
15
|
+
"""Download one mechanism file.
|
16
|
+
|
17
|
+
Args:
|
18
|
+
client (Client): EntitySDK client
|
19
|
+
ion_channel_model (IonChannelModel): IonChannelModel entitysdk object
|
20
|
+
output_dir (str or Pathlib.Path): directory to save the mechanism file
|
21
|
+
"""
|
22
|
+
output_dir = create_dir(output_dir)
|
23
|
+
asset = client.download_assets(
|
24
|
+
ion_channel_model,
|
25
|
+
selection={"content_type": "application/neuron-mod"},
|
26
|
+
output_path=output_dir,
|
27
|
+
).one()
|
28
|
+
|
29
|
+
return asset.output_path
|
@@ -0,0 +1,42 @@
|
|
1
|
+
"""Download functions for MEModel entities."""
|
2
|
+
|
3
|
+
from pathlib import Path
|
4
|
+
from typing import cast
|
5
|
+
|
6
|
+
from entitysdk.client import Client
|
7
|
+
from entitysdk.downloaders.emodel import download_hoc
|
8
|
+
from entitysdk.downloaders.ion_channel_model import download_ion_channel_mechanism
|
9
|
+
from entitysdk.downloaders.morphology import download_morphology
|
10
|
+
from entitysdk.models.emodel import EModel
|
11
|
+
from entitysdk.models.memodel import MEModel
|
12
|
+
from entitysdk.schemas.memodel import DownloadedMEModel
|
13
|
+
from entitysdk.utils.filesystem import create_dir
|
14
|
+
|
15
|
+
|
16
|
+
def download_memodel(client: Client, memodel: MEModel, output_dir=".") -> DownloadedMEModel:
|
17
|
+
"""Download all assets needed to run an me-model: hoc, ion channel models, and morphology.
|
18
|
+
|
19
|
+
Args:
|
20
|
+
client (Client): EntitySDK client
|
21
|
+
memodel (MEModel): MEModel entitysdk object
|
22
|
+
output_dir (str): directory to save the downloaded files, defaults to current directory
|
23
|
+
"""
|
24
|
+
# we have to get the emodel to get the ion channel models.
|
25
|
+
emodel = cast(
|
26
|
+
EModel,
|
27
|
+
client.get_entity(entity_id=memodel.emodel.id, entity_type=EModel), # type: ignore
|
28
|
+
)
|
29
|
+
|
30
|
+
hoc_path = download_hoc(client, emodel, Path(output_dir) / "hoc")
|
31
|
+
# only take .asc format for now.
|
32
|
+
# Will take specific format when morphology_format is integrated into MEModel
|
33
|
+
morphology_path = download_morphology(
|
34
|
+
client, memodel.morphology, Path(output_dir) / "morphology", "asc"
|
35
|
+
)
|
36
|
+
mechanisms_dir = create_dir(Path(output_dir) / "mechanisms")
|
37
|
+
for ic in emodel.ion_channel_models or []:
|
38
|
+
download_ion_channel_mechanism(client, ic, mechanisms_dir)
|
39
|
+
|
40
|
+
return DownloadedMEModel(
|
41
|
+
hoc_path=hoc_path, mechanisms_dir=mechanisms_dir, morphology_path=morphology_path
|
42
|
+
)
|
@@ -0,0 +1,36 @@
|
|
1
|
+
"""Download functions for Morphology entities."""
|
2
|
+
|
3
|
+
import logging
|
4
|
+
from pathlib import Path
|
5
|
+
|
6
|
+
from entitysdk.client import Client
|
7
|
+
from entitysdk.models.morphology import ReconstructionMorphology
|
8
|
+
from entitysdk.utils.filesystem import create_dir
|
9
|
+
|
10
|
+
logger = logging.getLogger(__name__)
|
11
|
+
|
12
|
+
|
13
|
+
def download_morphology(
|
14
|
+
client: Client,
|
15
|
+
morphology: ReconstructionMorphology,
|
16
|
+
output_dir: str | Path,
|
17
|
+
file_type: str,
|
18
|
+
) -> Path:
|
19
|
+
"""Download morphology file.
|
20
|
+
|
21
|
+
Args:
|
22
|
+
client (Client): EntitySDK client
|
23
|
+
morphology (ReconstructionMorphology): Morphology entitysdk object
|
24
|
+
output_dir (str or Path): directory to save the morphology file
|
25
|
+
file_type (str or None): type of the morphology file ('asc', 'swc' or 'h5').
|
26
|
+
Will take the first one if None.
|
27
|
+
"""
|
28
|
+
output_dir = create_dir(output_dir)
|
29
|
+
|
30
|
+
asset = client.download_assets(
|
31
|
+
morphology,
|
32
|
+
selection={"content_type": f"application/{file_type}"},
|
33
|
+
output_path=output_dir,
|
34
|
+
).one()
|
35
|
+
|
36
|
+
return asset.output_path
|
@@ -0,0 +1,12 @@
|
|
1
|
+
"""Utility functions for filesystem operations."""
|
2
|
+
|
3
|
+
from pathlib import Path
|
4
|
+
|
5
|
+
from entitysdk.types import StrOrPath
|
6
|
+
|
7
|
+
|
8
|
+
def create_dir(path: StrOrPath) -> Path:
|
9
|
+
"""Create directory and parents if it doesn't already exist."""
|
10
|
+
path = Path(path)
|
11
|
+
path.mkdir(parents=True, exist_ok=True)
|
12
|
+
return path
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: entitysdk
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.5.0
|
4
4
|
Summary: Python library for interacting with the entitycore service
|
5
5
|
Author-email: Open Brain Institute <info@openbraininstitute.org>
|
6
6
|
Maintainer-email: Open Brain Institute <info@openbraininstitute.org>
|
@@ -66,14 +66,14 @@ client = Client(
|
|
66
66
|
project_id=UUID("your-project-id"),
|
67
67
|
virtual_lab_id=UUID("your-lab-id")
|
68
68
|
),
|
69
|
-
environment="staging"
|
69
|
+
environment="staging",
|
70
|
+
token_manager=token
|
70
71
|
)
|
71
72
|
|
72
73
|
# Search for morphologies
|
73
74
|
iterator = client.search_entity(
|
74
75
|
entity_type=models.ReconstructionMorphology,
|
75
76
|
query={"mtype__pref_label": "L5_TPC:A"},
|
76
|
-
token=token,
|
77
77
|
limit=1,
|
78
78
|
)
|
79
79
|
morphology = next(iterator)
|
@@ -84,7 +84,6 @@ client.upload_file(
|
|
84
84
|
entity_type=models.ReconstructionMorphology,
|
85
85
|
file_path="path/to/file.swc",
|
86
86
|
file_content_type="application/swc",
|
87
|
-
token="your-token"
|
88
87
|
)
|
89
88
|
```
|
90
89
|
|
@@ -30,6 +30,11 @@ src/entitysdk.egg-info/SOURCES.txt
|
|
30
30
|
src/entitysdk.egg-info/dependency_links.txt
|
31
31
|
src/entitysdk.egg-info/requires.txt
|
32
32
|
src/entitysdk.egg-info/top_level.txt
|
33
|
+
src/entitysdk/downloaders/__init__.py
|
34
|
+
src/entitysdk/downloaders/emodel.py
|
35
|
+
src/entitysdk/downloaders/ion_channel_model.py
|
36
|
+
src/entitysdk/downloaders/memodel.py
|
37
|
+
src/entitysdk/downloaders/morphology.py
|
33
38
|
src/entitysdk/models/__init__.py
|
34
39
|
src/entitysdk/models/agent.py
|
35
40
|
src/entitysdk/models/asset.py
|
@@ -59,8 +64,10 @@ src/entitysdk/models/validation_result.py
|
|
59
64
|
src/entitysdk/schemas/__init__.py
|
60
65
|
src/entitysdk/schemas/asset.py
|
61
66
|
src/entitysdk/schemas/base.py
|
67
|
+
src/entitysdk/schemas/memodel.py
|
62
68
|
src/entitysdk/utils/__init__.py
|
63
69
|
src/entitysdk/utils/asset.py
|
70
|
+
src/entitysdk/utils/filesystem.py
|
64
71
|
tests/__init__.py
|
65
72
|
tests/integration/__init__.py
|
66
73
|
tests/integration/conftest.py
|
@@ -77,6 +84,10 @@ tests/unit/test_serdes.py
|
|
77
84
|
tests/unit/test_token_manager.py
|
78
85
|
tests/unit/test_util.py
|
79
86
|
tests/unit/util.py
|
87
|
+
tests/unit/downloaders/test_emodel.py
|
88
|
+
tests/unit/downloaders/test_ion_channel_model.py
|
89
|
+
tests/unit/downloaders/test_memodel.py
|
90
|
+
tests/unit/downloaders/test_morphology.py
|
80
91
|
tests/unit/models/__init__.py
|
81
92
|
tests/unit/models/test_agent.py
|
82
93
|
tests/unit/models/test_asset.py
|
@@ -98,4 +109,5 @@ tests/unit/models/data/memodel_calibration_result.json
|
|
98
109
|
tests/unit/models/data/reconstruction_morphology.json
|
99
110
|
tests/unit/models/data/simulation_campaign.json
|
100
111
|
tests/unit/models/data/validation_result.json
|
101
|
-
tests/unit/utils/test_asset.py
|
112
|
+
tests/unit/utils/test_asset.py
|
113
|
+
tests/unit/utils/test_filesystem.py
|
@@ -0,0 +1,70 @@
|
|
1
|
+
import uuid
|
2
|
+
|
3
|
+
from entitysdk.downloaders.emodel import download_hoc
|
4
|
+
from entitysdk.models.emodel import EModel
|
5
|
+
|
6
|
+
|
7
|
+
def _mock_asset_response(asset_id):
|
8
|
+
return {
|
9
|
+
"id": str(asset_id),
|
10
|
+
"path": "foo.hoc",
|
11
|
+
"full_path": "foo.hoc",
|
12
|
+
"is_directory": False,
|
13
|
+
"content_type": "application/hoc",
|
14
|
+
"size": 100,
|
15
|
+
"status": "created",
|
16
|
+
"meta": {},
|
17
|
+
"sha256_digest": "sha256_digest",
|
18
|
+
}
|
19
|
+
|
20
|
+
|
21
|
+
def test_download_hoc(
|
22
|
+
tmp_path,
|
23
|
+
client,
|
24
|
+
httpx_mock,
|
25
|
+
api_url,
|
26
|
+
request_headers,
|
27
|
+
):
|
28
|
+
"""Test downloading a hoc file from an EModel entity."""
|
29
|
+
emodel_id = uuid.uuid4()
|
30
|
+
asset_id = uuid.uuid4()
|
31
|
+
hierarchy_id = uuid.uuid4()
|
32
|
+
|
33
|
+
httpx_mock.add_response(
|
34
|
+
method="GET",
|
35
|
+
url=f"{api_url}/emodel/{emodel_id}/assets/{asset_id}",
|
36
|
+
match_headers=request_headers,
|
37
|
+
json=_mock_asset_response(asset_id) | {"path": "foo.hoc"},
|
38
|
+
)
|
39
|
+
httpx_mock.add_response(
|
40
|
+
method="GET",
|
41
|
+
url=f"{api_url}/emodel/{emodel_id}/assets/{asset_id}/download",
|
42
|
+
match_headers=request_headers,
|
43
|
+
content="foo",
|
44
|
+
)
|
45
|
+
|
46
|
+
emodel = EModel(
|
47
|
+
id=emodel_id,
|
48
|
+
name="foo",
|
49
|
+
species={"name": "foo", "taxonomy_id": "bar"},
|
50
|
+
brain_region={
|
51
|
+
"name": "foo",
|
52
|
+
"annotation_value": 997,
|
53
|
+
"acronym": "bar",
|
54
|
+
"parent_structure_id": None,
|
55
|
+
"hierarchy_id": str(hierarchy_id),
|
56
|
+
"color_hex_triplet": "#FFFFFF",
|
57
|
+
},
|
58
|
+
iteration="foofoo",
|
59
|
+
score=42,
|
60
|
+
seed=0,
|
61
|
+
assets=[_mock_asset_response(asset_id)],
|
62
|
+
)
|
63
|
+
|
64
|
+
output_path = download_hoc(
|
65
|
+
client=client,
|
66
|
+
emodel=emodel,
|
67
|
+
output_dir=tmp_path,
|
68
|
+
)
|
69
|
+
|
70
|
+
assert output_path.is_file()
|
@@ -0,0 +1,72 @@
|
|
1
|
+
import uuid
|
2
|
+
|
3
|
+
from entitysdk.downloaders.ion_channel_model import download_ion_channel_mechanism
|
4
|
+
from entitysdk.models.ion_channel_model import IonChannelModel, NeuronBlock
|
5
|
+
|
6
|
+
|
7
|
+
def _mock_asset_response(asset_id):
|
8
|
+
return {
|
9
|
+
"id": str(asset_id),
|
10
|
+
"path": "foo.mod",
|
11
|
+
"full_path": "foo.mod",
|
12
|
+
"is_directory": False,
|
13
|
+
"content_type": "application/neuron-mod",
|
14
|
+
"size": 100,
|
15
|
+
"status": "created",
|
16
|
+
"meta": {},
|
17
|
+
"sha256_digest": "sha256_digest",
|
18
|
+
}
|
19
|
+
|
20
|
+
|
21
|
+
def test_download_ion_channel_model(
|
22
|
+
tmp_path,
|
23
|
+
client,
|
24
|
+
httpx_mock,
|
25
|
+
api_url,
|
26
|
+
request_headers,
|
27
|
+
):
|
28
|
+
"""Test downloading an ion channel model file from an EModel entity."""
|
29
|
+
model_id = uuid.uuid4()
|
30
|
+
asset_id = uuid.uuid4()
|
31
|
+
hierarchy_id = uuid.uuid4()
|
32
|
+
|
33
|
+
httpx_mock.add_response(
|
34
|
+
method="GET",
|
35
|
+
url=f"{api_url}/ion-channel-model/{model_id}/assets/{asset_id}",
|
36
|
+
match_headers=request_headers,
|
37
|
+
json=_mock_asset_response(asset_id) | {"path": "foo.mod"},
|
38
|
+
)
|
39
|
+
httpx_mock.add_response(
|
40
|
+
method="GET",
|
41
|
+
url=f"{api_url}/ion-channel-model/{model_id}/assets/{asset_id}/download",
|
42
|
+
match_headers=request_headers,
|
43
|
+
content="foo",
|
44
|
+
)
|
45
|
+
|
46
|
+
ic_model = IonChannelModel(
|
47
|
+
id=model_id,
|
48
|
+
name="foo",
|
49
|
+
nmodl_suffix="Ca_HVA",
|
50
|
+
description="foo description",
|
51
|
+
species={"name": "foo", "taxonomy_id": "bar"},
|
52
|
+
brain_region={
|
53
|
+
"name": "foo",
|
54
|
+
"annotation_value": 997,
|
55
|
+
"acronym": "bar",
|
56
|
+
"parent_structure_id": None,
|
57
|
+
"hierarchy_id": str(hierarchy_id),
|
58
|
+
"color_hex_triplet": "#FFFFFF",
|
59
|
+
},
|
60
|
+
is_temperature_dependent=False,
|
61
|
+
temperature_celsius=34,
|
62
|
+
neuron_block=NeuronBlock(),
|
63
|
+
assets=[_mock_asset_response(asset_id)],
|
64
|
+
)
|
65
|
+
|
66
|
+
output_path = download_ion_channel_mechanism(
|
67
|
+
client=client,
|
68
|
+
ion_channel_model=ic_model,
|
69
|
+
output_dir=tmp_path,
|
70
|
+
)
|
71
|
+
|
72
|
+
assert output_path.is_file()
|
@@ -0,0 +1,199 @@
|
|
1
|
+
import os
|
2
|
+
import uuid
|
3
|
+
|
4
|
+
from entitysdk.downloaders.memodel import download_memodel
|
5
|
+
from entitysdk.models.emodel import EModel
|
6
|
+
from entitysdk.models.memodel import MEModel
|
7
|
+
from entitysdk.models.morphology import ReconstructionMorphology
|
8
|
+
from entitysdk.types import ValidationStatus
|
9
|
+
|
10
|
+
|
11
|
+
def _mock_morph_asset_response(asset_id):
|
12
|
+
"""Mock response for morphology asset."""
|
13
|
+
return {
|
14
|
+
"id": str(asset_id),
|
15
|
+
"path": "foo.asc",
|
16
|
+
"full_path": "foo.asc",
|
17
|
+
"is_directory": False,
|
18
|
+
"content_type": "application/asc",
|
19
|
+
"size": 100,
|
20
|
+
"status": "created",
|
21
|
+
"meta": {},
|
22
|
+
"sha256_digest": "sha256_digest",
|
23
|
+
}
|
24
|
+
|
25
|
+
|
26
|
+
def _mock_ic_asset_response(asset_id):
|
27
|
+
"""Mock response for ion channel model asset."""
|
28
|
+
return {
|
29
|
+
"id": str(asset_id),
|
30
|
+
"path": "foo.mod",
|
31
|
+
"full_path": "foo.mod",
|
32
|
+
"is_directory": False,
|
33
|
+
"content_type": "application/neuron-mod",
|
34
|
+
"size": 100,
|
35
|
+
"status": "created",
|
36
|
+
"meta": {},
|
37
|
+
"sha256_digest": "sha256_digest",
|
38
|
+
}
|
39
|
+
|
40
|
+
|
41
|
+
def _mock_emodel_asset_response(asset_id):
|
42
|
+
"""Mock response for emodel asset."""
|
43
|
+
return {
|
44
|
+
"id": str(asset_id),
|
45
|
+
"path": "foo.hoc",
|
46
|
+
"full_path": "foo.hoc",
|
47
|
+
"is_directory": False,
|
48
|
+
"content_type": "application/hoc",
|
49
|
+
"size": 100,
|
50
|
+
"status": "created",
|
51
|
+
"meta": {},
|
52
|
+
"sha256_digest": "sha256_digest",
|
53
|
+
}
|
54
|
+
|
55
|
+
|
56
|
+
def test_download_memodel(
|
57
|
+
tmp_path,
|
58
|
+
client,
|
59
|
+
httpx_mock,
|
60
|
+
api_url,
|
61
|
+
request_headers,
|
62
|
+
):
|
63
|
+
"""Test downloading all memodel-related files from an MEModel entity."""
|
64
|
+
memodel_id = uuid.uuid4()
|
65
|
+
morph_id = uuid.uuid4()
|
66
|
+
emodel_id = uuid.uuid4()
|
67
|
+
ic_model_id = uuid.uuid4()
|
68
|
+
morph_asset_id = uuid.uuid4()
|
69
|
+
emodel_asset_id = uuid.uuid4()
|
70
|
+
ic_asset_id = uuid.uuid4()
|
71
|
+
hierarchy_id = uuid.uuid4()
|
72
|
+
|
73
|
+
httpx_mock.add_response(
|
74
|
+
method="GET",
|
75
|
+
url=f"{api_url}/reconstruction-morphology/{morph_id}/assets/{morph_asset_id}",
|
76
|
+
match_headers=request_headers,
|
77
|
+
json=_mock_morph_asset_response(morph_id) | {"path": "foo.asc"},
|
78
|
+
)
|
79
|
+
httpx_mock.add_response(
|
80
|
+
method="GET",
|
81
|
+
url=f"{api_url}/reconstruction-morphology/{morph_id}/assets/{morph_asset_id}/download",
|
82
|
+
match_headers=request_headers,
|
83
|
+
content="foo",
|
84
|
+
)
|
85
|
+
httpx_mock.add_response(
|
86
|
+
method="GET",
|
87
|
+
url=f"{api_url}/emodel/{emodel_id}/assets/{emodel_asset_id}",
|
88
|
+
match_headers=request_headers,
|
89
|
+
json=_mock_emodel_asset_response(emodel_asset_id) | {"path": "foo.hoc"},
|
90
|
+
)
|
91
|
+
httpx_mock.add_response(
|
92
|
+
method="GET",
|
93
|
+
url=f"{api_url}/emodel/{emodel_id}/assets/{emodel_asset_id}/download",
|
94
|
+
match_headers=request_headers,
|
95
|
+
content="foo",
|
96
|
+
)
|
97
|
+
httpx_mock.add_response(
|
98
|
+
method="GET",
|
99
|
+
url=f"{api_url}/ion-channel-model/{ic_model_id}/assets/{ic_asset_id}",
|
100
|
+
match_headers=request_headers,
|
101
|
+
json=_mock_ic_asset_response(ic_asset_id) | {"path": "foo.mod"},
|
102
|
+
)
|
103
|
+
httpx_mock.add_response(
|
104
|
+
method="GET",
|
105
|
+
url=f"{api_url}/ion-channel-model/{ic_model_id}/assets/{ic_asset_id}/download",
|
106
|
+
match_headers=request_headers,
|
107
|
+
content="foo",
|
108
|
+
)
|
109
|
+
|
110
|
+
httpx_mock.add_response(
|
111
|
+
method="GET",
|
112
|
+
url=f"{api_url}/emodel/{emodel_id}",
|
113
|
+
match_headers=request_headers,
|
114
|
+
json={
|
115
|
+
"id": str(emodel_id),
|
116
|
+
"name": "foo",
|
117
|
+
"species": {"name": "foo", "taxonomy_id": "bar"},
|
118
|
+
"brain_region": {
|
119
|
+
"name": "foo",
|
120
|
+
"annotation_value": 997,
|
121
|
+
"acronym": "bar",
|
122
|
+
"parent_structure_id": None,
|
123
|
+
"hierarchy_id": str(hierarchy_id),
|
124
|
+
"color_hex_triplet": "#FFFFFF",
|
125
|
+
},
|
126
|
+
"iteration": "foofoo",
|
127
|
+
"score": 42,
|
128
|
+
"seed": 0,
|
129
|
+
"ion_channel_models": [
|
130
|
+
{
|
131
|
+
"id": str(ic_model_id),
|
132
|
+
"name": "foo",
|
133
|
+
"nmodl_suffix": "Ca_HVA",
|
134
|
+
"description": "foo description",
|
135
|
+
"species": {"name": "foo", "taxonomy_id": "bar"},
|
136
|
+
"brain_region": {
|
137
|
+
"name": "foo",
|
138
|
+
"annotation_value": 997,
|
139
|
+
"acronym": "bar",
|
140
|
+
"parent_structure_id": None,
|
141
|
+
"hierarchy_id": str(hierarchy_id),
|
142
|
+
"color_hex_triplet": "#FFFFFF",
|
143
|
+
},
|
144
|
+
"is_temperature_dependent": False,
|
145
|
+
"temperature_celsius": 34,
|
146
|
+
"neuron_block": {},
|
147
|
+
"assets": [_mock_ic_asset_response(ic_asset_id)],
|
148
|
+
}
|
149
|
+
],
|
150
|
+
"assets": [_mock_emodel_asset_response(emodel_asset_id)],
|
151
|
+
},
|
152
|
+
)
|
153
|
+
|
154
|
+
memodel = MEModel(
|
155
|
+
id=memodel_id,
|
156
|
+
name="foo",
|
157
|
+
species={"name": "foo", "taxonomy_id": "bar"},
|
158
|
+
brain_region={
|
159
|
+
"name": "foo",
|
160
|
+
"annotation_value": 997,
|
161
|
+
"acronym": "bar",
|
162
|
+
"parent_structure_id": None,
|
163
|
+
"hierarchy_id": str(hierarchy_id),
|
164
|
+
"color_hex_triplet": "#FFFFFF",
|
165
|
+
},
|
166
|
+
validation_status=ValidationStatus.done,
|
167
|
+
morphology=ReconstructionMorphology(
|
168
|
+
id=morph_id, name="foo", assets=[_mock_morph_asset_response(morph_asset_id)]
|
169
|
+
),
|
170
|
+
emodel=EModel(
|
171
|
+
id=emodel_id,
|
172
|
+
name="foo",
|
173
|
+
species={"name": "foo", "taxonomy_id": "bar"},
|
174
|
+
brain_region={
|
175
|
+
"name": "foo",
|
176
|
+
"annotation_value": 997,
|
177
|
+
"acronym": "bar",
|
178
|
+
"parent_structure_id": None,
|
179
|
+
"hierarchy_id": str(hierarchy_id),
|
180
|
+
"color_hex_triplet": "#FFFFFF",
|
181
|
+
},
|
182
|
+
iteration="foofoo",
|
183
|
+
score=42,
|
184
|
+
seed=0,
|
185
|
+
# assets=[
|
186
|
+
# _mock_emodel_asset_response(emodel_asset_id)
|
187
|
+
# ]
|
188
|
+
),
|
189
|
+
)
|
190
|
+
|
191
|
+
downloaded_memodel = download_memodel(
|
192
|
+
client=client,
|
193
|
+
memodel=memodel,
|
194
|
+
output_dir=tmp_path,
|
195
|
+
)
|
196
|
+
assert downloaded_memodel.hoc_path.is_file()
|
197
|
+
assert downloaded_memodel.morphology_path.is_file()
|
198
|
+
assert downloaded_memodel.mechanisms_dir.is_dir()
|
199
|
+
assert len(os.listdir(downloaded_memodel.mechanisms_dir)) == 1
|
@@ -0,0 +1,68 @@
|
|
1
|
+
import uuid
|
2
|
+
|
3
|
+
import pytest
|
4
|
+
|
5
|
+
from entitysdk.downloaders.morphology import download_morphology
|
6
|
+
from entitysdk.exception import IteratorResultError
|
7
|
+
from entitysdk.models.morphology import ReconstructionMorphology
|
8
|
+
|
9
|
+
|
10
|
+
def _mock_asset_response(asset_id):
|
11
|
+
return {
|
12
|
+
"id": str(asset_id),
|
13
|
+
"path": "foo.asc",
|
14
|
+
"full_path": "foo.asc",
|
15
|
+
"is_directory": False,
|
16
|
+
"content_type": "application/asc",
|
17
|
+
"size": 100,
|
18
|
+
"status": "created",
|
19
|
+
"meta": {},
|
20
|
+
"sha256_digest": "sha256_digest",
|
21
|
+
}
|
22
|
+
|
23
|
+
|
24
|
+
def test_download_morphology(
|
25
|
+
tmp_path,
|
26
|
+
client,
|
27
|
+
httpx_mock,
|
28
|
+
api_url,
|
29
|
+
request_headers,
|
30
|
+
):
|
31
|
+
"""Test downloading a morphology file from a Morphology entity."""
|
32
|
+
morph_id = uuid.uuid4()
|
33
|
+
asset_id = uuid.uuid4()
|
34
|
+
|
35
|
+
httpx_mock.add_response(
|
36
|
+
method="GET",
|
37
|
+
url=f"{api_url}/reconstruction-morphology/{morph_id}/assets/{asset_id}",
|
38
|
+
match_headers=request_headers,
|
39
|
+
json=_mock_asset_response(asset_id) | {"path": "foo.asc"},
|
40
|
+
)
|
41
|
+
httpx_mock.add_response(
|
42
|
+
method="GET",
|
43
|
+
url=f"{api_url}/reconstruction-morphology/{morph_id}/assets/{asset_id}/download",
|
44
|
+
match_headers=request_headers,
|
45
|
+
content="foo",
|
46
|
+
)
|
47
|
+
|
48
|
+
morphology = ReconstructionMorphology(
|
49
|
+
id=morph_id, name="foo", assets=[_mock_asset_response(asset_id)]
|
50
|
+
)
|
51
|
+
|
52
|
+
output_path = download_morphology(
|
53
|
+
client=client,
|
54
|
+
morphology=morphology,
|
55
|
+
output_dir=tmp_path,
|
56
|
+
file_type="asc",
|
57
|
+
)
|
58
|
+
|
59
|
+
assert output_path.is_file()
|
60
|
+
|
61
|
+
# should raise when the file type is not present in the morphology assets
|
62
|
+
with pytest.raises(IteratorResultError, match="Iterable is empty."):
|
63
|
+
output_path = download_morphology(
|
64
|
+
client=client,
|
65
|
+
morphology=morphology,
|
66
|
+
output_dir=tmp_path,
|
67
|
+
file_type="swc",
|
68
|
+
)
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|