API reference¶
Built from the docstrings in src/liulab_mbio/, so this page and the code cannot drift apart.
Write the docstring; this page follows.
What to import¶
liulab_mbio itself re-exports only __version__. Import a name from the module that owns it:
from liulab_mbio.io import read_record
from liulab_mbio.goldengate import plan_assembly
Two names are spelled twice across the package on purpose — Check and Junction each mean
something different in the two modules that define them. A
liulab_mbio.checks.Check is the judged check, with the value it measured. A
liulab_mbio.protocol.Check is how a protocol page shows one. A flat re-export would have to
rename one of each pair, and would import every dependency the moment you imported the package.
So the module path is the name.
liulab_mbio.goldengate re-exports the pipeline's entry point and its result types.
design and ligase are not re-exported: reach them at
liulab_mbio.goldengate.design and liulab_mbio.goldengate.ligase.
The examples are tests¶
pixi run check runs the Examples blocks in src/liulab_mbio/, so an example that no longer
matches its code fails the tests.
Write one where it makes the object easier to use, and leave it out where it would not. An example nobody keeps up to date is worse than none.
Keep an example cheap, offline and deterministic. It has to give the same answer on any
machine, with no network. A line that cannot do that needs # doctest: +SKIP at the end of
that line.
Two things about that marker are easy to get backwards:
- It covers only the line it sits on. It does not carry to the line below. In a block that mixes lines that run with lines that cannot, each line that cannot run needs its own.
- A trailing comment written as plain prose looks just like a marker and is not one. Only
the
# doctest:form is read as one.
The sequence model¶
Everything else reads and writes these. Coordinates are 0-based and half-open, and a span across the origin of a circular record ends past the record's length — see the coordinates decision.
liulab_mbio.sequence
¶
The sequence model every other module reads and writes.
Coordinates are 0-based and half-open: Segment(start, end) holds bases start to
end - 1. A segment across the origin of a circular record ends past the record's length.
File formats convert at their own boundary; see docs/adr/0001-coordinates.md.
BindingSite
dataclass
¶
Where a primer's 3' part anneals to a record.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
start
|
int
|
0-based, half-open, as for |
required |
end
|
int
|
0-based, half-open, as for |
required |
strand
|
Strand
|
|
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
Unless |
Source code in src/liulab_mbio/sequence.py
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | |
__post_init__
¶
__post_init__() -> None
Refuse an empty span or a strand that is neither forward nor reverse.
Source code in src/liulab_mbio/sequence.py
149 150 151 152 153 | |
Feature
dataclass
¶
A named, typed annotation over one or more segments.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
The label shown on a map. |
required |
type
|
str
|
A GenBank feature key, such as |
required |
segments
|
tuple[Segment, ...]
|
In top-strand order, whatever the strand. |
required |
strand
|
Strand
|
The strand the feature reads along. |
NONE
|
qualifiers
|
Mapping[str, tuple[str | int, ...]]
|
GenBank-style qualifiers, each holding one or more values. |
dict()
|
color
|
str | None
|
|
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in src/liulab_mbio/sequence.py
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | |
__post_init__
¶
__post_init__() -> None
Refuse a feature with no segment.
Source code in src/liulab_mbio/sequence.py
121 122 123 124 | |
Primer
dataclass
¶
A named oligonucleotide.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
The name it is ordered under. |
required |
sequence
|
str
|
5' to 3', tail included. Stored upper-case. |
required |
binding_sites
|
tuple[BindingSite, ...]
|
Where it anneals to the record that carries it. |
()
|
description
|
str
|
Free text. |
''
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in src/liulab_mbio/sequence.py
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | |
__post_init__
¶
__post_init__() -> None
Upper-case and check the sequence.
Source code in src/liulab_mbio/sequence.py
183 184 185 | |
Segment
dataclass
¶
One contiguous span of a feature.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
start
|
int
|
0-based, half-open. |
required |
end
|
int
|
0-based, half-open. |
required |
name
|
str
|
A label for this segment alone, such as a promoter's |
''
|
color
|
str | None
|
|
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
Unless |
Source code in src/liulab_mbio/sequence.py
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | |
__post_init__
¶
__post_init__() -> None
Refuse an empty or negative span.
Source code in src/liulab_mbio/sequence.py
83 84 85 | |
SequenceRecord
dataclass
¶
A DNA sequence with its topology, features, primers and notes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sequence
|
str
|
Stored upper-case. |
required |
topology
|
Topology
|
|
'linear'
|
name
|
str
|
The name shown on a map. |
''
|
features
|
tuple[Feature, ...]
|
Every feature segment and primer binding site must fit the sequence under its topology. |
()
|
primers
|
tuple[Feature, ...]
|
Every feature segment and primer binding site must fit the sequence under its topology. |
()
|
notes
|
Mapping[str, str]
|
Descriptive fields, such as |
dict()
|
extras
|
Mapping[str, object]
|
Format-specific data a reader keeps for its writer. Ignored by |
dict()
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in src/liulab_mbio/sequence.py
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 | |
__len__
¶
__len__() -> int
Return the number of bases.
Source code in src/liulab_mbio/sequence.py
235 236 237 | |
__post_init__
¶
__post_init__() -> None
Upper-case the sequence and check every span fits.
Source code in src/liulab_mbio/sequence.py
223 224 225 226 227 228 229 230 231 232 233 | |
extract
¶
Return the bases under a feature or segment, reading across the origin.
A reverse-strand feature reads as the reverse complement of its joined segments. A bare segment reads off the top strand.
Raises:
| Type | Description |
|---|---|
ValueError
|
If a segment does not fit this record. |
Examples:
>>> SequenceRecord("AACCGGTTAC", topology="circular").extract(Segment(8, 12))
'ACAA'
Source code in src/liulab_mbio/sequence.py
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 | |
Strand
¶
Bases: IntEnum
The strand a feature or primer binding site lies on.
Source code in src/liulab_mbio/sequence.py
47 48 49 50 51 52 53 54 | |
reverse_complement
¶
reverse_complement(sequence: str) -> str
Return the reverse complement of an IUPAC DNA sequence, keeping its case.
Examples:
>>> reverse_complement("GGTCTC")
'GAGACC'
Source code in src/liulab_mbio/sequence.py
24 25 26 27 28 29 30 31 32 | |
Checks¶
liulab_mbio.checks
¶
A check: one verdict and the value it judged, and the worst of several verdicts.
A check no sourced threshold judges carries no verdict, None, rather than a pass.
Check
dataclass
¶
One verdict on a primer, a pair or an assembled product, with the value it judged.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
What was measured, such as |
required |
status
|
Status | None
|
One of |
required |
value
|
float
|
The measurement, in the unit the module that judged it documents. |
required |
detail
|
str
|
What a reader needs besides the number. |
''
|
Source code in src/liulab_mbio/checks.py
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | |
worst
¶
worst(statuses: Iterable[Status | None]) -> Status
Return the worst of these verdicts, passing over any that is None.
Nothing judged at all is a pass.
Examples:
>>> worst(("pass", None, "warn"))
'warn'
Source code in src/liulab_mbio/checks.py
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | |
Files¶
liulab_mbio.io
¶
Read a sequence file into the shared model, choosing the reader by its suffix.
read_record
¶
read_record(path: str | PathLike[str]) -> SequenceRecord
Read a .dna, GenBank or FASTA file holding one sequence.
Raises:
| Type | Description |
|---|---|
ValueError
|
If the suffix names no reader, or the file holds no single record. |
Source code in src/liulab_mbio/io.py
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | |
liulab_mbio.snapgene
¶
Read and write SnapGene .dna files as SequenceRecord.
A .dna file is a stream of packets: a type byte, a big-endian 4-byte length, then the
payload. SnapGene's 1-based inclusive ranges are converted here and nowhere else.
What the model does not hold — the cut-site cache, history, display settings, and the extra
attributes SnapGene writes on a feature — is kept in record.extras and written back
verbatim. A packet that describes the bases is dropped once the sequence changes, so that
SnapGene recomputes it.
read_dna
¶
read_dna(path: str | PathLike[str]) -> SequenceRecord
Read a SnapGene .dna file.
SnapGene's HTML markup in note and qualifier text is kept as it is written.
Raises:
| Type | Description |
|---|---|
ValueError
|
If the file is not a SnapGene DNA file. |
Source code in src/liulab_mbio/snapgene.py
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 | |
write_dna
¶
write_dna(
record: SequenceRecord, path: str | PathLike[str]
) -> None
Write record as a SnapGene .dna file.
A feature or primer unchanged since the file it was read from is written back verbatim, so that what the model does not hold survives. A feature with no colour takes SnapGene's default grey.
Source code in src/liulab_mbio/snapgene.py
244 245 246 247 248 249 250 251 | |
liulab_mbio.edits
¶
Insert, delete and replace spans of a SequenceRecord, shifting what it annotates.
The functions here know no file format. Coordinates are the model's: 0-based, half-open, and a span across the origin of a circular record ends past the record's length.
EditReport
dataclass
¶
What an edit did to the features and binding sites it did not simply shift.
Every entry holds the feature or primer as it was before the edit.
Attributes:
| Name | Type | Description |
|---|---|---|
trimmed |
tuple[Feature, ...]
|
Features that lost bases, including any that lost a whole segment. |
dropped |
tuple[Feature, ...]
|
Features left with no bases at all. |
changed |
tuple[Feature, ...]
|
Features the edit fell inside: kept, and now spanning the new bases. |
dropped_sites |
tuple[tuple[Primer, BindingSite], ...]
|
Binding sites the edit overlapped, with the primer they belong to. A primer no longer anneals where its bases changed, so such a site is dropped rather than trimmed. |
Source code in src/liulab_mbio/edits.py
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | |
delete
¶
delete(
record: SequenceRecord, start: int, end: int
) -> tuple[SequenceRecord, EditReport]
Delete the bases in [start, end).
Source code in src/liulab_mbio/edits.py
60 61 62 | |
insert
¶
insert(
record: SequenceRecord, position: int, bases: str
) -> tuple[SequenceRecord, EditReport]
Insert bases before position, shifting everything after it.
Examples:
>>> record, report = insert(SequenceRecord("AACCGG"), 2, "TT")
>>> record.sequence
'AATTCCGG'
Source code in src/liulab_mbio/edits.py
48 49 50 51 52 53 54 55 56 57 | |
replace
¶
replace(
record: SequenceRecord, start: int, end: int, bases: str
) -> tuple[SequenceRecord, EditReport]
Replace the bases in [start, end) with bases.
On a circular record the span may run across the origin, ending past the record's length; the bases that remain keep their own indices where they can, so the origin moves only when the edit removes it.
Raises:
| Type | Description |
|---|---|
ValueError
|
If the span does not fit the record under its topology. |
Source code in src/liulab_mbio/edits.py
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | |
rotate
¶
rotate(
record: SequenceRecord, origin: int
) -> SequenceRecord
Return the circular record read from origin, which becomes its first base.
Raises:
| Type | Description |
|---|---|
ValueError
|
If the record is linear. |
Examples:
>>> rotate(SequenceRecord("AACCGG", topology="circular"), 2).sequence
'CCGGAA'
Source code in src/liulab_mbio/edits.py
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | |
Enzymes, sites and codons¶
liulab_mbio.enzymes
¶
Restriction enzymes: the shipped records and how their cut offsets are written.
A cut offset is a 0-based boundary counted from the first base of the recognition site as
written 5' to 3', like a slice point: offset k severs a strand between site bases k - 1
and k. Enzyme.top_cut is the cut in the strand carrying the site, Enzyme.bottom_cut the
cut in the complementary strand, written in that same frame — the bottom strand is severed
between the partners of bases k - 1 and k.
An offset outside 0..len(site) is a cut outside the site, which is what makes an enzyme
Type IIS. REBASE's GGTCTC(1/5) for BsaI is top_cut=7, bottom_cut=11.
Enzyme
dataclass
¶
One restriction enzyme and where it cuts.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
The REBASE name, such as |
required |
site
|
str
|
The recognition site, IUPAC, 5' to 3'. Stored upper-case. |
required |
top_cut
|
int
|
Cut offsets, as described in the module docstring. |
required |
bottom_cut
|
int
|
Cut offsets, as described in the module docstring. |
required |
isoschizomers
|
tuple[str, ...]
|
Enzymes a supplier sells that read and cut exactly this site. Neoschizomers — the same site cut elsewhere, as XmaI cuts SmaI's — are not among them. |
()
|
commercial_name
|
str | None
|
The product the other supplier fields describe, such as |
None
|
catalog_number
|
str | None
|
The product the other supplier fields describe, such as |
None
|
supplier
|
str | None
|
The product the other supplier fields describe, such as |
None
|
incubation_celsius
|
int | None
|
The supplier's digestion temperature, which is not always a protocol's temperature. |
None
|
heat_inactivation_celsius
|
int | None
|
|
None
|
heat_inactivation_minutes
|
int | None
|
|
None
|
methylation
|
Mapping[str, str]
|
The supplier's Dam, Dcm and CpG sensitivity, keyed |
dict()
|
unverified
|
tuple[str, ...]
|
Fields no source stated. Never a guess. |
()
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in src/liulab_mbio/enzymes.py
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | |
end
property
¶
end: EndType
The end left behind: "5'", "3'" or "blunt".
Examples:
>>> Enzyme("KpnI", "GGTACC", top_cut=5, bottom_cut=1).end
"3'"
supplier_label
property
¶
supplier_label: str
The enzyme as its supplier sells it: the commercial name and the catalogue number.
Examples:
>>> Enzyme("BsaI", "GGTCTC", top_cut=7, bottom_cut=11).supplier_label
'BsaI'
>>> sold = Enzyme("BsaI", "GGTCTC", top_cut=7, bottom_cut=11, commercial_name="BsaI-HFv2",
... catalog_number="R3733")
>>> sold.supplier_label
'BsaI-HFv2 (R3733)'
__post_init__
¶
__post_init__() -> None
Upper-case the site and refuse one that is not IUPAC DNA.
Source code in src/liulab_mbio/enzymes.py
77 78 79 80 81 82 83 84 | |
cut_positions
¶
cut_positions(
start: int, strand: Strand = FORWARD
) -> tuple[int, int]
Where this enzyme cuts a record holding its site at start.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
start
|
int
|
The 0-based index where the site begins on the top strand. A reverse-strand site is
the reverse complement of |
required |
strand
|
Strand
|
Which strand carries the site. |
FORWARD
|
Returns:
| Type | Description |
|---|---|
tuple[int, int]
|
The top-strand cut and the bottom-strand cut, in record coordinates and in that order whatever the strand. Either may fall outside the record, which is what a circular record's caller reduces modulo its length. |
Examples:
>>> Enzyme("BsaI", "GGTCTC", top_cut=7, bottom_cut=11).cut_positions(4)
(11, 15)
Source code in src/liulab_mbio/enzymes.py
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | |
overhang
¶
overhang(
record: SequenceRecord,
start: int,
strand: Strand = FORWARD,
) -> str
Return the top-strand bases this enzyme leaves single-stranded, 5' to 3'.
Empty for a blunt cutter. On a circular record the overhang reads across the origin.
Raises:
| Type | Description |
|---|---|
ValueError
|
If either cut falls off the end of a linear record. |
Source code in src/liulab_mbio/enzymes.py
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | |
enzymes
¶
enzymes() -> tuple[Enzyme, ...]
Return every shipped enzyme, ordered by name.
Source code in src/liulab_mbio/enzymes.py
214 215 216 | |
get_enzyme
¶
get_enzyme(name: str) -> Enzyme
Return one enzyme by its name, its commercial name, or an isoschizomer's name.
Raises:
| Type | Description |
|---|---|
KeyError
|
If no shipped enzyme answers to |
Examples:
>>> get_enzyme("BsaI-HFv2").site
'GGTCTC'
Source code in src/liulab_mbio/enzymes.py
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 | |
liulab_mbio.sites
¶
Find restriction sites in a record, put one there, and take one out of a coding sequence.
Two rules decide what counts as a site, and both matter to whoever asks whether an enzyme is free to use:
- A site is reported where the enzyme may cut. Every position of the match needs a base the
recognition site admits, so an IUPAC code in the template is read as the bases it stands for
and a site it could spell is reported.
CutSite.certainisFalsefor such a hit. Erring towards reporting is the safe direction here: an enzyme called free of sites is one a design goes on to rely on. - A palindromic site is one site, not two. Its recognition site reads the same on either strand, so only the forward match is reported.
Coordinates are the model's, 0-based and half-open, and a site across the origin of a circular record ends past the record's length.
CutSite
dataclass
¶
One recognition site found in a record, and where its enzyme cuts there.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
enzyme
|
Enzyme
|
The enzyme that reads this site. |
required |
start
|
int
|
0-based index of the first base of the match on the TOP strand, whichever strand the site lies on. |
required |
strand
|
Strand
|
|
required |
top_cut
|
int
|
Where the two strands are severed, in the record's own coordinates and in that order
whatever the strand. Reduced modulo the length on a circular record; on a linear one
either may fall outside the record, which is what |
required |
bottom_cut
|
int
|
Where the two strands are severed, in the record's own coordinates and in that order
whatever the strand. Reduced modulo the length on a circular record; on a linear one
either may fall outside the record, which is what |
required |
overhang
|
str | None
|
The top-strand bases the two cuts leave single-stranded, 5' to 3'; |
required |
certain
|
bool
|
|
True
|
Source code in src/liulab_mbio/sites.py
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | |
Domestication
dataclass
¶
One synonymous codon change, and the site it took away.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
site
|
CutSite
|
The site that was there before the change. |
required |
feature
|
Feature
|
The coding sequence the codon belongs to, as it read before the change. |
required |
position
|
int
|
0-based index on the TOP strand where the codon's three bases begin. A codon of a
reverse-strand coding sequence reads back from |
required |
codon_index
|
int
|
Which codon of the coding sequence this is, counting from zero. |
required |
old_codon
|
str
|
The codon before and after, read 5' to 3' along the coding sequence. |
required |
new_codon
|
str
|
The codon before and after, read 5' to 3' along the coding sequence. |
required |
amino_acid
|
str
|
The one-letter amino acid both codons spell. |
required |
Source code in src/liulab_mbio/sites.py
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | |
DomesticationReport
dataclass
¶
What domestication changed, and what it left for someone to decide.
Attributes:
| Name | Type | Description |
|---|---|---|
changes |
tuple[Domestication, ...]
|
Each site taken away, with the codon change that did it. |
outside_cds |
tuple[CutSite, ...]
|
Sites lying in no coding sequence. Removing one of these changes what the record spells, so it is reported and the choice is left to the caller. |
unchanged |
tuple[CutSite, ...]
|
Sites in a coding sequence that no synonymous change could take away. |
Source code in src/liulab_mbio/sites.py
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | |
Fragment
dataclass
¶
One piece a digest leaves, bounded by the cuts in the top strand.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
start
|
int
|
The two top-strand cuts that bound it, 0-based and half-open. A fragment across the
origin of a circular record keeps |
required |
end
|
int
|
The two top-strand cuts that bound it, 0-based and half-open. A fragment across the
origin of a circular record keeps |
required |
left_overhang
|
str
|
The single-stranded bases at each end, written as the TOP strand reads them 5' to 3',
and |
required |
right_overhang
|
str
|
The single-stranded bases at each end, written as the TOP strand reads them 5' to 3',
and |
required |
Source code in src/liulab_mbio/sites.py
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | |
length
property
¶
length: int
How many bases of top strand it carries, which is what a gel measures.
digest
¶
digest(
record: SequenceRecord,
enzymes: EnzymeLike | Iterable[EnzymeLike],
) -> tuple[Fragment, ...]
Cut record with one or more enzymes and return the fragments, in top-strand order.
A site whose cut falls off the end of a linear record is read but not cut, so it splits nothing. An uncut linear record is one fragment, being a molecule already; an uncut circular record is none, nothing having been cut.
Examples:
>>> [piece.length for piece in digest(SequenceRecord("AAAAGGTCTCGTTTTCCCC"), "BsaI")]
[11, 8]
Source code in src/liulab_mbio/sites.py
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 | |
domesticate
¶
domesticate(
record: SequenceRecord,
enzymes: EnzymeLike | Iterable[EnzymeLike],
*,
usage: CodonUsage | None = None,
avoid: Iterable[EnzymeLike] = (),
) -> tuple[SequenceRecord, DomesticationReport]
Take away every site of enzymes that a synonymous codon change can reach.
A site inside a coding sequence goes by changing one codon for another spelling the same
amino acid, keeping the reading frame and the protein. The replacement is the one the host
uses most often, among those that take the site away and spell no new site for enzymes or
avoid. A site lying in no coding sequence is reported and not edited: removing it
would change what the record spells, which is the caller's decision to make.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
record
|
SequenceRecord
|
The record to domesticate. |
required |
enzymes
|
EnzymeLike | Iterable[EnzymeLike]
|
The enzyme or enzymes whose sites should go. |
required |
usage
|
CodonUsage | None
|
The host's codon usage. The shipped E. coli K-12 table by default. |
None
|
avoid
|
Iterable[EnzymeLike]
|
Further enzymes whose sites no change may create. |
()
|
Returns:
| Type | Description |
|---|---|
tuple[SequenceRecord, DomesticationReport]
|
The edited record, and what changed and what did not. |
Source code in src/liulab_mbio/sites.py
434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 | |
find_sites
¶
find_sites(
record: SequenceRecord,
enzymes: EnzymeLike | Iterable[EnzymeLike],
) -> tuple[CutSite, ...]
Return every site one or more enzymes read in record, in top-strand order.
Both strands are searched, and a circular record is searched across its origin.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
record
|
SequenceRecord
|
The record to search. |
required |
enzymes
|
EnzymeLike | Iterable[EnzymeLike]
|
One enzyme or several, each an |
required |
Raises:
| Type | Description |
|---|---|
KeyError
|
If a name is not one the package ships. |
Examples:
>>> record = SequenceRecord("AAAAGGTCTCGTTTTCCCC")
>>> [(site.start, site.overhang) for site in find_sites(record, "BsaI")]
[(4, 'TTTT')]
Source code in src/liulab_mbio/sites.py
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 | |
free_enzymes
¶
free_enzymes(
records: Iterable[SequenceRecord],
enzymes: Iterable[EnzymeLike] | None = None,
) -> tuple[Enzyme, ...]
Return the enzymes with no site in any of records, in the order they were given.
These are the enzymes a Golden Gate design can use without domesticating anything.
Source code in src/liulab_mbio/sites.py
243 244 245 246 247 248 249 250 251 252 | |
has_site
¶
has_site(
record: SequenceRecord,
enzymes: EnzymeLike | Iterable[EnzymeLike],
) -> bool
Whether record still holds a site any of these enzymes reads.
Source code in src/liulab_mbio/sites.py
222 223 224 | |
insert_site
¶
insert_site(
record: SequenceRecord,
enzyme: EnzymeLike,
position: int,
*,
strand: Strand = FORWARD,
) -> tuple[SequenceRecord, EditReport]
Put one enzyme's recognition site into record before position.
Everything after the site shifts, and the report says which features the insertion fell inside. A reverse-strand site is written as the reverse complement, so the enzyme reaches back towards lower coordinates to cut.
Raises:
| Type | Description |
|---|---|
ValueError
|
If the recognition site holds an IUPAC code, there being no one sequence to write. |
Examples:
>>> edited, _ = insert_site(SequenceRecord("AAAACCCC"), "BsaI", 4)
>>> edited.sequence
'AAAAGGTCTCCCCC'
Source code in src/liulab_mbio/sites.py
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 | |
primer_tail
¶
primer_tail(
enzyme: EnzymeLike,
overhang: str = "",
*,
spacer: str | None = None,
spacer_length: int = SPACER_LENGTH,
avoid: Iterable[EnzymeLike] = (),
) -> str
Build the 5' tail of a cloning primer, 5' to 3', for the caller to put its own 3' end on.
The tail is a spacer, the recognition site, the bases the enzyme reaches over, and
then overhang — so that cutting the amplicon leaves exactly overhang single-stranded.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
enzyme
|
EnzymeLike
|
The enzyme the tail is cut by. |
required |
overhang
|
str
|
The overhang the cut should leave, as long as the enzyme leaves. Empty, and only empty, for an enzyme that cuts inside its own site. |
''
|
spacer
|
str | None
|
The bases 5' of the site. Chosen when not given, and checked when it is. |
None
|
spacer_length
|
int
|
How many bases to choose when |
SPACER_LENGTH
|
avoid
|
Iterable[EnzymeLike]
|
Enzymes besides this one whose sites the tail must not spell. |
()
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Examples:
>>> primer_tail("BsaI", "AATG")
'AAACACGGTCTCAAATG'
Source code in src/liulab_mbio/sites.py
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 | |
site_counts
¶
site_counts(
records: Iterable[SequenceRecord],
enzymes: Iterable[EnzymeLike] | None = None,
) -> dict[str, int]
Count the sites each enzyme reads across several records, keyed by enzyme name.
Every enzyme asked about gets an entry, so a count of zero is stated rather than missing.
enzymes defaults to every enzyme the package ships.
Source code in src/liulab_mbio/sites.py
227 228 229 230 231 232 233 234 235 236 237 238 239 240 | |
liulab_mbio.codons
¶
How often a host spells each codon, and the genetic code that groups them.
A table here counts every codon over every complete coding sequence of one genome, so it is a
measurement of that genome rather than a copy of a published compilation.
scripts/build_codon_usage.py rebuilds it and docs/research/codon-usage.md says where the
sequences came from.
A whole-genome table is the background the genome itself uses. It is not a highly expressed reference set, which is what a codon adaptation index wants and is a different object.
CodonUsage
dataclass
¶
How often one genome spells each of the 64 codons.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
The short name this table is asked for by, such as |
required |
organism
|
str
|
The organism as its genome record names it. |
required |
taxid
|
int
|
The NCBI taxonomy identifier, and the sequence record counted. |
required |
accession
|
int
|
The NCBI taxonomy identifier, and the sequence record counted. |
required |
counts
|
Mapping[str, int]
|
Codon to the number of times the coding sequences spell it. All 64 are present. |
required |
cds_count
|
int
|
How many coding sequences were counted, and how many codons they held. |
required |
codon_count
|
int
|
How many coding sequences were counted, and how many codons they held. |
required |
note
|
str
|
What the table is and is not, for a reader choosing between tables. |
''
|
Source code in src/liulab_mbio/codons.py
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | |
amino_acid
¶
amino_acid(codon: str) -> str
Return the amino acid this codon spells, or "*" for a stop.
Raises:
| Type | Description |
|---|---|
KeyError
|
If |
Source code in src/liulab_mbio/codons.py
52 53 54 55 56 57 58 59 60 | |
fraction
¶
fraction(codon: str) -> float
Return this codon's share of the codons spelling the same amino acid, 0 to 1.
Source code in src/liulab_mbio/codons.py
62 63 64 65 | |
per_thousand
¶
per_thousand(codon: str) -> float
How often this codon occurs in a thousand codons of the genome.
Source code in src/liulab_mbio/codons.py
67 68 69 | |
synonymous
¶
synonymous(codon: str) -> tuple[str, ...]
Every codon for the same amino acid, the one this genome uses most often first.
Examples:
>>> codon_usage().synonymous("GAC")
('GAT', 'GAC')
Source code in src/liulab_mbio/codons.py
71 72 73 74 75 76 77 78 79 80 | |
codon_tables
¶
codon_tables() -> tuple[str, ...]
Return the name of every codon usage table the package ships.
Source code in src/liulab_mbio/codons.py
83 84 85 | |
codon_usage
¶
codon_usage(name: str = DEFAULT_TABLE) -> CodonUsage
Return one host's codon usage.
Raises:
| Type | Description |
|---|---|
KeyError
|
If no shipped table is called |
Examples:
>>> codon_usage().organism
'Escherichia coli str. K-12 substr. MG1655'
Source code in src/liulab_mbio/codons.py
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | |
Primers¶
Every public name in the modules below imports from liulab_mbio.primers too:
from liulab_mbio.primers import design_pair works as well as the longer path.
liulab_mbio.primers
¶
Design PCR primers and judge them.
Every public name in its modules imports from here as well:
polymerase: a polymerase, the Tm in its buffer, its annealing and extension rules, and NEB's PCR for it.thresholds: the bands a check is judged by, and the words it is printed in.placement: where a primer anneals on a template, where else it primes, and amplicons.evaluation: judging a primer, or a pair on a template, and what a primer's length decides.design: choosing the annealing region of a primer or a pair.
liulab_mbio.primers.polymerase
¶
A DNA polymerase: the buffer its Tm is computed in, its cycling rules, and NEB's PCR for it.
Tm is the SantaLucia (1998) nearest-neighbour model computed by primer3-py, salt-corrected as
NEB's Tm Calculator does it: Owczarzy (2004) at the monovalent equivalent NEB assigns the
buffer, or Schildkraut (1965) for Phusion. Each Polymerase carries that buffer, the rule
turning a pair's Tms into an annealing temperature (Ta), and its extension rate:
Q5(the default), each primer 500 nM: Ta is the lower Tm + 1 °C, at most 72 °C, and NEB asks for at least 55 °C. Extension 72 °C, 20 s/kb.PHUSION, 500 nM: Ta is 0.93 * the lower Tm + 7.5 °C, at most 72 °C. Extension 72 °C, 15 s/kb.TAQandONETAQ, 200 nM: Ta is the lower Tm - 5 °C, at most 68 °C, and NEB asks for at least 45 °C. Extension 68 °C, 60 s/kb.
Each also carries its PcrProfile: the buffer, the enzyme and the cycling NEB's protocol sets.
Sources, and the values these reproduce: docs/research/primer-design-and-pcr.md.
PcrProfile
dataclass
¶
What NEB's protocol puts in one polymerase's PCR, and the program around it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
buffer_name
|
str
|
The reaction buffer as supplied, so its volume is the reaction over |
required |
buffer_fold
|
str
|
The reaction buffer as supplied, so its volume is the reaction over |
required |
units_per_ul
|
float
|
Polymerase in the reaction. |
required |
stock_units_ul
|
float
|
Polymerase in the tube it is pipetted from. |
required |
initial_denaturation_c
|
float
|
The step before the cycles. |
required |
initial_denaturation_seconds
|
float
|
The step before the cycles. |
required |
denaturation_c
|
float
|
Inside each cycle; the annealing temperature is the primer pair's. |
required |
denaturation_seconds
|
float
|
Inside each cycle; the annealing temperature is the primer pair's. |
required |
annealing_seconds
|
float
|
Inside each cycle; the annealing temperature is the primer pair's. |
required |
final_extension_seconds
|
int
|
At the polymerase's own extension temperature. |
required |
two_step_celsius
|
float
|
The lowest annealing temperature that gets a two-step program, annealing and extension combined. Taq's rule is "above 65 °C", which at a tenth of a degree is 65.1. |
required |
cycles
|
int
|
The rest of NEB's table. |
30
|
dntp_um_each
|
int
|
The rest of NEB's table. |
30
|
hold_c
|
int
|
The rest of NEB's table. |
30
|
Source code in src/liulab_mbio/primers/polymerase.py
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | |
Polymerase
dataclass
¶
A DNA polymerase, the buffer its Tm is computed in, and its cycling rules.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
As sold, such as |
required |
monovalent_mm
|
float
|
The monovalent cation concentration NEB's calculator assigns this buffer, mM. It stands for the whole buffer, so Mg²⁺ and dNTPs are left out of the Tm: primer3's Owczarzy (2008) magnesium term divides by an integer and vanishes. |
required |
salt_correction
|
str
|
primer3's |
required |
primer_nm
|
float
|
Each primer in the reaction, nanomolar. |
required |
tm_dna_conc_nm
|
float
|
What primer3 is given, which is four times |
required |
annealing_slope
|
float
|
Ta is |
required |
annealing_offset
|
float
|
Ta is |
required |
annealing_max
|
float
|
Ta is capped at |
required |
annealing_min
|
float
|
Ta is capped at |
required |
extension_temperature
|
float
|
°C. |
required |
extension_seconds_per_kb
|
int
|
Extension time per kilobase of amplicon. |
required |
pcr
|
PcrProfile
|
Its buffer, enzyme dose and cycling, as NEB's protocol for it sets them. |
required |
Source code in src/liulab_mbio/primers/polymerase.py
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | |
annealing_temperature
¶
annealing_temperature(tm: float, other_tm: float) -> float
Return the annealing temperature for a pair with these Tms, °C to a tenth.
Source code in src/liulab_mbio/primers/polymerase.py
111 112 113 114 115 116 | |
extension_seconds
¶
extension_seconds(amplicon_length: int) -> int
Return the extension time for an amplicon, rounded up to whole kilobases.
Source code in src/liulab_mbio/primers/polymerase.py
118 119 120 | |
melting_temperature
¶
melting_temperature(
sequence: str, polymerase: Polymerase = Q5
) -> float
Return the Tm of a sequence in a polymerase's buffer, °C.
The value NEB's Tm Calculator gives for that polymerase.
Examples:
>>> round(melting_temperature("GTAAAACGACGGCCAGT"))
62
Source code in src/liulab_mbio/primers/polymerase.py
254 255 256 257 258 259 260 261 262 263 264 265 266 | |
liulab_mbio.primers.thresholds
¶
The bands every primer check is judged by, and the words a check is printed in.
Band
dataclass
¶
The values a check passes on, and the wider band it only warns on.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
low
|
float
|
A value between them, inclusive, passes. |
required |
high
|
float
|
A value between them, inclusive, passes. |
required |
warn_low
|
float
|
A value between them warns; outside them the check fails. Infinite by default, so a value outside the passing band only warns. |
-inf
|
warn_high
|
float
|
A value between them warns; outside them the check fails. Infinite by default, so a value outside the passing band only warns. |
-inf
|
proposed
|
bool
|
Whether the passing band is the research note's own proposal rather than a published rule. A page prints it as proposed. |
False
|
Source code in src/liulab_mbio/primers/thresholds.py
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | |
grade
¶
grade(value: float) -> Status
Return the status of a value.
Source code in src/liulab_mbio/primers/thresholds.py
34 35 36 37 38 39 40 | |
Reading
dataclass
¶
One check in the few words a page prints.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
What a reader calls the check, such as |
required |
value
|
str
|
What it measured, with its unit, such as |
required |
limit
|
str
|
The band it was held to, such as |
''
|
Source code in src/liulab_mbio/primers/thresholds.py
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | |
Thresholds
dataclass
¶
Every threshold the checks are judged by, with its source.
Sources are in docs/research/primer-design-and-pcr.md; where it found no published
rule, the note's own proposal is marked below.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
length
|
Band
|
Annealing region, nt. primer3's minimum of 18 and IDT's 18-30, warning out to the longest primer primer3's Tm formula takes. The warning band is the note's proposal. |
Band(18, 30, 15, 35)
|
gc_percent
|
Band
|
Of the annealing region. NEB asks for 40-60%; primer3 allows 20-80. |
Band(40.0, 60.0, 20.0, 80.0)
|
gc_clamp
|
Band
|
Gs and Cs in the last five 3' bases. primer3 allows five; one to three is the note's proposal, from NEB's "avoid GC-rich 3' ends". |
Band(1, 3, 0, 5, proposed=True)
|
tm
|
Band
|
Of the annealing region, °C, on this polymerase's scale. IDT asks for 60-64 °C; the warning band is the note's proposal. |
Band(60.0, 64.0, 55.0, 70.0)
|
tm_difference
|
Band
|
Between a pair's annealing regions, °C. NEB's calculator warns above five. |
Band(0.0, 5.0)
|
mononucleotide_run
|
Band
|
Longest run of one base, and of G alone, anywhere in the primer. primer3 allows a run of five; IDT warns at four Gs. |
Band(0, 4, 0, 5)
|
guanine_run
|
Band
|
Longest run of one base, and of G alone, anywhere in the primer. primer3 allows a run of five; IDT warns at four Gs. |
Band(0, 4, 0, 5)
|
dinucleotide_repeat
|
Band
|
Most repeats of one dinucleotide anywhere in the primer. Four is the note's proposal; no source gives a limit. |
Band(0, 3, proposed=True)
|
hairpin
|
Band
|
Melting temperature of the structure at primer3's default conditions, °C: primer3's
|
Band(-inf, 47.0)
|
dimer
|
Band
|
Melting temperature of the structure at primer3's default conditions, °C: primer3's
|
Band(-inf, 47.0)
|
dimer_3prime
|
Band
|
As |
Band(-inf, 47.0, -inf, 47.0)
|
binding_sites
|
Band
|
Places on a template where the annealing region matches, and amplicons the pair can make. A primer wants exactly one of each. |
Band(1, 1, 1, 1)
|
products
|
Band
|
Places on a template where the annealing region matches, and amplicons the pair can make. A primer wants exactly one of each. |
Band(1, 1, 1, 1)
|
off_target
|
Band
|
Other places where it can prime, which warn. |
Band(0, 0)
|
binding_min_length
|
int
|
Bases at the 3' end that must match for a primer carrying no binding site to be placed on a template. The note's proposal. |
15
|
off_target_mismatches
|
int
|
What is worth scoring at all: at most five mismatches, and at most one in the last five 3' bases. Primer-BLAST's defaults (Ye et al. 2012, BMC Bioinformatics 13:134). |
5
|
off_target_3prime_window
|
int
|
What is worth scoring at all: at most five mismatches, and at most one in the last five 3' bases. Primer-BLAST's defaults (Ye et al. 2012, BMC Bioinformatics 13:134). |
5
|
off_target_3prime_mismatches
|
int
|
What is worth scoring at all: at most five mismatches, and at most one in the last five 3' bases. Primer-BLAST's defaults (Ye et al. 2012, BMC Bioinformatics 13:134). |
5
|
off_target_margin
|
float
|
How far under a perfect match's Tm a place can still prime, °C. primer3 sets its mispriming threshold 10 °C below its own minimum Tm. |
10.0
|
Source code in src/liulab_mbio/primers/thresholds.py
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | |
reading
¶
reading(
check: Check, thresholds: Thresholds = THRESHOLDS
) -> Reading
Return check in the words a page prints: its label, its value and its band.
A check no sourced threshold judges carries no band, so it says only what it measured.
Examples:
>>> reading(Check("gc_percent", "warn", 39.1)).detail
'39% (band 40-60)'
Source code in src/liulab_mbio/primers/thresholds.py
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | |
liulab_mbio.primers.placement
¶
Where a primer anneals on a template, where else it can prime, and what a pair amplifies.
A site or an amplicon crosses the origin of a circular template, ending past its length.
PrimingSite
dataclass
¶
Where a primer's 3' end can anneal on a template, and how strongly.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
site
|
BindingSite
|
What the annealing region covers, running past the end of a circular template when it crosses the origin. |
required |
tm
|
float
|
Of the primer annealed there, °C at primer3's default conditions. |
required |
mismatches
|
int
|
Bases of the annealing region that do not pair. |
required |
Source code in src/liulab_mbio/primers/placement.py
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | |
amplicon_sizes
¶
amplicon_sizes(
forward: Primer,
reverse: Primer,
template: SequenceRecord,
*,
thresholds: Thresholds = THRESHOLDS,
) -> tuple[int, ...]
Return the size of every amplicon a pair can make on a template, smallest first.
Tails count, as they do in PairReport.amplicon_length. A primer carrying binding sites is
taken to bind where they say, so asking about a template other than the one it was placed on
means clearing them first.
Source code in src/liulab_mbio/primers/placement.py
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | |
find_binding_sites
¶
find_binding_sites(
sequence: str,
template: SequenceRecord,
*,
thresholds: Thresholds = THRESHOLDS,
) -> tuple[BindingSite, ...]
Return every place a primer's 3' end matches a template exactly, on either strand.
The match runs from the 3' end back towards the 5' end, so a tail hangs off it; it must
reach Thresholds.binding_min_length. A site crosses the origin of a circular template.
Examples:
>>> template = SequenceRecord("CGGCGTAATCATGGTCATAGCTGTTTCC")
>>> sites = find_binding_sites("TTGGTCTCAGGCGTAATCATGGTCATAGC", template)
>>> [(site.start, site.end, site.strand.name) for site in sites]
[(1, 21, 'FORWARD')]
Source code in src/liulab_mbio/primers/placement.py
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | |
find_priming_sites
¶
find_priming_sites(
sequence: str,
template: SequenceRecord,
*,
thresholds: Thresholds = THRESHOLDS,
) -> tuple[PrimingSite, ...]
Return every place an annealing region can prime a template, on either strand.
A place counts when few enough of its bases mismatch, fewest of all at the 3' end, and
when the primer annealed there melts within Thresholds.off_target_margin of a perfect
match. Sites cross the origin of a circular template.
Source code in src/liulab_mbio/primers/placement.py
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | |
liulab_mbio.primers.evaluation
¶
Judge one primer, or a pair on a template, against the thresholds.
Hairpins and dimers are structure Tms at primer3's own default conditions, which is where its
47 °C threshold comes from. Sources, and the values these reproduce:
docs/research/primer-design-and-pcr.md.
PairReport
dataclass
¶
Every check on a primer pair, and the numbers its PCR needs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
forward
|
PrimerReport
|
What each primer scored on its own. |
required |
reverse
|
PrimerReport
|
What each primer scored on its own. |
required |
checks
|
tuple[Check, ...]
|
What only a pair can be judged on. |
required |
annealing_temperature
|
float
|
°C, by the polymerase's rule over the two annealing regions. |
required |
amplicon_length
|
int | None
|
Bases between the primers' 5' ends, tails included, or |
required |
extension_seconds
|
int | None
|
For that amplicon, or |
required |
Source code in src/liulab_mbio/primers/evaluation.py
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 | |
status
property
¶
status: Status
Return the worst status of either primer or of any pair check that was judged.
__getitem__
¶
__getitem__(name: str) -> Check
Return the pair check of that name.
Raises:
| Type | Description |
|---|---|
KeyError
|
If no check has it. |
Source code in src/liulab_mbio/primers/evaluation.py
171 172 173 174 175 176 177 178 179 | |
PrimerReport
dataclass
¶
Every check on one primer.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
primer
|
Primer
|
The primer judged. |
required |
checks
|
tuple[Check, ...]
|
In the order they were run. |
required |
Source code in src/liulab_mbio/primers/evaluation.py
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | |
__getitem__
¶
__getitem__(name: str) -> Check
Return the check of that name.
Raises:
| Type | Description |
|---|---|
KeyError
|
If no check has it. |
Source code in src/liulab_mbio/primers/evaluation.py
53 54 55 56 57 58 59 60 61 | |
annealing_checks
¶
annealing_checks(
annealing: str,
*,
polymerase: Polymerase = Q5,
thresholds: Thresholds = THRESHOLDS,
) -> tuple[Check, ...]
Judge what an annealing region's length decides: its length, GC, GC clamp and Tm.
These are the checks a design chooses a length by, so it keeps inside the bands it is judged by wherever some length can.
Examples:
>>> [check.status for check in annealing_checks("GTAAAACGACGGCCAGT")]
['warn', 'pass', 'pass', 'pass']
Source code in src/liulab_mbio/primers/evaluation.py
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | |
evaluate_pair
¶
evaluate_pair(
forward: Primer,
reverse: Primer,
template: SequenceRecord,
*,
polymerase: Polymerase = Q5,
thresholds: Thresholds = THRESHOLDS,
) -> PairReport
Judge a primer pair on a template, with the amplicon it makes.
Each primer is judged as on its own, and the pair adds the gap between their Tms, their heterodimers, and every product their binding sites can make. An amplicon runs from one primer's 5' end to the other's, tails counted, across the origin where it must.
Examples:
>>> from liulab_mbio.primers.design import design_pair
>>> template = SequenceRecord("GGCGTAATCATGGTCATAGCTGTTTCCTGTGTGAAATTGTTATCCGCT")
>>> pair = design_pair(template, 0, len(template))
>>> report = evaluate_pair(pair[0], pair[1], template)
>>> report.amplicon_length, report["products"].status
(48, 'pass')
Source code in src/liulab_mbio/primers/evaluation.py
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 | |
evaluate_primer
¶
evaluate_primer(
primer: Primer,
template: SequenceRecord | None = None,
*,
polymerase: Polymerase = Q5,
thresholds: Thresholds = THRESHOLDS,
) -> PrimerReport
Judge one primer, and where it anneals when a template is given.
The annealing region is the 3' part its binding site covers; a primer carrying none is
placed on the template by find_binding_sites, and judged whole without one. Length, GC
and Tm are of the annealing region, runs and structures of the whole primer. A primer
longer than primer3 will align is judged on its 3'-terminal bases. The full-primer Tm and
the 3'-end stability are reported without a verdict.
Examples:
>>> report = evaluate_primer(Primer("M13 fwd", "GTAAAACGACGGCCAGT"))
>>> report["gc_clamp"].value, report.status
(3, 'warn')
Source code in src/liulab_mbio/primers/evaluation.py
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | |
liulab_mbio.primers.design
¶
Design a primer, or a pair, by choosing the annealing region at a position on a template.
design_pair
¶
design_pair(
template: SequenceRecord,
start: int,
end: int,
*,
forward_tail: str = "",
reverse_tail: str = "",
forward_name: str = "",
reverse_name: str = "",
target_tm: float = TARGET_TM,
polymerase: Polymerase = Q5,
thresholds: Thresholds = THRESHOLDS,
) -> tuple[Primer, Primer]
Design a pair amplifying start to end, with their Tms as near each other as they go.
end passes the length of a circular template when the amplicon crosses the origin. The
two lengths are chosen together: the pair grading best, then its two primers grading best
together, then inside the length band, then the Tms sitting closest to each other and to
target_tm.
Raises:
| Type | Description |
|---|---|
ValueError
|
If no annealing region fits the template at either end. |
Source code in src/liulab_mbio/primers/design.py
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | |
design_primer
¶
design_primer(
template: SequenceRecord,
position: int,
strand: Strand,
*,
tail: str = "",
name: str = "",
target_tm: float = TARGET_TM,
polymerase: Polymerase = Q5,
thresholds: Thresholds = THRESHOLDS,
) -> Primer
Design a primer annealing at a position on a template.
A forward primer's annealing region starts at position and reads towards higher
coordinates; a reverse primer's ends there and reads back. Either crosses the origin of a
circular template. Each length Thresholds.length does not fail is graded by
annealing_checks; the chosen one grades best, then lies inside the band a length passes
on, then lands closest to target_tm. tail joins its 5' end and stays out of the binding
site.
Raises:
| Type | Description |
|---|---|
ValueError
|
If no annealing region fits the template there. |
Examples:
>>> template = SequenceRecord("GGCGTAATCATGGTCATAGCTGTTTCCTGTGTGAAATTGTTATCCGCT")
>>> design_primer(template, 0, Strand.FORWARD, name="MCS fwd").sequence
'GGCGTAATCATGGTCATAGC'
Source code in src/liulab_mbio/primers/design.py
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | |
Protocols¶
The model a bench protocol is written in, and the renderer that turns one into a single
self-contained HTML page. Check is how a page shows a verdict, with no value; Oligo is one
row of the order sheet, carrying its own verdict and the checks that fired where something
judged it; OVERVIEW_CHARS is the character budget for a header card, and a longer value is
refused rather than truncated.
liulab_mbio.protocol
¶
Bench protocols: a small model, loaded from JSON and rendered to one self-contained HTML file.
JSON keys are the field names of the classes below, lists stand for tuples, and only the fields without a default are required::
{"title": str, "summary": str, "overview": {label: short value},
"highlights": [sentence], "checks": [{"name", "status", "detail"}],
"materials": [{"name", "supplier", "catalog", "storage", "amount", "note"}],
"oligos": [{"name", "sequence", "purpose", "tm_c", "stock", "note", "status",
"checks": [{"name", "status", "detail"}]}],
"equipment": [str],
"steps": [{"title", "instructions": [str], "cautions": [str], "notes": [str],
"tables": [{"title", "reactions", "overage",
"components": [{"name", "volume_ul", "stock", "final", "master_mix"}]}],
"programs": [{"title", "lid_temperature_c",
"stages": [{"cycles", "incubations": [{"label", "temperature_c", "seconds"}]}]}],
"timers": [{"label", "seconds"}],
"gels": [{"title", "ladder": {"name", "bands_bp"}, "lanes": [{"label", "bands_bp"}]}],
"expected": [str], "troubleshooting": [{"problem", "solution"}]}],
"references": [{"text", "url"}]}
An incubation's "seconds": null holds indefinitely. A check's "status" is "pass",
"warn" or "fail"; an oligo's may also be absent, which says nothing judged that row. An
"overview" value is a card: a few words, never a sentence.
liulab_mbio.protocol.model
¶
The protocol model, and loading it from JSON.
Every class refuses, with ValueError, a value no bench could follow: an empty title, a
non-positive volume, time, cycle count or band size, or a link that is not http(s).
Check
dataclass
¶
One pass, warn or fail verdict on the work, shown in the header as a badge.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
What was judged, such as |
required |
status
|
Status
|
One of |
required |
detail
|
str
|
What a reader needs besides the verdict, shown only where the verdict is not a pass. |
''
|
Source code in src/liulab_mbio/protocol/model.py
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | |
__post_init__
¶
__post_init__() -> None
Refuse a verdict that is not one of the three.
Source code in src/liulab_mbio/protocol/model.py
74 75 76 77 78 79 | |
Component
dataclass
¶
One line of a reaction table.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
What to pipette. |
required |
volume_ul
|
float
|
Microlitres per reaction. |
required |
stock
|
str
|
Free-text concentrations, such as |
''
|
final
|
str
|
Free-text concentrations, such as |
''
|
master_mix
|
bool
|
|
True
|
Source code in src/liulab_mbio/protocol/model.py
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | |
__post_init__
¶
__post_init__() -> None
Refuse a volume that is not positive.
Source code in src/liulab_mbio/protocol/model.py
157 158 159 | |
Gel
dataclass
¶
A simulated agarose gel: a ladder lane followed by sample lanes.
Source code in src/liulab_mbio/protocol/model.py
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 | |
migration
¶
migration(bp: float) -> float
Return how far a band runs: 0 for the largest band on this gel, 1 for the smallest.
Linear in the logarithm of size, the usual approximation for agarose.
Source code in src/liulab_mbio/protocol/model.py
315 316 317 318 319 320 321 322 323 324 | |
Incubation
dataclass
¶
One temperature held for a time.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
Such as |
required |
temperature_c
|
float
|
Degrees Celsius. |
required |
seconds
|
float | None
|
|
required |
Source code in src/liulab_mbio/protocol/model.py
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 | |
__post_init__
¶
__post_init__() -> None
Refuse a time that is not positive.
Source code in src/liulab_mbio/protocol/model.py
224 225 226 227 228 229 | |
Ladder
dataclass
¶
A named DNA size marker and its band sizes in base pairs.
Source code in src/liulab_mbio/protocol/model.py
281 282 283 284 285 286 287 288 289 290 291 | |
__post_init__
¶
__post_init__() -> None
Refuse a ladder with no band or a non-positive band size.
Source code in src/liulab_mbio/protocol/model.py
288 289 290 291 | |
Lane
dataclass
¶
One sample lane of a simulated gel; no band sizes draws an empty lane.
Source code in src/liulab_mbio/protocol/model.py
294 295 296 297 298 299 300 301 302 303 | |
__post_init__
¶
__post_init__() -> None
Refuse a non-positive band size.
Source code in src/liulab_mbio/protocol/model.py
301 302 303 | |
Material
dataclass
¶
A reagent, kit or consumable the protocol needs. An oligo is an Oligo.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
As it is labelled on the tube or shelf. |
required |
supplier
|
str
|
Who sells it and the number to order it by. Left empty where they are not known, and never guessed: a catalogue number is ordered as written. |
''
|
catalog
|
str
|
Who sells it and the number to order it by. Left empty where they are not known, and never guessed: a catalogue number is ordered as written. |
''
|
storage
|
str
|
Such as |
''
|
amount
|
str
|
What one run takes, such as |
''
|
note
|
str
|
Anything else the bench needs, such as a stock concentration. |
''
|
Source code in src/liulab_mbio/protocol/model.py
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | |
Oligo
dataclass
¶
One synthetic DNA to order: a row of the order sheet, kept apart from the reagents.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
What to order it under, and what its tube is labelled. |
required |
sequence
|
str
|
5' to 3'. Shown with a copy button, and its length is counted from it. |
required |
purpose
|
str
|
What it is for, such as the title of the step that uses it. |
''
|
tm_c
|
float | None
|
Of the part that anneals, °C, or |
None
|
stock
|
str
|
The working dilution, such as |
''
|
note
|
str
|
Anything else, such as a modification or a purification. |
''
|
status
|
Status | None
|
The row's own verdict, one of |
None
|
checks
|
tuple[Check, ...]
|
Why the verdict is not a pass: the checks that fired, each in a few words. The sheet shows the verdict in the row and keeps these behind a toggle, so it stays a sheet. |
()
|
Source code in src/liulab_mbio/protocol/model.py
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | |
__post_init__
¶
__post_init__() -> None
Refuse an oligo with no sequence, or a verdict better than its own checks.
Source code in src/liulab_mbio/protocol/model.py
118 119 120 121 122 123 124 125 126 127 128 129 130 131 | |
Protocol
dataclass
¶
A bench protocol.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
title
|
str
|
The page heading. |
required |
summary
|
str
|
One paragraph: what the protocol does. |
''
|
overview
|
Mapping[str, str]
|
Short facts, label to value, shown as a grid of cards. A handful of words each, at most
|
dict()
|
highlights
|
tuple[str, ...]
|
What a fact means, a sentence each, shown as prose under the cards. A statement a reader
has to read rather than scan goes here and not in |
()
|
checks
|
tuple[Check, ...]
|
Verdicts on the work, shown as a strip of badges, so a warning is seen and not read. |
()
|
materials
|
tuple[Material, ...]
|
The reagents, the oligos to order, and the hardware. Three lists and not one, because an order sheet and a reagent list want different columns. |
()
|
oligos
|
tuple[Material, ...]
|
The reagents, the oligos to order, and the hardware. Three lists and not one, because an order sheet and a reagent list want different columns. |
()
|
equipment
|
tuple[Material, ...]
|
The reagents, the oligos to order, and the hardware. Three lists and not one, because an order sheet and a reagent list want different columns. |
()
|
steps
|
tuple[Step, ...]
|
In the order they are shown. |
()
|
references
|
tuple[Step, ...]
|
In the order they are shown. |
()
|
Source code in src/liulab_mbio/protocol/model.py
400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 | |
__post_init__
¶
__post_init__() -> None
Refuse an empty title, or an overview value too long to be a card.
Source code in src/liulab_mbio/protocol/model.py
437 438 439 440 441 442 443 444 445 | |
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> Protocol
Build a protocol from parsed JSON; keys are the field names, lists become tuples.
Raises:
| Type | Description |
|---|---|
ValueError
|
On an unknown or missing key, naming where it is, or a value the model refuses. |
Source code in src/liulab_mbio/protocol/model.py
447 448 449 450 451 452 453 454 455 456 | |
ReactionTable
dataclass
¶
Per-reaction volumes, scaled to a master mix for several reactions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
components
|
tuple[Component, ...]
|
In pipetting order; at least one. |
required |
title
|
str
|
Such as |
''
|
reactions
|
int
|
The reaction count shown first; the reader can change it. |
1
|
overage
|
float
|
Extra master mix as a fraction, so |
0.1
|
Source code in src/liulab_mbio/protocol/model.py
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | |
__post_init__
¶
__post_init__() -> None
Refuse an empty table, fewer than one reaction, or a negative overage.
Source code in src/liulab_mbio/protocol/model.py
184 185 186 187 188 | |
mix_volumes
¶
mix_volumes(reactions: int) -> tuple[float | None, ...]
Return each component's master-mix volume in µL, to 0.01 µL.
None marks a component added to each tube instead.
Examples:
>>> ReactionTable((Component("Buffer", 2.5),), overage=0.1).mix_volumes(8)
(22.0,)
Source code in src/liulab_mbio/protocol/model.py
190 191 192 193 194 195 196 197 198 199 200 201 202 203 | |
Reference
dataclass
¶
A citation, with an optional http(s) link.
Source code in src/liulab_mbio/protocol/model.py
347 348 349 350 351 352 353 354 355 356 357 358 359 360 | |
__post_init__
¶
__post_init__() -> None
Refuse a link that is not http or https.
Source code in src/liulab_mbio/protocol/model.py
355 356 357 358 359 360 | |
Stage
dataclass
¶
Incubations run in order, repeated cycles times.
Source code in src/liulab_mbio/protocol/model.py
232 233 234 235 236 237 238 239 240 241 242 243 | |
__post_init__
¶
__post_init__() -> None
Refuse an empty stage or fewer than one cycle.
Source code in src/liulab_mbio/protocol/model.py
240 241 242 243 | |
Step
dataclass
¶
One numbered step of a protocol.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
title
|
str
|
What the step achieves, such as |
required |
instructions
|
tuple[str, ...]
|
Ordered actions, one sentence each. |
()
|
cautions
|
tuple[str, ...]
|
Shown before and after the instructions. |
()
|
notes
|
tuple[str, ...]
|
Shown before and after the instructions. |
()
|
tables
|
tuple[ReactionTable, ...]
|
Reaction tables, thermocycler programs and countdowns the step uses. |
()
|
programs
|
tuple[ReactionTable, ...]
|
Reaction tables, thermocycler programs and countdowns the step uses. |
()
|
timers
|
tuple[ReactionTable, ...]
|
Reaction tables, thermocycler programs and countdowns the step uses. |
()
|
gels
|
tuple[Gel, ...]
|
What a successful step looks like. |
()
|
expected
|
tuple[Gel, ...]
|
What a successful step looks like. |
()
|
troubleshooting
|
tuple[Troubleshooting, ...]
|
Problems the reader may see here. |
()
|
Source code in src/liulab_mbio/protocol/model.py
363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 | |
__post_init__
¶
__post_init__() -> None
Refuse an empty title.
Source code in src/liulab_mbio/protocol/model.py
395 396 397 | |
ThermocyclerProgram
dataclass
¶
Stages run in order.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
stages
|
tuple[Stage, ...]
|
In run order; at least one. |
required |
title
|
str
|
The name to save the program under. |
''
|
lid_temperature_c
|
float | None
|
Heated lid, or |
None
|
Source code in src/liulab_mbio/protocol/model.py
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 | |
duration_seconds
property
¶
duration_seconds: float
Run time at the block temperatures, leaving out ramps and indefinite holds.
__post_init__
¶
__post_init__() -> None
Refuse a program with no stage.
Source code in src/liulab_mbio/protocol/model.py
265 266 267 | |
Timer
dataclass
¶
A countdown the reader can start from the step.
Source code in src/liulab_mbio/protocol/model.py
327 328 329 330 331 332 333 334 335 336 | |
__post_init__
¶
__post_init__() -> None
Refuse a time that is not positive.
Source code in src/liulab_mbio/protocol/model.py
334 335 336 | |
Troubleshooting
dataclass
¶
A problem the reader may see at a step, and what to do about it.
Source code in src/liulab_mbio/protocol/model.py
339 340 341 342 343 344 | |
read_protocol
¶
read_protocol(path: str | PathLike[str]) -> Protocol
Read a protocol from a JSON file; see Protocol.from_dict.
Source code in src/liulab_mbio/protocol/model.py
459 460 461 | |
liulab_mbio.protocol.render
¶
Render a protocol to one self-contained HTML page.
render_html
¶
render_html(protocol: Protocol) -> str
Return protocol as one HTML page with its styles and script inline.
The page loads nothing over the network, remembers check marks and reaction counts in the browser's local storage when it can, and prints without its controls.
Source code in src/liulab_mbio/protocol/render.py
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | |
write_html
¶
write_html(
protocol: Protocol, path: str | PathLike[str]
) -> Path
Write render_html(protocol) to path as UTF-8 and return the path.
Source code in src/liulab_mbio/protocol/render.py
50 51 52 53 54 | |
Bench¶
The numbers any cloning pipeline shares: DNA amounts, PCR and colony PCR, gels, the checks
that confirm a clone, heat inactivation, the phenotype a clone should show, the primer order
sheet, and the protocol steps any pipeline reuses. Every public name in the modules below imports
from liulab_mbio.bench too. A module that cites a source keeps its own REFERENCES, and
liulab_mbio.bench.REFERENCES gathers them all. steps is the one exception: a protocol cites
its DPNI_REFERENCE and PLATE_REFERENCE only when it runs the step they belong to.
liulab_mbio.bench
¶
The bench any cloning pipeline shares: reactions, programs, validation and protocol steps.
Every public name in its modules imports from here as well. A module that cites a source keeps
it as its own REFERENCES; REFERENCES here gathers them.
amounts: the weight of DNA, picomoles from nanograms, and what to pipette.pcr: the PCR and colony PCR reactions and programs.gels: the ladder and agarose percentage a range of bands takes.validation: the colony PCR that reads an assembly's junctions, and the Sanger reads.inactivation: an enzyme's heat inactivation.phenotype: what a clone is expected to show, read off the product's own features.oligos: the primer order sheet.steps: the protocol steps any pipeline reuses, built from plain facts. Its two references are cited only by a protocol that runs the step they belong to.
Nothing here imports liulab_mbio.goldengate.
liulab_mbio.bench.amounts
¶
How much DNA a reaction takes: its weight, picomoles from nanograms, and what to pipette.
The conversion is NEBioCalculator's, through docs/research/primer-design-and-pcr.md.
Amount
dataclass
¶
How much of one DNA a reaction takes, in the three units a bench needs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
The DNA's. |
required |
length_bp
|
str
|
The DNA's. |
required |
pmol
|
float
|
What the protocol asks for. |
required |
nanograms
|
float
|
The same amount weighed. |
required |
volume_ul
|
float
|
What to pipette at the DNA's concentration, or |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If any of the three is not positive. |
Source code in src/liulab_mbio/bench/amounts.py
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | |
__post_init__
¶
__post_init__() -> None
Refuse an amount no one can pipette.
Source code in src/liulab_mbio/bench/amounts.py
68 69 70 71 72 73 74 75 76 | |
dna_amount
¶
dna_amount(
name: str,
length_bp: int,
*,
pmol: float,
concentration_ng_ul: float | None = None,
) -> Amount
Return how much of one DNA a reaction takes, weighed and as a volume to pipette.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
What its tube is labelled. |
required |
length_bp
|
int
|
Base pairs. |
required |
pmol
|
float
|
What the reaction asks for. |
required |
concentration_ng_ul
|
float | None
|
Of that tube, or |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If the length, the concentration or the picomoles are not positive. |
Examples:
>>> dna_amount("pUC19", 2686, pmol=0.05).nanograms
82.72
Source code in src/liulab_mbio/bench/amounts.py
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | |
molecular_weight
¶
molecular_weight(length_bp: int) -> float
Return the weight of a double-stranded DNA molecule, g/mol.
Source code in src/liulab_mbio/bench/amounts.py
19 20 21 | |
to_nanograms
¶
to_nanograms(pmol: float, length_bp: int) -> float
Return what those picomoles of double-stranded DNA of this length weigh, ng.
Source code in src/liulab_mbio/bench/amounts.py
35 36 37 | |
to_pmol
¶
to_pmol(nanograms: float, length_bp: int) -> float
Return how many picomoles a mass of double-stranded DNA of this length is.
Examples:
>>> round(to_pmol(1000, 2686), 3)
0.604
Source code in src/liulab_mbio/bench/amounts.py
24 25 26 27 28 29 30 31 32 | |
liulab_mbio.bench.pcr
¶
PCR and colony PCR at the bench: the reaction and the thermocycler program for each.
Every number is NEB's, through docs/research/primer-design-and-pcr.md; each polymerase
carries its own profile. Functions return liulab_mbio.protocol values, so a protocol prints
them unchanged.
colony_pcr_master_mix_component
¶
colony_pcr_master_mix_component(
volume_ul: float = COLONY_PCR_VOLUME_UL,
) -> Component
Return the 2X master mix component of a colony PCR of volume_ul.
Source code in src/liulab_mbio/bench/pcr.py
116 117 118 | |
colony_pcr_program
¶
colony_pcr_program(
polymerase: Polymerase = ONETAQ,
*,
annealing_temperature: float,
amplicon_length: int,
cycles: int | None = None,
) -> ThermocyclerProgram
Return the colony PCR program, which opens the cells before it denatures anything.
Source code in src/liulab_mbio/bench/pcr.py
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | |
colony_pcr_reaction
¶
colony_pcr_reaction(
polymerase: Polymerase = ONETAQ,
*,
volume_ul: float = COLONY_PCR_VOLUME_UL,
reactions: int = 1,
) -> ReactionTable
Return NEB's colony PCR reaction, which is a 2X master mix and the two primers.
The colony itself is no line of the table: it is picked with a toothpick and stirred into the tube until the solution clouds.
Raises:
| Type | Description |
|---|---|
ValueError
|
If the primers and master mix do not fit |
Source code in src/liulab_mbio/bench/pcr.py
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | |
pcr_program
¶
pcr_program(
polymerase: Polymerase = Q5,
*,
annealing_temperature: float,
amplicon_length: int,
cycles: int | None = None,
title: str = "PCR",
) -> ThermocyclerProgram
Return the program for this polymerase, annealing temperature and amplicon.
Annealing and extension are combined into one step at the extension temperature once the
annealing temperature reaches the polymerase's PcrProfile.two_step_celsius. cycles, when
given, replaces the profile's own count.
Source code in src/liulab_mbio/bench/pcr.py
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | |
pcr_reaction
¶
pcr_reaction(
polymerase: Polymerase = Q5,
*,
volume_ul: float = 50.0,
reactions: int = 1,
template_volume_ul: float = DNA_VOLUME_UL,
title: str = "PCR",
) -> ReactionTable
Return the PCR NEB's protocol sets up for this polymerase, in its own order.
Volumes follow from the concentrations NEB's table gives: the buffer, the dNTP mix at
DNTP_STOCK_MM, each primer at PRIMER_STOCK_UM, and the polymerase from its own tube.
Template is added per tube.
Raises:
| Type | Description |
|---|---|
ValueError
|
If the components do not fit |
Source code in src/liulab_mbio/bench/pcr.py
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | |
liulab_mbio.bench.gels
¶
The ladder and the agarose percentage a range of bands takes.
Both are NEB's, through docs/research/primer-design-and-pcr.md.
agarose_percent
¶
agarose_percent(bands_bp: tuple[int, ...]) -> float
Return the agarose percentage these bands resolve on.
Raises:
| Type | Description |
|---|---|
ValueError
|
If no band is given. |
Source code in src/liulab_mbio/bench/gels.py
53 54 55 56 57 58 59 60 61 | |
choose_ladder
¶
choose_ladder(bands_bp: tuple[int, ...]) -> Ladder
Return the ladder covering these bands.
Raises:
| Type | Description |
|---|---|
ValueError
|
If no band is given. |
Source code in src/liulab_mbio/bench/gels.py
42 43 44 45 46 47 48 49 50 | |
liulab_mbio.bench.validation
¶
What confirms a clone: a colony PCR reading its junctions, and Sanger reads across them.
The distances are the ones docs/research/primer-design-and-pcr.md sets out for colony PCR
bands and for sequencing primers.
Clone
dataclass
¶
One plasmid a colony may carry, and the bands a colony PCR gives from it.
Source code in src/liulab_mbio/bench/validation.py
49 50 51 52 53 54 | |
ColonyCheck
dataclass
¶
A colony PCR reading across an assembly's junctions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
primers
|
tuple[Primer, ...]
|
The flanking pair first, then one junction primer per insert where they were asked for. |
required |
reports
|
tuple[PrimerReport, ...]
|
What each primer scored on the assembled plasmid. |
required |
clones
|
tuple[Clone, ...]
|
The candidates a colony can hold: the correct one, the empty vector, and one carrying each insert the other way round. |
required |
annealing_temperature
|
float
|
By the polymerase's rule over the two lowest Tms of the set, °C. |
required |
extension_seconds
|
int
|
For the largest band any candidate gives. |
required |
ladder
|
Ladder
|
Chosen for that band range. |
required |
agarose_percent
|
Ladder
|
Chosen for that band range. |
required |
Source code in src/liulab_mbio/bench/validation.py
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | |
tells_orientation
property
¶
tells_orientation: bool
Whether the gel separates every reversed insert from the correct clone.
Two vector primers flanking the inserts never do: they amplify them whichever way round they sit. A junction primer does, unless the two vector primers happen to lie the same distance from their own junctions.
SangerRead
dataclass
¶
A sequencing primer and the read it has to give.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
primer
|
Primer
|
Reading towards the junction it sits outside. |
required |
distance_bp
|
int
|
From its 3' end to that junction. |
required |
read_bp
|
int
|
From its 3' end to the far junction, which is what the read must cover for the insert to be confirmed at both ends. |
required |
Source code in src/liulab_mbio/bench/validation.py
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 | |
colony_pcr_check
¶
colony_pcr_check(
product: SequenceRecord,
junctions: Sequence[int],
*,
vector: SequenceRecord,
primers: tuple[Primer, ...] | None = None,
insert_primer: bool = False,
flank: int = COLONY_FLANK,
junction_offset: int = JUNCTION_OFFSET,
polymerase: Polymerase = ONETAQ,
thresholds: Thresholds = THRESHOLDS_FOR["colony PCR"],
) -> ColonyCheck
Return what a colony PCR across these junctions should show.
An assembly of n inserts has n + 1 junctions and the inserts are the spans between them, so
a product whose inserts cross the origin is rotated first. Without primers, a pair is
designed in the vector flank bases outside the first and the last junction;
insert_primer adds one primer per insert, annealing junction_offset bases into it. Those
are what tell a reversed insert apart and what put a band of their own on each junction.
Each candidate plasmid is amplified on its own, so the bands are simulated rather than
derived.
Raises:
| Type | Description |
|---|---|
ValueError
|
If the junctions are not two or more separate positions inside the product, if fewer than two primers are given, if an insert is too short for a junction primer, or if the primers amplify nothing at all. |
Source code in src/liulab_mbio/bench/validation.py
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 | |
sanger_primers
¶
sanger_primers(
product: SequenceRecord,
junctions: Sequence[int],
*,
flank: int = SANGER_FLANK,
polymerase: Polymerase = Q5,
thresholds: Thresholds = THRESHOLDS_FOR["sequencing"],
) -> tuple[SangerRead, SangerRead]
Return a sequencing primer reading into the inserts from outside the first and last junction.
Every 3' end lands at least flank bases from its own junction, near enough for the read to
be clean there, and SangerRead.read_bp is how far it must carry to reach the far junction.
A provider whose reads are shorter needs a primer inside the inserts as well.
Raises:
| Type | Description |
|---|---|
ValueError
|
If the junctions are not two or more separate positions inside the product, or no primer fits outside the first or the last. |
Source code in src/liulab_mbio/bench/validation.py
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 | |
liulab_mbio.bench.inactivation
¶
An enzyme's heat inactivation, as its supplier gives it.
heat_inactivation
¶
heat_inactivation(
enzyme: Enzyme,
) -> ThermocyclerProgram | None
Return the supplier's heat inactivation for this enzyme, or None where it gives none.
This is not the 60 °C end soak a Golden Gate program ends with, which is a digest.
Source code in src/liulab_mbio/bench/inactivation.py
7 8 9 10 11 12 13 14 15 16 17 18 | |
liulab_mbio.bench.phenotype
¶
What a clone is expected to show, read off the product's own features.
What drives the inserts, whether anything should be translated, and how a plate reads: a protocol states these from the features rather than a person asserting them.
Phenotype
dataclass
¶
What the product says about itself, read off its own features.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
insert
|
tuple[int, int]
|
The span the inserts occupy in the product, between the first junction and the last. |
required |
coding
|
Feature | None
|
The longest coding sequence in that span, or |
required |
promoter
|
Feature | None
|
The promoter nearest the insert on the promoter's own reading direction, or |
required |
gap_bp
|
int
|
Bases between that promoter and the insert. |
required |
driven
|
bool
|
Whether that promoter reads along the strand the insert is coded on. |
required |
ribosome_binding_site
|
bool
|
Whether one is annotated between that promoter and the insert. |
required |
reporter
|
Feature | None
|
The vector coding sequence the insertion interrupts, or |
required |
marker
|
Feature | None
|
The vector's selection marker, or |
required |
Source code in src/liulab_mbio/bench/phenotype.py
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | |
antibiotic
property
¶
antibiotic: str
What to select transformants on, or an empty string when the marker is unknown.
blue_white
property
¶
blue_white: bool
Whether X-gal and IPTG tell a correct clone from an empty vector.
True when the insertion interrupts a lacZ fragment, which is then not there to complement the host's own.
read_phenotype
¶
read_phenotype(
product: SequenceRecord,
insert: tuple[int, int],
*,
vector: SequenceRecord,
span: tuple[int, int],
) -> Phenotype
Read what the product says about itself off its own features.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
product
|
SequenceRecord
|
The plasmid a clone carries. |
required |
insert
|
tuple[int, int]
|
Where the inserts lie in it, from the first junction to the last. |
required |
vector
|
SequenceRecord
|
The plasmid they went into. |
required |
span
|
tuple[int, int]
|
The vector bases they replace. |
required |
Source code in src/liulab_mbio/bench/phenotype.py
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | |
liulab_mbio.bench.oligos
¶
The primer order sheet: every oligo a design asks for, as a table to order from.
primer_sheet writes it as a file, and oligo_row makes one row of a protocol's own sheet.
oligo_row
¶
oligo_row(
report: PrimerReport,
*,
purpose: str,
thresholds: Thresholds,
) -> Oligo
Return one oligo as a row of a protocol's order sheet, carrying its verdict.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
report
|
PrimerReport
|
What the oligo scored, the primer included. |
required |
purpose
|
str
|
The title of the step that uses it. |
required |
thresholds
|
Thresholds
|
What it was judged by, so a row prints the band beside each value that missed it. |
required |
Source code in src/liulab_mbio/bench/oligos.py
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | |
primer_sheet
¶
primer_sheet(reports: Sequence[PrimerReport]) -> str
Return these oligos as a tab-separated sheet, one row each, in the order given.
The columns are SHEET_COLUMNS: the name to order it under, the sequence 5' to 3', its
length, and the Tm of the part that anneals.
Source code in src/liulab_mbio/bench/oligos.py
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | |
liulab_mbio.bench.steps
¶
The protocol steps any cloning pipeline reuses, each built from plain facts.
A pipeline runs these in its own order around its own steps, and passes its own notes where it
has something of its own to say; they follow the step's. Every sentence about the phenotype is
read off liulab_mbio.bench.phenotype.
cleanup_step
¶
cleanup_step(*, notes: Sequence[str] = ()) -> Step
Return the spin-column cleanup of every amplicon, carrying the caller's own notes.
Source code in src/liulab_mbio/bench/steps.py
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 | |
colony_pcr_step
¶
colony_pcr_step(
check: ColonyCheck,
*,
junctions: int,
troubleshooting: Sequence[Troubleshooting] = (),
) -> Step
Return the colony PCR screen, saying which band means what.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
check
|
ColonyCheck
|
The colony PCR, its expected clones included. |
required |
junctions
|
int
|
How many junctions it reads. |
required |
troubleshooting
|
Sequence[Troubleshooting]
|
The caller's own, after the step's. |
()
|
Source code in src/liulab_mbio/bench/steps.py
332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 | |
dpni_step
¶
dpni_step(
pcrs: Sequence[str],
templates: Sequence[tuple[str, int]],
*,
notes: Sequence[str] = (),
) -> Step
Return the DpnI digest that takes the plasmid template away, so it cannot transform.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pcrs
|
Sequence[str]
|
The PCRs to digest, by name. |
required |
templates
|
Sequence[tuple[str, int]]
|
The plasmid each was amplified from, and the Dam sites it carries. |
required |
notes
|
Sequence[str]
|
The caller's own, after the step's. |
()
|
Source code in src/liulab_mbio/bench/steps.py
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 | |
gel_step
¶
gel_step(amplicons: Sequence[tuple[str, int]]) -> Step
Return the gel that checks every PCR before anything is spent on them.
amplicons gives each amplicon's name and its length in base pairs, one lane each.
Source code in src/liulab_mbio/bench/steps.py
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | |
listed
¶
listed(items: Sequence[str]) -> str
Join names the way a sentence does, with and before the last.
Examples:
>>> listed(("GFP", "Linker", "Tag"))
'GFP, Linker and Tag'
Source code in src/liulab_mbio/bench/steps.py
65 66 67 68 69 70 71 72 73 74 75 | |
pcr_step
¶
pcr_step(
name: str,
template: str,
length_bp: int,
*,
polymerase: Polymerase,
annealing_temperature: float,
extension_seconds: int | None,
cycles: int | None = None,
notes: Sequence[str] = (),
) -> Step
Return the step that makes one amplicon by PCR.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
What the amplicon is called, which titles the step, its reaction and its program. |
required |
template
|
str
|
What its template is called. |
required |
length_bp
|
int
|
The amplicon's length. |
required |
polymerase
|
Polymerase
|
The PCR's, as the primer pair's report gives them. |
required |
annealing_temperature
|
Polymerase
|
The PCR's, as the primer pair's report gives them. |
required |
extension_seconds
|
Polymerase
|
The PCR's, as the primer pair's report gives them. |
required |
cycles
|
int | None
|
Replaces the polymerase profile's own count. |
None
|
notes
|
Sequence[str]
|
The caller's own. |
()
|
Source code in src/liulab_mbio/bench/steps.py
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | |
pcr_title
¶
pcr_title(name: str) -> str
Return the title of the step that amplifies name, which its oligos name as their purpose.
Source code in src/liulab_mbio/bench/steps.py
78 79 80 | |
phenotype_sentences
¶
phenotype_sentences(
phenotype: Phenotype, inserts: Sequence[str]
) -> tuple[str, ...]
Return what the product's own features say about the insert and about the plate.
inserts names the inserts for a product that annotates no coding sequence among them.
Source code in src/liulab_mbio/bench/steps.py
437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 | |
quantify_step
¶
Return the step that measures what the next reaction is about to take.
Source code in src/liulab_mbio/bench/steps.py
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 | |
sequencing_step
¶
sequencing_step(
reads: Sequence[SangerRead],
*,
junctions: Sequence[str],
inserts: Sequence[str],
) -> Step
Return the sequencing that confirms the junctions, which is the only thing that settles it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
reads
|
Sequence[SangerRead]
|
The sequencing primers and the reads they have to give. |
required |
junctions
|
Sequence[str]
|
The bases each junction spells. |
required |
inserts
|
Sequence[str]
|
What the inserts are called. |
required |
Source code in src/liulab_mbio/bench/steps.py
392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 | |
transform_step
¶
transform_step(
host: str,
phenotype: Phenotype,
*,
inserts: Sequence[str],
colonies: str,
) -> Step
Return the transformation and plating, with the colour the plate should show.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
host
|
str
|
The competent strain. |
required |
phenotype
|
Phenotype
|
What the product says about itself. |
required |
inserts
|
Sequence[str]
|
What the inserts are called, for a product that annotates no coding sequence among them. |
required |
colonies
|
str
|
How many colonies to expect, as a sentence: a count belongs to the pipeline's reaction. |
required |
Source code in src/liulab_mbio/bench/steps.py
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 | |
Golden Gate¶
plan_assembly is the way in, and Plan.write puts the product, the primer sheet and the
protocol in one directory. The inserts are varargs, so Plan.inserts is a tuple — plural,
because one reaction joins as many inserts as the overhangs allow.
liulab_mbio.goldengate
¶
Golden Gate cloning: enzyme and overhang choice, assembly, and the reaction that joins it.
plan_assembly is the way in: it takes a vector and any number of inserts and runs the whole
design, and Plan.write puts the product, the primer sheet and the bench protocol in one
directory.
The submodules are the steps it is made of -- design, assembly, bench, oligos and
steps -- plus ligase, which reads a ligase fidelity matrix the user holds. bench is the
assembly reaction and its cycling, and steps the protocol's own steps and their order; what any
pipeline shares is liulab_mbio.bench. design and ligase are not
re-exported here: import them by module.
liulab_mbio.goldengate.plan
¶
One Golden Gate experiment, planned from a vector and the inserts that go round it.
plan_assembly joins as many inserts as the overhangs allow, given in the order they go round
the product, and runs the whole design: choose the enzyme, design the overhangs, simulate the
PCRs and the ligation, work out the bench quantities, and design the colony PCR and sequencing
that validate the clone. Plan.write puts the three things a bench needs in one directory --
the annotated product, a primer order sheet, and the interactive HTML protocol.
Every number the protocol prints is computed here or by the modules this one calls. What the
protocol says about the phenotype -- what drives the inserts, whether anything should be
translated, and how a plate reads -- is liulab_mbio.bench.phenotype, read off the product's
own features.
Files
dataclass
¶
The three files a plan writes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
product
|
Path
|
The annotated product, as a SnapGene |
required |
primers
|
Path
|
Every designed oligo, as a tab-separated sheet to order from. |
required |
protocol
|
Path
|
The interactive bench protocol, as one self-contained HTML page. |
required |
Source code in src/liulab_mbio/goldengate/plan.py
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | |
Plan
dataclass
¶
One planned Golden Gate experiment.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
vector
|
SequenceRecord
|
The records the plan was made from, the inserts in the order they go round the product and each on the strand that goes in. |
required |
inserts
|
SequenceRecord
|
The records the plan was made from, the inserts in the order they go round the product and each on the strand that goes in. |
required |
span
|
tuple[int, int]
|
The vector bases the assembly replaces, after any junction slide. |
required |
choice
|
EnzymeChoice
|
The enzyme the plan uses, and what using it costs. |
required |
ranking
|
tuple[EnzymeChoice, ...]
|
Every candidate enzyme, best first. |
required |
overhangs
|
OverhangSet
|
The overhang every junction takes, with the fidelity of the whole set. An assembly of n inserts has n + 1 junctions. |
required |
linearised_vector
|
Part
|
The part the vector is opened into. |
required |
insert_parts
|
tuple[Part, ...]
|
The part each insert is amplified into, in insert order. |
required |
assembly
|
Assembly
|
The simulated product, the parts and the junctions. |
required |
colony
|
ColonyCheck
|
The colony PCR that reads every junction and tells a correct clone from an empty vector or from one carrying an insert the other way round. |
required |
reads
|
tuple[SangerRead, SangerRead]
|
A sequencing primer reading in from outside the first junction and the last. |
required |
amounts
|
tuple[Amount, ...]
|
What to put in the assembly reaction, vector first. |
required |
phenotype
|
Phenotype
|
What the product says about itself. |
required |
designed_oligos
|
tuple[DesignedOligo, ...]
|
Every designed oligo and what it is for, in order: each part's PCR, the colony PCR, the reads. |
required |
host
|
str
|
The choices the protocol names. |
required |
polymerase
|
str
|
The choices the protocol names. |
required |
thresholds
|
Mapping[PrimerRole, Thresholds]
|
What those oligos were designed and judged by, for each role, so a page prints the band beside the value. |
THRESHOLDS_FOR
|
Source code in src/liulab_mbio/goldengate/plan.py
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 | |
oligos
property
¶
oligos: tuple[Primer, ...]
Every oligo the plan designs, in the order the sheet lists them.
parts
property
¶
parts: tuple[Part, ...]
The parts that go into the reaction, the linearised vector first.
reports
property
¶
reports: tuple[PrimerReport, ...]
Every designed oligo's evaluation, in the order the sheet lists them.
protocol
¶
protocol() -> Protocol
Return the bench protocol for this plan.
Source code in src/liulab_mbio/goldengate/plan.py
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 | |
write
¶
write(directory: str | PathLike[str]) -> Files
Write the product, the primer sheet and the protocol into directory.
The directory is made when it is not there. The three files are named by
PRODUCT_FILE, PRIMER_FILE and PROTOCOL_FILE, and a second run over the same
inputs writes the same bytes.
Source code in src/liulab_mbio/goldengate/plan.py
241 242 243 244 245 246 247 248 249 250 251 252 253 254 | |
flipped
¶
flipped(record: SequenceRecord) -> SequenceRecord
Return record read from the other strand, features and binding sites turned with it.
Raises:
| Type | Description |
|---|---|
ValueError
|
If a span runs across the origin, which has no place on the other strand of a record this turns end for end. |
Examples:
>>> flipped(SequenceRecord("AAAACCCG")).sequence
'CGGGTTTT'
Source code in src/liulab_mbio/goldengate/plan.py
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 | |
plan_assembly
¶
plan_assembly(
vector: SequenceRecord | str | PathLike[str],
*inserts: SequenceRecord | str | PathLike[str],
site: Site = None,
orientation: Orientation
| Sequence[Orientation] = "forward",
in_frame: bool | Sequence[bool] = False,
enzyme: EnzymeLike | None = None,
profile: LigaseProfile
| str
| PathLike[str]
| None = None,
prefer_profile: bool = False,
polymerase: Polymerase = Q5,
host: str = DEFAULT_HOST,
name: str = "",
window: int = VECTOR_WINDOW,
thresholds: Mapping[
PrimerRole, Thresholds
] = THRESHOLDS_FOR,
) -> Plan
Plan one Golden Gate experiment putting inserts into vector.
One reaction joins as many inserts as the overhangs allow, given in the order they go round
the product. The vector is opened by PCR across the span they replace, each insert is
amplified with tails of its own, and every junction is scarless: it takes the bases the part
already spells there. Only the vector junction may slide, by up to window bases, to get
past an overhang rule, which moves where the vector is cut and not what the inserts spell.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
vector
|
SequenceRecord | str | PathLike[str]
|
A record, or a path to a |
required |
inserts
|
SequenceRecord | str | PathLike[str]
|
A record, or a path to a |
required |
site
|
Site
|
Where the inserts go: a feature name, a |
None
|
orientation
|
Orientation | Sequence[Orientation]
|
|
'forward'
|
in_frame
|
bool | Sequence[bool]
|
Hold an insert's junction on a codon boundary of the coding sequence it lies in. One value covers every insert; a sequence gives one for each. |
False
|
enzyme
|
EnzymeLike | None
|
The Type IIS enzyme to use. Chosen by |
None
|
profile
|
LigaseProfile | str | PathLike[str] | None
|
A ligase fidelity matrix the caller holds, as a path or an already read |
None
|
prefer_profile
|
bool
|
Use it even where a shipped matrix covers the enzyme. |
False
|
polymerase
|
Polymerase
|
For the PCRs. The colony PCR uses OneTaq, which is what NEB's protocol asks for. |
Q5
|
host
|
str
|
The strain the protocol names, and what to call the product. |
DEFAULT_HOST
|
name
|
str
|
The strain the protocol names, and what to call the product. |
DEFAULT_HOST
|
window
|
int
|
How far the vector junction may slide. |
VECTOR_WINDOW
|
thresholds
|
Mapping[PrimerRole, Thresholds]
|
For each role, what its oligos are designed and judged by in |
THRESHOLDS_FOR
|
Returns:
| Type | Description |
|---|---|
Plan
|
The design, the simulated product and the validation. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If no insert is given, if no insertion site is named and the vector annotates none, if
the enzyme reads a site in a part, if no overhang passes every rule, if |
Source code in src/liulab_mbio/goldengate/plan.py
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 | |
liulab_mbio.goldengate.design
¶
Choosing the Type IIS enzyme an assembly uses, and the overhangs its junctions are cut to.
Three decisions, in the order a design makes them:
- Which enzyme. Rank the candidates by how many sites they read in the parts that end up in the product. An enzyme with no site needs nothing done to the parts, so domestication is proposed only when no candidate is free, and then as a report of what it would change.
- Which overhangs. Each junction takes an overhang of the length the enzyme leaves. A palindrome would let a fragment ligate to itself, a repeat would let two junctions swap, and a near-duplicate is what mis-ligates; each refusal is reported with the rule that made it.
- How well the set should ligate. Pryor et al. 2020 measured every overhang pair for five
enzymes, and that data ships here: fidelity is the product over the junctions of correct
ligations over all ligations. An enzyme they did not measure is scored against a ligase
profile the caller holds (
liulab_mbio.goldengate.ligase) where there is one and by the rules where there is not, and the report says which of the three scored it.
The fidelity data is src/liulab_mbio/data/ligation_fidelity.json, from the supplementary
tables of Pryor, J.M., Potapov, V., Kucera, R.B., Bilotti, K., Cantor, E.J. and Lohman, G.J.S.
(2020) PLoS One 15(9): e0238592, used under CC BY 4.0.
docs/research/ligation-fidelity.md records the licence, the axis convention and the rules.
Choice
dataclass
¶
The overhang one junction took.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
junction
|
Junction
|
The junction this is for. |
required |
overhang
|
str
|
The overhang it takes, written on the top strand. |
required |
offset
|
int
|
How far the junction moved from the position it was asked for. |
0
|
rejected
|
tuple[Rejection, ...]
|
Every candidate refused before this one, in the order they were tried. |
()
|
Source code in src/liulab_mbio/goldengate/design.py
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 | |
EnzymeChoice
dataclass
¶
One enzyme a design could use, and what using it would cost.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
enzyme
|
Enzyme
|
The enzyme. |
required |
sites
|
int
|
How many sites it reads across the parts. |
required |
measured
|
bool
|
Whether shipped ligation data can score its overhangs. |
False
|
changes
|
tuple[Domestication, ...]
|
The synonymous codon changes that would take its sites away. Empty while another candidate is free, because domestication is proposed only when none is. |
()
|
outside_cds
|
tuple[CutSite, ...]
|
Sites lying in no coding sequence, which a human has to decide about. |
()
|
unchanged
|
tuple[CutSite, ...]
|
Sites in a coding sequence that no synonymous change could take away. |
()
|
Source code in src/liulab_mbio/goldengate/design.py
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 | |
FidelityReport
dataclass
¶
How well a set of overhangs should ligate, and where the number came from.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
enzyme
|
str
|
The enzyme whose data scored the set. |
required |
source
|
str
|
The measurement, or a statement that the rules scored it instead. |
required |
measured
|
bool
|
|
required |
value
|
float
|
The probability that every junction ligates to its own partner. |
required |
ligations
|
tuple[Ligation, ...]
|
One entry per overhang, empty when the rules scored the set. |
()
|
weak
|
tuple[str, ...]
|
Overhangs whose Watson-Crick pair was seen fewer than |
()
|
mismatches
|
tuple[tuple[str, str, float], ...]
|
Top overhang, bottom overhang and normalised count, for every cross pair seen at least
|
()
|
enzyme_specific
|
bool
|
|
True
|
Source code in src/liulab_mbio/goldengate/design.py
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | |
Junction
dataclass
¶
Where two parts meet in the product, and how free its overhang is.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
What a report calls this junction. |
required |
record
|
SequenceRecord | None
|
The part the junction is read from, for a scarless or in-frame junction. |
None
|
position
|
int
|
Where the two parts separate: the 0-based top-strand index the downstream part begins at. |
0
|
scarless
|
bool
|
Take the overhang from |
False
|
in_frame
|
bool
|
A scarless junction inside a coding sequence that has to read through it: the junction sits on a codon boundary and moves only by whole codons. |
False
|
window
|
int
|
How many bases the junction may move by to get past a rule. A scarless junction that moves does not change what the product spells, only where the cut falls. |
0
|
overhang
|
str | None
|
Fixed by the caller. Still held to every rule, and the refusal says which one. |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If a fixed overhang is asked to be scarless too, or a scarless junction names no record, or the window is negative. |
Source code in src/liulab_mbio/goldengate/design.py
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 | |
__post_init__
¶
__post_init__() -> None
Refuse a junction whose fields ask for two different things.
Source code in src/liulab_mbio/goldengate/design.py
292 293 294 295 296 297 298 299 300 301 | |
Ligation
dataclass
¶
What the data says about one overhang of a set.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
overhang
|
str
|
The overhang, written on the top strand. |
required |
correct
|
int
|
Ligations of its two ends to each other, which is what the junction is for. |
required |
total
|
int
|
Ligations of its two ends to any end the reaction holds, correct and mismatched. |
required |
Source code in src/liulab_mbio/goldengate/design.py
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | |
LigationMatrix
dataclass
¶
How often each overhang pair was seen ligating, measured with one enzyme.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
enzyme
|
str
|
The enzyme, and the supplier's product the measurement used. |
required |
product
|
str
|
The enzyme, and the supplier's product the measurement used. |
required |
table
|
str
|
Which supplementary table of the paper this is. |
required |
overhang_length
|
int
|
How many bases the overhangs on both axes have. |
required |
cycling_celsius
|
tuple[int, int]
|
The two temperatures the measured reaction was cycled between. |
required |
observations
|
int
|
Every ligation event counted. |
required |
counts
|
Mapping[str, Mapping[str, int]]
|
Top-strand overhang to the bottom-strand overhangs it was seen ligating to. Both are written 5' to 3', so a row pairs with the column spelling its reverse complement. |
required |
citation
|
str
|
The paper the data comes from. |
''
|
Source code in src/liulab_mbio/goldengate/design.py
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | |
count
¶
count(top: str, bottom: str) -> int
How often a top-strand overhang was seen ligating to a bottom-strand one.
Source code in src/liulab_mbio/goldengate/design.py
132 133 134 | |
normalised
¶
normalised(top: str, bottom: str) -> float
Return the count per 100,000 ligation events, the scale NEB's thresholds use.
Source code in src/liulab_mbio/goldengate/design.py
136 137 138 | |
OverhangSet
dataclass
¶
The overhangs a design chose, one per junction.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
enzyme
|
Enzyme
|
The enzyme that will cut them. |
required |
choices
|
tuple[Choice, ...]
|
One per junction, in the order the junctions were given. |
required |
fidelity
|
FidelityReport
|
How well the set should ligate. |
required |
Source code in src/liulab_mbio/goldengate/design.py
350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 | |
overhangs
property
¶
overhangs: tuple[str, ...]
The chosen overhangs, in the order the junctions were given.
Rejection
dataclass
¶
One candidate overhang a rule refused.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
overhang
|
str
|
The candidate. |
required |
rule
|
RejectionRule
|
Which rule refused it. |
required |
detail
|
str
|
Why that rule refused this candidate. |
required |
Source code in src/liulab_mbio/goldengate/design.py
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 | |
choose_enzyme
¶
choose_enzyme(
parts: Iterable[SequenceRecord],
*,
enzymes: Iterable[EnzymeLike] = GOLDEN_GATE_ENZYMES,
usage: CodonUsage | None = None,
avoid: Iterable[EnzymeLike] = (),
) -> tuple[EnzymeChoice, ...]
Rank Type IIS enzymes for assembling these parts, best first.
The parts are the pieces that end up in the product, so a site anywhere in them is a site the enzyme would cut during assembly. An enzyme with no site is preferred; only when none is free is domestication proposed, and then every candidate carries what it would change.
A tie between free enzymes goes to the one whose overhangs shipped data can score, then to
the one leaving the longer overhang. LAST_RESORT enzymes rank behind everything.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
parts
|
Iterable[SequenceRecord]
|
The records going into the assembly. |
required |
enzymes
|
Iterable[EnzymeLike]
|
The candidates. Every one must be Type IIS. |
GOLDEN_GATE_ENZYMES
|
usage
|
CodonUsage | None
|
The host's codon usage, for a proposed domestication. |
None
|
avoid
|
Iterable[EnzymeLike]
|
Further enzymes whose sites a domestication may not create. |
()
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If a candidate cuts inside its own recognition site, leaving no overhang to design. |
Source code in src/liulab_mbio/goldengate/design.py
411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 | |
design_overhangs
¶
design_overhangs(
junctions: Iterable[Junction],
enzyme: EnzymeLike,
*,
avoid: Iterable[EnzymeLike] = (),
min_distance: int = MIN_DISTANCE,
allow_uniform: bool = False,
profile: LigaseProfile | None = None,
prefer_profile: bool = False,
) -> OverhangSet
Choose one overhang per junction, and say what was refused on the way.
Junctions whose overhang is already fixed are settled first, then the ones read from a record, then the free ones, so the constrained junctions are never blocked by a free one. The result lists them in the order they were given.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
junctions
|
Iterable[Junction]
|
The junctions to design for. |
required |
enzyme
|
EnzymeLike
|
The enzyme that will cut them, which sets the overhang length. |
required |
avoid
|
Iterable[EnzymeLike]
|
Enzymes besides this one whose sites a primer tail carrying the overhang must not spell. |
()
|
min_distance
|
int
|
How many bases two overhangs in the set must differ by. |
MIN_DISTANCE
|
allow_uniform
|
bool
|
Accept an overhang of one base kind. Refused by default: an all-GC junction truncates. |
False
|
profile
|
LigaseProfile | None
|
A ligase's own matrix, read by |
None
|
prefer_profile
|
bool
|
Use |
False
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If a junction has no candidate left, naming the rule that refused the last one, or if a profile covers overhangs of another length than the enzyme leaves. |
Examples:
>>> record = SequenceRecord("AAAACCTGAGGGTTTT")
>>> junction = Junction("insert", record=record, position=4, scarless=True)
>>> design_overhangs([junction], "BsaI").overhangs
('CCTG',)
Source code in src/liulab_mbio/goldengate/design.py
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 | |
fidelity
¶
fidelity(
overhangs: Iterable[str],
enzyme: EnzymeLike,
*,
profile: LigaseProfile | None = None,
prefer_profile: bool = False,
) -> FidelityReport
Score how well a set of overhangs should ligate to their own partners and nothing else.
With shipped data, this is Pryor 2020's definition: the product over the junctions of correct ligations divided by every ligation the junction was seen making with an end the reaction holds. A junction has two ends, one presenting the top-strand overhang and one presenting its reverse complement, and both are counted — which is what reproduces the fidelity the paper reports for its own worked examples.
A profile stands in where no shipped matrix covers the enzyme, and prefer_profile uses
it even where one does. A profile is a measurement of the ligase and the conditions and not
of the enzyme, so FidelityReport.enzyme_specific is then False and the source says so.
With neither, the rules score the set instead and FidelityReport.measured is False.
Those numbers are a ranking, not a prediction: they compare one candidate set with another
scored the same way and with nothing else.
Raises:
| Type | Description |
|---|---|
ValueError
|
If an overhang is not one this enzyme leaves, or a profile covers overhangs of another length than the enzyme leaves. |
Examples:
>>> round(fidelity(["AAAA"], "BsaI").value, 3)
1.0
Source code in src/liulab_mbio/goldengate/design.py
738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 | |
ligation_matrix
¶
ligation_matrix(
enzyme: EnzymeLike,
) -> LigationMatrix | None
Return the shipped ligation data measured with this enzyme, or None where there is none.
Matched by name. The measurement is of one supplier's product cycled at one pair of temperatures, so an isoschizomer sold by somebody else does not inherit it.
Examples:
>>> ligation_matrix("BsaI").count("TTTT", "AAAA")
635
>>> ligation_matrix("PaqCI") is None
True
Source code in src/liulab_mbio/goldengate/design.py
395 396 397 398 399 400 401 402 403 404 405 406 407 408 | |
liulab_mbio.goldengate.assembly
¶
Simulate a Golden Gate assembly: amplify each part, cut it, and ligate the pieces.
Every part reaches the reaction as a PCR product whose primers carry a Type IIS tail, so that
cutting the amplicon leaves the overhang the design asked for. The vector is one of those parts:
open_vector points its primers outward from the span the assembly replaces, so the whole
backbone amplifies and the template that templated it is removed with DpnI.
Two rules run through the module:
- An overhang is written on the top strand, so two ends join when the strings are equal.
That is
liulab_mbio.sites' rule, and it makes a junction simply the bases standing at that point of the product. - A part's
left_overhangreplaces the first bases of its own span. A junction that keeps what the template already spells passes those bases back; one that changes them changes the product there, and nothing is added or lost either way.
Coordinates are the model's, 0-based and half-open, and a span across the origin of a circular record ends past the record's length.
Assembly
dataclass
¶
What one Golden Gate reaction makes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
product
|
SequenceRecord
|
The circular plasmid: every part's features carried to their new coordinates, the
primers annotated where they anneal, and each junction drawn in |
required |
parts
|
tuple[Part, ...]
|
The parts that went in, in the order they were given. |
required |
junctions
|
tuple[Junction, ...]
|
Where they meet, in the product's own order. |
required |
enzyme
|
Enzyme
|
The enzyme the reaction was cut with. |
required |
Source code in src/liulab_mbio/goldengate/assembly.py
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 | |
checks
property
¶
checks: tuple[Check, ...]
Judge the product, as data a protocol can print.
The sites left for the enzyme come first — one that remains would cut the product open again — then a check for each part counting the copies of it the product holds, then how many junctions spell the overhang they claim. A part is counted from its template and not from the digest, so the count answers for the ligation rather than repeating it.
junction_positions
property
¶
junction_positions: tuple[int, ...]
Where each junction begins, which is what a validation design reads across.
__getitem__
¶
__getitem__(name: str) -> Check
Return the check of that name.
Raises:
| Type | Description |
|---|---|
KeyError
|
If no check has it. |
Source code in src/liulab_mbio/goldengate/assembly.py
414 415 416 417 418 419 420 421 422 423 424 425 | |
Junction
dataclass
¶
Where two parts meet in the product: the bases their two overhangs paired on.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
start
|
int
|
0-based index of the first of those bases in the product. |
required |
overhang
|
str
|
What they spell, written on the top strand. |
required |
before
|
str
|
The parts either side, named as they were given. |
required |
after
|
str
|
The parts either side, named as they were given. |
required |
Source code in src/liulab_mbio/goldengate/assembly.py
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 | |
Part
dataclass
¶
One piece of an assembly: the PCR that makes it, and the ends the enzyme leaves on it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
What its tube is labelled. |
required |
template
|
SequenceRecord
|
The record it is amplified from. |
required |
span
|
tuple[int, int]
|
The template bases it contributes to the product, 0-based and half-open. |
required |
forward
|
Primer
|
The primers, tails included. |
required |
reverse
|
Primer
|
The primers, tails included. |
required |
amplicon
|
SequenceRecord
|
What the PCR makes: both tails, the span, and the template's features and primers carried to their new coordinates. |
required |
left_overhang
|
str
|
The bases the enzyme leaves at the amplicon's left end, which stand in for the span's own first bases. |
required |
right_overhang
|
str
|
The bases at its right end. They belong to the next part round the circle, so they reach this part only through the reverse primer's tail. |
required |
dpni
|
bool
|
Whether DpnI should be used to take the template away afterwards. |
required |
report
|
PairReport
|
What the pair scored on the template, carrying the annealing temperature and the extension time the PCR needs. |
required |
Source code in src/liulab_mbio/goldengate/assembly.py
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | |
amplify
¶
amplify(
template: SequenceRecord,
enzyme: EnzymeLike,
start: int,
end: int,
*,
left_overhang: str,
right_overhang: str,
name: str = "",
dpni: bool | None = None,
polymerase: Polymerase = Q5,
thresholds: Thresholds = THRESHOLDS,
spacer: str | None = None,
spacer_length: int = SPACER_LENGTH,
avoid: Iterable[EnzymeLike] = (),
) -> Part
Design the PCR that turns template[start:end] into one part of an assembly.
Each primer carries a tail holding the recognition site pointing back into the part, so
cutting the amplicon leaves left_overhang at its left end and right_overhang at its
right. left_overhang stands in for the span's own first bases, so the annealing region
begins after them.
end passes the template's length when the span runs across the origin; open_vector is
that case with the arithmetic done for you.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
template
|
SequenceRecord
|
The record to amplify. |
required |
enzyme
|
EnzymeLike
|
The Type IIS enzyme the assembly is cut with. |
required |
start
|
int
|
The span of |
required |
end
|
int
|
The span of |
required |
left_overhang
|
str
|
The junctions at this part's two ends, written on the top strand. |
required |
right_overhang
|
str
|
The junctions at this part's two ends, written on the top strand. |
required |
name
|
str
|
Names the part, its amplicon and its two primers. |
''
|
dpni
|
bool | None
|
Whether DpnI removes the template. Decided from the template when not given: a circular
one is a plasmid from a Dam-positive host, and |
None
|
polymerase
|
Polymerase
|
Passed to |
Q5
|
thresholds
|
Polymerase
|
Passed to |
Q5
|
spacer
|
Polymerase
|
Passed to |
Q5
|
spacer_length
|
Polymerase
|
Passed to |
Q5
|
avoid
|
Polymerase
|
Passed to |
Q5
|
Returns:
| Type | Description |
|---|---|
Part
|
The primers, the amplicon they make, and the ends a digest will leave. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If an overhang is not one this enzyme leaves, if the span is no longer than its own left overhang, or if no annealing region fits either end. |
Source code in src/liulab_mbio/goldengate/assembly.py
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 | |
assemble
¶
Cut every part with enzyme and ligate them into one circular product.
Two ends join where their overhangs are equal, both being written on the top strand, so the parts are chained from the first one round until the circle closes. That first part sets the origin: the product is turned so its template's own first base keeps the place it had, which leaves the vector's coordinates readable and keeps a junction off base zero.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
parts
|
Sequence[Part]
|
Two or more, the linearised vector first. |
required |
enzyme
|
EnzymeLike
|
The Type IIS enzyme, which must be the one the parts carry tails for. |
required |
name
|
str
|
What to call the product. |
''
|
Returns:
| Type | Description |
|---|---|
Assembly
|
The product, the parts that made it, and the junctions between them. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If fewer than two parts are given, if cutting one does not leave the fragment its tails were designed for, or if the overhangs do not chain into one circle. |
Source code in src/liulab_mbio/goldengate/assembly.py
428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 | |
dam_sites
¶
dam_sites(record: SequenceRecord) -> int
Count the sites in record that DpnI can cut once Dam has methylated them.
A plasmid grown in a Dam-positive host carries them methylated and a PCR product does not, which is what lets DpnI take the template away and leave the amplicon.
Examples:
>>> dam_sites(SequenceRecord("AAGATCAA"))
1
Source code in src/liulab_mbio/goldengate/assembly.py
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | |
open_vector
¶
open_vector(
vector: SequenceRecord,
enzyme: EnzymeLike,
start: int,
end: int,
*,
overhangs: tuple[str, str],
name: str = "",
dpni: bool | None = None,
polymerase: Polymerase = Q5,
thresholds: Thresholds = THRESHOLDS,
spacer: str | None = None,
spacer_length: int = SPACER_LENGTH,
avoid: Iterable[EnzymeLike] = (),
) -> Part
Linearise a circular vector by PCR, replacing vector[start:end] with the assembly.
The primers face outward from that span, so the whole backbone amplifies and the plasmid that templated it is taken away with DpnI.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
vector
|
SequenceRecord
|
The circular record to open. |
required |
enzyme
|
EnzymeLike
|
The Type IIS enzyme the assembly is cut with. |
required |
start
|
int
|
The span the assembly replaces. |
required |
end
|
int
|
The span the assembly replaces. |
required |
overhangs
|
tuple[str, str]
|
The two junctions, in the vector's own coordinates: the one standing at |
required |
name
|
str
|
As |
''
|
dpni
|
str
|
As |
''
|
polymerase
|
str
|
As |
''
|
thresholds
|
str
|
As |
''
|
spacer
|
str
|
As |
''
|
spacer_length
|
str
|
As |
''
|
avoid
|
str
|
As |
''
|
Returns:
| Type | Description |
|---|---|
Part
|
The backbone, ready to assemble. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in src/liulab_mbio/goldengate/assembly.py
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 | |
liulab_mbio.goldengate.bench
¶
What a Golden Gate assembly takes at the bench: its reaction and its cycling.
Every number is NEB's, through docs/research/golden-gate-assembly.md. Functions return
liulab_mbio.protocol values, so a protocol prints them unchanged. What any cloning pipeline
shares -- DNA amounts, PCR, gels and validation -- is liulab_mbio.bench.
NEB ships two Golden Gate systems and their tables do not mix. LIGASE_MASTER_MIX is NEBridge
Ligase Master Mix (M1100), which takes any NEB Type IIS enzyme; KIT is one of the kits, which
carry their own enzyme mix and so exist only for BsaI-HFv2 and BsmBI-v2.
Dose
dataclass
¶
How much Type IIS enzyme one reaction takes, and the units that is.
Source code in src/liulab_mbio/goldengate/bench.py
76 77 78 79 80 81 | |
assembly_amounts
¶
assembly_amounts(
vector: tuple[str, int],
inserts: tuple[tuple[str, int], ...],
*,
vector_pmol: float = FRAGMENT_PMOL,
insert_ratio: float = INSERT_RATIO,
) -> tuple[Amount, ...]
Return what to put in the assembly, vector first.
The vector and each insert are a name and a length in base pairs. NEB asks for
FRAGMENT_PMOL of the destination plasmid and the same of each precloned insert;
insert_ratio is the insert to vector molar ratio for amplicon inserts.
Raises:
| Type | Description |
|---|---|
ValueError
|
If a length is not positive. |
Source code in src/liulab_mbio/goldengate/bench.py
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | |
assembly_program
¶
assembly_program(
enzyme: Enzyme,
*,
fragments: int,
system: System = LIGASE_MASTER_MIX,
library: bool = False,
) -> ThermocyclerProgram
Return the cycling for this enzyme and fragment count, ending with the 60 °C end soak.
fragments counts the vector. library picks NEB's longer single-insert incubation, which
it recommends for library construction rather than for cloning one gene.
Raises:
| Type | Description |
|---|---|
ValueError
|
If fewer than two fragments are given, or the enzyme has no NEB protocol. |
Source code in src/liulab_mbio/goldengate/bench.py
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 | |
assembly_reaction
¶
assembly_reaction(
enzyme: Enzyme,
amounts: tuple[Amount, ...],
*,
system: System = LIGASE_MASTER_MIX,
reactions: int = 1,
) -> ReactionTable
Return the Golden Gate reaction for these fragments, the vector counted among them.
DNA goes in each tube, everything else into the master mix, which is the order NEB asks for. The PaqCI activator line appears only for PaqCI.
Raises:
| Type | Description |
|---|---|
ValueError
|
If fewer than two fragments are given, if the enzyme has no NEB table for |
Source code in src/liulab_mbio/goldengate/bench.py
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | |
enzyme_component
¶
Return the Type IIS enzyme component of a Ligase Master Mix reaction joining fragments.
Raises:
| Type | Description |
|---|---|
ValueError
|
If NEB's Ligase Master Mix table has no row for the enzyme. |
Source code in src/liulab_mbio/goldengate/bench.py
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 | |
golden_gate_temperature
¶
golden_gate_temperature(enzyme: Enzyme) -> float
Return the temperature NEB's Golden Gate cycling runs this enzyme at, °C.
Raises:
| Type | Description |
|---|---|
ValueError
|
If NEB publishes no Golden Gate protocol for it. |
Examples:
>>> from liulab_mbio.enzymes import get_enzyme
>>> golden_gate_temperature(get_enzyme("BbsI-HF"))
37.0
Source code in src/liulab_mbio/goldengate/bench.py
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | |
ligase_master_mix_component
¶
ligase_master_mix_component(fragments: int) -> Component
Return the NEBridge Ligase Master Mix component of a reaction joining fragments.
Source code in src/liulab_mbio/goldengate/bench.py
235 236 237 238 | |
liulab_mbio.goldengate.ligase
¶
A ligase's own overhang profile, read from a matrix file the user already holds.
Potapov et al. 2018 profiled T4 DNA ligase across all 256 four-base overhangs, which covers the
Type IIS enzymes nobody has published a matrix for. That archive is CC BY-NC 4.0, so none of
it is in this package: read_profile reads a copy from the user's own disk and nothing is
redistributed. docs/research/ligation-fidelity.md says where the archive is and what it holds.
A profile belongs to the ligase and the conditions it was measured under, not to the Type IIS
enzyme, and liulab_mbio.goldengate.design.fidelity says so in the report it returns.
The two shapes the archive uses are both read here with the standard library alone: an .xlsx
is a zip of XML, so zipfile and xml.etree are enough, and a .csv is read by csv.
LigaseProfile
dataclass
¶
How often each overhang pair was seen ligating, measured with one ligase.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
The file it was read from. |
required |
conditions
|
str
|
The ligase, the incubation and the temperature. Empty where nothing states them. |
required |
overhang_length
|
int
|
How many bases the overhangs on both axes have. |
required |
observations
|
int
|
Every ligation event counted. |
required |
counts
|
Mapping[str, Mapping[str, int]]
|
Top-strand overhang to the bottom-strand overhangs it was seen ligating to. Both are written 5' to 3', so a row pairs with the column spelling its reverse complement. |
required |
Source code in src/liulab_mbio/goldengate/ligase.py
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | |
count
¶
count(top: str, bottom: str) -> int
How often a top-strand overhang was seen ligating to a bottom-strand one.
Source code in src/liulab_mbio/goldengate/ligase.py
76 77 78 | |
normalised
¶
normalised(top: str, bottom: str) -> float
Return the count per 100,000 ligation events, the scale NEB's thresholds use.
Source code in src/liulab_mbio/goldengate/ligase.py
80 81 82 | |
column_index
¶
column_index(reference: str) -> int
Return the 1-based column number of a cell reference such as "IW257".
Raises:
| Type | Description |
|---|---|
ValueError
|
If the reference carries no column letters. |
Examples:
>>> column_index("A1"), column_index("AA1")
(1, 27)
Source code in src/liulab_mbio/goldengate/ligase.py
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | |
read_csv
¶
read_csv(text: str) -> dict[str, dict[str, int]]
Read a comma-separated count matrix into the sparse form read_workbook returns.
Raises:
| Type | Description |
|---|---|
ValueError
|
If the file holds no row, or a cell holds something that is not a count. |
Source code in src/liulab_mbio/goldengate/ligase.py
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | |
read_profile
¶
read_profile(
path: str | PathLike[str], *, conditions: str = ""
) -> LigaseProfile
Read a ligation count matrix the user holds, as an .xlsx or a .csv file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | PathLike[str]
|
The matrix. Its conditions are read from its name where that is named the way the
archive names one, such as |
required |
conditions
|
str
|
What the reaction was, for a file whose name does not say, or to correct one that does. |
''
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If the file is not a count matrix, saying what one is. |
Examples:
>>> read_profile("FileS03_T4_18h_25C.xlsx").conditions
'T4 DNA ligase, 18 h at 25 °C'
Source code in src/liulab_mbio/goldengate/ligase.py
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | |
read_workbook
¶
read_workbook(
blob: bytes,
) -> tuple[str, dict[str, dict[str, int]]]
Read one workbook into its sheet name and a sparse count matrix.
The first row and the first column hold the overhang labels; every other cell is an observation count, and a zero is dropped.
Raises:
| Type | Description |
|---|---|
ValueError
|
If a cell is neither a shared string nor a number, which is not a shape these workbooks have and so is a sign the file is not the one expected. |
Source code in src/liulab_mbio/goldengate/ligase.py
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | |
liulab_mbio.goldengate.oligos
¶
Every oligo a Golden Gate plan orders, and what it is for.
DesignedOligo
dataclass
¶
One oligo a plan orders, and what it is for.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
report
|
PrimerReport
|
What it scored, the primer included. |
required |
role
|
PrimerRole
|
What it is for: amplifying a part, colony PCR, or sequencing the clone. It chooses the thresholds the oligo is designed and judged by. |
required |
part
|
Part | None
|
The part it amplifies, given for an amplification primer and for nothing else. |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If a part is given for any role but amplification, or not given for amplification. |
Source code in src/liulab_mbio/goldengate/oligos.py
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | |
__post_init__
¶
__post_init__() -> None
Refuse a part on anything but an amplification primer, and one missing from it.
Source code in src/liulab_mbio/goldengate/oligos.py
33 34 35 36 37 38 39 | |
liulab_mbio.goldengate.steps
¶
The Golden Gate bench protocol: its own two steps, its own notes, and the step order.
The steps any bench shares are liulab_mbio.bench.steps. This module runs them around the
assembly and its cycling and adds what only Golden Gate has to say. Every number is computed by
liulab_mbio.goldengate.plan or by the modules it calls; the constants below are the choices no
table of NEB's covers, and each says where it comes from.
protocol
¶
protocol(
*,
vector: SequenceRecord,
span: tuple[int, int],
overhangs: OverhangSet,
linearised_vector: Part,
insert_parts: Sequence[Part],
assembly: Assembly,
colony: ColonyCheck,
reads: Sequence[SangerRead],
amounts: tuple[Amount, ...],
phenotype: Phenotype,
oligos: Sequence[DesignedOligo],
checks: Sequence[Check],
host: str,
polymerase: Polymerase,
thresholds: Mapping[PrimerRole, Thresholds],
) -> Protocol
Return the bench protocol for one planned assembly, ready to render.
Each argument is the liulab_mbio.goldengate.plan.Plan field or property of that name, and
oligos is Plan.designed_oligos. The steps run in the order someone does them: one PCR
per part, the gel that checks them, the DpnI digest and cleanup, quantification, the
assembly, transformation and plating, colony PCR, and sequencing. Every step is per
experiment, however many parts there are.
Source code in src/liulab_mbio/goldengate/steps.py
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 | |
The command line¶
The whole module, because typer makes every verb a plain function with a docstring, and
liulab_mbio.cli:app — the object [project.scripts] registers — is built from them.
liulab_mbio.cli
¶
The command line: a version, and a sub-app for each thing the package does.
Typer, because every lab repo that ships a command line uses it: one typer.Typer named
app, no_args_is_help=True so a bare invocation prints help instead of nothing, and a
version command. A verb over a pipeline is mounted as a sub-app with app.add_typer.
version
¶
version() -> None
Print the installed package version.
Source code in src/liulab_mbio/cli.py
25 26 27 28 | |
liulab_mbio.goldengate.cli
¶
The goldengate verbs, mounted on the package command line.
plan
¶
plan(
vector: Annotated[
Path,
Argument(
exists=True,
dir_okay=False,
readable=True,
help="Vector sequence file.",
),
],
inserts: Annotated[
list[Path],
Argument(
exists=True,
dir_okay=False,
readable=True,
help="Insert sequence files, in the order they go round the product.",
),
],
out: Annotated[
Path,
Option(
--out,
-o,
file_okay=False,
help="Directory to write the three outputs into.",
),
],
site: Annotated[
str,
Option(
help="Feature name, or START-END, that the inserts replace."
),
] = "",
orientation: Annotated[
list[str] | None,
Option(
help="Which way round an insert goes: forward or reverse; once per insert."
),
] = None,
in_frame: Annotated[
bool,
Option(
"--in-frame",
help="Hold every insert's junction on a codon boundary.",
),
] = False,
enzyme: Annotated[
str,
Option(
help="Type IIS enzyme to use; the best free one when not given."
),
] = "",
ligase_matrix: Annotated[
Path | None,
Option(
--ligase - matrix,
envvar=LIGASE_MATRIX_ENV,
exists=True,
dir_okay=False,
readable=True,
help="A ligase fidelity matrix you hold (.xlsx or .csv), to score the overhangs of an enzyme nobody has measured.",
),
] = None,
prefer_ligase_matrix: Annotated[
bool,
Option(
--prefer - ligase - matrix,
help="Score with that matrix even where the enzyme has a measured one.",
),
] = False,
polymerase: Annotated[
str, Option(help="Polymerase for the two PCRs.")
] = name,
host: Annotated[
str, Option(help="Strain the protocol names.")
] = DEFAULT_HOST,
name: Annotated[
str, Option(help="What to call the product.")
] = "",
) -> None
Plan an assembly and write the product, the primer sheet and the protocol into OUT.
Source code in src/liulab_mbio/goldengate/cli.py
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | |
liulab_mbio.protocol.cli
¶
The protocol verbs, mounted on the package command line.
render
¶
render(
source: Annotated[
Path,
Argument(
exists=True,
dir_okay=False,
readable=True,
help="Protocol JSON file.",
),
],
output: Annotated[
Path | None,
Option(
--output,
-o,
help="HTML file to write; default: SOURCE with .html.",
),
] = None,
) -> None
Render a protocol JSON file to one self-contained HTML file.
Source code in src/liulab_mbio/protocol/cli.py
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | |