Entwicklung von Proteinen in der Cloud mit Python und Transcriptic oder Wie man ein Protein für 360 US-Dollar erstellt

Was ist, wenn Sie eine Idee für ein kühles, gesundes Protein haben und es in die Realität umsetzen möchten? Möchten Sie beispielsweise einen Impfstoff gegen H. pylori (wie das slowenische Team auf der iGEM 2008 ) erstellen, indem Sie ein Hybridprotein erstellen, das E. coli- Flagellinfragmente kombiniert, die die Immunantwort mit dem üblichen H. pylori- Flagellin stimulieren?

H. pylori Hybrid Flagellin Design Präsentiert vom slowenischen Team auf der iGEM 2008

Überraschenderweise sind wir dank der neuesten Entwicklungen in der Genomik, der synthetischen Biologie und zuletzt in Cloud-Labors sehr nahe daran, jedes gewünschte Protein zu erstellen, ohne Jupyters Notizbuch zu verlassen.

In diesem Artikel werde ich Python-Code von der Idee eines Proteins bis zu seiner Expression in einer Bakterienzelle zeigen, ohne eine Pipette zu berühren oder mit jemandem zu sprechen. Die Gesamtkosten betragen nur ein paar hundert Dollar! Unter Verwendung der Terminologie von Vijaya Pande aus A16Z ist dies Biologie 2.0.

Im folgenden Artikel führt der Python-Code des Cloud-Labors Folgendes aus:

  • Synthese einer DNA-Sequenz, die jedes gewünschte Protein codiert.
  • Klonierung dieser synthetischen DNA in einen Vektor , der sie exprimieren kann.
  • Transformation von Bakterien mit diesem Vektor und Bestätigung, dass eine Expression stattfindet.

Python-Setup


Zunächst die allgemeinen Python-Einstellungen, die für jeden Jupyter-Notizblock erforderlich sind. Wir importieren einige nützliche Python-Module und erstellen einige Dienstprogrammfunktionen, hauptsächlich für die Datenvisualisierung.

Code
import re import json import logging import requests import itertools import numpy as np import seaborn as sns import pandas as pd import matplotlib as mpl import matplotlib.pyplot as plt from io import StringIO from pprint import pprint from Bio.Seq import Seq from Bio.Alphabet import generic_dna from IPython.display import display, Image, HTML, SVG def uprint(astr): print(astr + "\n" + "-"*len(astr)) def show_html(astr): return display(HTML('{}'.format(astr))) def show_svg(astr, w=1000, h=1000): SVG_HEAD = '''<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">''' SVG_START = '''<svg viewBox="0 0 {w:} {h:}" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink= "http://www.w3.org/1999/xlink">''' return display(SVG(SVG_HEAD + SVG_START.format(w=w, h=h) + astr + '</svg>')) def table_print(rows, header=True): html = ["<table>"] html_row = "</td><td>".join(k for k in rows[0]) html.append("<tr style='font-weight:{}'><td>{}</td></tr>".format('bold' if header is True else 'normal', html_row)) for row in rows[1:]: html_row = "</td><td>".join(row) html.append("<tr style='font-family:monospace;'><td>{:}</td></tr>".format(html_row)) html.append("</table>") show_html(''.join(html)) def clean_seq(dna): dna = re.sub("\s","",dna) assert all(nt in "ACGTN" for nt in dna) return Seq(dna, generic_dna) def clean_aas(aas): aas = re.sub("\s","",aas) assert all(aa in "ACDEFGHIKLMNPQRSTVWY*" for aa in aas) return aas def Images(images, header=None, width="100%"): # to match Image syntax if type(width)==type(1): width = "{}px".format(width) html = ["<table style='width:{}'><tr>".format(width)] if header is not None: html += ["<th>{}</th>".format(h) for h in header] + ["</tr><tr>"] for image in images: html.append("<td><img src='{}' /></td>".format(image)) html.append("</tr></table>") show_html(''.join(html)) def new_section(title, color="#66aa33", padding="120px"): style = "text-align:center;background:{};padding:{} 10px {} 10px;".format(color,padding,padding) style += "color:#ffffff;font-size:2.55em;line-height:1.2em;" return HTML('<div style="{}">{}</div>'.format(style, title)) # Show or hide text HTML(""" <style> .section { display:flex;align-items:center;justify-content:center;width:100%; height:400px; background:#6a3;color:#eee;font-size:275%; } .showhide_label { display:block; cursor:pointer; } .showhide { position: absolute; left: -999em; } .showhide + div { display: none; } .showhide:checked + div { display: block; } .shown_or_hidden { font-size:85%; } </style> """) # Plotting style plt.rc("axes", titlesize=20, labelsize=15, linewidth=.25, edgecolor='#444444') sns.set_context("notebook", font_scale=1.2, rc={}) %matplotlib inline %config InlineBackend.figure_format = 'retina' # or 'svg' 

Cloud Labs


Wie AWS oder jede andere Computing-Cloud verfügt das Cloud-Labor über molekularbiologische Geräte sowie Roboter, die über das Internet geleast werden. Sie können Ihren Robotern Anweisungen erteilen, indem Sie auf einige Schaltflächen auf der Benutzeroberfläche klicken oder Code schreiben, der sie selbst programmiert. Es ist nicht notwendig, eigene Protokolle zu schreiben, wie ich es hier tun werde. Ein wesentlicher Teil der Molekularbiologie sind Standard-Routineaufgaben. Daher ist es normalerweise besser, sich auf ein zuverlässiges Alien-Protokoll zu verlassen, das eine gute Interaktion mit Robotern zeigt.

Vor kurzem sind eine Reihe von Unternehmen mit Cloud-Labors erschienen: Transcriptic , Autodesk Wet Lab Accelerator (Beta und auf Basis von Transcriptic), Arcturus BioCloud (Beta), Emerald Cloud Lab (Beta), Synthego (noch nicht gestartet). Es gibt sogar Unternehmen, die auf Cloud-Labors aufbauen, wie beispielsweise Desktop Genetics , das auf CRISPR spezialisiert ist. Wissenschaftliche Artikel über die Verwendung von Cloud Labs in der realen Wissenschaft beginnen zu erscheinen.

Zum Zeitpunkt dieses Schreibens ist nur Transcriptic gemeinfrei, daher werden wir es verwenden. Soweit ich weiß, basiert der größte Teil des Transcriptic-Geschäfts auf der Automatisierung gängiger Protokolle, und das Schreiben eigener Protokolle in Python (wie in diesem Artikel beschrieben) ist weniger verbreitet.


Transkriptionelle „Arbeitszelle“ mit Kühlschränken unten und verschiedenen Laborgeräten am Stand

Ich werde Transcriptic Robots Anweisungen zum Auto-Protokoll geben . Autoprotokoll ist eine JSON-basierte Sprache zum Schreiben von Protokollen für Laborroboter (und sozusagen für Menschen). Autoprotokoll wird hauptsächlich in dieser Python-Bibliothek erstellt . Die Sprache wurde ursprünglich erstellt und wird immer noch von Transcriptic unterstützt, ist aber meines Wissens vollständig offen. Es gibt eine gute Dokumentation .

Eine interessante Idee ist, dass Sie Anweisungen für Personen in entfernten Labors, beispielsweise in China oder Indien, über das Autoprotokoll schreiben können und möglicherweise einige Vorteile aus der Verwendung von Personen (deren Urteilsvermögen) und Robotern (mangelndes Urteilsvermögen) ziehen können. Wir müssen hier protocols.io erwähnen. Dies ist ein Versuch, Protokolle zu standardisieren, um die Reproduzierbarkeit zu verbessern, aber für Menschen, nicht für Roboter.

 "instructions": [ { "to": [ { "well": "water/0", "volume": "500.0:microliter" } ], "op": "provision", "resource_id": "rs17gmh5wafm5p" }, ... ] 

Beispiel für ein Autoprotokollfragment

Python-Einstellungen für die Molekularbiologie


Zusätzlich zum Importieren von Standardbibliotheken benötige ich einige spezifische molekularbiologische Dienstprogramme. Dieser Code ist hauptsächlich für Autoprotokoll und Transkription vorgesehen.

Das Konzept des "Totvolumens" findet sich häufig im Code. Dies bedeutet den letzten Tropfen Flüssigkeit, den Transkriptionsroboter nicht mit einer Pipette aus den Röhrchen nehmen können (weil sie ihn nicht sehen können!). Sie müssen viel Zeit aufwenden, um sicherzustellen, dass die Flaschen genügend Material haben.

Code
 import autoprotocol from autoprotocol import Unit from autoprotocol.container import Container from autoprotocol.protocol import Protocol from autoprotocol.protocol import Ref # "Link a ref name (string) to a Container instance." import requests import logging # Transcriptic authorization org_name = 'hgbrian' tsc_headers = {k:v for k,v in json.load(open("auth.json")).items() if k in ["X_User_Email","X_User_Token"]} # Transcriptic-specific dead volumes _dead_volume = [("96-pcr",3), ("96-flat",25), ("96-flat-uv",25), ("96-deep",15), ("384-pcr",2), ("384-flat",5), ("384-echo",15), ("micro-1.5",15), ("micro-2.0",15)] dead_volume = {k:Unit(v,"microliter") for k,v in _dead_volume} def init_inventory_well(well, headers=tsc_headers, org_name=org_name): """Initialize well (set volume etc) for Transcriptic""" def _container_url(container_id): return 'https://secure.transcriptic.com/{}/samples/{}.json'.format(org_name, container_id) response = requests.get(_container_url(well.container.id), headers=headers) response.raise_for_status() container = response.json() well_data = container['aliquots'][well.index] well.name = "{}/{}".format(container["label"], well_data['name']) if well_data['name'] is not None else container["label"] well.properties = well_data['properties'] well.volume = Unit(well_data['volume_ul'], 'microliter') if 'ERROR' in well.properties: raise ValueError("Well {} has ERROR property: {}".format(well, well.properties["ERROR"])) if well.volume < Unit(20, "microliter"): logging.warn("Low volume for well {} : {}".format(well.name, well.volume)) return True def touchdown(fromC, toC, durations, stepsize=2, meltC=98, extC=72): """Touchdown PCR protocol generator""" assert 0 < stepsize < toC < fromC def td(temp, dur): return {"temperature":"{:2g}:celsius".format(temp), "duration":"{:d}:second".format(dur)} return [{"cycles": 1, "steps": [td(meltC, durations[0]), td(C, durations[1]), td(extC, durations[2])]} for C in np.arange(fromC, toC-stepsize, -stepsize)] def convert_ug_to_pmol(ug_dsDNA, num_nts): """Convert ug dsDNA to pmol""" return float(ug_dsDNA)/num_nts * (1e6 / 660.0) def expid(val): """Generate a unique ID per experiment""" return "{}_{}".format(experiment_name, val) def µl(microliters): """Unicode function name for creating microliter volumes""" return Unit(microliters,"microliter") 

DNA-Synthese und synthetische Biologie


Trotz ihrer Verbindung mit der modernen synthetischen Biologie ist die DNA-Synthese eine ziemlich alte Technologie. Seit Jahrzehnten können wir Oligonukleotide herstellen (dh DNA-Sequenzen bis zu 200 Basen). Es war jedoch immer teuer und die Chemie erlaubte nie lange DNA-Sequenzen. In letzter Zeit ist es zu einem vernünftigen Preis möglich geworden, ganze Gene (bis zu Tausenden von Basen) zu synthetisieren. Diese Leistung eröffnet wirklich die Ära der „synthetischen Biologie“.

