From 77921e95c0de6eb4932967b53c65e8e1f12d899d Mon Sep 17 00:00:00 2001 From: caila-marashaj Date: Thu, 8 Aug 2024 14:59:39 -0400 Subject: [PATCH 01/11] first pass labware defs --- .../labware/labware_definition.py | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/shared-data/python/opentrons_shared_data/labware/labware_definition.py b/shared-data/python/opentrons_shared_data/labware/labware_definition.py index 1b2e68040de..188571cadc7 100644 --- a/shared-data/python/opentrons_shared_data/labware/labware_definition.py +++ b/shared-data/python/opentrons_shared_data/labware/labware_definition.py @@ -105,6 +105,33 @@ class DisplayCategory(str, Enum): other = "other" +class CircleArea(BaseModel): + radius: float + + +class RectangleArea(BaseModel): + length: float + width: float + + +class Hemisphere(BaseModel): + radius: float + depth: float + + +CrossSectionShape = Union[CircleArea, RectangleArea] + + +class CrossSection(BaseModel): + shape: CrossSectionShape + height: float + + +class InnerLabwareGeometry(BaseModel): + cross_sections: List[CrossSection] + hemisphere: Optional[Hemisphere] + + class LabwareRole(str, Enum): labware = "labware" fixture = "fixture" From be381d629dcacbb512ee81ce6be360def729cdc2 Mon Sep 17 00:00:00 2001 From: caila-marashaj Date: Mon, 12 Aug 2024 16:59:36 -0400 Subject: [PATCH 02/11] fix innerwellgeometry defs --- .../labware/labware_definition.py | 69 +++++++++++-------- .../opentrons_shared_data/labware/types.py | 29 ++++++++ 2 files changed, 71 insertions(+), 27 deletions(-) diff --git a/shared-data/python/opentrons_shared_data/labware/labware_definition.py b/shared-data/python/opentrons_shared_data/labware/labware_definition.py index 188571cadc7..7fa24d03449 100644 --- a/shared-data/python/opentrons_shared_data/labware/labware_definition.py +++ b/shared-data/python/opentrons_shared_data/labware/labware_definition.py @@ -105,33 +105,6 @@ class DisplayCategory(str, Enum): other = "other" -class CircleArea(BaseModel): - radius: float - - -class RectangleArea(BaseModel): - length: float - width: float - - -class Hemisphere(BaseModel): - radius: float - depth: float - - -CrossSectionShape = Union[CircleArea, RectangleArea] - - -class CrossSection(BaseModel): - shape: CrossSectionShape - height: float - - -class InnerLabwareGeometry(BaseModel): - cross_sections: List[CrossSection] - hemisphere: Optional[Hemisphere] - - class LabwareRole(str, Enum): labware = "labware" fixture = "fixture" @@ -251,6 +224,41 @@ class Config: ) +class InnerGeometrySection(BaseModel): + shape: Literal["rectangular", "circular", "hemisphere"] = Field( + ..., + description="Shape of a cross-section of a well used to determine how " + "to calculate area", + ) + xDimension: Optional[_NonNegativeNumber] = Field( + None, + description="x dimension of rectangular wells", + ) + yDimension: Optional[_NonNegativeNumber] = Field( + None, + description="y dimension of rectangular wells", + ) + diameter: Optional[_NonNegativeNumber] = Field( + None, + description="diameter of circular wells", + ) + + +class BoundedSection(BaseModel): + shape: InnerGeometrySection = Field( + ..., + description="Geometrical layout of the geometry of a section of the inside of a well", + ) + top_height: _NonNegativeNumber = Field( + ..., + description="The height at the top of a bounded subsection of a well" + ) + + +class InnerLabwareGeometry(BaseModel): + boundedSections: List[BoundedSection] + + class Metadata1(BaseModel): """ Metadata specific to a grid of wells in a labware @@ -353,3 +361,10 @@ class LabwareDefinition(BaseModel): default_factory=None, description="Force, in Newtons, with which the gripper should grip the labware.", ) + innerWellGeometry: Optional[InnerLabwareGeometry] = Field( + ..., + description="A layout describing the geometry of the inside of the wells.", + ) + + + diff --git a/shared-data/python/opentrons_shared_data/labware/types.py b/shared-data/python/opentrons_shared_data/labware/types.py index a938f337c0f..93b5221ccf6 100644 --- a/shared-data/python/opentrons_shared_data/labware/types.py +++ b/shared-data/python/opentrons_shared_data/labware/types.py @@ -37,6 +37,7 @@ Circular = Literal["circular"] Rectangular = Literal["rectangular"] +Hemisphere = Literal["hemisphere"] WellShape = Union[Circular, Rectangular] @@ -138,3 +139,31 @@ class LabwareDefinition(_RequiredLabwareDefinition, total=False): gripperOffsets: Dict[str, GripperOffsets] gripForce: float gripHeightFromLabwareBottom: float + + +class CircularArea(TypedDict): + shape: Circular + diameter: float + + +class RectangularArea(TypedDict): + shape: Rectangular + xDimension: float + yDimension: float + + +class HemisphereDimensions(TypedDict): + shape: Hemisphere + diameter: float + + +InnerGeometrySection = Union[CircularArea, RectangularArea, HemisphereDimensions] + + +class BoundedSection(TypedDict): + shape: InnerGeometrySection + top_height: float + + +class InnerLabwareGeometry(TypedDict): + bounded_sections: List[BoundedSection] From d1a65d279c070fc9765dc358b560a6d1032c431c Mon Sep 17 00:00:00 2001 From: caila-marashaj Date: Mon, 12 Aug 2024 17:40:39 -0400 Subject: [PATCH 03/11] j make innerwellgeometry a list of boundedsections --- .../protocol_runner/test_json_translator.py | 19 +++++++++++++++++++ .../labware/labware_definition.py | 14 +++++--------- .../opentrons_shared_data/labware/types.py | 7 ++----- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/api/tests/opentrons/protocol_runner/test_json_translator.py b/api/tests/opentrons/protocol_runner/test_json_translator.py index 0c65274ad9a..a4382c756d6 100644 --- a/api/tests/opentrons/protocol_runner/test_json_translator.py +++ b/api/tests/opentrons/protocol_runner/test_json_translator.py @@ -13,6 +13,8 @@ Group, Metadata1, WellDefinition, + BoundedSection, + InnerGeometrySection, ) from opentrons_shared_data.protocol.models import ( protocol_schema_v6, @@ -685,6 +687,23 @@ def _load_labware_definition_data() -> LabwareDefinition: }, dimensions=Dimensions(yDimension=85.5, zDimension=100, xDimension=127.75), cornerOffsetFromSlot=CornerOffsetFromSlot(x=0, y=0, z=0), + innerWellGeometry=[ + BoundedSection( + geometry=InnerGeometrySection( + shape="hemisphere", + diameter=25, + ), + top_height=10, + ), + BoundedSection( + geometry=InnerGeometrySection( + shape="rectangular", + xDimension=5.6, + yDimension=6.5, + ), + top_height=45, + ), + ], brand=BrandData(brand="foo"), metadata=Metadata( displayName="Foo 8 Well Plate 33uL", diff --git a/shared-data/python/opentrons_shared_data/labware/labware_definition.py b/shared-data/python/opentrons_shared_data/labware/labware_definition.py index 7fa24d03449..c85ab003441 100644 --- a/shared-data/python/opentrons_shared_data/labware/labware_definition.py +++ b/shared-data/python/opentrons_shared_data/labware/labware_definition.py @@ -245,9 +245,9 @@ class InnerGeometrySection(BaseModel): class BoundedSection(BaseModel): - shape: InnerGeometrySection = Field( + geometry: InnerGeometrySection = Field( ..., - description="Geometrical layout of the geometry of a section of the inside of a well", + description="Geometrical information needed to calculate the volume of a subsection of a well", ) top_height: _NonNegativeNumber = Field( ..., @@ -255,10 +255,6 @@ class BoundedSection(BaseModel): ) -class InnerLabwareGeometry(BaseModel): - boundedSections: List[BoundedSection] - - class Metadata1(BaseModel): """ Metadata specific to a grid of wells in a labware @@ -361,9 +357,9 @@ class LabwareDefinition(BaseModel): default_factory=None, description="Force, in Newtons, with which the gripper should grip the labware.", ) - innerWellGeometry: Optional[InnerLabwareGeometry] = Field( - ..., - description="A layout describing the geometry of the inside of the wells.", + innerWellGeometry: Optional[List[BoundedSection]] = Field( + None, + description="A list of bounded sections describing the geometry of the inside of the wells.", ) diff --git a/shared-data/python/opentrons_shared_data/labware/types.py b/shared-data/python/opentrons_shared_data/labware/types.py index 93b5221ccf6..9afcd12841d 100644 --- a/shared-data/python/opentrons_shared_data/labware/types.py +++ b/shared-data/python/opentrons_shared_data/labware/types.py @@ -157,13 +157,10 @@ class HemisphereDimensions(TypedDict): diameter: float +# This will either be a 2-Dimensional cross-section or a hemisphere InnerGeometrySection = Union[CircularArea, RectangularArea, HemisphereDimensions] class BoundedSection(TypedDict): - shape: InnerGeometrySection + geometry: InnerGeometrySection top_height: float - - -class InnerLabwareGeometry(TypedDict): - bounded_sections: List[BoundedSection] From 8dd5c2051b207cfde7e98c8f9e5c48576a7791f2 Mon Sep 17 00:00:00 2001 From: caila-marashaj Date: Tue, 13 Aug 2024 11:45:10 -0400 Subject: [PATCH 04/11] change name to topcrosssection --- .../protocol_runner/test_json_translator.py | 6 +++--- .../labware/labware_definition.py | 12 ++++-------- .../python/opentrons_shared_data/labware/types.py | 4 ++-- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/api/tests/opentrons/protocol_runner/test_json_translator.py b/api/tests/opentrons/protocol_runner/test_json_translator.py index a4382c756d6..363d564cbd0 100644 --- a/api/tests/opentrons/protocol_runner/test_json_translator.py +++ b/api/tests/opentrons/protocol_runner/test_json_translator.py @@ -14,7 +14,7 @@ Metadata1, WellDefinition, BoundedSection, - InnerGeometrySection, + TopCrossSection, ) from opentrons_shared_data.protocol.models import ( protocol_schema_v6, @@ -689,14 +689,14 @@ def _load_labware_definition_data() -> LabwareDefinition: cornerOffsetFromSlot=CornerOffsetFromSlot(x=0, y=0, z=0), innerWellGeometry=[ BoundedSection( - geometry=InnerGeometrySection( + geometry=TopCrossSection( shape="hemisphere", diameter=25, ), top_height=10, ), BoundedSection( - geometry=InnerGeometrySection( + geometry=TopCrossSection( shape="rectangular", xDimension=5.6, yDimension=6.5, diff --git a/shared-data/python/opentrons_shared_data/labware/labware_definition.py b/shared-data/python/opentrons_shared_data/labware/labware_definition.py index c85ab003441..bba8a55a3a9 100644 --- a/shared-data/python/opentrons_shared_data/labware/labware_definition.py +++ b/shared-data/python/opentrons_shared_data/labware/labware_definition.py @@ -224,11 +224,11 @@ class Config: ) -class InnerGeometrySection(BaseModel): +class TopCrossSection(BaseModel): shape: Literal["rectangular", "circular", "hemisphere"] = Field( ..., description="Shape of a cross-section of a well used to determine how " - "to calculate area", + "to calculate area", ) xDimension: Optional[_NonNegativeNumber] = Field( None, @@ -245,13 +245,12 @@ class InnerGeometrySection(BaseModel): class BoundedSection(BaseModel): - geometry: InnerGeometrySection = Field( + geometry: TopCrossSection = Field( ..., description="Geometrical information needed to calculate the volume of a subsection of a well", ) top_height: _NonNegativeNumber = Field( - ..., - description="The height at the top of a bounded subsection of a well" + ..., description="The height at the top of a bounded subsection of a well" ) @@ -361,6 +360,3 @@ class LabwareDefinition(BaseModel): None, description="A list of bounded sections describing the geometry of the inside of the wells.", ) - - - diff --git a/shared-data/python/opentrons_shared_data/labware/types.py b/shared-data/python/opentrons_shared_data/labware/types.py index 9afcd12841d..921000bc264 100644 --- a/shared-data/python/opentrons_shared_data/labware/types.py +++ b/shared-data/python/opentrons_shared_data/labware/types.py @@ -158,9 +158,9 @@ class HemisphereDimensions(TypedDict): # This will either be a 2-Dimensional cross-section or a hemisphere -InnerGeometrySection = Union[CircularArea, RectangularArea, HemisphereDimensions] +TopCrossSection = Union[CircularArea, RectangularArea, HemisphereDimensions] class BoundedSection(TypedDict): - geometry: InnerGeometrySection + geometry: TopCrossSection top_height: float From cd01d610e72c809e41252911bece55d48cc6f3b5 Mon Sep 17 00:00:00 2001 From: caila-marashaj Date: Wed, 14 Aug 2024 11:58:08 -0400 Subject: [PATCH 05/11] pull hemisphere out --- .../protocol_runner/test_json_translator.py | 37 +++++++----- .../labware/labware_definition.py | 30 ++++++++-- .../opentrons_shared_data/labware/types.py | 58 ++++++++++--------- 3 files changed, 79 insertions(+), 46 deletions(-) diff --git a/api/tests/opentrons/protocol_runner/test_json_translator.py b/api/tests/opentrons/protocol_runner/test_json_translator.py index 363d564cbd0..41914433b15 100644 --- a/api/tests/opentrons/protocol_runner/test_json_translator.py +++ b/api/tests/opentrons/protocol_runner/test_json_translator.py @@ -15,6 +15,8 @@ WellDefinition, BoundedSection, TopCrossSection, + InnerLabwareGeometry, + Hemisphere, ) from opentrons_shared_data.protocol.models import ( protocol_schema_v6, @@ -687,23 +689,30 @@ def _load_labware_definition_data() -> LabwareDefinition: }, dimensions=Dimensions(yDimension=85.5, zDimension=100, xDimension=127.75), cornerOffsetFromSlot=CornerOffsetFromSlot(x=0, y=0, z=0), - innerWellGeometry=[ - BoundedSection( - geometry=TopCrossSection( - shape="hemisphere", - diameter=25, + innerWellGeometry=InnerLabwareGeometry( + frusta=[ + BoundedSection( + geometry=TopCrossSection( + shape="rectangular", + xDimension=7.6, + yDimension=8.5, + ), + top_height=45, ), - top_height=10, - ), - BoundedSection( - geometry=TopCrossSection( - shape="rectangular", - xDimension=5.6, - yDimension=6.5, + BoundedSection( + geometry=TopCrossSection( + shape="rectangular", + xDimension=5.6, + yDimension=6.5, + ), + top_height=20, ), - top_height=45, + ], + bottom_shape=Hemisphere( + diameter=6, + depth=10, ), - ], + ), brand=BrandData(brand="foo"), metadata=Metadata( displayName="Foo 8 Well Plate 33uL", diff --git a/shared-data/python/opentrons_shared_data/labware/labware_definition.py b/shared-data/python/opentrons_shared_data/labware/labware_definition.py index bba8a55a3a9..2efbeca9d8d 100644 --- a/shared-data/python/opentrons_shared_data/labware/labware_definition.py +++ b/shared-data/python/opentrons_shared_data/labware/labware_definition.py @@ -224,23 +224,33 @@ class Config: ) +class Hemisphere(BaseModel): + diameter: _NonNegativeNumber = Field( + ..., + description="diameter of bottom subsection of wells", + ) + depth: _NonNegativeNumber = Field( + ..., description="The depth of a hemispherical bottom of a well" + ) + + class TopCrossSection(BaseModel): - shape: Literal["rectangular", "circular", "hemisphere"] = Field( + shape: Literal["rectangular", "circular"] = Field( ..., description="Shape of a cross-section of a well used to determine how " "to calculate area", ) xDimension: Optional[_NonNegativeNumber] = Field( None, - description="x dimension of rectangular wells", + description="x dimension of a subsection of wells", ) yDimension: Optional[_NonNegativeNumber] = Field( None, - description="y dimension of rectangular wells", + description="y dimension of a subsection of wells", ) diameter: Optional[_NonNegativeNumber] = Field( None, - description="diameter of circular wells", + description="diameter of a subsection of wells", ) @@ -282,6 +292,16 @@ class Group(BaseModel): ) +class InnerLabwareGeometry(BaseModel): + frusta: List[BoundedSection] = Field( + ..., + description="A list of all of the sections of the well that have a contiguous shape", + ) + bottom_shape: Optional[Hemisphere] = Field( + None, description="An optional non-frustum shape at the bottom of a well" + ) + + class LabwareDefinition(BaseModel): schemaVersion: Literal[1, 2] = Field( ..., description="Which schema version a labware is using" @@ -356,7 +376,7 @@ class LabwareDefinition(BaseModel): default_factory=None, description="Force, in Newtons, with which the gripper should grip the labware.", ) - innerWellGeometry: Optional[List[BoundedSection]] = Field( + innerWellGeometry: Optional[InnerLabwareGeometry] = Field( None, description="A list of bounded sections describing the geometry of the inside of the wells.", ) diff --git a/shared-data/python/opentrons_shared_data/labware/types.py b/shared-data/python/opentrons_shared_data/labware/types.py index 921000bc264..6aa1a72e088 100644 --- a/shared-data/python/opentrons_shared_data/labware/types.py +++ b/shared-data/python/opentrons_shared_data/labware/types.py @@ -3,7 +3,7 @@ types in this file by and large require the use of typing_extensions. this module shouldn't be imported unless typing.TYPE_CHECKING is true. """ -from typing import Dict, List, NewType, Union +from typing import Dict, List, NewType, Union, Optional from typing_extensions import Literal, TypedDict @@ -37,7 +37,6 @@ Circular = Literal["circular"] Rectangular = Literal["rectangular"] -Hemisphere = Literal["hemisphere"] WellShape = Union[Circular, Rectangular] @@ -118,6 +117,35 @@ class WellGroup(TypedDict, total=False): brand: LabwareBrandData +class CircularArea(TypedDict): + shape: Circular + diameter: float + + +class RectangularArea(TypedDict): + shape: Rectangular + xDimension: float + yDimension: float + + +TopCrossSection = Union[CircularArea, RectangularArea] + + +class Hemisphere(TypedDict): + diameter: float + depth: float + + +class BoundedSection(TypedDict): + geometry: TopCrossSection + top_height: float + + +class InnerLabwareGeometry(TypedDict): + frusta: List[BoundedSection] + bottom_shape: Optional[Hemisphere] + + class _RequiredLabwareDefinition(TypedDict): schemaVersion: Literal[2] version: int @@ -139,28 +167,4 @@ class LabwareDefinition(_RequiredLabwareDefinition, total=False): gripperOffsets: Dict[str, GripperOffsets] gripForce: float gripHeightFromLabwareBottom: float - - -class CircularArea(TypedDict): - shape: Circular - diameter: float - - -class RectangularArea(TypedDict): - shape: Rectangular - xDimension: float - yDimension: float - - -class HemisphereDimensions(TypedDict): - shape: Hemisphere - diameter: float - - -# This will either be a 2-Dimensional cross-section or a hemisphere -TopCrossSection = Union[CircularArea, RectangularArea, HemisphereDimensions] - - -class BoundedSection(TypedDict): - geometry: TopCrossSection - top_height: float + innerWellGeometry: Optional[InnerLabwareGeometry] From d396becb3633e246266f8ab47d01bb78276c2333 Mon Sep 17 00:00:00 2001 From: caila-marashaj Date: Wed, 14 Aug 2024 12:05:48 -0400 Subject: [PATCH 06/11] comment abt height relative to well bottom --- .../opentrons_shared_data/labware/labware_definition.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/shared-data/python/opentrons_shared_data/labware/labware_definition.py b/shared-data/python/opentrons_shared_data/labware/labware_definition.py index 2efbeca9d8d..b064fa70a89 100644 --- a/shared-data/python/opentrons_shared_data/labware/labware_definition.py +++ b/shared-data/python/opentrons_shared_data/labware/labware_definition.py @@ -260,7 +260,9 @@ class BoundedSection(BaseModel): description="Geometrical information needed to calculate the volume of a subsection of a well", ) top_height: _NonNegativeNumber = Field( - ..., description="The height at the top of a bounded subsection of a well" + ..., + description="The height at the top of a bounded subsection of a well, relative to the bottom" + "of the well", ) From 54f1606c149717a9c97605ae47f51ec576a69939 Mon Sep 17 00:00:00 2001 From: caila-marashaj Date: Wed, 14 Aug 2024 15:18:55 -0400 Subject: [PATCH 07/11] topcrosssection and bottomshape enums --- .../protocol_runner/test_json_translator.py | 13 +++--- .../labware/labware_definition.py | 45 ++++++++++++------- .../opentrons_shared_data/labware/types.py | 18 ++++---- 3 files changed, 45 insertions(+), 31 deletions(-) diff --git a/api/tests/opentrons/protocol_runner/test_json_translator.py b/api/tests/opentrons/protocol_runner/test_json_translator.py index 41914433b15..8bec47b3080 100644 --- a/api/tests/opentrons/protocol_runner/test_json_translator.py +++ b/api/tests/opentrons/protocol_runner/test_json_translator.py @@ -14,7 +14,7 @@ Metadata1, WellDefinition, BoundedSection, - TopCrossSection, + RectangularCrossSection, InnerLabwareGeometry, Hemisphere, ) @@ -692,23 +692,24 @@ def _load_labware_definition_data() -> LabwareDefinition: innerWellGeometry=InnerLabwareGeometry( frusta=[ BoundedSection( - geometry=TopCrossSection( + geometry=RectangularCrossSection( shape="rectangular", xDimension=7.6, yDimension=8.5, ), - top_height=45, + topHeight=45, ), BoundedSection( - geometry=TopCrossSection( + geometry=RectangularCrossSection( shape="rectangular", xDimension=5.6, yDimension=6.5, ), - top_height=20, + topHeight=20, ), ], - bottom_shape=Hemisphere( + bottomShape=Hemisphere( + shape="hemispherical", diameter=6, depth=10, ), diff --git a/shared-data/python/opentrons_shared_data/labware/labware_definition.py b/shared-data/python/opentrons_shared_data/labware/labware_definition.py index b064fa70a89..0d206c33752 100644 --- a/shared-data/python/opentrons_shared_data/labware/labware_definition.py +++ b/shared-data/python/opentrons_shared_data/labware/labware_definition.py @@ -224,21 +224,16 @@ class Config: ) -class Hemisphere(BaseModel): +class CircularCrossSection(BaseModel): + shape: Literal["circular"] = Field(..., description="Denote shape as circular") diameter: _NonNegativeNumber = Field( - ..., - description="diameter of bottom subsection of wells", - ) - depth: _NonNegativeNumber = Field( - ..., description="The depth of a hemispherical bottom of a well" + ..., description="The diameter of a circular cross section of a well" ) -class TopCrossSection(BaseModel): - shape: Literal["rectangular", "circular"] = Field( - ..., - description="Shape of a cross-section of a well used to determine how " - "to calculate area", +class RectangularCrossSection(BaseModel): + shape: Literal["rectangular"] = Field( + ..., description="Denote shape as rectangular" ) xDimension: Optional[_NonNegativeNumber] = Field( None, @@ -248,18 +243,32 @@ class TopCrossSection(BaseModel): None, description="y dimension of a subsection of wells", ) - diameter: Optional[_NonNegativeNumber] = Field( - None, - description="diameter of a subsection of wells", + + +class Hemisphere(BaseModel): + shape: Literal["hemispherical"] = Field( + ..., description="Denote shape as hemispherical" + ) + diameter: _NonNegativeNumber = Field( + ..., + description="diameter of bottom subsection of wells", ) + depth: _NonNegativeNumber = Field( + ..., description="The depth of a hemispherical bottom of a well" + ) + + +TopCrossSection = Union[CircularCrossSection, RectangularCrossSection] +BottomShape = Union[CircularCrossSection, RectangularCrossSection, Hemisphere] class BoundedSection(BaseModel): geometry: TopCrossSection = Field( ..., description="Geometrical information needed to calculate the volume of a subsection of a well", + discriminator="shape", ) - top_height: _NonNegativeNumber = Field( + topHeight: _NonNegativeNumber = Field( ..., description="The height at the top of a bounded subsection of a well, relative to the bottom" "of the well", @@ -299,8 +308,10 @@ class InnerLabwareGeometry(BaseModel): ..., description="A list of all of the sections of the well that have a contiguous shape", ) - bottom_shape: Optional[Hemisphere] = Field( - None, description="An optional non-frustum shape at the bottom of a well" + bottomShape: BottomShape = Field( + ..., + description="An optional non-frustum shape at the bottom of a well", + discriminator="shape", ) diff --git a/shared-data/python/opentrons_shared_data/labware/types.py b/shared-data/python/opentrons_shared_data/labware/types.py index 6aa1a72e088..49cf000b093 100644 --- a/shared-data/python/opentrons_shared_data/labware/types.py +++ b/shared-data/python/opentrons_shared_data/labware/types.py @@ -37,6 +37,7 @@ Circular = Literal["circular"] Rectangular = Literal["rectangular"] +Hemispherical = Literal["hemispherical"] WellShape = Union[Circular, Rectangular] @@ -117,33 +118,34 @@ class WellGroup(TypedDict, total=False): brand: LabwareBrandData -class CircularArea(TypedDict): +class CircularCrossSection(TypedDict): shape: Circular diameter: float -class RectangularArea(TypedDict): +class RectangularCrossSection(TypedDict): shape: Rectangular xDimension: float yDimension: float -TopCrossSection = Union[CircularArea, RectangularArea] - - class Hemisphere(TypedDict): + shape: Hemispherical diameter: float - depth: float + + +TopCrossSection = Union[CircularCrossSection, RectangularCrossSection] +BottomShape = Union[CircularCrossSection, RectangularCrossSection, Hemisphere] class BoundedSection(TypedDict): geometry: TopCrossSection - top_height: float + topHeight: float class InnerLabwareGeometry(TypedDict): frusta: List[BoundedSection] - bottom_shape: Optional[Hemisphere] + bottomShape: BottomShape class _RequiredLabwareDefinition(TypedDict): From be763340a57bf22d7aa4b038e9af411252e80153 Mon Sep 17 00:00:00 2001 From: caila-marashaj Date: Wed, 14 Aug 2024 15:23:43 -0400 Subject: [PATCH 08/11] update bottomshape description --- .../python/opentrons_shared_data/labware/labware_definition.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared-data/python/opentrons_shared_data/labware/labware_definition.py b/shared-data/python/opentrons_shared_data/labware/labware_definition.py index 0d206c33752..f2e231c8afe 100644 --- a/shared-data/python/opentrons_shared_data/labware/labware_definition.py +++ b/shared-data/python/opentrons_shared_data/labware/labware_definition.py @@ -310,7 +310,7 @@ class InnerLabwareGeometry(BaseModel): ) bottomShape: BottomShape = Field( ..., - description="An optional non-frustum shape at the bottom of a well", + description="The shape at the bottom of the well: either a hemisphere or a cross-section", discriminator="shape", ) From d651fd46d42e0eba18204cc8e0147228cba8e672 Mon Sep 17 00:00:00 2001 From: caila-marashaj Date: Wed, 14 Aug 2024 15:25:46 -0400 Subject: [PATCH 09/11] hemispherical whoopsie --- shared-data/python/opentrons_shared_data/labware/types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared-data/python/opentrons_shared_data/labware/types.py b/shared-data/python/opentrons_shared_data/labware/types.py index 49cf000b093..197d7460c58 100644 --- a/shared-data/python/opentrons_shared_data/labware/types.py +++ b/shared-data/python/opentrons_shared_data/labware/types.py @@ -135,7 +135,7 @@ class Hemisphere(TypedDict): TopCrossSection = Union[CircularCrossSection, RectangularCrossSection] -BottomShape = Union[CircularCrossSection, RectangularCrossSection, Hemisphere] +BottomShape = Union[CircularCrossSection, RectangularCrossSection, Hemispherical] class BoundedSection(TypedDict): From 8fde331edd53d2432bee31591b401d5219f803f6 Mon Sep 17 00:00:00 2001 From: caila-marashaj Date: Wed, 14 Aug 2024 15:50:09 -0400 Subject: [PATCH 10/11] change hemisphere to spherical segment --- .../protocol_runner/test_json_translator.py | 8 ++++---- .../labware/labware_definition.py | 16 +++++++--------- .../opentrons_shared_data/labware/types.py | 11 ++++++----- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/api/tests/opentrons/protocol_runner/test_json_translator.py b/api/tests/opentrons/protocol_runner/test_json_translator.py index 8bec47b3080..6dbba6a006c 100644 --- a/api/tests/opentrons/protocol_runner/test_json_translator.py +++ b/api/tests/opentrons/protocol_runner/test_json_translator.py @@ -16,7 +16,7 @@ BoundedSection, RectangularCrossSection, InnerLabwareGeometry, - Hemisphere, + SphericalSegment, ) from opentrons_shared_data.protocol.models import ( protocol_schema_v6, @@ -708,9 +708,9 @@ def _load_labware_definition_data() -> LabwareDefinition: topHeight=20, ), ], - bottomShape=Hemisphere( - shape="hemispherical", - diameter=6, + bottomShape=SphericalSegment( + shape="spherical", + radius_of_curvature=6, depth=10, ), ), diff --git a/shared-data/python/opentrons_shared_data/labware/labware_definition.py b/shared-data/python/opentrons_shared_data/labware/labware_definition.py index f2e231c8afe..537ea89ee27 100644 --- a/shared-data/python/opentrons_shared_data/labware/labware_definition.py +++ b/shared-data/python/opentrons_shared_data/labware/labware_definition.py @@ -245,21 +245,19 @@ class RectangularCrossSection(BaseModel): ) -class Hemisphere(BaseModel): - shape: Literal["hemispherical"] = Field( - ..., description="Denote shape as hemispherical" - ) - diameter: _NonNegativeNumber = Field( +class SphericalSegment(BaseModel): + shape: Literal["spherical"] = Field(..., description="Denote shape as spherical") + radius_of_curvature: _NonNegativeNumber = Field( ..., - description="diameter of bottom subsection of wells", + description="radius of curvature of bottom subsection of wells", ) depth: _NonNegativeNumber = Field( - ..., description="The depth of a hemispherical bottom of a well" + ..., description="The depth of a spherical bottom of a well" ) TopCrossSection = Union[CircularCrossSection, RectangularCrossSection] -BottomShape = Union[CircularCrossSection, RectangularCrossSection, Hemisphere] +BottomShape = Union[CircularCrossSection, RectangularCrossSection, SphericalSegment] class BoundedSection(BaseModel): @@ -310,7 +308,7 @@ class InnerLabwareGeometry(BaseModel): ) bottomShape: BottomShape = Field( ..., - description="The shape at the bottom of the well: either a hemisphere or a cross-section", + description="The shape at the bottom of the well: either a spherical segment or a cross-section", discriminator="shape", ) diff --git a/shared-data/python/opentrons_shared_data/labware/types.py b/shared-data/python/opentrons_shared_data/labware/types.py index 197d7460c58..c92c9d04dec 100644 --- a/shared-data/python/opentrons_shared_data/labware/types.py +++ b/shared-data/python/opentrons_shared_data/labware/types.py @@ -37,7 +37,7 @@ Circular = Literal["circular"] Rectangular = Literal["rectangular"] -Hemispherical = Literal["hemispherical"] +Spherical = Literal["spherical"] WellShape = Union[Circular, Rectangular] @@ -129,13 +129,14 @@ class RectangularCrossSection(TypedDict): yDimension: float -class Hemisphere(TypedDict): - shape: Hemispherical - diameter: float +class SphericalSegment(TypedDict): + shape: Spherical + radius_of_curvature: float + depth: float TopCrossSection = Union[CircularCrossSection, RectangularCrossSection] -BottomShape = Union[CircularCrossSection, RectangularCrossSection, Hemispherical] +BottomShape = Union[CircularCrossSection, RectangularCrossSection, Spherical] class BoundedSection(TypedDict): From 34b4fd44a42b35aea09a0412457de26a35b2b771 Mon Sep 17 00:00:00 2001 From: caila-marashaj Date: Wed, 14 Aug 2024 15:59:03 -0400 Subject: [PATCH 11/11] spherical segment should go in the bottom shape union --- shared-data/python/opentrons_shared_data/labware/types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared-data/python/opentrons_shared_data/labware/types.py b/shared-data/python/opentrons_shared_data/labware/types.py index c92c9d04dec..8a6135de8f9 100644 --- a/shared-data/python/opentrons_shared_data/labware/types.py +++ b/shared-data/python/opentrons_shared_data/labware/types.py @@ -136,7 +136,7 @@ class SphericalSegment(TypedDict): TopCrossSection = Union[CircularCrossSection, RectangularCrossSection] -BottomShape = Union[CircularCrossSection, RectangularCrossSection, Spherical] +BottomShape = Union[CircularCrossSection, RectangularCrossSection, SphericalSegment] class BoundedSection(TypedDict):