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): Partial tip pickup support for Single, Row and Partial Column #15585

Merged
merged 15 commits into from
Jul 12, 2024

Conversation

CaseyBatten
Copy link
Contributor

@CaseyBatten CaseyBatten commented Jul 5, 2024

Overview

Covers PLAT-51, PLAT-217 and PLAT-355

Publicly exposes Single and Row configurations. Introduces Partial Column configuration and the necessary logic to support it. Expands quadrants to accept a back_left_nozzle qualifier to help define shapes from the reverse direction, and partial columns build upon that infrastructure.

Test Plan

  • Execute a 96ch protocol on Flex that utilizes Single and Row configurations to consume multiple tipracks.
  • Execute an 8ch protocol on Flex that utilizes Single and Partial Column configuration to consume multiple tipracks in multiple partial configurations (2-7 nozzles/channels).
  • Execute an 8ch protocol on OT-2 that makes use of Single and Partial Column configuration in ways similar to users in the field.

Changelog

Review requests

The addition of end: Optional[str] = None, to configure_nozzle_layout was a decision based on input regarding what felt natural to a user when utilizing the Partial Column command. Functionally, end is either the back_left_nozzle or front_right_nozzle depending on the position of the start or primary nozzle. In this way, it is technically repetitious to have end as a parameter at all, but it may be beneficial from a readability and usability standpoint when creating linear partial column configurations (and in the future, partial row configurations). Let me know thoughts on this, if we feel it is unnecessary or if it is something we want to keep.

Risk assessment

Medium risk - No major changes to the existing behavior, however introduction of new configurations may mean we need to revalidate our collision checking to ensure that the risk of putting the pipette into a dangerous situation or commanding it to move outside of the robots extents cannot occur.

@CaseyBatten CaseyBatten requested review from a team as code owners July 5, 2024 15:21
Copy link

codecov bot commented Jul 5, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 81.03%. Comparing base (3479875) to head (639fded).
Report is 30 commits behind head on edge.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##             edge   #15585       +/-   ##
===========================================
+ Coverage   60.12%   81.03%   +20.90%     
===========================================
  Files         190      118       -72     
  Lines       10627     4112     -6515     
===========================================
- Hits         6390     3332     -3058     
+ Misses       4237      780     -3457     
Flag Coverage Δ
g-code-testing 92.43% <ø> (ø)
hardware ?
shared-data 75.85% <ø> (?)

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

see 154 files with indirect coverage changes

Copy link
Contributor

A PR has been opened to address analyses snapshot changes. Please review the changes here: https://github.com/Opentrons/opentrons/pull/

@ecormany
Copy link
Contributor

Once this merges, I'll follow up in a separate PR to describe the new parameters in the docstring, as well as describe their function in the corresponding article.

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.

Have to go over the tip handler changes but here's some initial thoughts. I think the introduction of end can cause more confusion if it's not handled correctly.

Also, can we break complex functions into smaller contained ones instead of adding noqa tags? noqa tagged functions tend to keep getting messier and harder to read or fix since any additions to it just keep getting ignored.

Comment on lines 2048 to 2055
if (
self._api_version
< _PARTIAL_NOZZLE_CONFIGURATION_SINGLE_ROW_PARTIAL_COLUMN_ADDED_IN
):
if style not in original_enabled_layouts:
raise ValueError(
f"Nozzle layout configuration of style {style.value} is unsupported in API Versions lower than {_PARTIAL_NOZZLE_CONFIGURATION_SINGLE_ROW_PARTIAL_COLUMN_ADDED_IN}."
)
Copy link
Member

Choose a reason for hiding this comment

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

Can be merged into one if statement

primary_nozzle=start,
front_right_nozzle=front_right,
back_left_nozzle=back_left,
)
# TODO (spp, 2023-12-05): verify that tipracks are on adapters for only full 96 channel config
Copy link
Member

Choose a reason for hiding this comment

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

Can remove this todo. We're doing that check durin pipette movement/ deck conflict check.

Comment on lines 815 to 816
assert primary_nozzle is not None
assert front_right_nozzle is not None or back_left_nozzle is not None
Copy link
Member

Choose a reason for hiding this comment

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

These should be verified in the configure_nozzle_layout API with user-friendly error messages rather than asserting here. (Looks like 'primary nozzle is not None' is already asserted in the API so this one is redundant).

With the verification done in the API method, this implementation can just use QuadrantNozzleLayoutConfiguration with the available args without verifying for partial column or plain old quadrant separately as done here and on lines 826-832.

Copy link
Member

@sanni-t sanni-t Jul 10, 2024

Choose a reason for hiding this comment

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

I think the introduction of end nozzle is adding further confusion and redundancy in this code. What if someone specifies the end nozzle instead of back_left or front_right and vice versa? If the start and end combo makes more sense to protocol authors, then maybe we should think about removing back_left and front_right from the API and keep it only in the layers underneath. Has this been discussed? Are there any reasons not to remove them? It will be a breaking change but a very low stakes since the released configurations until now only used the start nozzle. We could also deprecate them slowly so that it's not a breaking change.

If there are compelling reasons to not remove the redundant args, we should check that something like this should fail expectedly-

context.configure_nozzle_layout(style=PARTIAL_COLUMN, start="A1", end="D1", back_left="B1" )

Copy link
Contributor Author

@CaseyBatten CaseyBatten Jul 10, 2024

Choose a reason for hiding this comment

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

Theoretically you would want to keep all three, because if in the future quadrants exist as a concept then there are some cases where a user will need to specify a primary, front right and back left nozzle. One such situation would be making a 4x4 tip Quadrant with A12 as the primary nozzle (start), A9 as the back_left nozzle, and D12 as the front_right nozzle. Such a configuration would be impossible to create without all three parameters. Primary nozzle. H1 as primary has a similar potential issue. The addition of end as a parameter exists to simply the usage of Partial columns specifically, with end acting as a reflexive parameter (it is either the back left or front right, depending on the position of start). I do not believe it over complicates things, so long as we have good documentation to explain the addition of end. This was something @ecormany and I discussed regarding the documentation and functionality of the configure_nozzle_layout command.

Regardless, if we are going to keep it I will ensure that the error case you specified results in expected failure.

Copy link
Contributor

@SyntaxColoring SyntaxColoring Jul 11, 2024

Choose a reason for hiding this comment

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

@CaseyBatten Sorry, basic question. In that three-parameter situation you're describing, what's the special significance of the "primary" nozzle being A9? Why would someone want that instead of the primary nozzle being A9 or D12? What does that actually do?

Is it for choosing the direction in which tips are consumed, or is it for choosing which tip moves to the well when you do pipette.move_to(single_well), or both, or something else?

I don't understand this well enough to have an opinion on what to do, but my knee-jerk reaction is that all of this is quite confusing and we should try to simplify it if we can. As a user, style, start/end, and front_right/back_left seem like three different competing ways of specifying the same-ish thing?


A process note: I think I'm finding this confusing because I'm not seeing a complete, final summary of how the new interface is supposed to work. For example, I would have found it helpful if this PR updated the InstrumentContext.configure_nozzle_layout() docstring, or if there were a draft of it in Confluence. I see there's some existing discussion in PLAT-51, but it looks like a bit to catch up on; and you've talked about the new param in the PR description, but I'm not familiar enough with this feature for that to really make sense to me.

Copy link
Contributor

Choose a reason for hiding this comment

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

My bad for encouraging not updating the docstring here — there was some thought that we'd try to keep that out of edge and in a feature docs branch, but we already have lots of PAPI 2.20 content in edge and shouldn't feel restrained from adding more.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@SyntaxColoring Sorry let me clarify, as I think the formatting of that paragraph was confusing. The situation i was discussing was the following:

  • start (primary nozzle) = A12
  • back_left = A9
  • front_right = D12
    This will result in a 4x4 tip pickup in our "Quadrant" configuration (currently an engine-only configuration)
    What this will look like is this on the pipette:
    A9 X X A12
    X X X X
    X X X X
    X X X D12

So in this example, the three separate values define the edges of our tip "box" in the corner of the pipette. This is the only way to define a quadrant in corner A12, and also the only way to define a quadrant in corner H1 for the same reason.

@ecormany I agree it, I'll go through and add in the doc string explanations in this PR. It wasn't a bad idea to try to unify those elsewhere, but it played out against our favor here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

To further explain that example and address your questions Max, we're defining which nozzles on the pipette will be physically used, which will effect which tips are consumed and in what order on the tiprack. In short, if you Pick H12 as the primary nozzle on a 96ch, you will consume tips in our traditional fashion (top left to bottom right or tiprack). If you pick A1 as the primary nozzle on a 96ch, the opposite will occur (bottom right to top left). In essence, whichever starting nozzle you choose, the opposite welled tip will be selected on the tiprack for pickup. For the 8ch, this only applies on a per column level, so selecting H1 as your primary nozzle will pick up tip A1 on the tiprack.

The reasoning for the cross-behavior there is because of the physical layout of our pipettes. As an example, with an 8ch pipette if you tried to pick up tip H1 with nozzle H1, you would end up picking up all the tips from H1-A1 because the other 7 nozzles would line up with the other 7 tips. Same logic applies for the 96ch but on two axes.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks so much for that explanation and the updated docstring. I've read those and PLAT-51 and it's all making a lot more sense to me now. I have more suggestions and questions, but we'll move that to Slack.

Copy link
Contributor

A PR has been opened to address analyses snapshot changes. Please review the changes here: https://github.com/Opentrons/opentrons/pull/

Copy link
Contributor

A PR has been opened to address analyses snapshot changes. Please review the changes here: https://github.com/Opentrons/opentrons/pull/

@ecormany
Copy link
Contributor

Docstring additions look good to me, although I suspect that the note will eventually get folded into one of the API articles.

Copy link
Contributor

@vegano1 vegano1 left a comment

Choose a reason for hiding this comment

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

We went through the code and the changes make sense for what we need today, also if we don't currently have a use case for back_left/right etc that cannot be accomplished with just start and end then I think we can remove them.

@CaseyBatten CaseyBatten merged commit bf2b49a into edge Jul 12, 2024
44 of 45 checks passed
@CaseyBatten CaseyBatten deleted the partial_tip_api_for_single_row_partial_col branch July 12, 2024 18:59
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.

5 participants