Die synthetische Genomik von Craig Venter hat die synthetische Biologie am weitesten vorangetrieben, indem sie einen ganzen Organismus synthetisiert hat - mehr als eine Million Basen lang. Mit zunehmender Länge der DNA besteht das Problem nicht mehr in der Synthese, sondern in der Assemblierung (d. H. Zusammenfügen synthetisierter DNA-Sequenzen). Mit jeder Baugruppe können Sie die DNA-Länge (oder mehr) verdoppeln, sodass Sie nach etwa einem Dutzend Iterationen ein ziemlich langes Molekül erhalten ! Die Unterscheidung zwischen Synthese und Zusammenbau sollte dem Endbenutzer bald klar werden.

Moores Gesetz?


Der Preis für die DNA-Synthese sinkt ziemlich schnell von über 0,30 USD vor zwei Jahren auf heute etwa 0,10 USD, aber sie entwickelt sich eher wie Bakterien als wie Prozessoren. Im Gegensatz dazu fallen die Preise für DNA-Sequenzierung schneller als das Gesetz von Moore. Ein Ziel von 0,02 USD pro Base wird als Wendepunkt festgelegt, an dem Sie viele zeitaufwändige DNA-Manipulationen durch einfache Synthese ersetzen können. Zu diesem Preis können Sie beispielsweise ein ganzes 3-kb-Plasmid für 60 US-Dollar synthetisieren und eine Menge Molekularbiologie überspringen. Ich hoffe, wir werden dies in ein paar Jahren erreichen.


DNA-Synthesepreise im Vergleich zu DNA-Sequenzierungspreisen, Preis für 1 Base (Carlson, 2014)

DNA-Syntheseunternehmen


Auf dem Gebiet der DNA-Synthese gibt es mehrere große Unternehmen: IDT ist der größte Hersteller von Oligonukleotiden und kann auch längere (bis zu 2 kb) „Genfragmente“ ( gBlocks ) produzieren. Gen9 , Twist und DNA 2.0 sind normalerweise auf längere DNA-Sequenzen spezialisiert - dies sind Gensyntheseunternehmen. Es gibt auch einige interessante neue Unternehmen wie Cambrian Genomics und Genesis DNA , die an Synthesemethoden der nächsten Generation arbeiten.

Andere Unternehmen wie Amyris , Zymergen und Ginkgo Bioworks verwenden die von diesen Unternehmen synthetisierte DNA, um auf Körperebene zu arbeiten. Synthetic Genomics macht das auch, aber es synthetisiert die DNA selbst.

Ginkgo hat kürzlich einen Deal mit Twist abgeschlossen , um 100 Millionen Basen zu machen: den größten Deal, den ich je gesehen habe. Dies beweist, dass wir in der Zukunft leben. Twist hat sogar einen Werbecode auf Twitter beworben: Wenn Sie 10 Millionen DNA-Basen (fast das gesamte Hefegenom!) Kaufen, erhalten Sie weitere 10 Millionen kostenlos.


Twitter Twist Nischenangebot

Erster Teil: Versuchsaufbau


Grün fluoreszierendes Protein


In diesem Experiment synthetisieren wir eine DNA-Sequenz für ein einfaches, grün fluoreszierendes Protein (GFP). Das GFP-Protein wurde zuerst in einer Qualle gefunden , die unter ultraviolettem Licht fluoresziert. Dies ist ein äußerst nützliches Protein, da es leicht durch einfache Messung der Fluoreszenz nachgewiesen werden kann. Es gibt GFP-Optionen, die Gelb, Rot, Orange und andere Farben erzeugen.

Es ist interessant zu sehen, wie verschiedene Mutationen die Farbe eines Proteins beeinflussen, und dies ist ein potenziell interessantes Problem des maschinellen Lernens. In jüngerer Zeit mussten Sie dafür viel Zeit im Labor verbringen, aber jetzt werde ich Ihnen zeigen, dass es (fast) so einfach ist wie das Bearbeiten einer Textdatei!

Technisch gesehen ist mein GFP eine Super Folder Option (sfGFP) mit einigen Mutationen zur Verbesserung der Qualität.


In Superfolder-GFP (sfGFP) geben einige Mutationen ihm bestimmte nützliche Eigenschaften.


GFP-Struktur (visualisiert mit PV )

GFP-Synthese in Twist


Ich hatte das Glück, in Twists Alpha-Testprogramm einzusteigen, also nutzte ich ihren DNA-Synthesedienst (sie gaben freundlicherweise meine winzige Bestellung auf - danke, Twist!). Dies ist ein neues Unternehmen auf unserem Gebiet mit einem neuen vereinfachten Syntheseverfahren. Ihre Preise liegen bei 0,10 USD pro Basis oder darunter , aber sie befinden sich noch in der Beta und das Alpha-Programm, an dem ich teilgenommen habe, wurde geschlossen. Twist hat ungefähr 150 Millionen US-Dollar gesammelt, daher ist ihre Technologie lebendig.

Ich habe meine DNA-Sequenz als Excel-Tabelle an Twist gesendet (es gibt noch keine API, aber ich denke, es wird bald soweit sein), und sie haben die synthetisierte DNA direkt an meine Box im Transkriptionslabor gesendet (ich habe auch IDT für die Synthese verwendet, aber sie haben nicht gesendet DNA direkt in Transcriptic, was den Spaß ein bisschen verdirbt).

Offensichtlich ist dieser Prozess noch kein typischer Anwendungsfall geworden und erfordert Unterstützung, aber er hat funktioniert, sodass die gesamte Pipeline virtuell bleibt. Ohne dies würde ich wahrscheinlich Zugang zum Labor benötigen - viele Unternehmen werden keine DNA oder Reagenzien an ihre Heimatadresse senden.


GFP ist harmlos, daher wird jede Art hervorgehoben

Plasmidvektor


Um dieses Protein in Bakterien zu exprimieren, muss das Gen irgendwo leben, sonst wird die synthetische DNA, die das Gen codiert, einfach sofort abgebaut. In der Molekularbiologie verwenden wir in der Regel ein Plasmid, ein Stück runder DNA, das außerhalb des Bakteriengenoms lebt und Proteine ​​exprimiert. Plasmide sind eine bequeme Möglichkeit für Bakterien, nützliche, eigenständige Funktionsmodule wie Antibiotikaresistenz gemeinsam zu nutzen. In einer Zelle können sich Hunderte von Plasmiden befinden.

Die weit verbreitete Terminologie ist, dass ein Plasmid ein Vektor ist und synthetische DNA eine Insertion (Insertion) ist. Hier versuchen wir also, die Insertion in einen Vektor zu klonen und dann die Bakterien unter Verwendung des Vektors zu transformieren.


Bakteriengenom und Plasmid (nicht maßstabsgetreu!) ( Wikipedia )

pUC19


Ich habe ein ziemlich normales Plasmid in der pUC19- Serie gewählt. Dieses Plasmid wird sehr oft verwendet, und da es als Teil des Standard-Transkriptinventars verfügbar ist, müssen wir ihnen nichts senden.


Struktur von pUC19: Die Hauptkomponenten sind das Ampicillin-Resistenzgen lacZα, MCS / Polylinker und der Replikationsursprung (Wikipedia).

PUC19 hat eine nette Funktion: Da es das lacZα-Gen enthält, können Sie die blau-weiße Selektionsmethode verwenden und sehen, in welchen Kolonien die Insertion erfolgreich war. Es werden zwei Chemikalien benötigt: IPTG und X-Gal , und die Schaltung funktioniert wie folgt:

  • IPTG induziert die lacZα-Expression.
  • Wenn lacZα über DNA deaktiviert wird, die an der Mehrfachklonierungsstelle ( MCS / Polylinker ) in lacZα inseriert ist, kann das Plasmid X-Gal nicht hydrolysieren und diese Kolonien sind weiß statt blau.
  • Daher erzeugt eine erfolgreiche Insertion weiße Kolonien und eine fehlgeschlagene Insertion blaue Kolonien.


Die blau-weiße Auswahl zeigt, wo die lacZα-Expression deaktiviert wurde ( Wikipedia )

In der OpenWetware-Dokumentation heißt es:

E. coli DH5α benötigt kein IPTG, um die Expression des lac-Promotors zu induzieren, selbst wenn ein Lac-Repressor im Stamm exprimiert wird. Die Kopienzahl der meisten Plasmide übersteigt die Anzahl der Repressoren in den Zellen. Wenn Sie eine maximale Expression benötigen, fügen Sie IPTG bis zu einer Endkonzentration von 1 mM hinzu.

Synthetische DNA-Sequenzen


SfGFP-DNA-Sequenz


Es ist einfach, die DNA-Sequenz für sfGFP zu erhalten, indem die Proteinsequenz genommen und mit Codons codiert wird, die für den Wirtsorganismus geeignet sind (hier E. coli ). Dies ist ein mittelgroßes Protein mit 236 Aminosäuren, sodass die DNA-Synthese bei 10 Cent etwa 70 US-Dollar pro Base kostet.


Wolfram Alpha, Synthesekostenberechnung

Die ersten 12 Basen unseres sfGFP sind die Shine-Delgarno-Sequenz , die ich selbst hinzugefügt habe und die theoretisch die Expression erhöhen sollte (AGGAGGACAGCT, dann startet ATG ( Startcodon ) das Protein). Nach einem von Salis Lab entwickelten Rechenwerkzeug ( Vorlesungsfolien ) können wir eine mittlere bis hohe Expression unseres Proteins erwarten (Translationsinitiationsrate von 10.000 „willkürlichen Einheiten“).

 sfGFP_plus_SD = clean_seq(""" AGGAGGACAGCTATGTCGAAAGGAGAAGAACTGTTTACCGGTGTGGTTCCGATTCTGGTAGAACTGGA TGGGGACGTGAACGGCCATAAATTTAGCGTCCGTGGTGAGGGTGAAGGGGATGCCACAAATGGCAAAC TTACCCTTAAATTCATTTGCACTACCGGCAAGCTGCCGGTCCCTTGGCCGACCTTGGTCACCACACTG ACGTACGGGGTTCAGTGTTTTTCGCGTTATCCAGATCACATGAAACGCCATGACTTCTTCAAAAGCGC CATGCCCGAGGGCTATGTGCAGGAACGTACGATTAGCTTTAAAGATGACGGGACCTACAAAACCCGGG CAGAAGTGAAATTCGAGGGTGATACCCTGGTTAATCGCATTGAACTGAAGGGTATTGATTTCAAGGAA GATGGTAACATTCTCGGTCACAAATTAGAATACAACTTTAACAGTCATAACGTTTATATCACCGCCGA CAAACAGAAAAACGGTATCAAGGCGAATTTCAAAATCCGGCACAACGTGGAGGACGGGAGTGTACAAC TGGCCGACCATTACCAGCAGAACACACCGATCGGCGACGGCCCGGTGCTGCTCCCGGATAATCACTAT TTAAGCACCCAGTCAGTGCTGAGCAAAGATCCGAACGAAAAACGTGACCATATGGTGCTGCTGGAGTT CGTGACCGCCGCGGGCATTACCCATGGAATGGATGAACTGTATAAA""") print("Read in sfGFP plus Shine-Dalgarno: {} bases long".format(len(sfGFP_plus_SD))) sfGFP_aas = clean_aas("""MSKGEELFTGVVPILVELDGDVNGHKFSVRGEGEGDATNGKLTLKFICTTGKLPVPWPTLVTTLTYG VQCFSRYPDHMKRHDFFKSAMPEGYVQERTISFKDDGTYKTRAEVKFEGDTLVNRIELKGIDFKEDGNILGHKLEYNFNSHNVYITADKQKN GIKANFKIRHNVEDGSVQLADHYQQNTPIGDGPVLLPDNHYLSTQSVLSKDPNEKRDHMVLLEFVTAAGITHGMDELYK""") assert sfGFP_plus_SD[12:].translate() == sfGFP_aas print("Translation matches protein with accession 532528641") 

  Lesen Sie in sfGFP plus Shine-Dalgarno: 726 Basen lang
 Die Übersetzung stimmt mit dem Protein 532528641 überein 

