add corning fb plate compute volume#903
Conversation
|
thanks! |
|
Hi @xbtu2, Could you please refactor the height/volume function to their new format: See as an example: https://github.com/PyLabRobot/pylabrobot/blob/main/pylabrobot/resources/eppendorf/tubes.py This increases accuracy, and makes the gathered functions easier to (1) correct, (2) extend. # --------------------------------------------------------------------------- #
# 5 mL Eppendorf Tubes
# --------------------------------------------------------------------------- #
_eppendorf_tube_5mL_Vb_snapcap_height_to_volume_measurements = {
0.0: 0.0,
5.0: 1.342,
10.0: 1.875,
50.0: 4.975,
100.0: 6.975,
200.0: 9.909,
400.0: 13.742,
600.0: 16.242,
800.0: 18.375,
1000.0: 20.142,
1200.0: 21.809,
1500.0: 23.842,
2000.0: 27.242,
3000.0: 34.242,
4000.0: 41.009,
4500.0: 44.175,
5000.0: 47.509,
5500.0: 50.675,
}
_eppendorf_tube_5mL_Vb_snapcap_volume_to_height_measurements = {
v: k for k, v in _eppendorf_tube_5mL_Vb_snapcap_height_to_volume_measurements.items()
}
def _compute_volume_from_height_eppendorf_tube_5mL_Vb_snapcap(h: float) -> float:
"""Estimate liquid volume (µL) from observed liquid height (mm)
in the Eppendorf 5 mL V-bottom snap-cap tube,
using piecewise linear interpolation.
"""
if h < 0:
raise ValueError("Height must be ≥ 0 mm.")
if h > 55.4 * 1.05: # well cavity height + 5% tolerance
raise ValueError(f"Height {h} is too large for eppendorf_tube_5mL_Vb_snapcap.")
vol_ul = interpolate_1d(
h, data=_eppendorf_tube_5mL_Vb_snapcap_height_to_volume_measurements, bounds_handling="error"
)
return round(max(0.0, vol_ul), 3)
def _compute_height_from_volume_eppendorf_tube_5mL_Vb_snapcap(volume_ul: float) -> float:
"""Estimate liquid height (mm) from known liquid volume (µL)
in the Eppendorf 5 mL V-bottom snap-cap tube,
using piecewise linear interpolation.
"""
if volume_ul < 0:
raise ValueError(f"Volume must be ≥ 0 µL; got {volume_ul} µL")
h_mm = interpolate_1d(
volume_ul,
data=_eppendorf_tube_5mL_Vb_snapcap_volume_to_height_measurements,
bounds_handling="error",
)
return round(max(0.0, h_mm), 3)
def eppendorf_tube_5mL_Vb_snapcap(name: str) -> Tube:
"""Eppendorf cat. no.: 0030119401
5 mL snap-cap Eppendorf tube with V-bottom.
- Colour: transparent
- Material: Polypropylene
- Sterilized: No
- Autoclavable: No
- Chemical resistance:?
- Thermal resistance: ?
- Surface treatment: available as LoBind™ version
- Sealing options: na
- Centrifugation safety: Maximum safety and stability for centrifugation up to 25,000 x g
- Total volume = 5_000 ul
- URL: https://www.eppendorf.com/se-en/Products/Lab-Consumables/Lab-Tubes/EppendorfTubes-50mL-p-0030119401
- technical drawing: ./engineering_diagrams/Eppendorf_5mL_snapcap_tube.pdf
"""
diameter = 16.7
return Tube(
name=name,
size_x=diameter,
size_y=diameter,
size_z=56.7,
model=eppendorf_tube_5mL_Vb_snapcap.__name__,
max_volume=5_000, # units: ul
material_z_thickness=1.2,
bottom_type=TubeBottomType.V,
compute_volume_from_height=_compute_volume_from_height_eppendorf_tube_5mL_Vb_snapcap,
compute_height_from_volume=_compute_height_from_volume_eppendorf_tube_5mL_Vb_snapcap,
) |
|
@BioCam but the shape of the wells is cylindrical. would it make a difference? |
If it is perfectly cyclindral then no. The issue is that almost nothing is perfectly cyclindral: most wells are injection molded and require at least some tapering, which would make a cylindrical fit incorrect. But I think the main point is to use a model that enables increasing accuracy over time by providing simple means to change the data :) For this one I'd just take 2 datapoints: |
addded the appropriate compute_volume_from_height and compute_height_from_volume functions for Cor_96_wellplate_360ul_Fb in plates.py using standard cylinder volume calculations based on the well's dimensions