Composition Tracking#
robotools
automagically tracks the composition of well contents across liquid handling operations.
This comes in handy for tasks such as media mixing, dilution series, or checking if the final concentrations of assay components are as planned.
The composition tracking defaults to unique well-wise identifiers, but can be configured to name contents of wells explicitly.
import robotools
Let’s assume we have three labwares:
A
Trough
of water.A 5-column
Trough
with 10xMedia, 1000xAntibiotics and two empty columnsTwo Eppis with biomass of different microorganisms
From this we will prepare culture broths in the two empty trough colums to test the effectivity of the antibiotics.
minmax25 = dict(min_volume=1000, max_volume=25_000)
water = robotools.Trough("water", 1, 1, **minmax25, initial_volumes=25_000)
troughs = robotools.Trough(
"troughs", 1, columns=5, **minmax25,
initial_volumes=[10_000, 5_000, 0, 0, 0],
# Trough contents are named like this:
column_names=["10xMedia", "100xAntibiotics", None, None, None]
)
eppis = robotools.Labware(
"eppis", 2, 1, min_volume=50, max_volume=1500,
initial_volumes=500,
# Multi-well labware contents are named with a dict:
component_names={
"A01": "E.coli",
"B01": "Y.pestis",
}
)
The Labware.composition
property is a dictionary that holds the fractional composition of each well, indexed by the name of the component:
troughs.composition
{'10xMedia': array([[1., 0., 0., 0., 0.]]),
'100xAntibiotics': array([[0., 1., 0., 0., 0.]])}
We can use two of the empty trough columns to prepare and inoculate a culture broth:
V_MEDIUM = 10_000
V_FINAL = 4_000
with robotools.FluentWorklist() as wl:
wells_medium = troughs.wells[:, 2]
wells_strain_A = troughs.wells[:, 3]
wells_strain_B = troughs.wells[:, 4]
# Prepare the medium
wl.transfer(
troughs, troughs.wells[:, 0],
troughs, wells_medium,
volumes=V_MEDIUM / 10,
label="transfer 10x media"
)
wl.transfer(
troughs, troughs.wells[:, 1],
troughs, wells_medium,
volumes=V_MEDIUM / 100,
label="add antibiotics"
)
wl.transfer(
water, water.wells,
troughs, wells_medium,
volumes=(V_MEDIUM * 0.95) - troughs.volumes[:, 2],
label="add water up to 95 % of the final volume"
)
# Split the medium into the two empty troughs
for target in [wells_strain_A, wells_strain_B]:
wl.transfer(
troughs, wells_medium,
troughs, target,
volumes=0.95 * V_FINAL,
label="Transfer medium"
)
# Add inoculum from the eppis
wl.transfer(
eppis, "A01",
troughs, wells_strain_A,
volumes=0.05 * V_FINAL,
label="Inoculate A"
)
wl.transfer(
eppis, "B01",
troughs, wells_strain_B,
volumes=0.05 * V_FINAL,
label="Inoculate B"
)
We can see from the .composition
property of the troughs that there are new components:
troughs.composition
{'10xMedia': array([[1. , 0. , 0.10526316, 0.1 , 0.1 ]]),
'100xAntibiotics': array([[0. , 1. , 0.01052632, 0.01 , 0.01 ]]),
'water': array([[0. , 0. , 0.88421053, 0.84 , 0.84 ]]),
'E.coli': array([[0. , 0. , 0. , 0.05, 0. ]]),
'Y.pestis': array([[0. , 0. , 0. , 0. , 0.05]])}
The composition of the individual culture broth wells is often easier to read. We can see that the 10xMedia component indeed makes up 10 % of the final volume:
troughs.get_well_composition("A04")
{'10xMedia': 0.1,
'100xAntibiotics': 0.009999999999999997,
'water': 0.84,
'E.coli': 0.05}
troughs.get_well_composition("A05")
{'10xMedia': 0.1,
'100xAntibiotics': 0.009999999999999997,
'water': 0.84,
'Y.pestis': 0.05}
%load_ext watermark
%watermark -idu
Last updated: 2024-04-25T09:21:09.110232+02:00