PUC19-DNA-Sequenz


Zuerst überprüfe ich, ob die von der NEB heruntergeladene pUC19-Sequenz die richtige Länge hat und den erwarteten Polylinker enthält .

 pUC19_fasta = !cat puc19fsa.txt pUC19_fwd = clean_seq(''.join(pUC19_fasta[1:])) pUC19_rev = pUC19_fwd.reverse_complement() assert all(nt in "ACGT" for nt in pUC19_fwd) assert len(pUC19_fwd) == 2686 pUC19_MCS = clean_seq("GAATTCGAGCTCGGTACCCGGGGATCCTCTAGAGTCGACCTGCAGGCATGCAAGCTT") print("Read in pUC19: {} bases long".format(len(pUC19_fwd))) assert pUC19_MCS in pUC19_fwd print("Found MCS/polylinker") 

  Lesen Sie in pUC19: 2686 Basen lang
 Gefunden MCS / Polylinker 

Wir führen einige grundlegende QCs durch, um sicherzustellen, dass EcoRI und BamHI nur einmal in pUC19 vorhanden sind (die folgenden Restriktionsenzyme sind im Standard-Transkriptionsinventar verfügbar: PstI , PvuII , EcoRI , BamHI , BbsI , BsmBI ).

 REs = {"EcoRI":"GAATTC", "BamHI":"GGATTC"} for rename, res in REs.items(): assert (pUC19_fwd.find(res) == pUC19_fwd.rfind(res) and pUC19_rev.find(res) == pUC19_rev.rfind(res)) assert (pUC19_fwd.find(res) == -1 or pUC19_rev.find(res) == -1 or pUC19_fwd.find(res) == len(pUC19_fwd) - pUC19_rev.find(res) - len(res)) print("Asserted restriction enzyme sites present only once: {}".format(REs.keys())) 

Jetzt schauen wir uns die lacZα-Sequenz an und stellen sicher, dass nichts Unerwartetes vorliegt. Zum Beispiel sollte es mit Met beginnen und mit einem Stoppcodon enden. Es ist auch leicht zu bestätigen, dass dies der vollständige 324 bp lacZα ORF ist, indem die pUC19-Sequenz in den freien Snapgen-Viewer geladen wird .

 lacZ = pUC19_rev[2217:2541] print("lacZα sequence:\t{}".format(lacZ)) print("r_MCS sequence:\t{}".format(pUC19_MCS.reverse_complement())) lacZ_p = lacZ.translate() assert lacZ_p[0] == "M" and not "*" in lacZ_p[:-1] and lacZ_p[-1] == "*" assert pUC19_MCS.reverse_complement() in lacZ assert pUC19_MCS.reverse_complement() == pUC19_rev[2234:2291] print("Found MCS once in lacZ sequence") 

  lacZ-Sequenz: ATGACCATGATTACGCCAAGCTTGCATGCCTGCAGGTCGACTCTAGAGGATCCCCGGGTACCGAGCTCGAATTCACTGGCCGTCGTTTTACAACGTCGTGACTGGGAAAACCCTGGCGTTACCCAACTTAATCGCCTTGCAGCACATCCCCCTTTCGCCAGCTGGCGTAATAGCGAAGAGGCCCGCACCGATCGCCCTTCCCAACAGTTGCGCAGCCTGAATGGCGAATGGCGCCTGATGCGGTATTTTCTCCTTACGCATCTGTGCGGTATTTCACACCGCATATGGTGCACTCTCAGTACAATCTGCTCTGATGCCGCATAG
 r_MCS-Sequenz: AAGCTTGCATGCCTGCAGGTCGACTCTAGAGGATCCCCGGGTACCGAGCTCGAATTC
 MCS einmal in lacZ-Sequenz gefunden 

Gibson Montage


DNA zusammenzusetzen bedeutet einfach, Fragmente zu vernetzen. Normalerweise sammeln Sie mehrere DNA-Fragmente in einem längeren Segment und klonieren es dann in ein Plasmid oder Genom. In diesem Experiment möchte ich ein DNA-Segment in das pUC19-Plasmid unterhalb des lac-Promotors zur Expression in E. coli klonieren.

Es gibt viele Klonierungsmethoden (z. B. NEB , OpenWetware , Addgen ). Hier werde ich die Gibson-Baugruppe verwenden ( die 2009 von Daniel Gibson in Synthetic Genomics entwickelt wurde), die nicht unbedingt die billigste Methode ist, aber einfach und flexibel. Sie müssen nur die DNA, die Sie sammeln möchten (mit der entsprechenden Überlappung), in ein Reagenzglas mit dem Gibson Assembly Master Mix geben, und es wird sich selbst zusammensetzen!


Gibson Assembly Review ( NEB )

Ausgangsmaterial


Wir beginnen mit 100 ng synthetischer DNA in 10 μl Flüssigkeit. Dies entspricht 0,21 Picomol DNA oder einer Konzentration von 10 ng / μl.

 pmol_sfgfp = convert_ug_to_pmol(0.1, len(sfGFP_plus_SD)) print("Insert: 100ng of DNA of length {:4d} equals {:.2f} pmol".format(len(sfGFP_plus_SD), pmol_sfgfp)) 

  Insert: 100 ng DNA mit einer Länge von 726 entsprechen 0,21 pmol 

Nach dem NEB-Montageprotokoll ist dies genug Quellmaterial:

Die NEB empfiehlt insgesamt 0,02 bis 0,5 Picomol DNA-Fragmente, wenn 1 oder 2 Fragmente zu dem Vektor zusammengesetzt werden, oder 0,2 bis 1,0 Picomol DNA-Fragmente, wenn 4 bis 6 Fragmente gesammelt werden.

0,02-0,5 pmol * X & mgr; l
* Die optimierte Klonierungseffizienz beträgt 50-100 ng Vektoren mit einem 2-3-fachen Überschuss an Insertionen. Verwenden Sie fünfmal mehr Einfügungen, wenn die Größe weniger als 200 Bit / s beträgt. Das Gesamtvolumen an ungefilterten PCR-Fragmenten in der Gibson-Assemblierungsreaktion sollte 20% nicht überschreiten.

NEBuilder für Gibson-Montage


Der NEBuilder von Biolab ist ein wirklich großartiges Tool zum Erstellen des Gibson-Build-Protokolls. Sie erhalten sogar ein umfassendes vierseitiges PDF mit allen Informationen. Mit diesem Tool entwickeln wir ein Protokoll zum Schneiden von pUC19 mit EcoRI und verwenden dann PCR [PCR, Polymerasekettenreaktion ermöglicht einen signifikanten Anstieg kleiner Konzentrationen bestimmter DNA-Fragmente in biologischem Material - ca. per.], um der Insertion Fragmente der entsprechenden Größe hinzuzufügen.



Teil zwei: Experiment


Das Experiment besteht aus vier Phasen:

  1. Polymeraseketteninsertionsreaktion zur Zugabe von Material mit einer flankierenden Sequenz.
  2. Schneiden eines Plasmids zur Aufnahme.
  3. Assemblierung durch Gibson-Insertion und Plasmide.
  4. Transformation von Bakterien unter Verwendung des zusammengesetzten Plasmids.

Schritt 1. PCR-Insertion


Die Gibson-Assemblierung hängt von der DNA-Sequenz ab, die Sie sammeln, und weist eine überlappende Sequenz auf (siehe NEB-Protokoll mit detaillierten Anweisungen oben). Zusätzlich zur einfachen Amplifikation können Sie mit der PCR auch eine flankierende DNA-Sequenz hinzufügen, indem Sie einfach eine zusätzliche Sequenz in die Primer aufnehmen (kann auch nur mit OE-PCR kloniert werden ).

Wir synthetisieren Primer gemäß dem obigen NEB-Protokoll. Ich habe das Schnellstartprotokoll auf der Transcriptic-Site ausprobiert, aber es gibt immer noch einen Autoprotokollbefehl . Transcriptic selbst synthetisiert keine Oligonukleotide. Nach 1-2 Tagen Wartezeit erscheinen diese Primer auf magische Weise in meinem Inventar (beachten Sie, dass der genspezifische Teil der Primer unten in Großbuchstaben angegeben ist, dies sind jedoch nur kosmetische Dinge).

 insert_primers = ["aaacgacggccagtgTTTATACAGTTCATCCATTCCATG", "cgggtaccgagctcgAGGAGGACAGCTATGTCG"] 

Primer-Analyse


Sie können die Eigenschaften dieser Primer mit dem IDT OligoAnalyzer analysieren . PCR primer dimer , NEB .

 Gene-specific portion of flank (uppercase)
  Melt temperature: 51C, 53.5C
Full sequence
  Melt temperature: 64.5C, 68.5C
  Hairpin: -.4dG, -5dG
  Self-dimer: -9dG, -16dG
  Heterodimer: -6dG 

PCR, , PCR. ( ), : . . , — .

