-
Notifications
You must be signed in to change notification settings - Fork 178
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(shared-data, api): return latest pipette version from pipetteName #15002
Conversation
@@ -5,15 +5,15 @@ | |||
"uiMaxFlowRate": 26.7, | |||
"defaultAspirateFlowRate": { | |||
"default": 35, | |||
"valuesByApiLevel": { "2.14": 35 } | |||
"valuesByApiLevel": { "2.14": 26.7 } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i updated these to match the uiMaxFlowRate
- see #14859 for more details
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## edge #15002 +/- ##
==========================================
+ Coverage 67.50% 76.31% +8.81%
==========================================
Files 2521 42 -2479
Lines 72090 2804 -69286
Branches 9311 0 -9311
==========================================
- Hits 48666 2140 -46526
+ Misses 21228 664 -20564
+ Partials 2196 0 -2196
Flags with carried forward coverage won't be shown. Click here to find out more.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some inline things, I think we can rework that main function a bit.
It's weird that the test asks for a kind of pipette that does not exist... maybe we can add a couple more cases to it?
else: | ||
return 1 | ||
|
||
|
||
def version_from_generation(pipette_name_list: List[str]) -> PipetteVersionType: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's drop an lru_cache
on this, it's a perfect candidate:
- it will often be called with the same thing when something tries to load data
- it is pretty expensive to call since it does a whole ton of filesystem interactions
get_shared_data_root() / "pipette" / "definitions" / "2" / "general" | ||
) | ||
|
||
highest_minor_version: Literal[0, 1, 2, 3, 4, 5, 6] = 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we'd have to update this whenever we add a new minor version, right? can we weaken its type to int
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, so the return type of version_from_generation
is PipetteVersionType
, which is a Literal. I guess i could weaken it so the return type is just an int
. i agree it should be weakened so that we don't have to always update it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nevermind, this is giving me a hard time updating because all the other utils in the file use PipetteVersionType
as well 🤔 maybe it can be refactored in a followup? Plus there is this comment in types.py
# TODO Literals are only good for writing down
# exact values. Is there a better typing mechanism
# so we don't need to keep track of versions in two
# different places?
PipetteModelMajorVersionType = Literal[1, 2, 3]
PipetteModelMinorVersionType = Literal[0, 1, 2, 3, 4, 5, 6]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, a followup is fine i suppose. could we maybe have this be highest_minor_version: PipetteModelMinorVersionType = 0
then? that way we wouldn't have to change it in two places
if highest_minor_version < minor_version_lit: | ||
highest_minor_version = minor_version_lit | ||
|
||
if highest_minor_version == 0: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i don't think we need this, right? 0
is a valid value there, and the major version is the same, so we can unconditionally return PipetteVersionType(major_version_from_pipette_name, highest_minor_version)
and it's fine if highest_minor_version
is 0
|
||
highest_minor_version: Literal[0, 1, 2, 3, 4, 5, 6] = 0 | ||
|
||
for channel_dir in os.listdir(paths_to_validate): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The outer two for
loops don't seem to be doing much, I think. we're iterating through them and checking for exact equality to the values we already have, so let's just construct the path at the beginning:
versions_path = (paths_to_validate
/ channel_from_pipette_name
/ model_from_pipette_name)
for version_file in version_paths.iterdir():
...
continue | ||
|
||
for version_file in os.listdir(paths_to_validate / channel_dir / model_dir): | ||
version_list = version_file.split(".json")[0].split("_") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
version_list = version_file.split(".json")[0].split("_") | |
version_list = version_file.stem.split("_") |
(as long as we're using e.g. (paths_to_validate/channel_dir/model_dir).iterdir()
rather than os.listdir
so we get path objects)
minor_version = version_list[1] | ||
|
||
# Check if the major version matches the expected major version | ||
if major_version == str(major_version_from_pipette_name): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe invert logic and continue to save some indentation, i.e.
if major_version != str(major_version_from_pipette_name):
continue
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great!
closes AUTH-357
Overview
Previously, if you have access to only the
pipetteName
, the pipette definitions you get back are the first pipette version for the generation. For example, if you have ap1000_single_flex
, you would get the pipette definitions for3_0
. After speaking with Seth, Andy, Ed, and Sanniti, we decided that this is not great because 1) version.0
s are prototypes and aren't in the wild and 2) the latest versions have the most up to date specs for things such asflowRate
s. (slack conversation about this if interested)We thought about making the prototype versions the "perfect definitions" but that requires maintenance and it is much easier in the long run just to return the latest version that exists.
This change is already implemented in the frontend (see
getPipetteV2Specs
), so Protocol Designer (et al) will have the latest flow rates 🚀 .But, we needed to align in the api as well so
opentrons-simulate
and analysis also have the latest data. This PR updates theversion_from_generation
def inshared-data
to return the latest version.Note: the downfall to the current approach is there are a few api tests that will need to be updated whenever the specific pipette has a new version - see the PR for which tests those are.
Test Plan
upload this to the app on edge and look at the run log - the aspirate/dispense flow rate should be 160 ul/sec, which is the 1000uL tip default flow rate for the
3_0
model.then upload this to the app on this branch and look at the run log - the aspirate/dispense flow rate should be 716 ul/sec, which is the 1000uL tip default flow rate for the
3_6
model.Changelog
version_from_generation
test_convert_pipette_name
pipetteName
p50_single_3.6
pipette definition to match the ui max flow rate (see feat(shared-data, api): add uiMaxFlowRate key to pipette definitions #14859 for details on why)Review requests
Please review the code and logic and let me know if there is anything else I need to change?
Risk assessment
low