PlatePlan
Software to help plan your high-throughput, combinatorial liquid handling dispenses.
Install / Use
/learn @jensenlab/PlatePlanREADME
Welcome to PlatePlan
PlatePlan is the bridge between your hypotheses and results. In order to make that jump, a lot goes into the logistics and planning out an experiment, from how many multi-well plates to use and where to dispense each reagent, to which reagents to batch together and how much volume to dispense. These logistics are especially challenging in the case of high-throughput, combinatorial assays where you may have tens of thousands of unique dispenses to manage and keep track of.
PlatePlan takes some of that burden away from the experimenter by handling those logistics for you. It has been tailored to our lab's set up (Jensen Lab, UIUC) to take advantage of the Formulatrix Mantis liquid handling robot for combinatorial bacteria growth assays, but can be adapted to fit another use case with relative ease.
It does so by generalizing an experimental structure into Python objects, explained further in depth in Structure. We've tried to make it easy for an experimenter to get started. To make an experiment, you must make a protocol interfacing with the PlatePlan package in the form of a .py file. The biggest hurdle to use PlatePlan is determining what final solutions you want your liquid handler to complete for you--this comes in the form of a list of Solutions that each map a Reagent to its final concentration. Beyond inputting a few extra experimental parameters like how many replicates or blanks you need, that's it.
You can refer to Running an Experiment for more detailed requirements and instructions or look at our sample experiment in templates/l2o_amino_acids.py which is an experiment we've developed to perform a large scale leave-two-out growth assay for amino acids in a chemically defined medium (CDM). A simpler example experiment is also located in templates/pair_combos.py and used as the example code for the sections below.
Software requirements
- Clone this repo using
git clone https://github.com/jensenlab/PlatePlan.git - run
cd PlatePlanto enter the directory - You need a Pipenv virtual environment for this project
- 2.1. Install pipenv, a Python virtual environment manager
- 2.2. run
pipenv --python 3.6in the root project directory to initialize a Pipenv environment - 2.3. run
pipenv installin the root project directory to install the required dependencies - 2.4. run
pipenv shellin the root project directory to enter the virtual environment. You should see a(PlatePlan)prefix in the terminal to indicate you are in a virtual environment
- A copy of Gurobi optimizer must be installed in your environment, with the Python interface set up
- 4.1. Install Gurobi on your computer and activate the license. Once this is completed, set up the Python interface for the Pipenv virtual environment below
- 4.2. In the
(PlatePlan)virtual environment, runwhich pythonand copy this path - 4.3.
cdto the install location of your Gurobi install. On Linux it might be similar to/opt/gurobi811/ - 4.4.
cd linux64 - 4.5. Paste your copied path from Step 4.2
[copied Python path] setup.py install. Depending on your path location, you may need elevated permissions. If so, addsudobefore the command - 4.6. If necessary (Linux), set up your environment variables according to the Quickstart Guide in Step 4
- 4.7 To test if it installed correctly, run
pythonto start a Python shell in your terminal. Then runimport gurobipy. If there are no errors, the Gurobi interface has installed successfully!
- You are ready to make your first PlatePlan protocol
Structure
In order to define an experiment, the user needs to define the input Ingredients: Solutions, Reagents, and Stocks. Stocks represent the physical analog of Solutions which are virtual themselves. Solutions can consist of single or multiple reagents, as long as you define a concentration for each.
Ingredients
Reagents
Reagents are the smallest unit of the experiment you are planning, usually a singular component/reagent. They have 3 properties:
id: An identifier string of the reagent, e.g. 'sodium_chloride'
name: A secondary name of the reagent, e.g. 'NaCl'
molecular_weight: A string of the molecular weight, e.g. '58.44 g/mol'
Solutions
Solutions are composed of one or more Reagent.id and their concentrations in solution. Solutions represent both the solutions you are dispensing and the solutions you are trying to make. They are composed of 3 components:
properties:
id: A string of the solution name, e.g. 'sodium_chloride'
reagents: A dictionary mapping Reagent.id -> concentration (as string), e.g.
{
'sodium_chloride' : '50 mg/L',
'sodium_carbonate' : '50 mg/L'
}
solvent: A string of the solvent
Stocks
Stocks contain a single Solution with additional real-world laboratory information, useful for inventory and management. They are composed of the following attributes:
ingredient: The corresponding Solution object
id: The ID of this new stock
quantity: The volume of the stock you have stored
labware: The type of labware the stock is stored in
location: The location of the stock
date_made: The date the stock was made
date_expires: The expiry date of the stock
Example experiment set up using stocks and solutions
For this example experiment, we will make all combinations of 2 of the following three amino acids: alanine, arginine, aspartic acid. We have them stored as 100x stocks in our lab. And the final concentration of each will be 10 mg/ml. We need to generate 3 Reagents (alanine, arginine, aspartic acid) , 3 100x Solution Stocks (alanine stock, arginine stock, aspartic acid stock), and 3 Solutions to make (alanine+arginine, alanine+aspartic acid, arginine+aspartic acid).
Generate 3 Solution Stocks:
"""pair_combos.py"""
from plateplan import (
constants, ingredients, makeids, mantis, mapper, scheduling, units
)
amino_acid_ids = ["ALA", "ARG", "ASP"]
amino_acid_names = ["alanine", "arginine", "aspartic acid"]
final_conc = {
"ALA": "10 mg/ml",
"ARG": "10 mg/ml",
"ASP": "10 mg/ml"
}
reagents = {}
stocks = {}
# Define stock solutions and reagents
for i in range(3):
id_ = amino_acid_ids[i] # Get id value
name = amino_acid_names[i] # Get name value
conc = str(units.parse(final_conc[id_]) * 100) #Get 100x stock conc value
reagents[id_] = ingredients.Reagent(id_=id_, name=name) # Not used in this experiment
soln = ingredients.Solution(reagents={id_: conc}, id_=id_+"_stock") # Make solution
stocks[id_] = ingredients.Stock(
ingredient=soln,
date_made=datetime.date.today(), #Today's date
date_expires=datetime.date.today() + datetime.timedelta(6 * 365 / 12), # +6 months for expiry date
quantity=units.parse("10 ml"), # Amount of stock we have stored
labware="Conical15ml", # What its stored in
) # Make stock from Solution, soln and add it to stocks list
...
Generate Solutions to Make:
"""pair_combos.py"""
...
solutions = []
# Define solutions you want to make
pairs = [["ALA", "ARG"], ["ALA", "ASP"], ["ARG", "ASP"]]
for first, second in pairs:
reagents = {
first: final_conc[first],
second: final_conc[second]
}
id_ = first + "_" + second + "_mixture"
soln = ingredients.Solution(reagents=reagents, id_=id_) # Make solution
solutions.append(soln)
# Add water to solutions so we can use it as a blank
water = ingredients.Solution(reagents={"water": "0 g/l"}, id_="water") # Make solution
solutions.append(water)
...
Running an Experiment
Once you have generated all the necessary Solutions and Stocks needed to run the experiment, you must now define the other experiment parameters and run the scheduler.
Defining your experiment parameters
solutions: list of ingredients.Solutions you want to make. Each one of these Solutions.id must be present in a Stock in stocks below.
strains: list of str of the bacteria you want to use
environments: list of str of the environments you want to grow in
stocks: list of ingredients.Stocks that you have for dispensing
plate: a constants.labware Labware plate, e.g. constants.labware["WP384"] for 384-well plate
replicates: int number of replicates
plate_control: tuple of (Solution.id, quantity) to use for the control, e.g. ("CDM", 1). This Solution.id MUST be a solution given in
solutions. The scheduler will not make any extra wells of the control Solution, but rather uses the actual Solution dispenses as the control wells, unlike the blanks.
plate_blank: tuple of (Solution.id, quantity) to use for the blank, e.g. ("CDM", 1). This Solution.id MUST be a solution that exists in the solutions . The scheduler will make quantity * replicates number of extra wells of the blank Solution to use as the blank wells, unlike the controls.
randomize: boolean flag to set if replicates should have randomized locations within the plate (replicates will always be placed on the same plate)
plate_prefix: str to add to the plate name
total_volume: str of volume in each well, e.g. "80 ul"
working_volume: str of the working volume in each well, e.g. "80 ul"
min_drop_size: str of the volume corresponding to the maximum resolution for your liquid handler, e.g. "0.1 ul"
quantity_units: str of concentration unit to use for liquid handler, e.g. "ug/ul"
excess: str of reagen
Related Skills
node-connect
352.5kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
111.3kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
352.5kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
352.5kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