Code
 """ PCR overlap extension of sfGFP according to NEB protocol. v5: Use 3/10ths as much primer as the v4 protocol. v6: more complex touchdown pcr procedure. The Q5 temperature was probably too hot v7: more time at low temperature to allow gene-specific part to anneal v8: correct dNTP concentration, real touchdown """ p = Protocol() # --------------------------------------------------- # Set up experiment # experiment_name = "sfgfp_pcroe_v8" template_length = 740 _options = {'dilute_primers' : False, # if working stock has not been made 'dilute_template': False, # if working stock has not been made 'dilute_dNTP' : False, # if working stock has not been made 'run_gel' : True, # run a gel to see the plasmid size 'run_absorbance' : False, # check absorbance at 260/280/320 'run_sanger' : False} # sanger sequence the new sequence options = {k for k,v in _options.items() if v is True} # --------------------------------------------------- # Inventory and provisioning # https://developers.transcriptic.com/v1.0/docs/containers # # 'sfgfp2': 'ct17yx8h77tkme', # inventory; sfGFP tube #2, micro-1.5, cold_20 # 'sfgfp_puc19_primer1': 'ct17z9542mrcfv', # inventory; micro-2.0, cold_4 # 'sfgfp_puc19_primer2': 'ct17z9542m5ntb', # inventory; micro-2.0, cold_4 # 'sfgfp_idt_1ngul': 'ct184nnd3rbxfr', # inventory; micro-1.5, cold_4, (ERROR: no template) # inv = { 'Q5 Polymerase': 'rs16pcce8rdytv', # catalog; Q5 High-Fidelity DNA Polymerase 'Q5 Buffer': 'rs16pcce8rmke3', # catalog; Q5 Reaction Buffer 'dNTP Mixture': 'rs16pcb542c5rd', # catalog; dNTP Mixture (25mM?) 'water': 'rs17gmh5wafm5p', # catalog; Autoclaved MilliQ H2O 'sfgfp_pcroe_v5_puc19_primer1_10uM': 'ct186cj5cqzjmr', # inventory; micro-1.5, cold_4 'sfgfp_pcroe_v5_puc19_primer2_10uM': 'ct186cj5cq536x', # inventory; micro-1.5, cold_4 'sfgfp1': 'ct17yx8h759dk4', # inventory; sfGFP tube #1, micro-1.5, cold_20 } # Existing inventory template_tube = p.ref("sfgfp1", id=inv['sfgfp1'], cont_type="micro-1.5", storage="cold_4").well(0) dilute_primer_tubes = [p.ref('sfgfp_pcroe_v5_puc19_primer1_10uM', id=inv['sfgfp_pcroe_v5_puc19_primer1_10uM'], cont_type="micro-1.5", storage="cold_4").well(0), p.ref('sfgfp_pcroe_v5_puc19_primer2_10uM', id=inv['sfgfp_pcroe_v5_puc19_primer2_10uM'], cont_type="micro-1.5", storage="cold_4").well(0)] # New inventory resulting from this experiment dilute_template_tube = p.ref("sfgfp1_0.25ngul", cont_type="micro-1.5", storage="cold_4").well(0) dNTP_10uM_tube = p.ref("dNTP_10uM", cont_type="micro-1.5", storage="cold_4").well(0) sfgfp_pcroe_out_tube = p.ref(expid("amplified"), cont_type="micro-1.5", storage="cold_4").well(0) # Temporary tubes for use, then discarded mastermix_tube = p.ref("mastermix", cont_type="micro-1.5", storage="cold_4", discard=True).well(0) water_tube = p.ref("water", cont_type="micro-1.5", storage="ambient", discard=True).well(0) pcr_plate = p.ref("pcr_plate", cont_type="96-pcr", storage="cold_4", discard=True) if 'run_absorbance' in options: abs_plate = p.ref("abs_plate", cont_type="96-flat", storage="cold_4", discard=True) # Initialize all existing inventory all_inventory_wells = [template_tube] + dilute_primer_tubes for well in all_inventory_wells: init_inventory_well(well) print(well.name, well.volume, well.properties) # ----------------------------------------------------- # Provision water once, for general use # p.provision(inv["water"], water_tube, µl(500)) # ----------------------------------------------------- # Dilute primers 1/10 (100uM->10uM) and keep at 4C # if 'dilute_primers' in options: for primer_num in (0,1): p.transfer(water_tube, dilute_primer_tubes[primer_num], µl(90)) p.transfer(primer_tubes[primer_num], dilute_primer_tubes[primer_num], µl(10), mix_before=True, mix_vol=µl(50)) p.mix(dilute_primer_tubes[primer_num], volume=µl(50), repetitions=10) # ----------------------------------------------------- # Dilute template 1/10 (10ng/ul->1ng/ul) and keep at 4C # OR # Dilute template 1/40 (10ng/ul->0.25ng/ul) and keep at 4C # if 'dilute_template' in options: p.transfer(water_tube, dilute_template_tube, µl(195)) p.mix(dilute_template_tube, volume=µl(100), repetitions=10) # Dilute dNTP to exactly 10uM if 'dilute_DNTP' in options: p.transfer(water_tube, dNTP_10uM_tube, µl(6)) p.provision(inv["dNTP Mixture"], dNTP_10uM_tube, µl(4)) # ----------------------------------------------------- # Q5 PCR protocol # www.neb.com/protocols/2013/12/13/pcr-using-q5-high-fidelity-dna-polymerase-m0491 # # 25ul reaction # ------------- # Q5 reaction buffer 5 µl # Q5 polymerase 0.25 µl # 10mM dNTP 0.5 µl -- 1µl = 4x12.5mM # 10uM primer 1 1.25 µl # 10uM primer 2 1.25 µl # 1pg-1ng Template 1 µl -- 0.5 or 1ng/ul concentration # ------------------------------- # Sum 9.25 µl # # # Mastermix tube will have 96ul of stuff, leaving space for 4x1ul aliquots of template p.transfer(water_tube, mastermix_tube, µl(64)) p.provision(inv["Q5 Buffer"], mastermix_tube, µl(20)) p.provision(inv['Q5 Polymerase'], mastermix_tube, µl(1)) p.transfer(dNTP_10uM_tube, mastermix_tube, µl(1), mix_before=True, mix_vol=µl(2)) p.transfer(dilute_primer_tubes[0], mastermix_tube, µl(5), mix_before=True, mix_vol=µl(10)) p.transfer(dilute_primer_tubes[1], mastermix_tube, µl(5), mix_before=True, mix_vol=µl(10)) p.mix(mastermix_tube, volume="48:microliter", repetitions=10) # Transfer mastermix to pcr_plate without template p.transfer(mastermix_tube, pcr_plate.wells(["A1","B1","C1"]), µl(24)) p.transfer(mastermix_tube, pcr_plate.wells(["A2"]), µl(24)) # acknowledged dead volume problems p.mix(pcr_plate.wells(["A1","B1","C1","A2"]), volume=µl(12), repetitions=10) # Finally add template p.transfer(template_tube, pcr_plate.wells(["A1","B1","C1"]), µl(1)) p.mix(pcr_plate.wells(["A1","B1","C1"]), volume=µl(12.5), repetitions=10) # --------------------------------------------------------- # Thermocycle with Q5 and hot start # 61.1 annealing temperature is recommended by NEB protocol # p.seal is enforced by transcriptic # extension_time = int(max(2, np.ceil(template_length * (11.0/1000)))) assert 0 < extension_time < 60, "extension time should be reasonable for PCR" cycles = [{"cycles": 1, "steps": [{"temperature": "98:celsius", "duration": "30:second"}]}] + \ touchdown(70, 61, [8, 25, extension_time], stepsize=0.5) + \ [{"cycles": 16, "steps": [{"temperature": "98:celsius", "duration": "8:second"}, {"temperature": "61.1:celsius", "duration": "25:second"}, {"temperature": "72:celsius", "duration": "{:d}:second".format(extension_time)}]}, {"cycles": 1, "steps": [{"temperature": "72:celsius", "duration": "2:minute"}]}] p.seal(pcr_plate) p.thermocycle(pcr_plate, cycles, volume=µl(25)) # -------------------------------------------------------- # Run a gel to hopefully see a 740bp fragment # if 'run_gel' in options: p.unseal(pcr_plate) p.mix(pcr_plate.wells(["A1","B1","C1","A2"]), volume=µl(12.5), repetitions=10) p.transfer(pcr_plate.wells(["A1","B1","C1","A2"]), pcr_plate.wells(["D1","E1","F1","D2"]), [µl(2), µl(4), µl(8), µl(8)]) p.transfer(water_tube, pcr_plate.wells(["D1","E1","F1","D2"]), [µl(18),µl(16),µl(12),µl(12)], mix_after=True, mix_vol=µl(10)) p.gel_separate(pcr_plate.wells(["D1","E1","F1","D2"]), µl(20), "agarose(10,2%)", "ladder1", "10:minute", expid("gel")) #--------------------------------------------------------- # Absorbance dilution series. Take 1ul out of the 25ul pcr plate wells # if 'run_absorbance' in options: p.unseal(pcr_plate) abs_wells = ["A1","B1","C1","A2","B2","C2","A3","B3","C3"] p.transfer(water_tube, abs_plate.wells(abs_wells[0:6]), µl(10)) p.transfer(water_tube, abs_plate.wells(abs_wells[6:9]), µl(9)) p.transfer(pcr_plate.wells(["A1","B1","C1"]), abs_plate.wells(["A1","B1","C1"]), µl(1), mix_after=True, mix_vol=µl(5)) p.transfer(abs_plate.wells(["A1","B1","C1"]), abs_plate.wells(["A2","B2","C2"]), µl(1), mix_after=True, mix_vol=µl(5)) p.transfer(abs_plate.wells(["A2","B2","C2"]), abs_plate.wells(["A3","B3","C3"]), µl(1), mix_after=True, mix_vol=µl(5)) for wavelength in [260, 280, 320]: p.absorbance(abs_plate, abs_plate.wells(abs_wells), "{}:nanometer".format(wavelength), exp_id("abs_{}".format(wavelength)), flashes=25) # ----------------------------------------------------------------------------- # Sanger sequencing: https://developers.transcriptic.com/docs/sanger-sequencing # "Each reaction should have a total volume of 15 µl and we recommend the following composition of DNA and primer: # PCR product (40 ng), primer (1 µl of a 10 µM stock)" # # By comparing to the gel ladder concentration (175ng/lane), it looks like 5ul of PCR product has approximately 30ng of DNA # if 'run_sanger' in options: p.unseal(pcr_plate) seq_wells = ["G1","G2"] for primer_num, seq_well in [(0, seq_wells[0]),(1, seq_wells[1])]: p.transfer(dilute_primer_tubes[primer_num], pcr_plate.wells([seq_well]), µl(1), mix_before=True, mix_vol=µl(50)) p.transfer(pcr_plate.wells(["A1"]), pcr_plate.wells([seq_well]), µl(5), mix_before=True, mix_vol=µl(10)) p.transfer(water_tube, pcr_plate.wells([seq_well]), µl(9)) p.mix(pcr_plate.wells(seq_wells), volume=µl(7.5), repetitions=10) p.sangerseq(pcr_plate, pcr_plate.wells(seq_wells[0]).indices(), expid("seq1")) p.sangerseq(pcr_plate, pcr_plate.wells(seq_wells[1]).indices(), expid("seq2")) # ------------------------------------------------------------------------- # Then consolidate to one tube. Leave at least 3ul dead volume in each tube # remaining_volumes = [well.volume - dead_volume['96-pcr'] for well in pcr_plate.wells(["A1","B1","C1"])] print("Consolidated volume", sum(remaining_volumes, µl(0))) p.consolidate(pcr_plate.wells(["A1","B1","C1"]), sfgfp_pcroe_out_tube, remaining_volumes, allow_carryover=True) uprint("\nProtocol 1. Amplify the insert (oligos previously synthesized)") jprotocol = json.dumps(p.as_dict(), indent=2) !echo '{jprotocol}' | transcriptic analyze open("protocol_{}.json".format(experiment_name),'w').write(jprotocol) 

 WARNING:root:Low volume for well sfGFP 1 /sfGFP 1 : 2.0:microliter 

 sfGFP 1 /sfGFP 1 2.0:microliter {'dilution': '0.25ng/ul'}
sfgfp_pcroe_v5_puc19_primer1_10uM 75.0:microliter {}
sfgfp_pcroe_v5_puc19_primer2_10uM 75.0:microliter {}
Consolidated volume 52.0:microliter

Protocol 1. Amplify the insert (oligos previously synthesized)
---------------------------------------------------------------

  
✓ Protocol analyzed
  11 instructions
  8 containers
  Total Cost: $32.18
  Workcell Time: $4.32
  Reagents & Consumables: $27.86 

: PCR



( ) ( ). , , .

D1, E1, F1 2 , 4 8 . (50 ). , .

GelEval , , , , . . GelEval 40 /.

, , dNTP , , 12,5 , 6 740bp 25 . GelEval 40 x 25 (1 2 ), , .


- EcoRI- pUC19, (D1, E1, F1), (D2)

PCR


Transcriptic . , .

, . 35 PCR, PCR . — ! — , PCR , .


PCR: , 35 42

2.


sfGFP pUC19, . NEB, EcoRI . Transcriptic , : NEB EcoRI 10x CutSmart , NEB pUC19 .

