UniteLabs
Labware

Troughs

Define custom reagent troughs using the Trough base class.

Troughs

Troughs are used to store large amounts of liquid such as water, ethanol, or buffer solutions. In contrast to a plate, aspiration from or to a trough with multiple channels work from the same shared container volume.

Conceptually, a trough is a collection of Fillables with a defined number of access points (Hole objects) for pipetting channels. These Fillables and holes can be arranged in any layout. In the example below, a grid of 96 holes is generated — similar to a 96-well plate layout — so that multi-channel heads can access the trough at each column position. cols and rows are hints for the arrangement of the Holes.

import collections.abc
import dataclasses

from unitelabs.labware import (
    Container,
    Cuboid,
    Fillable,
    Hole,
    StandardMicroplateDimensions,
    Trough,
    Vector,
    place_standardized,
)


@dataclasses.dataclass
class StandardTrough(Trough, StandardMicroplateDimensions):
    """A standard trough."""

    cols: int = 12
    rows: int = 8
    dimensions: Vector = dataclasses.field(default_factory=lambda: Vector(z=44))
    children: collections.abc.Sequence[Fillable] = dataclasses.field(
        repr=False,
        default_factory=lambda: [
            Fillable(
                container=Container(max_volume=300_000, sections=[Cuboid(width=108, depth=72, height=40)]),
                children=[
                    Hole(dimensions=dimensions).copy(location=location)
                    for location, dimensions in place_standardized(count=96, boundary_height=44, item_height=40)
                ],
            )
        ],
    )

More complex troughs can have multiple containers, as with "12-column troughs" or "8-row troughs". For consistency across these labware types, troughs' containers are accessed like trough.containers[0], even if there is only one container (i.e. the standard trough above, the most common case).

Lids

Since labware 0.29.0, troughs are liddable — they share the same lid API as plates. A Lid can be placed at construction, queried, removed, and put back:

from unitelabs.labware import StandardTrough
from unitelabs.labware.plates import StandardLid

# Place a lid at construction
trough = StandardTrough(lid=StandardLid())

trough.has_lid       # True
trough.get_lid()     # the StandardLid instance

# Remove the lid (returns it) and put it back
lid = trough.open()
trough.has_lid       # False
trough.close(lid)
trough.has_lid       # True

A trough has no lid by default (StandardTrough().has_lid is False). When a lid is on, the trough's height accounts for it: dimensions.z + lid.dimensions.z - lid.fitting_depth (the fitting_depth is the overlap between lid and trough).

Because StandardTrough and standard plates both use StandardMicroplateDimensions, the same StandardLid fits either, and a single lid instance can be moved between them:

from unitelabs.labware.plates import Standard96Plate

lid = StandardLid()
plate = Standard96Plate(lid=lid)
trough = StandardTrough()

# Reassign the lid from the plate to the trough
plate.reassign(to=trough, lid=lid)
plate.has_lid    # False
trough.has_lid   # True