diff --git a/docs/resources/library/agilent.md b/docs/resources/library/agilent.md
index 5131d14b33e..c1a09ced213 100644
--- a/docs/resources/library/agilent.md
+++ b/docs/resources/library/agilent.md
@@ -6,4 +6,4 @@
| Description | Image | PLR definition |
|-|-|-|
-| 'agilent_96_wellplate_150uL_Ub'
Part no.: 5042-8502
[manufacturer website](https://www.agilent.com/store/en_US/Prod-5042-8502/5042-8502) |  | `agilent_96_wellplate_150uL_Ub` |
+| 'agilent_96_wellplate_150uL_Vb'
Part no.: 5042-8502
[manufacturer website](https://www.agilent.com/store/en_US/Prod-5042-8502/5042-8502) |  | `agilent_96_wellplate_150uL_Vb` |
diff --git a/docs/resources/library/img/agilent/agilent_96_wellplate_150uL_Ub.jpg b/docs/resources/library/img/agilent/agilent_96_wellplate_150uL_Vb.jpg
similarity index 100%
rename from docs/resources/library/img/agilent/agilent_96_wellplate_150uL_Ub.jpg
rename to docs/resources/library/img/agilent/agilent_96_wellplate_150uL_Vb.jpg
diff --git a/pylabrobot/resources/agilent/plates.py b/pylabrobot/resources/agilent/plates.py
index 55685de6590..0d9535c7367 100644
--- a/pylabrobot/resources/agilent/plates.py
+++ b/pylabrobot/resources/agilent/plates.py
@@ -1,12 +1,69 @@
+import warnings
+
+from pylabrobot.resources.height_volume_functions import (
+ calculate_liquid_height_container_1segment_round_vbottom,
+ calculate_liquid_volume_container_1segment_round_vbottom,
+)
from pylabrobot.resources.plate import Plate
from pylabrobot.resources.utils import create_ordered_items_2d
from pylabrobot.resources.well import Well, WellBottomType
-def agilent_96_wellplate_150uL_Ub(name: str) -> Plate:
+def _compute_volume_from_height_agilent_96_wellplate_150uL_Vb(
+ h: float,
+):
+ # well depth: 12.5 mm
+ # well diameter at the top: 6.0 mm
+ if h > 12.5:
+ raise ValueError(f"Height {h} is too large for agilent_96_wellplate_150uL_Vb")
+ return calculate_liquid_volume_container_1segment_round_vbottom(
+ d=6.4, h_pyramid=12.5, liquid_height=h
+ )
+
+
+def _compute_height_from_volume_agilent_96_wellplate_150uL_Vb(
+ v: float,
+):
+ if v > 150:
+ raise ValueError(f"Volume {v} is too large for agilent_96_wellplate_150uL_Vb")
+ return calculate_liquid_height_container_1segment_round_vbottom(
+ d=6.4, h_pyramid=12.5, liquid_volume=v
+ )
+
+
+def agilent_96_wellplate_150uL_Vb(name: str) -> Plate:
"""
Part number: 5042-8502
+ Well Number | 96
+ Well Form | Round
+ Well Diameter (A) | 6.4 mm
+ Well Bottom Shape | Conical
+ Well Volume | 150 µL
+ Well Working Volume | 120 µL
+ Well Depth (B) | 14.0 mm
+ Plate Height (C) | 15.9 mm
+ Plate Width (D) | 85.5 mm
+ Plate Length (E) | 127.8 mm
+ Row Distance (F) | 9 mm
+ Column Distance (G) | 9 mm
+ Row Offset (H) | 11.2 mm
+ Column Offset (I) | 14.4 mm
+ Frame Footprint | SBS
+ Frame Numbering | Alphanumeric
+ Skirted | Yes
+ Color | Clear
+ Material | Well: polypropylene
+ | Frame: polycarbonate
+ Temperature Range | -80 to 120 °C
+ Autoclavable | Yes
+ Sterile | Nonsterile
+ Stackable | Yes
+ Pack Size | 25, p/n 5042-8502
+ Compatible Closing Mat | p/n 5067-5154 (not recommended for
+ | chromatography autosamplers)
+ Agilent Instrument Definition| Not applicable
+
https://www.agilent.com/cs/library/datasheets/public/ds-well-plate-specifications-5994-6035en-agilent.pdf
"""
@@ -19,6 +76,8 @@ def agilent_96_wellplate_150uL_Ub(name: str) -> Plate:
"bottom_type": WellBottomType.U,
"material_z_thickness": 0.88, # measured using z-probing
"max_volume": 150,
+ "compute_volume_from_height": _compute_volume_from_height_agilent_96_wellplate_150uL_Vb,
+ "compute_height_from_volume": _compute_height_from_volume_agilent_96_wellplate_150uL_Vb,
}
return Plate(
@@ -27,17 +86,26 @@ def agilent_96_wellplate_150uL_Ub(name: str) -> Plate:
size_y=85.5, # standard
size_z=15.9, # from spec
lid=None,
- model=agilent_96_wellplate_150uL_Ub.__name__,
+ model=agilent_96_wellplate_150uL_Vb.__name__,
ordered_items=create_ordered_items_2d(
Well,
num_items_x=12,
num_items_y=8,
dx=14.4 - diameter / 2, # from spec
dy=11.2 - diameter / 2, # from spec
- dz=16.0 - 14.0 - 0.88, # spec - spec - measured
+ dz=15.9 - 14.0 - 0.88, # spec - spec - measured manually
item_dx=9.0, # standard
item_dy=9.0, # standard
**well_kwargs,
),
plate_type="skirted",
)
+
+
+def agilent_96_wellplate_150uL_Ub(name: str) -> Plate:
+ """Deprecated for agilent_96_wellplate_150uL_Vb. Use that one instead."""
+ warnings.warn(
+ "agilent_96_wellplate_150uL_Ub is deprecated. Use agilent_96_wellplate_150uL_Vb instead.",
+ DeprecationWarning,
+ )
+ return agilent_96_wellplate_150uL_Vb(name)
diff --git a/pylabrobot/resources/height_volume_functions.py b/pylabrobot/resources/height_volume_functions.py
index ee5e53f0cc0..62f6bdb1212 100644
--- a/pylabrobot/resources/height_volume_functions.py
+++ b/pylabrobot/resources/height_volume_functions.py
@@ -434,6 +434,33 @@ def calculate_liquid_height_container_1segment_round_fbottom(
return liquid_height
+def calculate_liquid_height_container_1segment_round_vbottom(
+ d: float, h_pyramid: float, liquid_volume: float
+) -> float:
+ """Calculate the height of liquid in a container with a cylindrical pyramid (cone) shape.
+
+ Parameters:
+ d: The diameter of the base of the cone in mm.
+ h_pyramid: The height of the cone in mm.
+ liquid_volume: The volume of the liquid in the container in cubic millimeters.
+
+ Returns:
+ The height of the liquid in the container in mm.
+ """
+ r = d / 2
+ max_volume = (1 / 3) * math.pi * r**2 * h_pyramid
+
+ if liquid_volume > max_volume:
+ raise ValueError(
+ """WARNING: Liquid overflow detected;
+ check your labware definition and/or that you are using the right labware."""
+ )
+
+ scale_factor: float = (liquid_volume / max_volume) ** (1 / 3)
+ liquid_height = scale_factor * h_pyramid
+ return liquid_height
+
+
def calculate_liquid_volume_container_1segment_round_fbottom(
d: float, h_cylinder: float, liquid_height: float
) -> float:
@@ -458,6 +485,31 @@ def calculate_liquid_volume_container_1segment_round_fbottom(
return cylinder_liquid_volume
+def calculate_liquid_volume_container_1segment_round_vbottom(
+ d: float, h_pyramid: float, liquid_height: float
+) -> float:
+ """Calculate the volume of liquid in a container with a cylindrical pyramid (cone) shape.
+
+ Parameters:
+ d: The diameter of the base of the cone in mm.
+ h_pyramid: The height of the cone in mm.
+ liquid_height: The height of the liquid in the container in mm.
+
+ Returns:
+ The volume of the liquid in cubic millimeters.
+ """
+ r = d / 2
+ if liquid_height > h_pyramid:
+ raise ValueError(
+ """WARNING: Liquid overflow detected;
+ check your labware definition and/or that you are using the right labware."""
+ )
+
+ scale_factor = liquid_height / h_pyramid
+ liquid_volume = (1 / 3) * math.pi * r**2 * h_pyramid * (scale_factor**3)
+ return liquid_volume
+
+
### Example of usage using a lambda function:
# def Rectangular_Reservoir(name: str) -> Plate:
# """ An 8 well reservoir with a 30mL volume. """