, . , Transcriptic :

 Item ID Amount Concentration Price
------------ ------ ------------- ----------------- ------
CutSmart 10x B7204S 5 ml 10 X $19.00
EcoRI R3101L 50,000 units 20,000 units/ml $225.00
pUC19 N3041L 250 µg 1,000 µg/ml $268.00 

NEB:

. 10X dH2O 1X. , , , , . 50 5 10x NEBuffer , dH2O.

, 1 λ 1 37°C 50 . , 5-10 10-20 1- .

1 50 .

Code
 """Protocol for cutting pUC19 with EcoRI.""" p = Protocol() experiment_name = "puc19_ecori_v3" options = {} inv = { 'water': "rs17gmh5wafm5p", # catalog; Autoclaved MilliQ H2O; ambient "pUC19": "rs17tcqmncjfsh", # catalog; pUC19; cold_20 "EcoRI": "rs17ta8xftpdk6", # catalog; EcoRI-HF; cold_20 "CutSmart": "rs17ta93g3y85t", # catalog; CutSmart Buffer 10x; cold_20 "ecori_p10x": "ct187v4ea85k2h", # inventory; EcoRI diluted 10x } # Tubes and plates I use then discard re_tube = p.ref("re_tube", cont_type="micro-1.5", storage="cold_4", discard=True).well(0) water_tube = p.ref("water_tube", cont_type="micro-1.5", storage="cold_4", discard=True).well(0) pcr_plate = p.ref("pcr_plate", cont_type="96-pcr", storage="cold_4", discard=True) # The result of the experiment, a pUC19 cut by EcoRI, goes in this tube for storage puc19_cut_tube = p.ref(expid("puc19_cut"), cont_type="micro-1.5", storage="cold_20").well(0) # ------------------------------------------------------------- # Provisioning and diluting. # Diluted EcoRI can be used more than once # p.provision(inv["water"], water_tube, µl(500)) if 'dilute_ecori' in options: ecori_p10x_tube = p.ref("ecori_p10x", cont_type="micro-1.5", storage="cold_20").well(0) p.transfer(water_tube, ecori_p10x_tube, µl(45)) p.provision(inv["EcoRI"], ecori_p10x_tube, µl(5)) else: # All "inventory" (stuff I own at transcriptic) must be initialized ecori_p10x_tube = p.ref("ecori_p10x", id=inv["ecori_p10x"], cont_type="micro-1.5", storage="cold_20").well(0) init_inventory_well(ecori_p10x_tube) # ------------------------------------------------------------- # Restriction enzyme cutting pUC19 # # 50ul total reaction volume for cutting 1ug of DNA: # 5ul CutSmart 10x # 1ul pUC19 (1ug of DNA) # 1ul EcoRI (or 10ul diluted EcoRI, 20 units, >10 units per ug DNA) # p.transfer(water_tube, re_tube, µl(117)) p.provision(inv["CutSmart"], re_tube, µl(15)) p.provision(inv["pUC19"], re_tube, µl(3)) p.mix(re_tube, volume=µl(60), repetitions=10) assert re_tube.volume == µl(120) + dead_volume["micro-1.5"] print("Volumes: re_tube:{} water_tube:{} EcoRI:{}".format(re_tube.volume, water_tube.volume, ecori_p10x_tube.volume)) p.distribute(re_tube, pcr_plate.wells(["A1","B1","A2"]), µl(40)) p.distribute(water_tube, pcr_plate.wells(["A2"]), µl(10)) p.distribute(ecori_p10x_tube, pcr_plate.wells(["A1","B1"]), µl(10)) assert all(well.volume == µl(50) for well in pcr_plate.wells(["A1","B1","A2"])) p.mix(pcr_plate.wells(["A1","B1","A2"]), volume=µl(25), repetitions=10) # Incubation to induce cut, then heat inactivation of EcoRI p.seal(pcr_plate) p.incubate(pcr_plate, "warm_37", "60:minute", shaking=False) p.thermocycle(pcr_plate, [{"cycles": 1, "steps": [{"temperature": "65:celsius", "duration": "21:minute"}]}], volume=µl(50)) # -------------------------------------------------------------- # Gel electrophoresis, to ensure the cutting worked # p.unseal(pcr_plate) p.mix(pcr_plate.wells(["A1","B1","A2"]), volume=µl(25), repetitions=5) p.transfer(pcr_plate.wells(["A1","B1","A2"]), pcr_plate.wells(["D1","E1","D2"]), µl(8)) p.transfer(water_tube, pcr_plate.wells(["D1","E1","D2"]), µl(15), mix_after=True, mix_vol=µl(10)) assert all(well.volume == µl(20) + dead_volume["96-pcr"] for well in pcr_plate.wells(["D1","E1","D2"])) p.gel_separate(pcr_plate.wells(["D1","E1","D2"]), µl(20), "agarose(10,2%)", "ladder2", "15:minute", expid("gel")) # ---------------------------------------------------------------------------- # Then consolidate all cut plasmid to one tube (puc19_cut_tube). # remaining_volumes = [well.volume - dead_volume['96-pcr'] for well in pcr_plate.wells(["A1","B1"])] print("Consolidated volume: {}".format(sum(remaining_volumes, µl(0)))) p.consolidate(pcr_plate.wells(["A1","B1"]), puc19_cut_tube, remaining_volumes, allow_carryover=True) assert all(tube.volume >= dead_volume['micro-1.5'] for tube in [water_tube, re_tube, puc19_cut_tube, ecori_p10x_tube]) # --------------------------------------------------------------- # Test protocol # jprotocol = json.dumps(p.as_dict(), indent=2) !echo '{jprotocol}' | transcriptic analyze #print("Protocol {}\n\n{}".format(experiment_name, jprotocol)) open("protocol_{}.json".format(experiment_name),'w').write(jprotocol) 

 Volumes: re_tube:135.0:microliter water_tube:383.0:microliter EcoRI:30.0:microliter
Consolidated volume: 78.0:microliter

  
✓ Protocol analyzed
  12 instructions
  5 containers
  Total Cost: $30.72
  Workcell Time: $3.38
  Reagents & Consumables: $27.34 

:


, . .

«» ( 1,5 15 !). , D1 E1 ( ). , EcoRI .

, D1 E1 2,6kb. D2 : , .

-. , Transcriptic .


, pUC19 (2,6kb) D1 E1, pUC19 D2

3.


, — , M13 ( ) qPCR , , . , , , .

, M13 , M13.

Code
 """Debugging transformation protocol: Gibson assembly followed by qPCR and a gel v2: include v3 Gibson assembly""" p = Protocol() options = {} experiment_name = "debug_sfgfp_puc19_gibson_seq_v2" inv = { "water" : "rs17gmh5wafm5p", # catalog; Autoclaved MilliQ H2O; ambient "M13_F" : "rs17tcpqwqcaxe", # catalog; M13 Forward (-41); cold_20 (1ul = 100pmol) "M13_R" : "rs17tcph6e2qzh", # catalog; M13 Reverse (-48); cold_20 (1ul = 100pmol) "SensiFAST_SYBR_No-ROX" : "rs17knkh7526ha", # catalog; SensiFAST SYBR for qPCR "sfgfp_puc19_gibson_v1_clone" : "ct187rzdq9kd7q", # inventory; assembled sfGFP; cold_4 "sfgfp_puc19_gibson_v3_clone" : "ct188ejywa8jcv", # inventory; assembled sfGFP; cold_4 } # --------------------------------------------------------------- # First get my sfGFP pUC19 clones, assembled with Gibson assembly # clone_plate1 = p.ref("sfgfp_puc19_gibson_v1_clone", id=inv["sfgfp_puc19_gibson_v1_clone"], cont_type="96-pcr", storage="cold_4", discard=False) clone_plate2 = p.ref("sfgfp_puc19_gibson_v3_clone", id=inv["sfgfp_puc19_gibson_v3_clone"], cont_type="96-pcr", storage="cold_4", discard=False) water_tube = p.ref("water", cont_type="micro-1.5", storage="cold_4", discard=True).well(0) master_tube = p.ref("master", cont_type="micro-1.5", storage="cold_4", discard=True).well(0) primer_tube = p.ref("primer", cont_type="micro-1.5", storage="cold_4", discard=True).well(0) pcr_plate = p.ref(expid("pcr_plate"), cont_type="96-pcr", storage="cold_4", discard=False) init_inventory_well(clone_plate1.well("A1")) init_inventory_well(clone_plate2.well("A1")) seq_wells = ["B2","B4","B6", # clone_plate1 "D2","D4","D6", # clone_plate2 "F2","F4"] # control # clone_plate2 was diluted 4X (20ul->80ul), according to NEB instructions assert clone_plate1.well("A1").volume == µl(18), clone_plate1.well("A1").volume assert clone_plate2.well("A1").volume == µl(78), clone_plate2.well("A1").volume # -------------------------------------------------------------- # Provisioning # p.provision(inv["water"], water_tube, µl(500)) # primers, diluted 2X, discarded at the end p.provision(inv["M13_F"], primer_tube, µl(13)) p.provision(inv["M13_R"], primer_tube, µl(13)) p.transfer(water_tube, primer_tube, µl(26), mix_after=True, mix_vol=µl(20), repetitions=10) # ------------------------------------------------------------------- # PCR Master mix -- 10ul SYBR mix, plus 1ul each undiluted primer DNA (100pmol) # Also add 15ul of dead volume # p.provision(inv['SensiFAST_SYBR_No-ROX'], master_tube, µl(11+len(seq_wells)*10)) p.transfer(primer_tube, master_tube, µl(4+len(seq_wells)*4)) p.mix(master_tube, volume=µl(63), repetitions=10) assert master_tube.volume == µl(127) # 15ul dead volume p.distribute(master_tube, pcr_plate.wells(seq_wells), µl(14), allow_carryover=True) p.distribute(water_tube, pcr_plate.wells(seq_wells), [µl(ul) for ul in [5,4,2, 4,2,0, 6,6]], allow_carryover=True) # Template -- starting with some small, unknown amount of DNA produced by Gibson p.transfer(clone_plate1.well("A1"), pcr_plate.wells(seq_wells[0:3]), [µl(1),µl(2),µl(4)], one_tip=True) p.transfer(clone_plate2.well("A1"), pcr_plate.wells(seq_wells[3:6]), [µl(2),µl(4),µl(6)], one_tip=True) assert all(pcr_plate.well(w).volume == µl(20) for w in seq_wells) assert clone_plate1.well("A1").volume == µl(11) assert clone_plate2.well("A1").volume == µl(66) # -------------------------------------------------------------- # qPCR # standard melting curve parameters # p.seal(pcr_plate) p.thermocycle(pcr_plate, [{"cycles": 1, "steps": [{"temperature": "95:celsius","duration": "2:minute"}]}, {"cycles": 40, "steps": [{"temperature": "95:celsius","duration": "5:second"}, {"temperature": "60:celsius","duration": "20:second"}, {"temperature": "72:celsius","duration": "15:second", "read": True}]}], volume=µl(20), # volume is optional dataref=expid("qpcr"), dyes={"SYBR": seq_wells}, # dye must be specified (tells transcriptic what aborbance to use?) melting_start="65:celsius", melting_end="95:celsius", melting_increment="0.5:celsius", melting_rate="5:second") # -------------------------------------------------------------- # Gel -- 20ul required # Dilute such that I have 11ul for sequencing # p.unseal(pcr_plate) p.distribute(water_tube, pcr_plate.wells(seq_wells), µl(11)) p.gel_separate(pcr_plate.wells(seq_wells), µl(20), "agarose(8,0.8%)", "ladder1", "10:minute", expid("gel")) # This appears to be a bug in Transcriptic. The actual volume should be 11ul # but it is not updating after running a gel with 20ul. # Primer tube should be equal to dead volume, or it's a waste assert all(pcr_plate.well(w).volume==µl(31) for w in seq_wells) assert primer_tube.volume == µl(16) == dead_volume['micro-1.5'] + µl(1) assert water_tube.volume > µl(25) # --------------------------------------------------------------- # Test and run protocol # jprotocol = json.dumps(p.as_dict(), indent=2) !echo '{jprotocol}' | transcriptic analyze open("protocol_{}.json".format(experiment_name),'w').write(jprotocol) 

 WARNING:root:Low volume for well sfgfp_puc19_gibson_v1_clone/sfgfp_puc19_gibson_v1_clone : 11.0:microliter 

 ✓ Protocol analyzed
  11 instructions
  6 containers
  Total Cost: $32.09
  Workcell Time: $6.98
  Reagents & Consumables: $25.11 

: qPCR


qPCR JSON Transcriptic API. , . API , .

-, :

 project_id, run_id = "p16x6gna8f5e9", "r18mj3cz3fku7" api_url = "https://secure.transcriptic.com/hgbrian/{}/runs/{}/data.json".format(project_id, run_id) data_response = requests.get(api_url, headers=tsc_headers) data = data_response.json() 

id, «» qPCR:

 qpcr_id = data['debug_sfgfp_puc19_gibson_seq_v1_qpcr']['id'] pp_api_url = "https://secure.transcriptic.com/data/{}.json?key=postprocessed_data".format(qpcr_id) data_response = requests.get(pp_api_url, headers=tsc_headers) pp_data = data_response.json() 

Ct ( ) . Ct — , . , (, , , ).

 # Simple util to convert wellnum to wellname n_w = {str(wellnum):'ABCDEFGH'[wellnum//12]+str(1+wellnum%12) for wellnum in range(96)} w_n = {v: k for k, v in n_w.items()} ct_vals = {n_w[k]:v for k,v in pp_data["amp0"]["SYBR"]["cts"].items()} ct_df = pd.DataFrame(ct_vals, index=["Ct"]).T ct_df["well"] = ct_df.index f, ax = plt.subplots(figsize=(16,6)) _ = sns.barplot(y="well", x="Ct", data=ct_df) 



, D2/4/6 ( «v3»), B2/4/6 ( «v1»). v1 v3 , v3 4X NEB, . 30 (F2, F4), -, , .

qPCR, .

 f, ax = plt.subplots(figsize=(16,6)) ax.set_color_cycle(['#fb6a4a', '#de2d26', '#a50f15', '#74c476', '#31a354', '#006d2c', '#08519c', '#6baed6']) amp0 = pp_data['amp0']['SYBR']['baseline_subtracted'] _ = [plt.plot(amp0[w_n[well]], label=well) for well in ['B2', 'B4', 'B6', 'D2', 'D4', 'D6', 'F2', 'F4']] _ = ax.set_ylim(0,) _ = plt.title("qPCR (reds=Gibson v1, greens=Gibson v3, blues=control)") _ = plt.legend(bbox_to_anchor=(1, .75), bbox_transform=plt.gcf().transFigure) 



, qPCR , . v3 , v1, .

:


, 1kb B2, B4, B6, D2, D4, D6: ( 740bp, M13 — 40bp ). . , F2 F4 .


: v3 (D2, D4, D6), qPCR

4.


— . E. coli sfGFP- pUC19.

Zymo DH5α Mix&Go . — Transcriptic. , , , , . , , .


Zymo Mix & Go


— , . (« »), , («, »). , .

. , 37°C. , , , , Transcriptic — , . , , - , . . .

: (, , Mix&Go ); (, ); (, PCR ).

, , , , . , , !


, , , pUC19 (. . sfGFP) . pUC19 , , .

(«6-flat» Transcriptic), , . , , , . .

Code
 """Simple transformation protocol: transformation with unaltered pUC19""" p = Protocol() experiment_name = "debug_sfgfp_puc19_gibson_v1" inv = { "water" : "rs17gmh5wafm5p", # catalog; Autoclaved MilliQ H2O; ambient "DH5a" : "rs16pbj944fnny", # catalog; Zymo DH5α; cold_80 "LB Miller" : "rs17bafcbmyrmh", # catalog; LB Broth Miller; cold_4 "Amp 100mgml" : "rs17msfk8ujkca", # catalog; Ampicillin 100mg/ml; cold_20 "pUC19" : "rs17tcqmncjfsh", # catalog; pUC19; cold_20 } # Catalog transform_plate = p.ref("transform_plate", cont_type="96-pcr", storage="ambient", discard=True) transform_tube = transform_plate.well(0) # ------------------------------------------------------------------------------------ # Plating transformed bacteria according to Tali's protocol (requires different code!) # http://learn.transcriptic.com/blog/2015/9/9/provisioning-commercial-reagents # Add 1-5ul plasmid and pre-warm culture plates to 37C before starting. # # # Extra inventory for plating # inv["lb-broth-100ug-ml-amp_6-flat"] = "ki17sbb845ssx9" # (kit, not normal ref) from blogpost inv["noAB-amp_6-flat"] = "ki17reefwqq3sq" # kit id inv["LB Miller"] = "rs17bafcbmyrmh" # # Ampicillin and no ampicillin plates # amp_6_flat = Container(None, p.container_type('6-flat')) p.refs["amp_6_flat"] = Ref('amp_6_flat', {"reserve": inv['lb-broth-100ug-ml-amp_6-flat'], "store": {"where": 'cold_4'}}, amp_6_flat) noAB_6_flat = Container(None, p.container_type('6-flat')) p.refs["noAB_6_flat"] = Ref('noAB_6_flat', {"reserve": inv['noAB-amp_6-flat'], "store": {"where": 'cold_4'}}, noAB_6_flat) # # Provision competent bacteria # p.provision(inv["DH5a"], transform_tube, µl(50)) p.provision(inv["pUC19"], transform_tube, µl(2)) # # Heatshock the bacteria to transform using a PCR machine # p.seal(transform_plate) p.thermocycle(transform_plate, [{"cycles": 1, "steps": [{"temperature": "4:celsius", "duration": "5:minute"}]}, {"cycles": 1, "steps": [{"temperature": "37:celsius", "duration": "30:minute"}]}], volume=µl(50)) p.unseal(transform_plate) # # Then dilute bacteria and spread onto 6-flat plates # Put more on ampicillin plates for more opportunities to get a colony # p.provision(inv["LB Miller"], transform_tube, µl(355)) p.mix(transform_tube, µl(150), repetitions=5) for i in range(6): p.spread(transform_tube, amp_6_flat.well(i), µl(55)) p.spread(transform_tube, noAB_6_flat.well(i), µl(10)) assert transform_tube.volume >= µl(15), transform_tube.volume # # Incubate and image 6-flat plates over 18 hours # for flat_name, flat in [("amp_6_flat", amp_6_flat), ("noAB_6_flat", noAB_6_flat)]: for timepoint in [6,12,18]: p.cover(flat) p.incubate(flat, "warm_37", "6:hour") p.uncover(flat) p.image_plate(flat, mode="top", dataref=expid("{}_t{}".format(flat_name, timepoint))) # --------------------------------------------------------------- # Analyze protocol # jprotocol = json.dumps(p.as_dict(), indent=2) !echo '{jprotocol}' | transcriptic analyze #print("Protocol {}\n\n{}".format(experiment_name, protocol)) open("protocol_{}.json".format(experiment_name),'w').write(jprotocol) 

 ✓ Protocol analyzed
  43 instructions
  3 containers
  $45.43 

:


, ( ) , , . , Transcriptic , .

( ) , . , , , , 55 10 . . , . , , .

( , , , E. coli . , , ).

, , , .


, pUC19, 18 : () ()


pUC19, , , , sfGFP.

, IPTG X-gal, - . , pUC19, sfGFP, .


, sfGFP 485 / 510 . , Transcriptic 485/535. , 485 510 . 600 ( OD600 ).


GFP ( biotek )

IPTG X-gal


IPTG 1M 1:1000. , X-gal 20 / 1:1000 (20 /). , 2000µl LB 2 .

40 X-gal 20 / 40 IPTG 0,1 mM ( 4 IPTG 1M), 30 . , IPTG, X-gal .

Code
 """Full Gibson assembly and transformation protocol for sfGFP and pUC19 v1: Spread IPTG and X-gal onto plates, then spread cells v2: Mix IPTG, X-gal and cells; spread the mixture v3: exclude X-gal so I can do colony picking better v4: repeat v3 to try other excitation/emission wavelengths""" p = Protocol() options = { "gibson" : False, # do a new gibson assembly "sanger" : False, # sanger sequence product "control_pUC19" : True, # unassembled pUC19 "XGal" : False # excluding X-gal should make the colony picking easier } for k, v in list(options.items()): if v is False: del options[k] experiment_name = "sfgfp_puc19_gibson_plates_v4" # ----------------------------------------------------------------------- # Inventory # inv = { # catalog "water" : "rs17gmh5wafm5p", # catalog; Autoclaved MilliQ H2O; ambient "DH5a" : "rs16pbj944fnny", # catalog; Zymo DH5α; cold_80 "Gibson Mix" : "rs16pfatkggmk5", # catalog; Gibson Mix (2X); cold_20 "LB Miller" : "rs17bafcbmyrmh", # catalog; LB Broth Miller; cold_4 "Amp 100mgml" : "rs17msfk8ujkca", # catalog; Ampicillin 100mg/ml; cold_20 "pUC19" : "rs17tcqmncjfsh", # catalog; pUC19; cold_20 # my inventory "puc19_cut_v2": "ct187v4ea7vvca", # inventory; pUC19 cut with EcoRI; cold_20 "IPTG" : "ct18a2r5wn6tqz", # inventory; IPTG at 1M (conc semi-documented); cold_20 "XGal" : "ct18a2r5wp5hcv", # inventory; XGal at 0.1M (conc not documented); cold_20 "sfgfp_pcroe_v8_amplified" : "ct1874zqh22pab", # inventory; sfGFP amplified to 40ng/ul; cold_4 "sfgfp_puc19_gibson_v3_clone" : "ct188ejywa8jcv", # inventory; assembled sfGFP; cold_4 # kits (must be used differently) "lb-broth-100ug-ml-amp_6-flat" : "ki17sbb845ssx9", # catalog; ampicillin plates "noAB-amp_6-flat" : "ki17reefwqq3sq" # catalog; no antibiotic plates } # # Catalog (all to be discarded afterward) # water_tube = p.ref("water", cont_type="micro-1.5", storage="ambient", discard=True).well(0) transform_plate = p.ref("trn_plate", cont_type="96-pcr", storage="ambient", discard=True) transform_tube = transform_plate.well(39) # experiment transform_tube_L = p.ref("trn_tubeL", cont_type="micro-1.5", storage="ambient", discard=True).well(0) transctrl_tube = transform_plate.well(56) # control transctrl_tube_L = p.ref("trc_tubeL", cont_type="micro-1.5", storage="ambient", discard=True).well(0) # # Plating according to Tali's protocol # http://learn.transcriptic.com/blog/2015/9/9/provisioning-commercial-reagents # amp_6_flat = Container(None, p.container_type('6-flat')) p.refs[expid("amp_6_flat")] = Ref(expid("amp_6_flat"), {"reserve": inv['lb-broth-100ug-ml-amp_6-flat'], "store": {"where": 'cold_4'}}, amp_6_flat) noAB_6_flat = Container(None, p.container_type('6-flat')) p.refs[expid("noAB_6_flat")] = Ref(expid("noAB_6_flat"), {"reserve": inv['noAB-amp_6-flat'], "store": {"where": 'cold_4'}}, noAB_6_flat) # # My inventory: EcoRI-cut pUC19, oePCR'd sfGFP, Gibson-assembled pUC19, IPTG and X-Gal # if "gibson" in options: puc19_cut_tube = p.ref("puc19_ecori_v2_puc19_cut", id=inv["puc19_cut_v2"], cont_type="micro-1.5", storage="cold_20").well(0) sfgfp_pcroe_amp_tube = p.ref("sfgfp_pcroe_v8_amplified", id=inv["sfgfp_pcroe_v8_amplified"], cont_type="micro-1.5", storage="cold_4").well(0) clone_plate = p.ref(expid("clone"), cont_type="96-pcr", storage="cold_4", discard=False) else: clone_plate = p.ref("sfgfp_puc19_gibson_v3_clone", id=inv["sfgfp_puc19_gibson_v3_clone"], cont_type="96-pcr", storage="cold_4", discard=False) IPTG_tube = p.ref("IPTG", id=inv["IPTG"], cont_type="micro-1.5", storage="cold_20").well(0) if "XGal" in options: XGal_tube = p.ref("XGal", id=inv["XGal"], cont_type="micro-1.5", storage="cold_20").well(0) # # Initialize inventory # if "gibson" in options: all_inventory_wells = [puc19_cut_tube, sfgfp_pcroe_amp_tube, IPTG_tube] assert puc19_cut_tube.volume == µl(66), puc19_cut_tube.volume assert sfgfp_pcroe_amp_tube.volume == µl(36), sfgfp_pcroe_amp_tube.volume else: all_inventory_wells = [IPTG_tube, clone_plate.well(0)] if "XGal" in options: all_inventory_wells.append(XGal_tube) for well in all_inventory_wells: init_inventory_well(well) print("Inventory: {} {} {}".format(well.name, well.volume, well.properties)) # # Provisioning. Water is used all over the protocol. Provision an excess since it's cheap # p.provision(inv["water"], water_tube, µl(500)) # ----------------------------------------------------------------------------- # Cloning/assembly (see NEBuilder protocol above) # # "Optimized efficiency is 50–100 ng of vectors with 2 fold excess of inserts." # pUC19 is 20ng/ul (78ul total). # sfGFP is ~40ng/ul (48ul total) # Therefore 4ul of each gives 80ng and 160ng of vector and insert respectively # def do_gibson_assembly(): # # Combine all the Gibson reagents in one tube and thermocycle # p.provision(inv["Gibson Mix"], clone_plate.well(0), µl(10)) p.transfer(water_tube, clone_plate.well(0), µl(2)) p.transfer(puc19_cut_tube, clone_plate.well(0), µl(4)) p.transfer(sfgfp_pcroe_amp_tube, clone_plate.well(0), µl(4), mix_after=True, mix_vol=µl(10), repetitions=10) p.seal(clone_plate) p.thermocycle(clone_plate, [{"cycles": 1, "steps": [{"temperature": "50:celsius", "duration": "16:minute"}]}], volume=µl(50)) # # Dilute assembled plasmid 4X according to the NEB Gibson assembly protocol (20ul->80ul) # p.unseal(clone_plate) p.transfer(water_tube, clone_plate.well(0), µl(60), mix_after=True, mix_vol=µl(40), repetitions=5) return # -------------------------------------------------------------------------------------------------- # Transformation # "Transform NEB 5-alpha Competent E. coli cells with 2 μl of the # assembled product, following the appropriate transformation protocol." # # Mix & Go http://www.zymoresearch.com/downloads/dl/file/id/173/t3015i.pdf # "[After mixing] Immediately place on ice and incubate for 2-5 minutes" # "The highest transformation efficiencies can be obtained by incubating Mix & Go cells with DNA on # ice for 2-5 minutes (60 minutes maximum) prior to plating." # "It is recommended that culture plates be pre-warmed to >20°C (preferably 37°C) prior to plating." # "Avoid exposing the cells to room temperature for more than a few seconds at a time." # # "If competent cells are purchased from other manufacture, dilute assembled products 4-fold # with H2O prior transformation. This can be achieved by mixing 5 μl of assembled products with # 15 μl of H2O. Add 2 μl of the diluted assembled product to competent cells." # def _do_transformation(): # # Combine plasmid and competent bacteria in a pcr_plate and shock # p.provision(inv["DH5a"], transform_tube, µl(50)) p.transfer(clone_plate.well(0), transform_tube, µl(3), dispense_speed="10:microliter/second") assert clone_plate.well(0).volume == µl(54), clone_plate.well(0).volume if 'control_pUC19' in options: p.provision(inv["DH5a"], transctrl_tube, µl(50)) p.provision(inv["pUC19"], transctrl_tube, µl(1)) # # Heatshock the bacteria to transform using a PCR machine # p.seal(transform_plate) p.thermocycle(transform_plate, [{"cycles": 1, "steps": [{"temperature": "4:celsius", "duration": "5:minute"}]}, {"cycles": 1, "steps": [{"temperature": "37:celsius", "duration": "30:minute"}]}], volume=µl(50)) return def _transfer_transformed_to_plates(): assert transform_tube.volume == µl(53), transform_tube.volume p.unseal(transform_plate) num_ab_plates = 4 # antibiotic places # # Transfer bacteria to a bigger tube for diluting # Then spread onto 6-flat plates # Generally you would spread 50-100ul of diluted bacteria # Put more on ampicillin plates for more opportunities to get a colony # I use a dilution series since it's unclear how much to plate # p.provision(inv["LB Miller"], transform_tube_L, µl(429)) # # Add all IPTG and XGal to the master tube # 4ul (1M) IPTG on each plate; 40ul XGal on each plate # p.transfer(IPTG_tube, transform_tube_L, µl(4*num_ab_plates)) if 'XGal' in options: p.transfer(XGal_tube, transform_tube_L, µl(40*num_ab_plates)) # # Add the transformed cells and mix (use new mix op in case of different pipette) # p.transfer(transform_tube, transform_tube_L, µl(50)) p.mix(transform_tube_L, volume=transform_tube_L.volume/2, repetitions=10) assert transform_tube.volume == dead_volume['96-pcr'] == µl(3), transform_tube.volume assert transform_tube_L.volume == µl(495), transform_tube_L.volume # # Spread an average of 60ul on each plate == 480ul total # for i in range(num_ab_plates): p.spread(transform_tube_L, amp_6_flat.well(i), µl(51+i*6)) p.spread(transform_tube_L, noAB_6_flat.well(i), µl(51+i*6)) assert transform_tube_L.volume == dead_volume["micro-1.5"], transform_tube_L.volume # # Controls: include 2 ordinary pUC19-transformed plates as a control # if 'control_pUC19' in options: num_ctrl = 2 assert num_ab_plates + num_ctrl <= 6 p.provision(inv["LB Miller"], transctrl_tube_L, µl(184)+dead_volume["micro-1.5"]) p.transfer(IPTG_tube, transctrl_tube_L, µl(4*num_ctrl)) if "XGal" in options: p.transfer(XGal_tube, transctrl_tube_L, µl(40*num_ctrl)) p.transfer(transctrl_tube, transctrl_tube_L, µl(48)) p.mix(transctrl_tube_L, volume=transctrl_tube_L.volume/2, repetitions=10) for i in range(num_ctrl): p.spread(transctrl_tube_L, amp_6_flat.well(num_ab_plates+i), µl(55+i*10)) p.spread(transctrl_tube_L, noAB_6_flat.well(num_ab_plates+i), µl(55+i*10)) assert transctrl_tube_L.volume == dead_volume["micro-1.5"], transctrl_tube_L.volume assert IPTG_tube.volume == µl(808), IPTG_tube.volume if "XGal" in options: assert XGal_tube.volume == µl(516), XGal_tube.volume return def do_transformation(): _do_transformation() _transfer_transformed_to_plates() # ------------------------------------------------------ # Measure growth in plates (photograph) # def measure_growth(): # # Incubate and photograph 6-flat plates over 18 hours # to see blue or white colonies # for flat_name, flat in [(expid("amp_6_flat"), amp_6_flat), (expid("noAB_6_flat"), noAB_6_flat)]: for timepoint in [9,18]: p.cover(flat) p.incubate(flat, "warm_37", "9:hour") p.uncover(flat) p.image_plate(flat, mode="top", dataref=expid("{}_t{}".format(flat_name, timepoint))) return # --------------------------------------------------------------- # Sanger sequencing, TURNED OFF # Sequence to make sure assembly worked # 500ng plasmid, 1 µl of a 10 µM stock primer # "M13_F" : "rs17tcpqwqcaxe", # catalog; M13 Forward (-41); cold_20 (1ul = 100pmol) # "M13_R" : "rs17tcph6e2qzh", # catalog; M13 Reverse (-48); cold_20 (1ul = 100pmol) # def do_sanger_seq(): seq_primers = [inv["M13_F"], inv["M13_R"]] seq_wells = ["G1","G2"] p.unseal(pcr_plate) for primer_num, seq_well in [(0, seq_wells[0]),(1, seq_wells[1])]: p.provision(seq_primers[primer_num], pcr_plate.wells([seq_well]), µl(1)) p.transfer(pcr_plate.wells(["A1"]), pcr_plate.wells(seq_wells), µl(5), mix_before=True, mix_vol=µl(10)) p.transfer(water_tube, pcr_plate.wells(seq_wells), µl(9)) p.mix(pcr_plate.wells(seq_wells), volume=µl(7.5), repetitions=10) p.sangerseq(pcr_plate, pcr_plate.wells(seq_wells[0]).indices(), expid("seq1")) p.sangerseq(pcr_plate, pcr_plate.wells(seq_wells[1]).indices(), expid("seq2")) return # --------------------------------------------------------------- # Generate protocol # # Skip Gibson since I already did it if 'gibson' in options: do_gibson_assembly() do_transformation() measure_growth() if 'sanger' in options: do_sanger_seq() # --------------------------------------------------------------- # Output protocol # jprotocol = json.dumps(p.as_dict(), indent=2) !echo '{jprotocol}' | transcriptic analyze #print("\nProtocol {}\n\n{}".format(experiment_name, jprotocol)) open("protocol_{}.json".format(experiment_name),'w').write(jprotocol) 

 Inventory: IPTG/IPTG/IPTG/IPTG/IPTG/IPTG 832.0:microliter {}
Inventory: sfgfp_puc19_gibson_v3_clone/sfgfp_puc19_gibson_v3_clone/sfgfp_puc19_gibson_v3_clone/sfgfp_puc19_gibson_v3_clone/sfgfp_puc19_gibson_v3_clone 57.0:microliter {}

  
✓ Protocol analyzed
  40 instructions
  8 containers
  Total Cost: $53.20
  Workcell Time: $17.35
  Reagents & Consumables: $35.86 


, «» 96- . ( autopick ).

Code
 """Pick colonies from plates and grow in amp media and check for fluorescence. v2: try again with a new plate (no blue colonies) v3: repeat with different emission and excitation wavelengths""" p = Protocol() options = {} for k, v in list(options.items()): if v is False: del options[k] experiment_name = "sfgfp_puc19_gibson_pick_v3" def plate_expid(val): """refer to the previous plating experiment's outputs""" plate_exp = "sfgfp_puc19_gibson_plates_v4" return "{}_{}".format(plate_exp, val) # ----------------------------------------------------------------------- # Inventory # inv = { # catalog "water" : "rs17gmh5wafm5p", # catalog; Autoclaved MilliQ H2O; ambient "LB Miller" : "rs17bafcbmyrmh", # catalog; LB Broth Miller; cold_4 "Amp 100mgml" : "rs17msfk8ujkca", # catalog; Ampicillin 100mg/ml; cold_20 "IPTG" : "ct18a2r5wn6tqz", # inventory; IPTG at 1M (conc semi-documented); cold_20 # plates from previous experiment, must be changed every new experiment plate_expid("amp_6_flat") : "ct18snmr9avvg9", # inventory; Ampicillin plates with blue-white screening of pUC19 plate_expid("noAB_6_flat") : "ct18snmr9dxfw2", # inventory; no AB plates with blue-white screening of pUC19 } # Tubes and plates lb_amp_tubes = [p.ref("lb_amp_{}".format(i+1), cont_type="micro-2.0", storage="ambient", discard=True).well(0) for i in range(4)] lb_xab_tube = p.ref("lb_xab", cont_type="micro-2.0", storage="ambient", discard=True).well(0) growth_plate = p.ref(expid("growth"), cont_type="96-flat", storage="cold_4", discard=False) # My inventory IPTG_tube = p.ref("IPTG", id=inv["IPTG"], cont_type="micro-1.5", storage="cold_20").well(0) # ampicillin plate amp_6_flat = Container(None, p.container_type('6-flat')) p.refs[plate_expid("amp_6_flat")] = Ref(plate_expid("amp_6_flat"), {"id":inv[plate_expid("amp_6_flat")], "store": {"where": 'cold_4'}}, amp_6_flat) # Use a total of 50 wells abs_wells = ["{}{}".format(row,col) for row in "BCDEF" for col in range(1,11)] abs_wells_T = ["{}{}".format(row,col) for col in range(1,11) for row in "BCDEF"] assert abs_wells[:3] == ["B1","B2","B3"] and abs_wells_T[:3] == ["B1","C1","D1"] def prepare_growth_wells(): # # To LB, add ampicillin at ~1/1000 concentration # Mix slowly in case of overflow # p.provision(inv["LB Miller"], lb_xab_tube, µl(1913)) for lb_amp_tube in lb_amp_tubes: p.provision(inv["Amp 100mgml"], lb_amp_tube, µl(2)) p.provision(inv["LB Miller"], lb_amp_tube, µl(1911)) p.mix(lb_amp_tube, volume=µl(800), repetitions=10) # # Add IPTG but save on X-Gal # http://openwetware.org/images/f/f1/Dh5a_sub.pdf # "If you are concerned about obtaining maximal levels of expression, add IPTG to a final concentration of 1 mM." # 2ul of IPTG in 2000ul equals 1mM # p.transfer(IPTG_tube, [lb_xab_tube] + lb_amp_tubes, µl(2), one_tip=True) # # Distribute LB among wells, row D is control (no ampicillin) # cols = range(1,11) row = "D" # control, no AB cwells = ["{}{}".format(row,col) for col in cols] assert set(cwells).issubset(set(abs_wells)) p.distribute(lb_xab_tube, growth_plate.wells(cwells), µl(190), allow_carryover=True) rows = "BCEF" for row, lb_amp_tube in zip(rows, lb_amp_tubes): cwells = ["{}{}".format(row,col) for col in cols] assert set(cwells).issubset(set(abs_wells)) p.distribute(lb_amp_tube, growth_plate.wells(cwells), µl(190), allow_carryover=True) assert all(lb_amp_tube.volume == lb_xab_tube.volume == dead_volume['micro-2.0'] for lb_amp_tube in lb_amp_tubes) return def measure_growth_wells(): # # Growth: absorbance and fluorescence over 24 hours # Absorbance at 600nm: cell growth # Absorbance at 615nm: X-gal, in theory # Fluorescence at 485nm/510nm: sfGFP # or 450nm/508nm (http://www.ncbi.nlm.nih.gov/pmc/articles/PMC2695656/) # hr = 4 for t in range(0,24,hr): if t > 0: p.cover(growth_plate) p.incubate(growth_plate, "warm_37", "{}:hour".format(hr), shaking=True) p.uncover(growth_plate) p.fluorescence(growth_plate, growth_plate.wells(abs_wells).indices(), excitation="485:nanometer", emission="535:nanometer", dataref=expid("fl2_{}".format(t)), flashes=25) p.fluorescence(growth_plate, growth_plate.wells(abs_wells).indices(), excitation="450:nanometer", emission="508:nanometer", dataref=expid("fl1_{}".format(t)), flashes=25) p.fluorescence(growth_plate, growth_plate.wells(abs_wells).indices(), excitation="395:nanometer", emission="508:nanometer", dataref=expid("fl0_{}".format(t)), flashes=25) p.absorbance(growth_plate, growth_plate.wells(abs_wells).indices(), wavelength="600:nanometer", dataref=expid("abs_{}".format(t)), flashes=25) return # --------------------------------------------------------------- # Protocol steps # prepare_growth_wells() batch = 10 for i in range(5): p.autopick(amp_6_flat.well(i), growth_plate.wells(abs_wells_T[i*batch:i*batch+batch]), dataref=expid("autopick_{}".format(i))) p.image_plate(amp_6_flat, mode="top", dataref=expid("autopicked_{}".format(i))) measure_growth_wells() # --------------------------------------------------------------- # Output protocol # jprotocol = json.dumps(p.as_dict(), indent=2) !echo '{jprotocol}' | transcriptic analyze open("protocol_{}.json".format(experiment_name),'w').write(jprotocol) 

 ✓ Protocol analyzed
  62 instructions
  8 containers
  Total Cost: $66.38
  Workcell Time: $57.59
  Reagents & Consumables: $8.78 

:


– , , (1-4) (5-6). , , , , IPTG X-gal, Transcriptic.


- (1-4) (5-6)

- - . ( GraphicsMagick ). , , ( , ).

, Transcriptic. , 10 . , , . . , , , , .


- (1-4) (5-6),

– . , . , . X-gal.

- . , .


, (1-4) (5-6)

:


50 96- 20 , sfGFP. ( , ) Transcriptic Tecan Infinite .

, , , sfGFP. , , - , sfGFP . , sfGFP, , , , .

(OD600) 20 ( 60 ).

 for t in [0,4,8,12,16,20]: abs_data = pd.read_csv("glow/sfgfp_puc19_gibson_pick_v3_abs_{}.csv".format(t), index_col="Well") flr_data = pd.read_csv("glow/sfgfp_puc19_gibson_pick_v3_fl2_{}.csv".format(t), index_col="Well") if t == 0: new_data = abs_data.join(flr_data) else: new_data = new_data.join(abs_data, rsuffix='_{}'.format(t)) new_data = new_data.join(flr_data, rsuffix='_{}'.format(t)) new_data.columns = ["OD 600:nanometer_0", "Fluorescence_0"] + list(new_data.columns[2:]) 

20- . , .

 svg = [] W, H = 800, 500 min_x, max_x = 0, 0.8 min_y, max_y = 0, 50000 def _toxy(x, y): return W*(x-min_x)/(max_x-min_x), HH*(y-min_y)/(max_y-min_y) def _topt(x, y): return ','.join(map(str,_toxy(x,y))) ab_fls = [[row[0]] + [list(row[1])] for row in new_data.iterrows()] # axes svg.append('<g fill="#888" font-size="18" transform="translate(20,0),scale(.95)">') svg.append('<text x="0" y="{}">OD600 →</text>'.format(H+20)) svg.append('<text x="0" y="0" transform="rotate(-90),translate(-{},-8)">Fluorescence →</text>'.format(H)) svg.append('<line x1="0" y1="{}" x2="{}" y2="{}" style="stroke:#888;stroke-width:2" />'.format(H,W,H)) svg.append('<line x1="0" y1="0" x2="0" y2="{}" style="stroke:#888;stroke-width:2" />'.format(H)) # glow filter svg.append("""<filter id="glow" x="-200%" y="-200%" height="400%" width="400%"> <feColorMatrix type="matrix" values="0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 1 0"/> <feGaussianBlur stdDeviation="10" result="coloredBlur"/> <feMerge><feMergeNode in="coloredBlur"/><feMergeNode in="SourceGraphic"/></feMerge> </filter>""") for n, (well, vals) in enumerate(ab_fls): fill = "#444" if not well.startswith("D") else "#aaa" gfilter = 'filter="url(#glow)"' if well in ["C3", "D1", "D3"] else "" cx, cy = _toxy(*vals[-2:]) svg.append('''<g id="point{n:d}"><circle {gfilter:s} r="12" cx="{cx:f}" cy="{cy:f}" fill="{fill:s}" /> <text x="{cx:f}" y="{cy:f}" font-size="10" text-anchor="middle" fill="#fff" alignment-baseline="middle">{txt:s}</text></g> '''.format(n=n, cx=cx, cy=cy, fill=fill, txt=well, gfilter=gfilter)) pathd = 'M{} '.format(_topt(*vals[:2])) pathd += ' '.join("L{}".format(_topt(*vals[i:i+2])) for i in range(2,len(vals),2)) svg.append('''<path d="{pathd:}" stroke="#ccc" stroke-width=".2" fill="none" id="path{n:d}"/>'''.format(pathd=pathd, n=n)) svg.append("</g>") # entire chart group show_svg(''.join(svg), w=W, h=H) 



OD600: , . , sfGFP

miniprep , , 13. , - miniprep - Transcriptic, . (C1, D1, D3) (B1, B3, E1), sfGFP muscle .

C1, D3 D3 sfGFP, B1, B3 E1 .


, . , 0 (40 000 ). 20- OD600 (, - ), . , , , , 11-15 .

(. . , ), , , ).

, , 50 sfGFP . , . , ( , , miniprep), 200 , .

, . , GFP, Python!

:


Preis


, , $360, :

  • $70
  • $32 PCR
  • $31
  • $32
  • $53
  • $67
  • $75 3 miniprep'

, $250-300 . , 50 , , .

, ( ) ( IT). Transcriptic , . , , . , , , , .

, . , - , . , : , , IDT .

:


, . , :

  • ! , . autoprotocol, .
  • . 100 , .
  • , , PCR. , , ? / ? , , , « 2-3 ». ?
  • . . , .
  • . .
  • . . , 1 96 (96−x) 96- , .
  • . csv , .
  • . - , .

, , , . , 1994 :

  • Transcriptic — . , , , . , , .
  • — Transcriptic.
  • , . Transcriptic ( , , ).
  • , ( : ~$0). , .
  • Transcriptic . , , .


, , - , , .

, :

  • Twist/IDT/Gen9 Transcriptic (, - ).
  • , , , , . .
  • ( NEB, IDT) (, primer3 ).

( ) , , . , in vivo (. . ).

, , : RBS , ; ; .

?


, . :

  • - //, .
  • , , .
  • in vivo split-GFP .
  • scFv . scFvs - .
  • BiTE , ( , ).
  • , ( ).
  • , . 1000 10 000 ? , GFP?

, , iGEM .

Transcriptic .

Source: https://habr.com/ru/post/de451124/


All Articles