1 Example clients
Four small Python programs, all built on one library. They are written to be read as much as run — between them they cover everything in this guide.
| File | What it does | Changes the machine |
|---|---|---|
| kb_client.py | the library the others use | — |
| kb_watch.py | prints what the machine is doing, live | no |
| kb_queue_assay.py | groups a FASTA file into pools and queues it | yes |
| kb_run_head.py | starts a run and answers the machine | yes |
| kb_lamp_primers.fasta | the example assay | — |
1.1 What you need
Python 3 and requests. Nothing else.
pip install requests
Put the files in one directory; the three programs import kb_client from alongside
themselves.
1.2 Watch the machine
Start here. It only reads, so it is safe against a Kilobaser that is in the middle of a real run, and it is the quickest way to see what the device actually broadcasts.
python3 kb_watch.py --host kilobaser.lab.example.org --user apibot --insecure --queue
Leave it running in one terminal while you make calls in another. Expect long silences — a machine that is not doing anything sends nothing at all.
1.3 Queue an assay
python3 kb_queue_assay.py --host kilobaser.lab.example.org --user apibot \
--insecure --dry-run kb_lamp_primers.fasta
--dry-run prints the plan and touches nothing. Run it that way first:
Standard Cartridge + Standard chip (2 / 2)
6 oligos, 162 bases
! 162 bases needs 2 cartridges (Standard Cartridge holds 150)
LAMP-042_RPP30-F3 18 nt
...
6-FAM Cartridge + 6-FAM+BHQ-1 chip (3 / 3-BHQ1)
1 oligo, 24 bases
LAMP-042_RPP30-P 24 nt
dry run -- nothing was queued
It reads the compatibility matrix from the device, groups by cartridge and chip, orders
fluorophore groups last, and checks each group against the cartridge budget before
queueing anything. Drop --dry-run to submit.
Records default to an unmodified oligo. A record that needs something else says so in its header:
>LAMP-042_RPP30-P cartridge=3 chip=3-BHQ1
AGCCTGACTTGCAAGGTCATGCTT
1.4 Drive a run
python3 kb_run_head.py --host kilobaser.lab.example.org --user apibot --insecure
Starts the first entry in the queue and answers each checkpoint as it appears, following the machine through the chip and cartridge steps it inserts on the way.
Somebody has to be at the Kilobaser. Most checkpoints are the machine asking whether a physical thing has been done; this program confirms that it has. Running it against a machine nobody is attending will confirm a chip that was never inserted.
--on-finish chooses what to do when a run completes: end stops so the product can be
collected, continue goes straight into the next queued run.
1.5 The library
kb_client.py is about 250 lines and exists mostly to absorb four things that would
otherwise surprise you:
- the session is a cookie, and it dies when the device restarts, so every call re-authenticates once and retries;
- errors arrive double-encoded, so
KilobaserErrorunwraps them into a code and a message; POST /processRuns/queuedoes not return the id, soqueue_oligoreads the queue back and returns the created entry;processRunQueueevents replace the queue whileprocessRunsevents merge a single run, sowatch()applies each correctly.
The two pieces worth copying into your own code are watch(), which maintains a mirror
of the device from the event stream, and wait_for(), which blocks until a predicate
over that mirror is true. Between them they are the whole of an integration's control
flow:
kb.wait_for(lambda s: not s["queue"]) # everything has run
kb.wait_for(lambda s: checkpoint(s)) # the machine wants an answer
1.6 Adapting them
They are examples, not a supported SDK. Take them apart.
Two things to change before using any of this in earnest: replace verify=False with the
device's certificate, as in connect and authenticate, and give
the integration its own account rather than a person's, so the run history says where a
submission came from.