Liquid Classes
A liquid class encapsulates all the parameters needed for one pipetting cycle, from aspiration through dispense. This includes flow or velocity rates, timing, and a volume correction curve that ensures the commanded volume matches what is actually transferred.
Water, ethanol, DMSO, and blood all behave differently under a pipette. A fixed set of flow rates and dwell times optimized for water will over-aspirate ethanol and under-aspirate glycerol. A liquid class is the SDK's way of naming "the full pipetting recipe for this fluid," so the same aspirate(volume=100) call can produce the correct physical result regardless of what the well contains.
Two device models, one concept
Hamilton and Bravo both use liquid classes, but the internal models differ significantly. Knowing the shape of each model is important — protocols written for one do not trivially port to the other.
| Hamilton | Bravo | |
|---|---|---|
| Motion control | Flow rates (µL/s) + dispense mode | Velocity + acceleration per phase (mm/s, mm/s²) |
| Volume correction | Correction curve dict (target → corrected) | Polynomial coefficients |
| Auto-selection | Must be passed explicitly | Auto-selected by tip type + volume |
| Dispense modes | Jet empty, jet part, surface empty, surface part | PipetteMode enum (SURFACE / BOTTOM) |
Hamilton treats pipetting as plunger flow: flow rate controls the plunger, a correction-curve dictionary maps commanded volume to corrected volume, and the dispense mode (jet vs. surface, empty vs. part) changes how the tip positions itself relative to the liquid. Every call must be passed an explicit liquid class.
Bravo treats pipetting as motion: velocity and acceleration govern the plunger per phase, a polynomial corrects the commanded volume, and the pipette mode distinguishes above-liquid vs. in-liquid dispense. When no liquid class is passed, the SDK auto-selects one based on the mounted tip type and the requested volume.
A liquid class is a dataclass
Regardless of vendor, liquid classes are Python dataclasses. Predefined classes ship with the SDK (Hamilton's LiquidClass enum, Bravo's BravoLiquidClasses factory); custom classes are defined by subclassing the vendor's base class and overriding only the fields you need to change. All other fields inherit their defaults.
This shape — dataclass, override-what-changes, serializable to dict — means liquid classes can be versioned in code, shared between protocols, and generated from calibration data. A calibration curve can fit a polynomial for Bravo or a correction-curve dict for Hamilton, and the result is a liquid class you commit to your repo alongside the protocol that uses it.
Using them in practice
- On Hamilton: pick a predefined
LiquidClassmember and pass it to every pipetting call, or subclassHamiltonLiquidClassand define your own. - On Bravo: usually rely on auto-selection; pass a specific class explicitly when you need to override the default, or subclass
BravoLiquidClassto encode your reagent.
See Liquid Classes for the procedural how-to, including predefined-class browsing, parameter reference tables, and custom-class examples.
Liquids
How to represent liquids in the SDK — predefined types, custom instances with physical metadata, traceable samples, and custom aliases — and when to use each.
Tips and Tip Tracking
How the SDK models tips as tracked, lifecycle-managed resources, and why independent-channel heads and monolithic 96-heads work differently.