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): inner well geometry unit tests #17082

Merged
merged 19 commits into from
Jan 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 13 additions & 44 deletions api/src/opentrons/protocol_engine/state/frustum_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,19 +82,12 @@ def _circular_frustum_polynomial_roots(


def _volume_from_height_circular(
target_height: float,
total_frustum_height: float,
bottom_radius: float,
top_radius: float,
target_height: float, segment: ConicalFrustum
) -> float:
"""Find the volume given a height within a circular frustum."""
a, b, c = _circular_frustum_polynomial_roots(
bottom_radius=bottom_radius,
top_radius=top_radius,
total_frustum_height=total_frustum_height,
)
volume = a * (target_height**3) + b * (target_height**2) + c * target_height
return volume
heights = segment.height_to_volume_table.keys()
best_fit_height = min(heights, key=lambda x: abs(x - target_height))
return segment.height_to_volume_table[best_fit_height]


def _volume_from_height_rectangular(
Expand Down Expand Up @@ -138,26 +131,12 @@ def _volume_from_height_squared_cone(


def _height_from_volume_circular(
volume: float,
total_frustum_height: float,
bottom_radius: float,
top_radius: float,
target_volume: float, segment: ConicalFrustum
) -> float:
"""Find the height given a volume within a circular frustum."""
a, b, c = _circular_frustum_polynomial_roots(
bottom_radius=bottom_radius,
top_radius=top_radius,
total_frustum_height=total_frustum_height,
)
d = volume * -1
x_intercept_roots = (a, b, c, d)

height_from_volume_roots = roots(x_intercept_roots)
height = _reject_unacceptable_heights(
potential_heights=list(height_from_volume_roots),
max_height=total_frustum_height,
)
return height
"""Find the height given a volume within a squared cone segment."""
volumes = segment.volume_to_height_table.keys()
best_fit_volume = min(volumes, key=lambda x: abs(x - target_volume))
return segment.volume_to_height_table[best_fit_volume]


def _height_from_volume_rectangular(
Expand Down Expand Up @@ -243,9 +222,7 @@ def _get_segment_capacity(segment: WellSegment) -> float:
return (
_volume_from_height_circular(
target_height=section_height,
total_frustum_height=section_height,
bottom_radius=(segment.bottomDiameter / 2),
top_radius=(segment.topDiameter / 2),
segment=segment,
)
* segment.count
)
Expand Down Expand Up @@ -293,12 +270,7 @@ def height_at_volume_within_section(
radius_of_curvature=section.radiusOfCurvature,
)
case ConicalFrustum():
return _height_from_volume_circular(
volume=target_volume_relative,
top_radius=(section.bottomDiameter / 2),
bottom_radius=(section.topDiameter / 2),
total_frustum_height=section_height,
)
return _height_from_volume_circular(target_volume_relative, section)
case CuboidalFrustum():
return _height_from_volume_rectangular(
volume=target_volume_relative,
Expand Down Expand Up @@ -334,10 +306,7 @@ def volume_at_height_within_section(
case ConicalFrustum():
return (
_volume_from_height_circular(
target_height=target_height_relative,
total_frustum_height=section_height,
bottom_radius=(section.bottomDiameter / 2),
top_radius=(section.topDiameter / 2),
target_height=target_height_relative, segment=section
)
* section.count
)
Expand Down Expand Up @@ -427,7 +396,7 @@ def _find_height_in_partial_frustum(
if (
bottom_section_volume
< target_volume
< (bottom_section_volume + section_volume)
<= (bottom_section_volume + section_volume)
):
relative_target_volume = target_volume - bottom_section_volume
section_height = section.topHeight - section.bottomHeight
Expand Down
1 change: 0 additions & 1 deletion api/src/opentrons/protocol_engine/state/labware.py
Original file line number Diff line number Diff line change
Expand Up @@ -524,7 +524,6 @@ def get_well_definition(
will be used.
"""
definition = self.get_definition(labware_id)

if well_name is None:
well_name = definition.ordering[0][0]

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
"""Arguments needed to test inner geometry.

Each labware has 2 nominal volumes calculated in solidworks.
- One is a nominal bottom volume, calculated some set distance from the bottom of the inside of the well.
- The other is a nominal top volume, calculated some set distance from the top of the inside of the well.
"""
INNER_WELL_GEOMETRY_TEST_PARAMS = [
[
"opentrons_10_tuberack_nest_4x50ml_6x15ml_conical",
"conicalWell15mL",
16.7,
15546.9,
3.0,
5.0,
],
[
"opentrons_10_tuberack_nest_4x50ml_6x15ml_conical",
"conicalWell50mL",
111.2,
56110.3,
3.0,
5.0,
],
["opentrons_24_tuberack_nest_2ml_screwcap", "conicalWell", 66.6, 2104.9, 3.0, 3.0],
[
"opentrons_24_tuberack_nest_1.5ml_screwcap",
"conicalWell",
19.5,
1750.8,
3.0,
3.0,
],
["nest_1_reservoir_290ml", "cuboidalWell", 16570.380, 271690.520, 3.0, 3.0],
["opentrons_24_tuberack_nest_2ml_snapcap", "conicalWell", 69.62, 2148.5, 3.0, 3.0],
["nest_96_wellplate_2ml_deep", "cuboidalWell", 118.3, 2060.4, 3.0, 3.0],
["opentrons_24_tuberack_nest_1.5ml_snapcap", "conicalWell", 27.8, 1682.3, 3.0, 3.0],
["nest_12_reservoir_15ml", "cuboidalWell", 1219.0, 13236.1, 3.0, 3.0],
["nest_1_reservoir_195ml", "cuboidalWell", 14034.2, 172301.9, 3.0, 3.0],
[
"opentrons_24_tuberack_nest_0.5ml_screwcap",
"conicalWell",
21.95,
795.4,
3.0,
3.0,
],
[
"opentrons_96_wellplate_200ul_pcr_full_skirt",
"conicalWell",
14.3,
150.2,
3.0,
3.0,
],
["nest_96_wellplate_100ul_pcr_full_skirt", "conicalWell", 15.5, 150.8, 3.0, 3.0],
["nest_96_wellplate_200ul_flat", "conicalWell", 96.3, 259.8, 3.0, 3.0],
[
"opentrons_10_tuberack_falcon_4x50ml_6x15ml_conical",
"50mlconicalWell",
163.9,
57720.5,
3.0,
3.0,
],
[
"opentrons_10_tuberack_falcon_4x50ml_6x15ml_conical",
"15mlconicalWell",
40.8,
15956.6,
3.0,
3.0,
],
["usascientific_12_reservoir_22ml", "cuboidalWell", 529.36, 21111.5, 3.0, 3.0],
["thermoscientificnunc_96_wellplate_2000ul", "conicalWell", 73.5, 1768.0, 3.0, 3.0],
[
"usascientific_96_wellplate_2.4ml_deep",
"cuboidalWell",
72.220,
2241.360,
3.0,
3.0,
],
["agilent_1_reservoir_290ml", "cuboidalWell", 15652.9, 268813.8, 3.0, 3.0],
[
"opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap",
"conicalWell",
25.8,
1576.1,
3.0,
3.0,
],
["thermoscientificnunc_96_wellplate_1300ul", "conicalWell", 73.5, 1155.1, 3.0, 3.0],
["corning_12_wellplate_6.9ml_flat", "conicalWell", 1156.3, 5654.8, 3.0, 3.0],
["corning_24_wellplate_3.4ml_flat", "conicalWell", 579.0, 2853.4, 3.0, 3.0],
["corning_6_wellplate_16.8ml_flat", "conicalWell", 2862.1, 13901.9, 3.0, 3.0],
["corning_48_wellplate_1.6ml_flat", "conicalWell", 268.9, 1327.0, 3.0, 3.0],
["biorad_96_wellplate_200ul_pcr", "conicalWell", 17.9, 161.2, 3.0, 3.0],
["axygen_1_reservoir_90ml", "cuboidalWell", 22373.4, 70450.6, 3.0, 3.0],
["corning_384_wellplate_112ul_flat", "flatWell", 22.4, 77.4, 2.88, 3.0],
["corning_96_wellplate_360ul_flat", "conicalWell", 97.2, 257.1, 3.0, 3.0],
["biorad_384_wellplate_50ul", "conicalWell", 7.7, 27.8, 3.0, 3.0],
[
"appliedbiosystemsmicroamp_384_wellplate_40ul",
"conicalWell",
7.44,
26.19,
3.0,
3.0,
],
[
"opentrons_24_tuberack_eppendorf_2ml_safelock_snapcap",
"conicalWell",
60.940,
2163.980,
3.0,
3.0,
],
[
"opentrons_10_tuberack_nest_4x50ml_6x15ml_conical",
"conicalWell15mL",
16.690,
15546.930,
3.0,
5.0,
],
[
"opentrons_10_tuberack_nest_4x50ml_6x15ml_conical",
"conicalWell50mL",
111.200,
56110.279,
3.0,
5.0,
],
[
"opentrons_10_tuberack_falcon_4x50ml_6x15ml_conical",
"15mlconicalWell",
40.830,
15956.600,
3.0,
3.0,
],
[
"opentrons_10_tuberack_falcon_4x50ml_6x15ml_conical",
"50mlconicalWell",
163.860,
57720.510,
3.0,
3.0,
],
]
Loading
Loading