Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(api, robot-server): set sent runtime values and report parameters in analysis #14735

Merged
merged 14 commits into from
Mar 28, 2024

Conversation

jbleon95
Copy link
Contributor

@jbleon95 jbleon95 commented Mar 26, 2024

Overview

Completes the analysis portion of AUTH-222.

This PR hooks up the runtime parameter API code to setting sent override values as well as reporting the parameters in the analysis summary, using the Pydantic models created in #14638 and #14718.

To report the parameters in analysis, a new method was added to the definitions to convert them into the Pydantic models. This method can then be used by the ParameterContext to get a list of all defined definitions. In order to have access to these after run execution, the ProtocolRunner was refactored to own this class so we can have access to it after the parameters are parsed and validated.

A method to set the parameters was also added and hooked up to excute and run_python, which will validate and set all sent parameters to be used in the protocol, for both analysis and execution.

Test Plan

Used this protocol and checked the analysis result to make sure all parameters were being properly reported.

metadata = {
    'protocolName': 'Parameter Analysis Reporting Test',
}

requirements = {
    "robotType": "Flex",
    "apiLevel": "2.18"
}


def add_parameters(parameters):
    parameters.add_int(
        display_name="Sample count",
        variable_name="sample_count",
        default=6,
        minimum=1,
        maximum=12,
        description="How many samples to process."
    )
    parameters.add_float(
        display_name="Pipette volume",
        variable_name="volume",
        default=20.1,
        choices=[
            {"display_name": "Low Volume", "value": 10.23},
            {"display_name": "Medium Volume", "value": 20.1},
            {"display_name": "High Volume", "value": 50.5},
        ],
        description="How many microliters to pipette of each sample.",
        unit="µL"
    )
    parameters.add_bool(
        display_name="Dry Run",
        variable_name="dry_run",
        default=False,
        description="Skip aspirate and dispense steps."
    )
    parameters.add_str(
        display_name="Pipette Name",
        variable_name="pipette",
        choices=[
            {"display_name": "Single channel 50µL", "value": "flex_1channel_50"},
            {"display_name": "Eight Channel 50µL", "value": "flex_8channel_50"},
        ],
        default="flex_1channel_50",
        description="What pipette to use during the protocol.",
    )



def run(context):
    trash_bin = context.load_trash_bin('A3')
    tip_rack = context.load_labware('opentrons_flex_96_tiprack_50ul', 'D2')
    source = context.load_labware('opentrons_96_wellplate_200ul_pcr_full_skirt', 'C1')
    destination = context.load_labware('opentrons_96_wellplate_200ul_pcr_full_skirt', 'C3')

    pipette = context.load_instrument(context.params.pipette, mount="left", tip_racks=[tip_rack])

    for i in range(context.params.sample_count):
        source_well = source.wells()[i]
        destination_well = destination.wells()[i]

        pipette.pick_up_tip()
        pipette.move_to(source_well.top())
        if not context.params.dry_run:
            pipette.aspirate(context.params.volume, source_well)
            pipette.dispense(context.params.volume, destination_well)

        pipette.drop_tip()

and in the analysis

  "runTimeParameters": [
    {
      "displayName": "Sample count",
      "variableName": "sample_count",
      "description": "How many samples to process.",
      "type": "int",
      "min": 1,
      "max": 12,
      "value": 6,
      "default": 6
    },
    {
      "displayName": "Pipette volume",
      "variableName": "volume",
      "description": "How many microliters to pipette of each sample.",
      "type": "float",
      "choices": [
        {
          "displayName": "Low Volume",
          "value": 10.23
        },
        {
          "displayName": "Medium Volume",
          "value": 20.1
        },
        {
          "displayName": "High Volume",
          "value": 50.5
        }
      ],
      "value": 20.1,
      "default": 20.1
    },
    {
      "displayName": "Dry Run",
      "variableName": "dry_run",
      "description": "Skip aspirate and dispense steps.",
      "type": "bool",
      "value": false,
      "default": false
    },
    {
      "displayName": "Pipette Name",
      "variableName": "pipette",
      "description": "What pipette to use during the protocol.",
      "type": "str",
      "choices": [
        {
          "displayName": "Single channel 50µL",
          "value": "flex_1channel_50"
        },
        {
          "displayName": "Eight Channel 50µL",
          "value": "flex_8channel_50"
        }
      ],
      "value": "flex_1channel_50",
      "default": "flex_1channel_50"
    }
  ],

