Skip to content

Commit 2e40260

Browse files
authored
Merge pull request #436 from AllenNeuralDynamics/test-launcher
Upgrade aind-clabe to v0.8.0 and refactor launcher script
2 parents 8f16ad5 + 5ce89f8 commit 2e40260

File tree

13 files changed

+125
-203
lines changed

13 files changed

+125
-203
lines changed

.github/workflows/vr-foraging-cicd.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,9 @@ jobs:
303303
uses: actions/checkout@v5
304304

305305
- name: Install uv
306-
uses: astral-sh/setup-uv@v3
306+
uses: astral-sh/setup-uv@v6
307+
with:
308+
enable-cache: true
307309

308310
- name: Setup Graphviz
309311
uses: ts-graphviz/setup-graphviz@v2

docs/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,5 +90,5 @@ def export_model_diagram(model: BaseModel, root: str = _static_path) -> None:
9090

9191
# -- Dataset rendering
9292

93-
with open(f"{_static_path}/dataset.txt", "w", encoding="utf-8") as f:
93+
with open(f"{_static_path}/dataset.html", "w", encoding="utf-8") as f:
9494
f.write(contract.render_dataset())

docs/dataset.rst

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
Data Contract
22
-------------
33

4-
.. literalinclude:: /_static/dataset.txt
5-
:language: text
6-
:caption: Dataset
4+
.. raw:: html
5+
6+
<iframe
7+
src="_static/dataset.html"
8+
style="width:100%; height:600px; border:none; border-radius:8px; box-shadow:0 2px 4px rgba(0,0,0,0.1);"
9+
title="Data Contract visualization">
10+
</iframe>

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ Changelog = "https://github.com/AllenNeuralDynamics/Aind.Behavior.VrForaging/rel
3131
data = ["contraqctor<0.6.0"]
3232

3333
launcher = [
34-
"aind-clabe[aind-services]>=0.7",
34+
"aind-clabe[aind-services] >= 0.8.0 ,<0.9.0",
3535
"aind-data-schema>=2",
3636
"aind_behavior_vr_foraging[data]",
3737
]

src/aind_behavior_vr_foraging/data_contract/__init__.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ def dataset(path: os.PathLike, version: str = __semver__) -> contraqctor.contrac
4141

4242
def render_dataset(version: str = __semver__) -> str:
4343
"""Renders the dataset as a tree-like structure for visualization."""
44-
from contraqctor.contract.utils import print_data_stream_tree
44+
from contraqctor.contract.utils import print_data_stream_tree_html
4545

4646
dataset_constructor = _dataset_lookup_helper(version)
47-
return print_data_stream_tree(dataset_constructor(Path("<RootPath>")), show_missing_indicator=False, show_type=True)
47+
return print_data_stream_tree_html(
48+
dataset_constructor(Path("<RootPath>")), show_missing_indicator=False, show_type=True
49+
)

src/aind_behavior_vr_foraging/data_mappers/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ def cli_cmd(self):
4646

4747
repo = Repo(self.repo_path)
4848
session_mapped = AindSessionDataMapper(
49-
session_model=session,
50-
rig_model=rig,
49+
session=session,
50+
rig=rig,
5151
task_logic_model=task_logic,
5252
repository=repo,
5353
script_path=Path("./src/main.bonsai"),

src/aind_behavior_vr_foraging/data_mappers/_rig.py

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import platform
55
from decimal import Decimal
66
from pathlib import Path
7-
from typing import Any, Callable, Optional, cast
7+
from typing import Optional, cast
88

99
import aind_behavior_services.rig as AbsRig
1010
from aind_behavior_services import calibration as AbsCalibration
@@ -14,7 +14,6 @@
1414
from aind_data_schema_models import coordinates as aind_schema_model_coordinates
1515
from aind_data_schema_models import modalities, units
1616
from clabe.data_mapper import aind_data_schema as ads
17-
from clabe.launcher import Launcher
1817

1918
from aind_behavior_vr_foraging.rig import AindVrForagingRig
2019

@@ -45,10 +44,10 @@ def get_spawned_device(self, name: str) -> devices.Device:
4544
class AindRigDataMapper(ads.AindDataSchemaRigDataMapper):
4645
def __init__(
4746
self,
48-
rig_model: AindVrForagingRig,
47+
rig: AindVrForagingRig,
4948
):
5049
super().__init__()
51-
self.rig_model = rig_model
50+
self.rig_model = rig
5251
self._mapped: Optional[instrument.Instrument] = None
5352

5453
def rig_schema(self):
@@ -75,17 +74,6 @@ def mapped(self) -> instrument.Instrument:
7574
def is_mapped(self) -> bool:
7675
return self.mapped is not None
7776

78-
@classmethod
79-
def build_runner(cls) -> Callable[[Launcher[AindVrForagingRig, Any, Any]], "AindRigDataMapper"]:
80-
def _new(
81-
launcher: Launcher[AindVrForagingRig, Any, Any],
82-
) -> "AindRigDataMapper":
83-
new = cls(rig_model=launcher.get_rig(strict=True))
84-
new.map()
85-
return new
86-
87-
return _new
88-
8977
## From here on, private methods only!
9078
## Lasciate ogne speranza, voi ch'entrate
9179

src/aind_behavior_vr_foraging/data_mappers/_session.py

Lines changed: 10 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import os
44
import sys
55
from pathlib import Path
6-
from typing import Callable, Dict, List, Optional, Union
6+
from typing import List, Optional, Union
77

88
import aind_behavior_services.rig as AbsRig
99
import git
@@ -17,7 +17,6 @@
1717
from clabe.apps import CurriculumSuggestion
1818
from clabe.data_mapper import aind_data_schema as ads
1919
from clabe.data_mapper import helpers as data_mapper_helpers
20-
from clabe.launcher import Launcher
2120

2221
from aind_behavior_vr_foraging.rig import AindVrForagingRig
2322
from aind_behavior_vr_foraging.task_logic import AindVrForagingTaskLogic
@@ -30,24 +29,22 @@
3029
class AindSessionDataMapper(ads.AindDataSchemaSessionDataMapper):
3130
def __init__(
3231
self,
33-
session_model: AindBehaviorSessionModel,
34-
rig_model: AindVrForagingRig,
35-
task_logic_model: AindVrForagingTaskLogic,
32+
session: AindBehaviorSessionModel,
33+
rig: AindVrForagingRig,
34+
task_logic: AindVrForagingTaskLogic,
3635
repository: Union[os.PathLike, git.Repo] = Path("."),
3736
script_path: os.PathLike = Path("./src/main.bonsai"),
3837
session_end_time: Optional[datetime.datetime] = None,
3938
curriculum_suggestion: Optional[CurriculumSuggestion] = None,
40-
output_parameters: Optional[Dict] = None,
4139
):
42-
self.session_model = session_model
43-
self.rig_model = rig_model
44-
self.task_logic_model = task_logic_model
40+
self.session_model = session
41+
self.rig_model = rig
42+
self.task_logic_model = task_logic
4543
self.repository = repository
4644
if isinstance(self.repository, os.PathLike | str):
4745
self.repository = git.Repo(Path(self.repository))
4846
self.script_path = script_path
4947
self._session_end_time = session_end_time
50-
self.output_parameters = output_parameters
5148
self._mapped: Optional[acquisition.Acquisition] = None
5249
self.curriculum = curriculum_suggestion
5350

@@ -60,28 +57,6 @@ def session_end_time(self) -> datetime.datetime:
6057
def session_schema(self):
6158
return self.mapped
6259

63-
@classmethod
64-
def build_runner(
65-
cls,
66-
curriculum_suggestion: Optional[Callable[[], CurriculumSuggestion | None]] = None,
67-
) -> Callable[
68-
[Launcher[AindVrForagingRig, AindBehaviorSessionModel, AindVrForagingTaskLogic]], "AindSessionDataMapper"
69-
]:
70-
def _new(
71-
launcher: Launcher[AindVrForagingRig, AindBehaviorSessionModel, AindVrForagingTaskLogic],
72-
) -> "AindSessionDataMapper":
73-
new = cls(
74-
session_model=launcher.get_session(strict=True),
75-
rig_model=launcher.get_rig(strict=True),
76-
task_logic_model=launcher.get_task_logic(strict=True),
77-
repository=launcher.repository,
78-
curriculum_suggestion=curriculum_suggestion() if curriculum_suggestion is not None else None,
79-
)
80-
new.map()
81-
return new
82-
83-
return _new
84-
8560
@property
8661
def session_name(self) -> str:
8762
if self.session_model.session_name is None:
@@ -97,7 +72,7 @@ def mapped(self) -> acquisition.Acquisition:
9772
def is_mapped(self) -> bool:
9873
return self.mapped is not None
9974

100-
def map(self) -> Optional[acquisition.Acquisition]:
75+
def map(self) -> acquisition.Acquisition:
10176
logger.info("Mapping aind-data-schema Session.")
10277
try:
10378
self._mapped = self._map()
@@ -120,7 +95,7 @@ def _map(self) -> acquisition.Acquisition:
12095
acquisition_end_time=utcnow(),
12196
acquisition_start_time=self.session_model.date,
12297
experimenters=self.session_model.experimenter,
123-
acquisition_type=self.session_model.experiment,
98+
acquisition_type=self.session_model.experiment or self.task_logic_model.name,
12499
coordinate_system=_make_origin_coordinate_system(),
125100
data_streams=self._get_data_streams(),
126101
calibrations=self._get_calibrations(),
@@ -245,7 +220,7 @@ def _get_stimulus_epochs(self) -> List[acquisition.StimulusEpoch]:
245220
stimulus_start_time=self.session_model.date,
246221
stimulus_end_time=self.session_end_time,
247222
configurations=stimulus_epoch_configurations,
248-
stimulus_name=self.session_model.experiment,
223+
stimulus_name=self.session_model.experiment or self.task_logic_model.name,
249224
stimulus_modalities=stimulus_modalities,
250225
performance_metrics=performance_metrics,
251226
curriculum_status=curriculum_status,

src/aind_behavior_vr_foraging/data_mappers/_utils.py

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,16 @@
11
import enum
22
import logging
3-
from pathlib import Path
4-
from typing import TYPE_CHECKING, Any, Callable, List, Optional, Type, TypeVar, Union
3+
from typing import List, Optional, Type, TypeVar, Union
54

65
import aind_behavior_services.calibration as AbsCalibration
76
import pydantic
87
from aind_behavior_services.utils import get_fields_of_type, utcnow
98
from aind_data_schema.components import coordinates, measurements
109
from aind_data_schema.core import acquisition
1110
from aind_data_schema_models import units
12-
from clabe.launcher import Launcher, Promise
1311

1412
from aind_behavior_vr_foraging.rig import AindVrForagingRig
1513

16-
if TYPE_CHECKING:
17-
from ._rig import AindRigDataMapper
18-
from ._session import AindSessionDataMapper
19-
else:
20-
AindRigDataMapper = AindSessionDataMapper = Any
21-
2214
TTo = TypeVar("TTo", bound=pydantic.BaseModel)
2315

2416
T = TypeVar("T")
@@ -38,22 +30,6 @@ def coerce_to_aind_data_schema(value: Union[pydantic.BaseModel, dict], target_ty
3830
return target_type(**_normalized_input)
3931

4032

41-
def write_ads_mappers(
42-
session_mapper: Promise[[Launcher], AindSessionDataMapper], rig_mapper: Promise[[Launcher], AindRigDataMapper]
43-
) -> Callable[[Launcher], None]:
44-
def _run(launcher: Launcher) -> None:
45-
session_directory = launcher.session_directory
46-
_session = session_mapper.result.mapped
47-
_rig = rig_mapper.result.mapped
48-
_session.instrument_id = _rig.instrument_id
49-
logger.info("Writing session.json to %s", session_directory)
50-
_session.write_standard_file(Path(session_directory))
51-
logger.info("Writing rig.json to %s", session_directory)
52-
_rig.write_standard_file(Path(session_directory))
53-
54-
return _run
55-
56-
5733
def _get_water_calibration(rig_model: AindVrForagingRig) -> List[measurements.VolumeCalibration]:
5834
def _mapper(
5935
device_name: Optional[str], water_calibration: AbsCalibration.water_valve.WaterValveCalibration

0 commit comments

Comments
 (0)