Skip to content

Commit

Permalink
feat(robot-server): add runTimeParameters field to analysis response (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
sanni-t authored Mar 13, 2024
1 parent d5095bb commit 7382daf
Show file tree
Hide file tree
Showing 13 changed files with 108 additions and 2 deletions.
5 changes: 5 additions & 0 deletions api/src/opentrons/cli/analyze.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from typing import Any, Dict, List, Optional, Sequence, Union
from typing_extensions import Literal

from opentrons.protocol_engine.types import RunTimeParameter
from opentrons.protocols.api_support.types import APIVersion
from opentrons.protocol_reader import (
ProtocolReader,
Expand Down Expand Up @@ -99,6 +100,9 @@ async def _analyze(
),
metadata=protocol_source.metadata,
robotType=protocol_source.robot_type,
# TODO(spp, 2024-03-12): update this once protocol reader/ runner can parse
# and report the runTimeParameters
runTimeParameters=[],
commands=analysis.commands,
errors=analysis.state_summary.errors,
labware=analysis.state_summary.labware,
Expand Down Expand Up @@ -156,6 +160,7 @@ class AnalyzeResults(BaseModel):

# Fields that should match robot-server:
robotType: RobotType
runTimeParameters: List[RunTimeParameter]
commands: List[Command]
labware: List[LoadedLabware]
pipettes: List[LoadedPipette]
Expand Down
64 changes: 64 additions & 0 deletions api/src/opentrons/protocol_engine/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -837,3 +837,67 @@ def from_hw_state(cls, state: HwTipStateType) -> "TipPresenceStatus":
HwTipStateType.PRESENT: TipPresenceStatus.PRESENT,
HwTipStateType.ABSENT: TipPresenceStatus.ABSENT,
}[state]


class RTPBase(BaseModel):
"""Parameters defined in a protocol."""

displayName: str = Field(..., description="Display string for the parameter.")
variableName: str = Field(..., description="Python variable name of the parameter.")
description: str = Field(..., description="Detailed description of the parameter.")
suffix: Optional[str] = Field(
None,
description="Units (like mL, mm/sec, etc) or a custom suffix for the parameter.",
)


class IntParameter(RTPBase):
"""An integer parameter defined in a protocol."""

min: int = Field(
..., description="Minimum value that the integer param is allowed to have."
)
max: int = Field(
..., description="Maximum value that the integer param is allowed to have."
)
default: int = Field(
...,
description="Default value of the parameter, to be used when there is no client-specified value.",
)


class FloatParameter(RTPBase):
"""A float parameter defined in a protocol."""

min: float = Field(
..., description="Minimum value that the float param is allowed to have."
)
max: float = Field(
..., description="Maximum value that the float param is allowed to have."
)
default: float = Field(
...,
description="Default value of the parameter, to be used when there is no client-specified value.",
)


class EnumChoice(BaseModel):
"""Components of choices used in RTP Enum Parameters."""

displayName: str = Field(..., description="Display string for the param's choice.")
value: str = Field(..., description="Enum value of the param's choice.")


class EnumParameter(RTPBase):
"""A string enum defined in a protocol."""

choices: List[EnumChoice] = Field(
..., description="List of valid choices for this parameter."
)
default: str = Field(
...,
description="Default value of the parameter, to be used when there is no client-specified value.",
)


RunTimeParameter = Union[IntParameter, FloatParameter, EnumParameter]
12 changes: 12 additions & 0 deletions robot-server/robot_server/protocols/analysis_models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
"""Response models for protocol analysis."""
# TODO(mc, 2021-08-25): add modules to simulation result
from enum import Enum

from opentrons.protocol_engine.types import RunTimeParameter
from opentrons_shared_data.robot.dev_types import RobotType
from pydantic import BaseModel, Field
from typing import List, Optional, Union
Expand Down Expand Up @@ -102,6 +104,16 @@ class CompletedAnalysis(BaseModel):
" in analyses that were originally created on older versions."
),
)
runTimeParameters: List[RunTimeParameter] = Field(
default_factory=list,
description=(
"Run time parameters used during analysis."
" These are the parameters that are defined in the protocol, with values"
" specified either in the protocol creation request or reanalysis request"
" (whichever started this analysis), or default values from the protocol"
" if none are specified in the request."
),
)
commands: List[Command] = Field(
...,
description="The protocol commands the run is expected to produce",
Expand Down
5 changes: 5 additions & 0 deletions robot-server/robot_server/protocols/analysis_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

from logging import getLogger
from typing import Dict, List, Optional

from opentrons.protocol_engine.types import RunTimeParameter
from typing_extensions import Final
from opentrons_shared_data.robot.dev_types import RobotType

Expand Down Expand Up @@ -122,6 +124,7 @@ async def update(
self,
analysis_id: str,
robot_type: RobotType,
run_time_parameters: List[RunTimeParameter],
commands: List[Command],
labware: List[LoadedLabware],
modules: List[LoadedModule],
Expand All @@ -135,6 +138,7 @@ async def update(
analysis_id: The ID of the analysis to promote.
Must point to a valid pending analysis.
robot_type: See `CompletedAnalysis.robotType`.
run_time_parameters: See `CompletedAnalysis.runTimeParameters`.
commands: See `CompletedAnalysis.commands`.
labware: See `CompletedAnalysis.labware`.
modules: See `CompletedAnalysis.modules`.
Expand All @@ -161,6 +165,7 @@ async def update(
result=result,
robotType=robot_type,
status=AnalysisStatus.COMPLETED,
runTimeParameters=run_time_parameters,
commands=commands,
labware=labware,
modules=modules,
Expand Down
6 changes: 6 additions & 0 deletions robot-server/robot_server/protocols/protocol_analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ async def analyze(
await self._analysis_store.update(
analysis_id=analysis_id,
robot_type=protocol_resource.source.robot_type,
# TODO (spp, 2024-03-12): populate the RTP field if we decide to have
# parameter parsing and validation in protocol reader itself.
run_time_parameters=[],
commands=[],
labware=[],
modules=[],
Expand All @@ -64,6 +67,9 @@ async def analyze(
await self._analysis_store.update(
analysis_id=analysis_id,
robot_type=protocol_resource.source.robot_type,
# TODO(spp, 2024-03-12): update this once protocol reader/ runner can parse
# and report the runTimeParameters
run_time_parameters=[],
commands=result.commands,
labware=result.state_summary.labware,
modules=result.state_summary.modules,
Expand Down
5 changes: 4 additions & 1 deletion robot-server/robot_server/protocols/protocol_models.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Protocol file models."""
from datetime import datetime
from pydantic import BaseModel, Extra, Field
from typing import Any, List, Optional
from typing import Any, List, Optional, Dict, Union

from opentrons.protocol_reader import (
ProtocolType as ProtocolType,
Expand Down Expand Up @@ -109,3 +109,6 @@ class Protocol(ResourceModel):
" See `POST /protocols`."
),
)


RunTimeParameterDict = Dict[str, Union[str, int, float, bool]]
1 change: 1 addition & 0 deletions robot-server/robot_server/protocols/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ async def create_protocol(
)

try:
# Can make the passed in RTPs as part of protocolSource returned here
source = await protocol_reader.save(
files=buffered_files,
directory=protocol_directory / protocol_id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ stages:
status: completed
result: ok
robotType: OT-2 Standard
runTimeParameters: []
pipettes:
- id: pipetteId
pipetteName: p10_single
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ stages:
status: completed
result: ok
robotType: OT-3 Standard
runTimeParameters: []
pipettes:
- id: pipetteId
pipetteName: p1000_96
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ stages:
status: completed
result: ok
robotType: OT-2 Standard
runTimeParameters: []
pipettes:
- id: pipetteId
pipetteName: p10_single
Expand Down
5 changes: 5 additions & 0 deletions robot-server/tests/protocols/test_analysis_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ async def test_returned_in_order_added(
await subject.update(
analysis_id=analysis_id,
robot_type="OT-2 Standard",
run_time_parameters=[],
labware=[],
modules=[],
pipettes=[],
Expand Down Expand Up @@ -175,6 +176,7 @@ async def test_update_adds_details_and_completes_analysis(
await subject.update(
analysis_id="analysis-id",
robot_type="OT-2 Standard",
run_time_parameters=[],
labware=[labware],
pipettes=[pipette],
# TODO(mm, 2022-10-21): Give the subject some commands, errors, and liquids here
Expand All @@ -193,6 +195,7 @@ async def test_update_adds_details_and_completes_analysis(
status=AnalysisStatus.COMPLETED,
result=AnalysisResult.OK,
robotType="OT-2 Standard",
runTimeParameters=[],
labware=[labware],
pipettes=[pipette],
modules=[],
Expand All @@ -206,6 +209,7 @@ async def test_update_adds_details_and_completes_analysis(
"result": "ok",
"status": "completed",
"robotType": "OT-2 Standard",
"runTimeParameters": [],
"labware": [
{
"id": "labware-id",
Expand Down Expand Up @@ -276,6 +280,7 @@ async def test_update_infers_status_from_errors(
await subject.update(
analysis_id="analysis-id",
robot_type="OT-2 Standard",
run_time_parameters=[],
commands=commands,
errors=errors,
labware=[],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,13 +159,13 @@ async def test_get_by_analysis_id_as_document(
"id": "analysis-id",
"result": "ok",
"status": "completed",
"runTimeParameters": [],
"commands": [],
"errors": [],
"labware": [],
"liquids": [],
"modules": [],
"pipettes": [],
"result": "ok",
}


Expand Down
2 changes: 2 additions & 0 deletions robot-server/tests/protocols/test_protocol_analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ async def test_analyze(
await analysis_store.update(
analysis_id="analysis-id",
robot_type=robot_type,
run_time_parameters=[],
commands=[analysis_command],
labware=[analysis_labware],
modules=[],
Expand Down Expand Up @@ -237,6 +238,7 @@ async def test_analyze_updates_pending_on_error(
await analysis_store.update(
analysis_id="analysis-id",
robot_type=robot_type,
run_time_parameters=[],
commands=[],
labware=[],
modules=[],
Expand Down

0 comments on commit 7382daf

Please sign in to comment.