Changelog

  • Added methods to get a list of all defined parameter as Pydantic model objects to send to client
  • Hooked up parameters to be reported in analysis
  • Use the values sent over via the protocols endpoint (and the runs in the future`) to set defined parameters

Review requests

Risk assessment

Low, no significant architecture changes and mostly adding real data to stubs.

Copy link

codecov bot commented Mar 26, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 67.19%. Comparing base (b82b030) to head (6b5eb3c).
Report is 3 commits behind head on edge.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             edge   #14735      +/-   ##
==========================================
- Coverage   67.19%   67.19%   -0.01%     
==========================================
  Files        2495     2495              
  Lines       71520    71460      -60     
  Branches     9020     9039      +19     
==========================================
- Hits        48056    48015      -41     
+ Misses      21342    21312      -30     
- Partials     2122     2133      +11     
Flag Coverage Δ
g-code-testing 92.43% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files Coverage Δ
...i/src/opentrons/protocol_runner/legacy_wrappers.py 100.00% <ø> (ø)
...i/src/opentrons/protocol_runner/protocol_runner.py 100.00% <ø> (ø)
api/src/opentrons/protocols/execution/execute.py 90.00% <ø> (-0.91%) ⬇️
...rc/opentrons/protocols/execution/execute_python.py 89.18% <ø> (-0.56%) ⬇️
...server/robot_server/protocols/protocol_analyzer.py 100.00% <ø> (ø)
robot-server/robot_server/runs/engine_store.py 95.91% <ø> (ø)

... and 40 files with indirect coverage changes

@jbleon95 jbleon95 marked this pull request as ready for review March 27, 2024 18:28
@jbleon95 jbleon95 requested a review from a team as a code owner March 27, 2024 18:28
@jbleon95 jbleon95 requested review from a team and sanni-t March 27, 2024 18:42
Copy link
Member

@sanni-t sanni-t left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🙌 🎉 So exciting!! This looks really good!
Just have a few nitpicks

api/src/opentrons/protocol_runner/protocol_runner.py Outdated Show resolved Hide resolved
api/src/opentrons/protocol_runner/protocol_runner.py Outdated Show resolved Hide resolved
api/src/opentrons/protocols/execution/execute.py Outdated Show resolved Hide resolved
if isinstance(value, float) and parameter_type is int and value.is_integer():
validated_value = int(value)
else:
validated_value = value
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if value = 123.4 and the parameter type is int then this will assign 123.4 as the validated value instead of raising an error.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, is this value then going to go through validate_type and will then raise an error?
In that case, can we add this explanation in the docstring?

api/src/opentrons/protocols/parameters/validation.py Outdated Show resolved Hide resolved
Comment on lines 71 to 78
validated_value: Union[float, bool, str]
if isinstance(value, bool):
raise ParameterValueError("Cannot send a boolean value as an enum type")
elif isinstance(value, int):
validated_value = float(value)
else:
validated_value = value
return validated_value
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this necessary? I think pydantic will just accept the int without any issues. As for the boolean value, wouldn't that be covered by the conversion you do in as_protocol_engine_type?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could have sworn I was getting mypy errors for this, but removing it has no issue. Guess it was the same memory I had of putting in the set_parameters method

Copy link
Member

@sanni-t sanni-t left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for making the changes!

@jbleon95 jbleon95 merged commit 691e372 into edge Mar 28, 2024
22 checks passed
@jbleon95 jbleon95 deleted the report_rtp_in_analysis branch March 28, 2024 19:16
Carlos-fernandez pushed a commit that referenced this pull request May 20, 2024
…s in analysis (#14735)

Runtime parameter values sent via protocols endpoint will now be set, and all parameters and values used are now reported in analysis.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants