feat(shared-data): change schema 2 to include user-defined volumes#18815
feat(shared-data): change schema 2 to include user-defined volumes#18815caila-marashaj merged 27 commits intoedgefrom
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## edge #18815 +/- ##
==========================================
+ Coverage 23.96% 25.23% +1.26%
==========================================
Files 3358 3357 -1
Lines 294546 294581 +35
Branches 31020 31053 +33
==========================================
+ Hits 70588 74324 +3736
+ Misses 223937 220230 -3707
- Partials 21 27 +6
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
8e03737 to
2eb5ef7
Compare
SyntaxColoring
left a comment
There was a problem hiding this comment.
Thank you! This looks fundamentally right.
Just lots of small things, sorry for the wall of text. Only some of these are blocking change requests. Blocking change requests are prefixed with
7a03bc8 to
75b42fc
Compare
6860105 to
67362ef
Compare
| from opentrons.protocol_engine.errors.exceptions import InvalidLiquidHeightFound | ||
|
|
||
|
|
||
| @pytest.fixture |
There was a problem hiding this comment.
No change needed for this PR, just a Hot Pytest Tip.
I think you might be falling into a common Pytest trap of overusing fixtures. I see a lot of people do this. Something in the Pytest docs must be pushing fixtures too hard, or something.
The way I see it, fixtures are helpful when you want to do any of the following:
- Separate the fixture's setup and teardown code from the test code
- for better error reporting in the CLI output
- for better timing statistics in the CLI output
- to save a level of indentation inside the test function
- Share an expensive object across multiple tests, for performance
- Automatically run test functions with multiple values of the fixture
But for something like this, the fanciness of fixtures isn't doing anything for us. it may as well be a regular module-level constant, like USER_DEFINED_VOLUMES_PARAMS = {...}.
The downside to fixtures is that they break type checking and IDE features like "find references." There have been pushes for Pytest to change the fixture syntax to fix that (pytest-dev/pytest#5981, pytest-dev/pytest#9946), but it doesn't seem like they're budging.
| decoy.when( | ||
| mock_well_math_utils[target_measurement + "_" + well_def_type]( | ||
| sentinel.arbitrary_height_volume, geometry_def | ||
| ) | ||
| ).then_return(sentinel.arbitrary_return_val) |
There was a problem hiding this comment.
I appreciate the effort to deduplicate between the find_height_at_well_volume() test and the find_volume_at_well_height() test, which are basically structurally identical. But dynamically constructing the function name to mock out feels a bit too sneaky.
I would do it the "dumb" way and have one decoy.when() call inside the if target_measurement == "height" block and one decoy.when() call inside the elif target_measurement == "volume" block.
Feel free to defer if you want to focus on getting the JS side passing and getting this merged.
1af4b24 to
0ca35de
Compare
Co-authored-by: Max Marrone <max@opentrons.com>
068fdf2 to
6fed787
Compare
Overview
Liquid-level detection is out now, and its main blind-spot is labware that don't already have
InnerLabwareGeometrydefinitions in our shared-data repo. This is difficult for users to fill in on their own, as it comes from some pretty intensive measuring and modeling from our hardware department.As an alternative, we can give users/support people the option to add
UserDefinedVolumesto their labware's shared-data file, which will be a list of small dictionaries, each containing aheightentry and avolumeentry, like this:"innerLabwareGeometry": { "userVolumes": { "heightToVolumeMap": [ { "height": 0.5, "volume": 3 }, { "height": 2.0, "volume": 10 }, { "height": 10.4, "volume": 70 }, { "height": 30.8, "volume": 100 }, { "height": 59.3, "volume": 300 } ] }This pr enables this type of data to be used as input for the same liquid-level detection functionality that
InnerWellGeometrydefinitions use, likelabware.height_from_volumeandlabware.volume_from_height.InnerWellGeometrywill use the same geometric calculations we've been using before, and estimations usingUserDefinedVolumeswill use linear interpolations of the user-specified volumes and heights. This obviously won't be as accurate, but for a lot of labware, especially small labware, it won't matter a ton, so this is a good jumping off point I think.Changelog
InnerLabwareGeometryto be eitherInnerWellGeometryorUserDefinedVolumeslabware_definitionsas wellUserDefinedVolumesinfrustum_helpersgeometry.pydetermine the type ofInnerLabwareGeometryand call the right kind of calculationTesting
Hardware testing is coming up with a protocol that will allow users to automatically generate these
UserDefinedVolumesdata by dispensing known volumes into a well, and probing the liquid height in the well after dispensing. The math itself hasn't been rigorously tested yet, but once we get some more data to work with, we're going to use this protocol to come up withUserDefinedVolumesdata for labware with knownInnerWellGeometrydata, and compare the results ofheight_from_volumeandvolume_from_heighta bunch of times to evaluate the efficacy.