def __init__(self, inputs, pcr1inputconc=0.05, used=None,doqpcr=True,inputPlate=decklayout.SAMPLEPLATE): super(Barcoding, self).__init__() if used is None: used = [] self.inputs = inputs self.qconc = 50e-12 # Target qPCR concentration self.qprimers = ["End"] self.doqpcr=doqpcr self.bc1_inputvol = 4 # ul of input samples self.mix_conc = 100e-9 # Concentration of mixdown self.pcr1inputconc = pcr1inputconc for inp in inputs: bc = "%s-%s" % (inp['left'], inp['right']) if bc in used: logging.error("Barcode %s is being reused for %s" % (bc, inp['name'])) used.append(bc) for x in inputs: if not reagents.isReagent(x['name']): reagents.add(x['name'], inputPlate, well=x['well'] if 'well' in x else None, conc=Concentration(stock=x['conc'], units="nM"), initVol=self.bc1_inputvol, extraVol=0) else: r = reagents.getsample(x['name']) if r.conc.stock != x['conc']: logging.error('Input %s has conflicting concentrations set: %f and %f', x['name'], r.conc.stock, x['conc']) assert False self.q = None # Defined in pgm()
def addTemplates(self,names,stockconc,finalconc=None,units="nM",plate=decklayout.EPPENDORFS,looplengths=None,extraVol=30,wellnames=None,initVol=0): 'Add templates as "reagents", return the list of them' if finalconc is None: logging.warning("final concentration of template not specified, assuming 0.6x (should add to addTemplates() call") [names,stockconc]=listify([names,stockconc]) finalconc=[0.6*x for x in stockconc] else: [names,stockconc,finalconc]=listify([names,stockconc,finalconc]) if len(set(names))!=len(names): logging.error("addTemplates: template names must be unique") r=[] if looplengths is not None: assert(len(names)==len(looplengths)) for i in range(len(names)): if wellnames is None: well=None else: well=wellnames[i] if reagents.isReagent(names[i]): r.append(reagents.lookup(names[i])) elif looplengths is None: r.append(reagents.add(names[i],plate=plate,conc=Concentration(stockconc[i],finalconc[i],units),extraVol=extraVol,well=well,initVol=initVol)) else: r.append(reagents.add(names[i],plate=plate,conc=Concentration(stockconc[i],finalconc[i],units),extraVol=extraVol,extrainfo=looplengths[i],well=well,initVol=initVol)) return r
def runQPCR(self,src,vol,primers,nreplicates=1,enzName="EvaUSER"): ## QPCR setup worklist.comment("runQPCR: primers=%s, source=%s"%([p for p in primers],[s.name for s in src])) [src,vol,nreplicates]=listify([src,vol,nreplicates]) self.e.shakeSamples(src,returnPlate=True) # Build a list of sets to be run torun=[] for repl in range(max(nreplicates)): for p in primers: for i in range(len(src)): if nreplicates[i]<=repl: continue if repl==0: sampname="%s.Q%s"%(src[i].name,p) else: sampname="%s.Q%s.%d"%(src[i].name,p,repl+1) s=Sample(sampname,decklayout.QPCRPLATE) torun=torun+[(src[i],s,p,vol[i])] # Add enzyme e=reagents.getsample(enzName) v=[a[3]/e.conc.dilutionneeded() for a in torun] t=[a[1] for a in torun] self.e.multitransfer(v,e,t) # Make the target have 'none' concentration so we can multiadd to it again for s in t: s.conc=None # Fill the master mixes dil={} for p in primers: mname="P-%s"%p if not reagents.isReagent(mname): reagents.add(name=mname,conc=4,extraVol=30) mq=reagents.getsample(mname) t=[a[1] for a in torun if a[2]==p] v=[a[3]/mq.conc.dilutionneeded() for a in torun if a[2]==p] assert(v>0) self.e.multitransfer(v,mq,t,(False,False)) dil[p]=1.0/(1-1/e.conc.dilutionneeded()-1/mq.conc.dilutionneeded()) # Add the samples self.e.sanitize() # In case we are aligned for a in torun: s=a[0] t=a[1] p=a[2] v=a[3]/dil[p] t.conc=None # Concentration of master mix is irrelevant now self.e.transfer(v,s,t) return [a[1] for a in torun]
def __init__(self, inputs, nmolecules, nconstrict, vol): super(Constrict, self).__init__() self.inputs = inputs self.nmolecules = nmolecules self.nconstrict = nconstrict self.qconc = 20e-12 # Target qPCR concentration self.qprimers = ["End"] self.mix_conc = 100e-9 # Concentration of mixdown self.con_dilvol = 100 # Volume to use for constriction dilutions self.con_maxdilperstage = 100 / 3.0 # Maximum dilution/stage self.con_pcr1vol = 100 self.con_pcr1inputvol = 2 self.con_pcr1tgtconc = self.qconc * 4 # Enough to take qPCR without dilutiojn self.con_pcr2dil = 4 self.con_pcr2vol = 50 self.con_pcr2tgtconc = 10e-9 self.regen_predilvol = 100 self.regen_predil = 25 self.regen_dil = 25 self.regen_vol = 100 self.regen_cycles = 10 self.rsrc = [reagents.add("%s-%s-%s" % (inputs[i]['name'], inputs[i]['left'], inputs[i]['right']), decklayout.SAMPLEPLATE, well=inputs[i]['well'] if 'well' in inputs[i] else None, conc=Concentration(stock=inputs[i]['bconc'], units="nM"), initVol=vol, extraVol=0) for i in range(len(inputs))] self.q = None # Defined in pgm()
def runQPCR(self, src, vol, srcdil, primers=["A", "B"], nreplicates=1): ## QPCR setup worklist.comment("runQPCR: primers=%s, source=%s" % ([p for p in primers], [s.name for s in src])) [src, vol, srcdil, nreplicates] = listify([src, vol, srcdil, nreplicates]) self.e.shakeSamples(src, returnPlate=True) # Build a list of sets to be run torun = [] for repl in range(max(nreplicates)): for p in primers: for i in range(len(src)): if nreplicates[i] <= repl: continue if repl == 0: sampname = "%s.Q%s" % (src[i].name, p) else: sampname = "%s.Q%s.%d" % (src[i].name, p, repl + 1) s = Sample(sampname, decklayout.QPCRPLATE) torun = torun + [(src[i], s, p, vol[i])] # Fill the master mixes dil = {} for p in primers: mname = "MQ%s" % p if not reagents.isReagent(mname): reagents.add(name=mname, conc=15.0 / 9.0, extraVol=30) mq = reagents.getsample(mname) t = [a[1] for a in torun if a[2] == p] v = [a[3] / mq.conc.dilutionneeded() for a in torun if a[2] == p] self.e.multitransfer(v, mq, t, (False, False)) dil[p] = 1.0 / (1 - 1 / mq.conc.dilutionneeded()) # Add the samples self.e.sanitize() # In case we are aligned for a in torun: s = a[0] t = a[1] p = a[2] v = a[3] / dil[p] t.conc = None # Concentration of master mix is irrelevant now self.e.transfer(v, s, t) return [a[1] for a in torun]
def addTemplates(self,names,stockconc,finalconc=None,units="nM",plate=decklayout.EPPENDORFS): 'Add templates as "reagents", return the list of them' if finalconc is None: print "WARNING: final concentration of template not specified, assuming 0.6x (should add to addTemplates() call" [names,stockconc]=listify([names,stockconc]) finalconc=[0.6*x for x in stockconc] else: [names,stockconc,finalconc]=listify([names,stockconc,finalconc]) r=[] for i in range(len(names)): r.append(reagents.add(names[i],plate=plate,conc=Concentration(stockconc[i],finalconc[i],units),extraVol=30)) return r
def __init__(self, inputs): super(IDPrep, self).__init__() self.inputs = inputs self.qconc = 0.020 # Target qPCR concentration in nM self.qprimers = ["End"] self.bc1_inputvol = 2 # ul into PCR1 used = [] for inp in inputs: bc = "%s-%s" % (inp['left'], inp['right']) if bc in used: logging.error("Barcode %s is being reused for %s" % (bc, inp['name'])) used.append(bc) print("used=",used) self.rsrc = [reagents.add("%s-%s-%s" % (inputs[i]['name'], inputs[i]['left'], inputs[i]['right']), decklayout.SAMPLEPLATE, well=inputs[i]['well'] if 'well' in inputs[i] else None, conc=Concentration(stock=inputs[i]['conc'], units="nM"), initVol=self.bc1_inputvol, extraVol=0) for i in range(len(inputs))] self.q = None # Defined in pgm()
def addTemplates(self, names, stockconc, finalconc=None, units="nM", plate=decklayout.EPPENDORFS): 'Add templates as "reagents", return the list of them' if finalconc is None: print "WARNING: final concentration of template not specified, assuming 0.6x (should add to addTemplates() call" [names, stockconc] = listify([names, stockconc]) finalconc = [0.6 * x for x in stockconc] else: [names, stockconc, finalconc] = listify([names, stockconc, finalconc]) r = [] for i in range(len(names)): r.append( reagents.add(names[i], plate=plate, conc=Concentration(stockconc[i], finalconc[i], units), extraVol=30)) return r
from Experiment.sample import Sample from Experiment.experiment import Experiment from Experiment.concentration import Concentration from Experiment import worklist, reagents, decklayout, clock from Experiment import globals import os import sys import math import argparse maxVolumePerWell=150 reagents.add("MT7",well="A1",conc=2.5,extraVol=30) reagents.add("MPosRT",well="B1",conc=2,extraVol=30) reagents.add("MKlenow",well="C1",conc=2,extraVol=30) reagents.add("MUser",well="D1",conc=2,extraVol=30) reagents.add("MLigBT7W",well="E1",conc=3) reagents.add("MLigase",well="A2",conc=3) reagents.add("MStopXBio",well="B2",conc=2) reagents.add("MStopXSelfExtendW",well="B2",conc=5) reagents.add("MStpX",well="C2",conc=2) reagents.add("MStopXSelfExtendB",well="C2",conc=5) reagents.add("MQREF",well="D2",conc=10.0/6) reagents.add("MQAX",well="E2",conc=10.0/6) reagents.add("MQBX",well="A3",conc=10.0/6) reagents.add("MPCRAX",well="B3",conc=4.0/3) reagents.add("MPCRBX",well="C3",conc=4.0/3) reagents.add("MQMX",well="D3",conc=10.0/6) reagents.add("MQWX",well="E3",conc=10.0/6) reagents.add("SSD",well="A4",conc=10.0)
def pgm(self): q = QSetup(self, maxdil=self.maxdilstep, debug=False, mindilvol=60) self.e.addIdleProgram(q.idler) if self.barcoding: # Setup barcode primers for cleaved rounds only self.bcprimers = [[ "BC-%s-R%d_T7" % (inp['ligand'], r + 1) for inp in self.inputs ] if self.rounds[r] == 'C' else None for r in range(len(self.rounds))] for bcp in self.bcprimers: if bcp is not None: for p in ["P-%s" % pp for pp in bcp]: if not reagents.isReagent(p): reagents.add(name=p, conc=4, extraVol=30, plate=decklayout.REAGENTPLATE, well="B2") s = reagents.getsample(p) # Force allocation of a well print "Adding %s to reagents at well %s" % ( p, s.plate.wellname(s.well)) print "BC primers=", self.bcprimers # Add any missing fields to inputs for i in range(len(self.inputs)): if 'ligand' not in self.inputs[i]: self.inputs[i]['ligand'] = None if 'round' not in self.inputs[i]: self.inputs[i]['round'] = None if 'name' not in self.inputs[i]: if self.inputs[i]['ligand'] is None: self.inputs[i]['name'] = '%s_%d_R%d' % ( self.inputs[i]['prefix'], self.inputs[i]['ID'], self.inputs[i]['round']) else: self.inputs[i]['name'] = '%s_%d_R%d_%s' % ( self.inputs[i]['prefix'], self.inputs[i]['ID'], self.inputs[i]['round'], self.inputs[i]['ligand']) # Add templates if self.directT7: self.srcs = self.addTemplates( [inp['name'] for inp in self.inputs], stockconc=self.tmplFinalConc / self.templateDilution, finalconc=self.tmplFinalConc, plate=decklayout.SAMPLEPLATE, looplengths=[inp['looplength'] for inp in self.inputs], initVol=self.t7vol[0] * self.templateDilution, extraVol=0) else: self.srcs = self.addTemplates( [inp['name'] for inp in self.inputs], stockconc=self.tmplFinalConc / self.templateDilution, finalconc=self.tmplFinalConc, plate=decklayout.DILPLATE, looplengths=[inp['looplength'] for inp in self.inputs], extraVol=15) t7in = [s.getsample() for s in self.srcs] if "negative" in self.qpcrStages: q.addSamples(decklayout.SSDDIL, 1, self.allprimers, save=False) # Negative controls if "reference" in self.qpcrStages: q.addReferences(dstep=10, nsteps=5, primers=["T7WX", "MX", "T7X"], ref=reagents.getsample("BT5310"), nreplicates=1) q.addReferences(dstep=10, nsteps=5, primers=["T7WX", "MX", "T7X"], ref=reagents.getsample("BT5310"), nreplicates=1) # Save RT product from first (uncleaved) round and then use it during 2nd (cleaved) round for ligation and qPCR measurements self.rndNum = 0 self.nextID = self.firstID curPrefix = [inp['prefix'] for inp in self.inputs] r1 = t7in for roundType in self.rounds: # Run a single round of roundType with r1 as input # roundType is either "U" for uncleaved, or a new prefix for a cleaved round (with "T" being a T7 prepend) # Set r1 to new output at end # Computed output prefix if roundType == 'U': prefixOut = curPrefix stop = ["Unclvd" for p in curPrefix] else: if roundType == 'T': stop = ['T7%s' % p for p in curPrefix] prefixOut = curPrefix elif any([p == roundType for p in curPrefix]): logging.error( "Round %d is a cleaved round but goes to %s without changing prefix" % (self.rndNum, roundType)) assert (False) else: prefixOut = [roundType for p in curPrefix] stop = prefixOut # May be explicitly overridden for i in range(len(self.inputs)): if 'stop' in self.inputs[i]: if isinstance(self.inputs[i]['stop'], list): assert (len(self.inputs[i]['stop']) == len( self.rounds)) t = self.inputs[i]['stop'][self.rndNum] else: t = self.inputs[i]['stop'] if (roundType == 'U') != (t == 'U'): print "Attempt to override round %d (type %s) with a input-specific round type of %s" % ( self.rndNum, roundType, t) assert (False) if roundType != 'U': if t == 'T': stop[i] = 'T7%s' % curPrefix[i] prefixOut[i] = curPrefix[i] else: stop[i] = t prefixOut[i] = t self.rndNum = self.rndNum + 1 self.finalRound = self.rndNum == len(self.rounds) r1 = self.oneround(q, r1, prefixOut=prefixOut, stop=stop, prefixIn=curPrefix, keepCleaved=(roundType != 'U'), rtvol=self.rtvol[self.rndNum - 1], t7vol=self.t7vol[self.rndNum - 1], cycles=self.pcrcycles[self.rndNum - 1], pcrdil=self.pcrdil[self.rndNum - 1], pcrvol=self.pcrvol[self.rndNum - 1], dolig=self.allLig or (roundType != 'U')) for i in range(len(r1)): r1[i].name = "%s_%d" % (prefixOut[i], self.nextID) if self.inputs[i]['round'] is not None: r1[i].name = "%s_R%d%c" % (r1[i].name, self.inputs[i]['round'] + self.rndNum, roundType) if self.inputs[i]['ligand'] is not None: r1[i].name = "%s_%s" % (r1[i].name, self.inputs[i]['ligand']) print "Used ID ", self.nextID, " for ", r1[i].name, ": ", r1[i] self.nextID += 1 r1[i].conc.final = r1[i].conc.stock * self.templateDilution curPrefix = prefixOut if "finalpcr" in self.qpcrStages: for i in range(len(r1)): if self.singlePrefix: q.addSamples(src=r1[i], needDil=r1[i].conc.stock / self.qConc, primers=["T7X", "MX"]) else: q.addSamples(src=r1[i], needDil=r1[i].conc.stock / self.qConc, primers=["T7X", prefixOut[i] + "X", "MX"]) print "######### qPCR ########### %.0f min" % (clock.elapsed() / 60) self.allprimers = q.allprimers() q.run(confirm=self.qpcrWait)
# Generic selection progam import debughook import math from Experiment.concentration import Concentration from Experiment.sample import Sample from Experiment import worklist, reagents, decklayout, logging, clock from TRPLib.TRP import TRP from TRPLib.QSetup import QSetup from pcrgain import pcrgain reagents.add("BT5310", well="B5", conc=Concentration(20, 20, "pM")) class PGMSelect(TRP): '''Selection experiment''' def __init__(self, inputs, rounds, firstID, pmolesIn, directT7=True, templateDilution=0.3, tmplFinalConc=50, saveDil=24, qpcrWait=False, allLig=False, qpcrStages=["negative", "template", "ext", "finalpcr"], finalPlus=True, t7dur=30, usertime=10,
def runPCR(self, prefix, src, vol, srcdil, tgt=None, ncycles=20, suffix='S', sepPrimers=True, primerDil=4): ## PCR [prefix, src, tgt, vol, srcdil, suffix] = listify([prefix, src, tgt, vol, srcdil, suffix]) for i in range(len(tgt)): if tgt[i] is None: tgt[i] = Sample( "%s.P%s%s" % (src[i].name, prefix[i], suffix[i]), src[i].plate) # Adjust source dilution for i in range(len(src)): src[i].conc = Concentration(srcdil[i], 1) if sepPrimers: sampvols = [vol[i] / srcdil[i] for i in range(len(src))] mm = reagents.getsample("MPCR") mmvols = [ vol[i] / mm.conc.dilutionneeded() for i in range(len(src)) ] for s in prefix + suffix: if not reagents.isReagent(s): reagents.add(name=s, conc=primerDil, extraVol=30) sprefix = [reagents.getsample(p) for p in prefix] ssuffix = [reagents.getsample(p) for p in suffix] prefixvols = [ vol[i] / sprefix[i].conc.dilutionneeded() for i in range(len(src)) ] suffixvols = [ vol[i] / ssuffix[i].conc.dilutionneeded() for i in range(len(src)) ] watervols = [ vol[i] - mmvols[i] - prefixvols[i] - suffixvols[i] - sampvols[i] for i in range(len(src)) ] print "water=", watervols, ", mm=", mmvols, ", prefix=", prefixvols, ", suffix=", suffixvols, ", samp=", sampvols self.e.multitransfer(watervols, decklayout.WATER, tgt, (False, False)) # Transfer water self.e.multitransfer(mmvols, mm, tgt, (False, False)) # PCR master mix sprefixset = set(sprefix) ssuffixset = set(ssuffix) if len(sprefixset) < len(ssuffixset): # Distribute sprefix first for p in sprefixset: self.e.multitransfer([ prefixvols[i] for i in range(len(src)) if sprefix[i] == p ], p, [tgt[i] for i in range(len(src)) if sprefix[i] == p], (False, False)) # Then individually add ssuffix for i in range(len(src)): self.e.transfer(suffixvols[i], ssuffix[i], tgt[i], (False, False)) else: # Distribute ssuffix first for p in ssuffixset: self.e.multitransfer([ suffixvols[i] for i in range(len(src)) if ssuffix[i] == p ], p, [tgt[i] for i in range(len(src)) if ssuffix[i] == p], (False, False)) # Then individually add sprefix for i in range(len(src)): self.e.transfer(prefixvols[i], sprefix[i], tgt[i], (False, False)) # Now add templates for i in range(len(src)): self.e.transfer(sampvols[i], src[i], tgt[i], (False, False)) else: primer = [prefix[i] + suffix[i] for i in range(len(prefix))] print "primer=", primer for up in set(primer): s = "MPCR%s" % up if not reagents.isReagent(s): reagents.add(name=s, conc=4 / 3.0, extraVol=30) self.e.stage( 'PCR%s' % up, [reagents.getsample("MPCR%s" % up)], [src[i] for i in range(len(src)) if primer[i] == up], [tgt[i] for i in range(len(tgt)) if primer[i] == up], [vol[i] for i in range(len(vol)) if primer[i] == up], destMix=False) pgm = "PCR%d" % ncycles self.e.shakeSamples(tgt, returnPlate=False) # worklist.pyrun('PTC\\ptcsetpgm.py %s TEMP@95,120 TEMP@95,30 TEMP@55,30 TEMP@72,25 GOTO@2,%d TEMP@72,180 TEMP@16,2'%(pgm,ncycles-1)) worklist.pyrun( 'PTC\\ptcsetpgm.py %s TEMP@95,120 TEMP@95,10 TEMP@57,10 GOTO@2,%d TEMP@72,120 TEMP@25,2' % (pgm, ncycles - 1)) self.e.runpgm(pgm, 4.80 + 1.55 * ncycles, False, max(vol), hotlidmode="CONSTANT", hotlidtemp=100) return tgt
from __future__ import print_function import math from Experiment import decklayout, reagents, clock, worklist from Experiment.concentration import Concentration from Experiment.sample import Sample from TRPLib.QSetup import QSetup from TRPLib.TRP import TRP reagents.add("BT5310", well="D1", conc=Concentration(20, 20, "pM")) reagents.add("MKapa", well='A1', conc=Concentration(2.5, 1, 'x'), extraVol=30, ingredients={'glycerol': 1, 'Water': 39}) reagents.add("MConstrict", well='A6', conc=Concentration(100.0 / 98.0, 1, 'x'), extraVol=30, ingredients={'glycerol': 1, 'Water': 97}) reagents.add("P-End", well="C1", conc=4) class Constrict(TRP): # Mix constriction inputs, constrict, PCR, remove barcodes pcreff = 1.98 def __init__(self, inputs, nmolecules, nconstrict, vol): super(Constrict, self).__init__() self.inputs = inputs self.nmolecules = nmolecules self.nconstrict = nconstrict self.qconc = 20e-12 # Target qPCR concentration self.qprimers = ["End"]
# Generic selection progam from __future__ import print_function import math from Experiment import worklist, reagents, decklayout, logging, clock, thermocycler from Experiment.concentration import Concentration from Experiment.sample import Sample from TRPLib.QSetup import QSetup from TRPLib.TRP import TRP from .pcrgain import pcrgain from Experiment.db import db reagents.add("BT5310",well="B5",conc=Concentration(20,20,"pM")) # noinspection PyAttributeOutsideInit class PGMSelect(TRP): """Selection experiment""" def __init__(self, inputs, rounds=None, firstID=None, pmolesIn=None, rnddef=None, directT7=True, templateDilution=0.3, tmplFinalConc=50, saveDil=24, qpcrWait=False, allLig=False, qpcrStages=None, finalPlus=True, t7dur=30, usertime=10, singlePrefix=False, noPCRCleave=False, saveRNA=False, useMX=True, refillable=False,enrich=1.4): # Initialize field values which will never change during multiple calls to pgm() # Can use rounds="UZUWUZ" (e.g.) OR rnddef which is a list of specs for each round with rtype (U,W,Z), tref, barcode super(PGMSelect, self).__init__() if refillable: reagents.lookup("MT7").refillable=True reagents.lookup("MPosRT").refillable=True reagents.lookup("MTaqU").refillable=True
def barcoding(self, names, left, right): """Perform barcoding of the given inputs; rsrsc,left,right should all be equal length""" pcrcycles = [5, 10] pcr1inputdil = 10 pcr1vol = 30 pcr1postdil = 100.0 / pcr1vol pcr2dil = 10*pcr1postdil pcr2vol = 40.0 samps = [reagents.getsample(s) for s in names] print("Inputs:") for i in range(len(samps)): print("%2s %-10s %8s-%-8s %s" % ( samps[i].plate.wellname(samps[i].well), self.inputs[i]['name'], left[i], right[i], str(samps[i].conc))) wellnum = 5 for s in left + right: primer = "P-" + s if not reagents.isReagent(primer): reagents.add(primer, conc=Concentration(2.67, 0.4, 'uM'), extraVol=30, plate=decklayout.REAGENTPLATE, well=decklayout.REAGENTPLATE.wellname(wellnum)) wellnum += 1 for s in samps: # Dilute down to desired conc dil = s.conc.stock / self.pcr1inputconc / pcr1inputdil if dil < 1.0: logging.error("Input %s requires dilution of %.2f" % (s.name, dil)) elif dil > 1.0: dilvol = s.volume * dil if dilvol > 150.0: maxdil = 150.0 / s.volume logging.info( "Dilution of input %s (%.1f ul) by %.2f would require %.1f ul -- only diluting by %.1fx" % ( s.name, s.volume, dil, dilvol, maxdil)) dil = maxdil self.diluteInPlace(tgt=[s], dil=dil) print("Diluting %s by %.1f" % (s.name, dil)) print("### PCR1 #### (%.0f min)" % (clock.elapsed() / 60.0)) pcr1 = self.runPCR(src=samps, srcdil=[s.conc.stock / self.pcr1inputconc for s in samps], ncycles=pcrcycles[0], vol=pcr1vol, primers=[[left[i], right[i]] for i in range(len(left))], usertime=30, fastCycling=False, inPlace=False, master="MPCR1", kapa=False, annealTemp=57) pcr1finalconc = self.pcr1inputconc * 2 ** pcrcycles[0] print("PCR1 output concentration = %.1f nM" % pcr1finalconc) if pcr1postdil > 1: pcr1finalconc /= pcr1postdil print("Post dilute PCR1 by %.2fx to %.3f nM " % (pcr1postdil, pcr1finalconc)) self.diluteInPlace(tgt=pcr1, dil=pcr1postdil) for x in pcr1: x.conc = Concentration(stock=pcr1finalconc, units='nM') if len(pcrcycles) > 1: # Second PCR with 235p/236p on mixture (use at least 4ul of prior) print("### PCR2 #### (%.0f min)" % (clock.elapsed() / 60.0)) pcr2 = self.runPCR(src=pcr1, srcdil=pcr2dil / pcr1postdil, vol=pcr2vol, ncycles=pcrcycles[1], primers=None, fastCycling=False, master="MPCR2", kapa=True, annealTemp=64) pcr2finalconc = pcr1finalconc / (pcr2dil / pcr1postdil) * 2 ** pcrcycles[1] print("PCR2 final conc = %.1f nM" % pcr2finalconc) if pcr2finalconc > 200: print("Capping at 200nM") pcr2finalconc = 200 for x in pcr2: x.conc = Concentration(stock=pcr2finalconc, units='nM') if self.doqpcr: self.q.addSamples(src=pcr2, needDil=pcr2finalconc * 1e-9 / self.qconc, primers=self.qprimers) res = pcr2 else: self.q.addSamples(src=pcr1, needDil=pcr1finalconc / (self.qconc * 1e9), primers=self.qprimers, save=True, nreplicates=1) res = pcr1 return res
"""Barcoding""" from __future__ import print_function import logging import numpy as np from Experiment import reagents, worklist, decklayout, clock from Experiment.concentration import Concentration from Experiment.sample import Sample from TRPLib.QSetup import QSetup from TRPLib.TRP import TRP from TRPLib.mixsplit import mixsplit reagents.add("MPCR1", well="A1", conc=30.0 / 18.0, ingredients={'Kapa': 3.33 / 2, 'USER': 1.67 / 2, 'glycerol': 2.5, 'Water': 95}) reagents.add("MPCR2", well="B1", conc=10.0 / 9.0, ingredients={'Kapa': 2.22 / 2, 'glycerol': 2.22 / 2, 'Water': 97.78},extraVol=100) reagents.add("P-End", well="C1", conc=4) reagents.add("BT5310", well="D1", conc=Concentration(20, 20, "pM")) class Barcoding(TRP): """Barcode multiple samples, mix them""" def __init__(self, inputs, pcr1inputconc=0.05, used=None,doqpcr=True,inputPlate=decklayout.SAMPLEPLATE): super(Barcoding, self).__init__() if used is None: used = [] self.inputs = inputs self.qconc = 50e-12 # Target qPCR concentration self.qprimers = ["End"]
def idbarcoding(self, rsrc, left, right): """Perform barcoding of the given inputs; rsrsc,left,right should all be equal length""" pcrcycles = [4] # Don't need 2nd PCR since this will go directly into constriction #pcr1inputconc = 0.05 # PCR1 concentration final in reaction pcr1inputdil = 10 pcr1vol = 30 pcr1postdil = 100.0 / pcr1vol pcr2dil = 50 pcr2minvol = 50.0 samps = [s.getsample() for s in rsrc] print("Inputs:") for i in range(len(samps)): print("%2s %-10s %8s-%-8s %.1f%s" % ( samps[i].plate.wellname(samps[i].well), self.inputs[i]['name'], left[i], right[i], samps[i].conc.stock,samps[i].conc.units)) # Compute pcr1inputconc such that lowest concentration input ends up with at least 30ul after dilution pcr1inputconc=min([s.conc.stock*s.volume/30.0/pcr1inputdil for s in samps]) print("Diluting inputs so PCR1 final template conc = %.0f pM"%(pcr1inputconc*1000)) wellnum = 5 for s in left + right: primer = "P-" + s if not reagents.isReagent(primer): reagents.add(primer, conc=Concentration(2.67, 0.4, 'uM'), extraVol=30, plate=decklayout.REAGENTPLATE, well=decklayout.REAGENTPLATE.wellname(wellnum)) wellnum += 1 # Run first pass dilution where needed for i in range(len(samps)): # Dilute down to desired conc dil = samps[i].conc.stock / pcr1inputconc / pcr1inputdil dilvol = samps[i].volume * dil if dilvol > 100.0: logging.notice("Dilution of input %s (%.1f ul) by %.2f would require %.1f ul" % ( samps[i].name, samps[i].volume, dil, dilvol)) # Do a first pass dilution into 150ul, then remove enough so second dilution can go into 100ul dil1 = 100.0 / samps[i].volume self.diluteInPlace(tgt=[samps[i]], dil=dil1) print("First pass dilution of %s by %.1f/%.1f (conc now %.3f nM)" % (samps[i].name, dil1, dil, samps[i].conc.stock)) dil /= dil1 # Make sure they are all mixed self.e.shakeSamples(samps) # Final dilution for s in samps: # Dilute down to desired conc dil = s.conc.stock / pcr1inputconc / pcr1inputdil if dil < 1.0: logging.error("Input %s requires dilution of %.2f" % (s.name, dil)) elif dil > 1.0: dilvol = s.volume * dil if dilvol>100: toremove=s.volume-100.0/dil print("Removing %.1f ul from %s to allow enough room for dilution"%(toremove,s.name)) self.e.dispose(toremove, s) self.diluteInPlace(tgt=[s], dil=dil) print("Diluting %s by %.1f" % (s.name, dil)) pcr1 = self.runPCR(src=samps, srcdil=pcr1inputdil, ncycles=pcrcycles[0], vol=pcr1vol, primers=[[left[i], right[i]] for i in range(len(left))], usertime=0, fastCycling=False, inPlace=False, master="MKapa", kapa=True) pcr1finalconc = pcr1inputconc * self.pcreff ** pcrcycles[0] print("PCR1 output concentration = %.3f nM" % pcr1finalconc) if pcr1postdil > 1: pcr1finalconc /= pcr1postdil print("Post dilute PCR1 by %.2fx to %.3f nM " % (pcr1postdil, pcr1finalconc)) self.diluteInPlace(tgt=pcr1, dil=pcr1postdil) for x in pcr1: x.conc = Concentration(stock=pcr1finalconc, units='nM') self.q.addSamples(src=pcr1, needDil=pcr1finalconc / self.qconc, primers=self.qprimers, save=True, nreplicates=1) if len(pcrcycles) > 1: # Second PCR with 235p/236p on mixture (use at least 4ul of prior) pcr2 = self.runPCR(src=pcr1, srcdil=pcr2dil / pcr1postdil, vol=max(pcr2minvol, pcr2dil / pcr1postdil * 4), ncycles=pcrcycles[1], primers="End", fastCycling=False, master="MKapa", kapa=True) pcr2finalconc = min(200, pcr1finalconc / (pcr2dil / pcr1postdil) * self.pcreff ** pcrcycles[1]) print("PCR2 final conc = %.1f nM" % pcr2finalconc) d2 = min(4.0, 150.0 / max([p.volume for p in pcr2])) if d2 > 1: pcr2finalconc /= d2 print("Post-dilute PCR2 by %.1fx to %.3fnM" % (d2, pcr2finalconc)) self.diluteInPlace(tgt=pcr2, dil=d2) self.e.shakeSamples(pcr2) for x in pcr2: x.conc = Concentration(stock=pcr2finalconc, units='nM') self.q.addSamples(src=pcr2, needDil=pcr2finalconc / self.qconc, primers=self.qprimers, save=True, nreplicates=2) res = pcr2 else: res = pcr1 return res
def setVolumes(self): # Computed parameters # Observed data: 0.1nM@30min -> gain ~1000 self.rnaConc=8314.0*self.tmplFinalConc/(self.tmplFinalConc+55)*self.t7dur/30 if self.tmplFinalConc<1: self.rnaConc*=6 # Kludge based on being off at 0.1nM template concentrations self.rnaConc=max(40.0,self.rnaConc) # Another kludge if isinstance(self.stopConc,list): minStopConc=min(self.stopConc) else: minStopConc=self.stopConc maxConc=1000*minStopConc*4/0.9 if maxConc<self.rnaConc: logging.warning( "Stop@%.1f uM limits usable RNA to %.0f/%.0f nM"%(minStopConc,maxConc,self.rnaConc)) self.rnaConc=min(maxConc,self.rnaConc) stopConc=self.rnaConc*0.9 rtConc=stopConc/self.rtDil rtdilConc=[rtConc/self.rtpostdil[i] for i in range(len(self.rounds))] ligConc=[None if self.rounds[i]=='U' else rtdilConc[i]/1.25 for i in range(len(self.rounds))] ligdilConc=[None if self.rounds[i]=='U' else ligConc[i]/self.extpostdil[i] for i in range(len(self.rounds))] pcrConc=[rtConc/self.pcrdil[i] if self.rounds[i]=='U' else ligConc[i]/self.pcrdil[i] for i in range(len(self.rounds))] for i in range(len(self.rounds)): if ligConc[i] is None: print("R%d Concs(nM): RNA: %.0f, Stop: %.0f, RT: %.0f, RTDil: %.0f, PCRIn: %.0f"%(i, self.rnaConc, stopConc, rtConc, rtdilConc[i], pcrConc[i])) else: print("R%d Concs(nM): RNA: %.0f, Stop: %.0f, RT: %.0f, RTDil: %.0f, Lig: %.0f, LigDil: %.0f, PCRIn: %.0f"%(i, self.rnaConc, stopConc, rtConc, rtdilConc[i], ligConc[i], ligdilConc[i], pcrConc[i])) self.pcrvol=[self.pcrcopies*self.pmolesIn*1000/pcrConc[i]/math.pow(self.enrich,(i+1.0)) for i in range(len(self.rounds))] # Use at least 100ul so the evaporation of the saved sample that occurs during the run will be relatively small self.pcrvol=[max(100,v) for v in self.pcrvol] print("pcrvol=[%s]"%(",".join(["%.1f"%v for v in self.pcrvol]))) pcrExtra=[1.4*math.ceil(v*1.0/self.maxPCRVolume) for v in self.pcrvol] print("pcrExtra=[%s]"%(",".join(["%.1f"%v for v in pcrExtra]))) self.minligvol=[(self.pcrvol[i]*1.0+pcrExtra[i])/self.pcrdil[i]+((4.4 if self.saveDil is not None else 5.4 if 'ext' in self.qpcrStages else 0)+15.1)/self.extpostdil[i] for i in range(len(self.pcrvol))] print("minligvol=[%s]"%(",".join(["%.1f"%v for v in self.minligvol]))) # Compute RT volume self.rtvol=[ ((self.minligvol[i]/1.25+3.3)/self.rtpostdil[i]) if self.rounds[i]!='U' else (self.pcrvol[i]*1.0/self.pcrdil[i]+(pcrExtra[i]+15.1+3.3)/self.rtpostdil[i]) for i in range(len(self.rounds))] print("self.rtvol=",self.rtvol,", rtSave=",self.rtSave) if self.rtSave: self.rtvol=[max(15.0/self.rtpostdil[i],self.rtvol[i])+(self.rtSaveVol+1.4)/self.rtpostdil[i] for i in range(len(self.rtvol))] # Extra for saves elif "rt" in self.qpcrStages: # Take from save if rtSave is set self.rtvol=[max(15.0/self.rtpostdil[i],self.rtvol[i])+5.4/self.rtpostdil[i] for i in range(len(self.rtvol))] # Extra for qPCR self.rtvol=[max(v,8.0) for v in self.rtvol] # Minimum volume self.rtvol=[min(v,self.maxSampVolume) for v in self.rtvol] # Maximum volume # print ("self.rtvol=",self.rtvol) self.t7extravols=((4+1.4) if 'stopped' in self.qpcrStages else 0)+ ((self.saveRNAVolume+1.4) if self.saveRNA else 0) # + 3.3 # 3.3 in case pipette mixing used #print "self.t7extravols=%.1f ul\n"%self.t7extravols #print "self.rtvol=%s ul\n"%(",".join(["%.1f "%x for x in self.rtvol])) # Compute dilutions due to tref additions trefdil=[1 for _ in self.rnddef ] for i in range(len(self.rnddef)-1): rd=self.rnddef[i] if 'tref' in rd: tref = rd['tref'][0] if tref is not None: trefname = 'TRef%d' % tref if not reagents.isReagent(trefname): reagents.add(name=trefname, conc=10, extraVol=30, well="E4") trefs = reagents.getsample(trefname) trefdil[i+1]=(trefs.conc.dilutionneeded())/(trefs.conc.dilutionneeded()-1) print("Extra dilution due to tref additions: ",trefdil) self.t7vol=[max((15.1+self.rtvol[i]/4.0+1.4)+self.t7extravols,self.pmolesIn*1000.0/(self.tmplFinalConc if i==0 else 200*self.templateDilution)*trefdil[i]/math.pow(self.enrich,i*1.0)) for i in range(len(self.rounds))] print("self.t7vol=%s ul\n"%(",".join(["%.1f "%x for x in self.t7vol]))) #self.t7vol=[max(18.0,v) for v in self.t7vol] # Make sure that there's enough to add at least 2ul of stop if 'template' in self.qpcrStages: self.t7vol[0]+=5.4 self.t7vol=[min(self.maxSampVolume,v) for v in self.t7vol] # Make sure no tubes overflow
def runPCR(self,primers,src,srcdil,vol=None,tgt=None,ncycles=20,usertime=None,fastCycling=False,inPlace=False,master="MTaq",annealTemp=None,kapa=False): ## PCR if inPlace: if vol!=None: print "runPCR: cannot specify volume when using inPlace=True, srcdil and input volume determine reaction volume" assert(False) if tgt!=None: print "runPCR: cannot specify tgt when using inPlace=True" assert(False) [primers,src,vol,srcdil]=listify([primers,src,vol,srcdil]) vol=[src[i].volume*srcdil[i] for i in range(len(src))] tgt=src else: [primers,src,tgt,vol,srcdil]=listify([primers,src,tgt,vol,srcdil]) for i in range(len(tgt)): if tgt[i] is None: if isinstance(primers[i],list): tgt[i]=Sample("%s.P%s"%(src[i].name,"+".join(primers[i])),src[i].plate) else: tgt[i]=Sample("%s.P%s"%(src[i].name,primers[i]),src[i].plate) # Adjust source dilution for i in range(len(src)): src[i].conc=Concentration(srcdil[i],1) logging.notice( "primer="+str(primers)) # Add reagent entries for any missing primers if isinstance(primers[0],list): allprimers=[x for y in primers for x in y] else: allprimers=primers for up in set(allprimers): s="P-%s"%up if not reagents.isReagent(s): reagents.add(name=s,conc=4,extraVol=30) if isinstance(primers[0],list): # Multiple primers if inPlace: assert len(primers[0])==2 self.runRxInPlace(src,vol,reagents.getsample(master),master2=[reagents.getsample("P-%s"%p[0]) for p in primers],master3=[reagents.getsample("P-%s"%p[1]) for p in primers],returnPlate=False) else: for i in range(len(primers)): self.e.stage('PCR%d'%i,[reagents.getsample(master)]+[reagents.getsample("P-%s"%s) for s in primers[i]],src[i:i+1] ,tgt[i:i+1],vol[i:i+1],destMix=False) #self.e.shakeSamples(tgt,returnPlate=False) else: # Single primer if inPlace: self.runRxInPlace(src,vol,reagents.getsample(master),master2=[reagents.getsample("P-%s"%p) for p in primers],returnPlate=False) else: for up in set(primers): self.e.stage('PCR%s'%up,[reagents.getsample(master),reagents.getsample("P-%s"%up)],[src[i] for i in range(len(src)) if primers[i]==up],[tgt[i] for i in range(len(tgt)) if primers[i]==up],[vol[i] for i in range(len(vol)) if primers[i]==up],destMix=False) #self.e.shakeSamples(tgt,returnPlate=False) pgm="PCR%d"%ncycles if usertime is None: runTime=0 else: runTime=usertime if annealTemp is None: annealTemp=60 if kapa else 57 meltTemp=98 if kapa else 95 hotTime=180 if kapa else 30 extTemp=72 if kapa else 68 if fastCycling: cycling='TEMP@37,%d TEMP@95,%d TEMP@%.1f,10 TEMP@%.1f,10 TEMP @%.1f,1 GOTO@3,%d TEMP@%.1f,60 TEMP@25,2'%(1 if usertime is None else usertime*60,hotTime,meltTemp,annealTemp,extTemp,ncycles-1,extTemp) runTime+=hotTime/60+2.8+1.65*ncycles else: cycling='TEMP@37,%d TEMP@95,%d TEMP@%.1f,30 TEMP@%.1f,30 TEMP@%.1f,30 GOTO@3,%d TEMP@%.1f,60 TEMP@25,2'%(1 if usertime is None else usertime*60,hotTime,meltTemp,annealTemp,extTemp,ncycles-1,extTemp) runTime+=hotTime/60+2.8+3.0*ncycles print "PCR volume=[",",".join(["%.1f"%t.volume for t in tgt]), "], srcdil=[",",".join(["%.1fx"%s for s in srcdil]),"], program: %s"%cycling worklist.pyrun('PTC\\ptcsetpgm.py %s %s'%(pgm,cycling)) self.e.runpgm(pgm,runTime,False,max(vol),hotlidmode="CONSTANT",hotlidtemp=100) # Mark samples as mixed (by thermal convection) print "Marking samples as mixed (by thermal convection)" for t in tgt: t.wellMixed=True t.lastMixed=clock.elapsed() #self.e.shakeSamples(tgt,returnPlate=True) return tgt
def pgm(self): q = QSetup(self,maxdil=self.maxdilstep,debug=False,mindilvol=60) self.e.addIdleProgram(q.idler) if self.barcoding: # Setup barcode primers for cleaved rounds only self.bcprimers=[["BC-%s-R%d_T7"%(inp['ligand'],r+1) for inp in self.inputs] if self.rounds[r]=='C' else None for r in range(len(self.rounds))] for bcp in self.bcprimers: if bcp is not None: for p in ["P-%s"%pp for pp in bcp]: if not reagents.isReagent(p): reagents.add(name=p,conc=4,extraVol=30,plate=decklayout.REAGENTPLATE,well="B2") s=reagents.getsample(p) # Force allocation of a well print("Adding %s to reagents at well %s"%(p,s.plate.wellname(s.well))) print("BC primers=", self.bcprimers) # Add any missing fields to inputs for i in range(len(self.inputs)): if 'ligand' not in self.inputs[i]: self.inputs[i]['ligand']=None if 'negligand' not in self.inputs[i]: self.inputs[i]['negligand']=None if 'round' not in self.inputs[i]: self.inputs[i]['round']=None if 'name' not in self.inputs[i]: if self.inputs[i]['ligand'] is None: self.inputs[i]['name']='%s_%d_R%d'%(self.inputs[i]['prefix'],self.inputs[i]['ID'],self.inputs[i]['round']) else: self.inputs[i]['name']='%s_%d_R%d_%s'%(self.inputs[i]['prefix'],self.inputs[i]['ID'],self.inputs[i]['round'],self.inputs[i]['ligand']) # Add templates if self.directT7: self.srcs = self.addTemplates([inp['name'] for inp in self.inputs],stockconc=self.tmplFinalConc/self.templateDilution,finalconc=self.tmplFinalConc,plate=decklayout.SAMPLEPLATE,looplengths=[inp['looplength'] for inp in self.inputs],initVol=self.t7vol[0]*self.templateDilution,extraVol=0) else: self.srcs = self.addTemplates([inp['name'] for inp in self.inputs],stockconc=self.tmplFinalConc/self.templateDilution,finalconc=self.tmplFinalConc,plate=decklayout.DILPLATE,looplengths=[inp['looplength'] for inp in self.inputs],extraVol=15) if self.dopcr: # Reserve space for PCR products pcrprods=[ [Sample("R%d-T%s"%(r,inp['ligand']),self.savePlate) for inp in self.inputs] for r in range(len(self.rounds))] else: pcrprods=None t7in = [s.getsample() for s in self.srcs] if "negative" in self.qpcrStages: q.addSamples(decklayout.SSDDIL,1,self.allprimers,save=False) # Negative controls if "reference" in self.qpcrStages: q.addReferences(dstep=10,nsteps=5,primers=["WX","MX","T7X"] if self.useMX else ["WX","T7X"],ref=reagents.getsample("BT5310"),nreplicates=1) # Save RT product from first (uncleaved) round and then use it during 2nd (cleaved) round for ligation and qPCR measurements self.rndNum=0 self.nextID=self.firstID curPrefix=[inp['prefix'] for inp in self.inputs] r1=t7in for roundType in self.rounds: # Run a single round of roundType with r1 as input # roundType is either "U" for uncleaved, or a new prefix for a cleaved round (with "T" being a T7 prepend) # Set r1 to new output at end if self.roundCallback is not None: self.roundCallback(self,self.rndNum,roundType) # Computed output prefix if roundType=='U': prefixOut=curPrefix stop=["Unclvd" for _ in curPrefix] else: if roundType=='T': stop=['T7%s'%p for p in curPrefix] prefixOut=curPrefix elif any([p==roundType for p in curPrefix]): logging.error( "Round %d is a cleaved round but goes to %s without changing prefix"%(self.rndNum, roundType)) assert False else: prefixOut=[roundType for _ in curPrefix] stop=prefixOut # May be explicitly overridden for i in range(len(self.inputs)): if 'stop' in self.inputs[i]: if isinstance(self.inputs[i]['stop'],list): assert(len(self.inputs[i]['stop'])==len(self.rounds)) t=self.inputs[i]['stop'][self.rndNum] else: t=self.inputs[i]['stop'] if (roundType=='U') != (t=='U'): print("Attempt to override round %d (type %s) with a input-specific round type of %s"%(self.rndNum, roundType, t)) assert False if roundType!='U': if t=='T': stop[i]='T7%s'%curPrefix[i] prefixOut[i]=curPrefix[i] else: stop[i]=t prefixOut[i]=t self.rndNum=self.rndNum+1 self.finalRound=self.rndNum==len(self.rounds) db.pushStatus("%s%d"%(roundType,self.rndNum)) [r1,bc1]=self.oneround(q,r1,prefixOut=prefixOut,stop=stop,prefixIn=curPrefix,keepCleaved=(roundType!='U'),rtvol=self.rtvol[self.rndNum-1],t7vol=self.t7vol[self.rndNum-1],cycles=self.pcrcycles[self.rndNum-1],pcrdil=self.pcrdil[self.rndNum-1],pcrvol=self.pcrvol[self.rndNum-1],dolig=self.allLig or (roundType!='U'),pcrtgt=None if pcrprods is None else pcrprods[self.rndNum-1]) db.popStatus() # Add TRefs specified in rnddefs if 'tref' in self.rnddef[self.rndNum-1]: tref=self.rnddef[self.rndNum-1]['tref'] assert len(tref)==len(r1) for i in range(len(r1)): if tref[i] is not None: trefname='TRef%d'%tref[i] print("Adding %s to %s"%(trefname,r1[i].name)) if not reagents.isReagent(trefname): reagents.add(name=trefname,conc=10,extraVol=30,well="E4") trefSamp=reagents.getsample(trefname) oldConc=r1[i].conc.stock oldUnits=r1[i].conc.units oldVol=r1[i].volume self.e.transfer(r1[i].volume/(trefSamp.conc.dilutionneeded()-1),trefSamp,r1[i],mix=(False,False)) # TODO: Check that these end up mixed r1[i].conc=Concentration(stock=oldConc*oldVol/r1[i].volume, units=oldUnits) # Treat TRef as straight dilution print("New conc=",r1[i].conc) for i in range(len(r1)): if self.inputs[i]['round'] is None: r1[i].name="%s_%d"%(prefixOut[i],self.nextID) else: r1[i].name="%d_%s_R%d%c"%(self.nextID,prefixOut[i],self.inputs[i]['round']+self.rndNum,roundType) if self.inputs[i]['ligand'] is not None: r1[i].name="%s_%s"%(r1[i].name,self.inputs[i]['ligand']) print("Used ID ", self.nextID," for ", r1[i].name,": ",r1[i]) self.nextID+=1 r1[i].conc.final=r1[i].conc.stock*self.templateDilution for i in range(len(bc1)): #print("Renaming",bc1[i].name) pts=bc1[i].name.split(".") bc1[i].name="%d_BC_R%d%c"%(self.nextID,self.inputs[i//2]['round']+self.rndNum,roundType) if self.inputs[i//2]['ligand'] is not None: bc1[i].name="%s_%s"%(bc1[i].name,self.inputs[i//2]['ligand']) bc1[i].name+="_"+pts[-2] print("Used ID ", self.nextID," for ", bc1[i].name,":",bc1[i]) self.nextID+=1 curPrefix=prefixOut if "finalpcr" in self.qpcrStages: for i in range(len(r1)): if self.singlePrefix: q.addSamples(src=r1[i],needDil=r1[i].conc.stock/self.qConc,primers=["T7X","MX"] if self.useMX else ["T7X"]) else: # noinspection PyUnboundLocalVariable q.addSamples(src=r1[i],needDil=r1[i].conc.stock/self.qConc,primers=["T7X",prefixOut[i]+"X"]+(["MX"] if self.useMX else [])) # Add TRefs if needed for i in range(len(r1)): if 'tref' in self.inputs[i]: trefname='TRef%d'%self.inputs[i]['tref'] if not reagents.isReagent(trefname): reagents.add(name=trefname,conc=10,extraVol=30) tref=reagents.getsample(trefname) self.e.transfer(r1[i].volume/(tref.conc.dilutionneeded()-1),tref,r1[i],mix=(False,False)) db.pushStatus('qPCR') print("######### qPCR ########### %.0f min"%(clock.elapsed()/60)) self.allprimers=q.allprimers() q.run(confirm=self.qpcrWait) db.popStatus()
from Experiment.plate import Plate from Experiment.experiment import Experiment from Experiment.concentration import Concentration from Experiment import worklist, reagents, decklayout, clock, logging from Experiment import globals import os import sys import math import argparse maxVolumePerWell=150 # Ingredients based on volumes in spreadsheet to make 100ul (can be scaled arbitrarily) reagents.add("MT7",well="A1",conc=2.5,extraVol=30,ingredients={'glycerol':0.5*37.5,'SuperaseIn':0.5*12.5,'T7':0.5*25,'T7-ABE':62.5}) reagents.add("MPosRT",well="B1",conc=2,extraVol=30,ingredients={'Omniscript':0.5*10,'glycerol':0.5*10,'RT-ABE':90}) reagents.add("MExo",well="C1",conc=5,extraVol=30,ingredients={'ExoI':0.5*55,'ExoIII':0.5*7,'glycerol':0.5*(55+7),'NEBuffer1':10,'Water':28}) reagents.add("MTaq",well="D1",conc=3,ingredients={'Taq':0.5*1.5,'USER':0.5*1.5,'glycerol':0.5*3,'TAQ-ABE':95.5,'Water':1.5}) reagents.add("MLigase",well="E1",conc=3,extraVol=30,ingredients={'T4DNALigase':0.5*2.50,'glycerol':0.5*2.50,'T4-ABE':97.47}) reagents.add("MUser",well="B2",conc=5,extraVol=30,ingredients={'USER':0.5*2.5,'glycerol':0.5*2.5,'CutSmart':25,'Water':72.5}) #reagents.add("Ampure",well="C2",conc=None,hasBeads=True) #reagents.add("EtOH80",well="D2") reagents.add("SSD",well="A4",conc=10.0) #reagents.add("NaOH",well="B4",conc=1.0) #reagents.add("BeadBuffer",well="C4",conc=1) #reagents.add("Dynabeads",well="D4",conc=4,hasBeads=True) reagents.add("TheoX",well="C1",conc=4) reagents.add("TE8",well="E4",conc=None) reagents.add("EDTA",well="A4",conc=Concentration(20,2,'mM'),extraVol=30)
def oneround(self, q, inputs, prefixOut, stop, prefixIn, keepCleaved, t7vol, rtvol, pcrdil, cycles, pcrvol, dolig,pcrtgt=None): primerSet=[set(["REF","T7X",prefixIn[i]+"X",prefixOut[i]+"X"]+(["MX"] if self.useMX else [])) for i in range(len(prefixIn))] if self.extraQPCRPrimers is not None: primerSet=[set(list(p) + self.extraQPCRPrimers) for p in primerSet] print("primerSet=",primerSet) if keepCleaved: print("Starting new cleavage round, will add prefix: ",prefixOut) assert dolig else: print("Starting new uncleaved round, will retain prefix: ",prefixIn) print("stop=",stop,"prefixOut=",prefixOut,", prefixIn=",prefixIn,",t7vol=",round(t7vol,ndigits=2),",rtvol=",rtvol,",pcrdil=",pcrdil,",cycles=",cycles,",dolig=",dolig) if self.rtCarryForward: assert dolig names=[i.name for i in inputs] if self.rnaInput: rxs=inputs stopDil=1 else: print("######## T7 ########### %.0f min"%(clock.elapsed()/60)) db.pushStatus("T7") print("Inputs: (t7vol=%.2f)"%t7vol) for inp in inputs: if inp.conc.units=='nM': print(" %s: %.1ful@%.1f %s, use %.1f ul (%.3f pmoles)"%(inp.name,inp.volume,inp.conc.stock,inp.conc.units,t7vol/inp.conc.dilutionneeded(), t7vol*inp.conc.final/1000)) else: print(" %s: %.1ful@%.1f %s, use %.1f ul"%(inp.name,inp.volume,inp.conc.stock,inp.conc.units,t7vol/inp.conc.dilutionneeded())) # inp.conc.final=inp.conc.stock*self.templateDilution units=list(set([inp.conc.units for inp in inputs])) if len(units)>1: print("Inputs have inconsistent concentration units: ",units) assert False if units[0]=='nM': needDil = max([inp.conc.stock for inp in inputs]) * 1.0 / self.qConc else: needDil = 100 / self.qConc # Assume 100nM if self.directT7 and self.rndNum==1: # Just add ligands and MT7 to each well mconc=reagents.getsample("MT7").conc.dilutionneeded() for i in range(len(inputs)): watervol=t7vol*(1-1/mconc) - inputs[i].volume if watervol<-0.1: print("Negative amount of water (%.1f ul) needed for T7 setup"%watervol) assert False elif watervol>0.1: self.e.transfer(watervol, decklayout.WATER, inputs[i], mix=(False, False)) self.e.transfer(t7vol / mconc, reagents.getsample("MT7"), inputs[i], mix=(False, False)) assert(abs(inputs[i].volume - t7vol) < 0.1) # Add ligands last in case they crash out when they hit aqueous; this way, they'll be as dilute as possible if keepCleaved: for i in range(len(inputs)): if self.inputs[i]['negligand'] is not None: negligand=reagents.getsample(self.inputs[i]['negligand']) self.e.transfer(t7vol / negligand.conc.dilutionneeded(), negligand, inputs[i], mix=(False, False)) names[i]+="+" else: for i in range(len(inputs)): if self.inputs[i]['ligand'] is not None: ligand=reagents.getsample(self.inputs[i]['ligand']) self.e.transfer(t7vol / ligand.conc.dilutionneeded(), ligand, inputs[i], mix=(False, False)) names[i]+="+" rxs=inputs self.e.shakeSamples(inputs,returnPlate=True) elif self.rndNum==len(self.rounds) and self.finalPlus and keepCleaved: rxs = self.runT7Setup(ligands=[reagents.getsample(inp['ligand']) for inp in self.inputs],src=inputs, vol=t7vol, srcdil=[inp.conc.dilutionneeded() for inp in inputs]) for i in range(len(inputs)): inp=inputs[i] if self.inputs[i]['ligand'] is not None: rxs += self.runT7Setup(ligands=[reagents.getsample(self.inputs[i]['ligand'])],src=[inp],vol=t7vol,srcdil=[inp.conc.dilutionneeded()]) prefixIn+=[prefixIn[i]] prefixOut+=[prefixOut[i]] stop+=[stop[i]] primerSet+=[primerSet[i]] names+=["%s+"%names[i]] elif keepCleaved: rxs = self.runT7Setup(ligands=[reagents.getsample(inp['negligand']) for inp in self.inputs], src=inputs, vol=t7vol, srcdil=[inp.conc.dilutionneeded() for inp in inputs]) else: rxs = self.runT7Setup(ligands=[reagents.getsample(inp['ligand']) for inp in self.inputs], src=inputs, vol=t7vol, srcdil=[inp.conc.dilutionneeded() for inp in inputs]) if self.rndNum==1 and "template" in self.qpcrStages: # Initial input for i in range(len(rxs)): q.addSamples(src=rxs[i],needDil=needDil,primers=primerSet[i],names=["%s.T"%names[i]]) self.runT7Pgm(dur=self.t7dur,vol=t7vol) for i in range(len(rxs)): rxs[i].name="%s.t7"%names[i] self.e.lihahome() print("Estimate usable RNA concentration in T7 reaction at %.0f nM"%self.rnaConc) if self.rndNum==1: worklist.userprompt("T7 Incubation Started",120) self.e.waitpgm() # So elapsed time will be updated db.popStatus() if self.edtastop: print("######## Stop ########### %.0f min"%(clock.elapsed()/60)) db.pushStatus("Stop") print("Have %.1f ul before stop"%rxs[0].volume) preStopVolume=rxs[0].volume self.addEDTA(tgt=rxs,finalconc=2) # Stop to 2mM EDTA final db.popStatus("Stop") stopDil=rxs[0].volume/preStopVolume else: stopDil=1 if self.pauseAfterStop: worklist.userprompt("Post EDTA pause") if self.saveRNA: self.saveSamps(src=rxs,vol=self.saveRNAVolume,dil=self.saveRNADilution,plate=self.savePlate,dilutant=reagents.getsample("TE8"),mix=(False,False)) # Save to check [RNA] on Qubit, bioanalyzer needDil = self.rnaConc/self.qConc/stopDil if "stopped" in self.qpcrStages: for i in range(len(rxs)): q.addSamples(src=rxs[i:i+1],needDil=needDil,primers=primerSet[i],names=["%s.stopped"%names[i]]) print("######## RT Setup ########### %.0f min"%(clock.elapsed()/60)) db.pushStatus("RT") hiTemp=95 stop=["%s-Stop"%n for n in stop] rt=self.runRT(src=rxs,vol=rtvol,srcdil=self.rtDil,heatInactivate=self.rtHI,hiTemp=hiTemp,dur=self.rtdur,incTemp=50,stop=[reagents.getsample(s) for s in stop],stopConc=self.stopConc) # Heat inactivate also allows splint to fold rxs=rt for i in range(len(rxs)): if dolig and not self.singlePrefix: rxs[i].name=names[i]+"."+prefixOut[i]+".rt" else: rxs[i].name=names[i]+".rt" print("RT volume= [",",".join(["%.1f "%x.volume for x in rxs]),"]") needDil /=self.rtDil if self.rtpostdil[self.rndNum-1]>1: print("Dilution after RT: %.2f"%self.rtpostdil[self.rndNum-1]) self.diluteInPlace(tgt=rxs,dil=self.rtpostdil[self.rndNum-1]) needDil=needDil/self.rtpostdil[self.rndNum-1] # Discard extra volume of any sample that has more than current rt volume so that we can shake at high speed for r in Sample.getAllOnPlate(rxs[0].plate): if r not in rxs and r.volume>max(15+1.4,rxs[0].volume)+4: remove=r.volume-(15+1.4) oldvol=r.volume if r.lastMixed is None: r.lastMixed=clock.elapsed # Override since we don't care about mixing for disposal self.e.dispose(remove,r) print("Discarding some of %s to reduce volume from %.1f to %.1f to allow faster shaking"%(r.name,oldvol,r.volume)) print("RT volume= ",[x.volume for x in rxs]) self.e.shakeSamples(rxs) if self.rtSave: rtsv=self.saveSamps(src=rxs,vol=self.rtSaveVol,dil=self.rtSaveDil,plate=self.savePlate,dilutant=reagents.getsample("TE8"),mix=(False,False)) # Save to check RT product on gel (2x dil) if "rt" in self.qpcrStages: for i in range(len(rxs)): q.addSamples(src=rtsv[i:i+1],needDil=needDil/2,primers=self.rtprimers[self.rndNum-1] if hasattr(self,'rtprimers') else primerSet[i],names=["%s.rt"%names[i]]) else: if "rt" in self.qpcrStages: for i in range(len(rxs)): q.addSamples(src=rxs[i:i+1],needDil=needDil,primers=self.rtprimers[self.rndNum-1] if hasattr(self,'rtprimers') else primerSet[i],names=["%s.rt"%names[i]]) rtCarryForwardDil=10 rtCarryForwardVol=3.5 if self.rtCarryForward and not keepCleaved: # Also include RT from a prior round from here on for r in self.lastSaved: newsamp=Sample("%s.samp"%r.name,decklayout.SAMPLEPLATE) self.e.transfer(rxs[0].volume,r,newsamp,(False,False)) rxs.append(newsamp) db.popStatus() if dolig: print("######## Ligation setup ########### %.0f min"%(clock.elapsed()/60)) db.pushStatus("Ligation") extdil=5.0/4 reagents.getsample("MLigase").conc=Concentration(5) if self.ligInPlace: rxs=self.runLig(rxs,inPlace=True,srcdil=extdil,incTime=self.ligdur) else: rxs=self.runLig(rxs,inPlace=False,srcdil=extdil,vol=20,incTime=self.ligdur) print("Ligation volume= ",[x.volume for x in rxs]) needDil=needDil/extdil if self.extpostdil[self.rndNum-1]>1: print("Dilution after extension: %.2f"%self.extpostdil[self.rndNum-1]) self.diluteInPlace(tgt=rxs,dil=self.extpostdil[self.rndNum-1]) needDil=needDil/self.extpostdil[self.rndNum-1] pcrdil=pcrdil*1.0/self.extpostdil[self.rndNum-1] if self.saveDil is not None: ext=self.saveSamps(src=rxs,vol=3,dil=self.saveDil,dilutant=reagents.getsample("TE8"),tgt=[Sample("%s.ext"%n,self.savePlate) for n in names],mix=(False,True)) # Save cDNA product for subsequent NGS if "ext" in self.qpcrStages: for i in range(len(ext)): # Make sure we don't take more than 2 more steps maxdil=q.MAXDIL*q.MAXDIL if needDil/self.saveDil>maxdil: logging.notice( "Diluting ext by %.0fx instead of needed %.0f to save steps"%(maxdil,needDil/self.saveDil)) pset=primerSet[i] if "extraQPCR" in self.inputs[i]: pset.udpate(self.inputs[i]["extraQPCR"]) q.addSamples(src=[ext[i]],needDil=min(maxdil,needDil/self.saveDil),primers=pset,names=["%s.ext"%names[i]],save=False) else: if "ext" in self.qpcrStages: print("needDil=",needDil) for i in range(len(names)): pset=primerSet[i] if "extraQPCR" in self.inputs[i]: pset.update(self.inputs[i]["extraQPCR"]) q.addSamples(src=[rxs[i]],needDil=needDil,primers=pset,names=["%s.ext"%names[i]]) isave=i+len(names) if isave<len(rxs): # samples restored q.addSamples(src=[rxs[isave]],needDil=needDil/rtCarryForwardDil,primers=primerSet[isave]) db.popStatus() else: extdil=1 self.extpostdil[self.rndNum-1]=1 if self.rtpostdil[self.rndNum-1]>1: pcrdil=pcrdil*1.0/self.rtpostdil[self.rndNum-1] totalDil=stopDil*self.rtDil*self.rtpostdil[self.rndNum-1]*extdil*self.extpostdil[self.rndNum-1] fracRetained=rxs[0].volume/(t7vol*totalDil) print("Total dilution from T7 to Pre-pcr Product = %.2f*%.2f*%.2f*%.2f*%.2f = %.2f, fraction retained=%.0f%%"%(stopDil,self.rtDil,self.rtpostdil[self.rndNum-1],extdil,self.extpostdil[self.rndNum-1],totalDil,fracRetained*100)) if self.rtCarryForward and not keepCleaved: # Remove the extra samples assert(len(self.lastSaved)>0) rxs=rxs[:len(rxs)-len(self.lastSaved)] self.lastSaved=[] if len(rxs)>len(inputs): # Have extra samples due when self.finalPlus is True rxs= rxs[0:len(inputs)] # Only keep -target products prefixOut= prefixOut[0:len(inputs)] prefixIn= prefixIn[0:len(inputs)] stop= stop[0:len(inputs)] if self.dopcr and not (keepCleaved and self.noPCRCleave): print("######### PCR ############# %.0f min"%(clock.elapsed()/60)) db.pushStatus("PCR") print("PCR Volume: %.1f, Dilution: %.1f, volumes available for PCR: [%s]"%(pcrvol, pcrdil,",".join(["%.1f"%r.volume for r in rxs]))) initConc=needDil*self.qConc/pcrdil if keepCleaved: initConc=initConc*self.cleavage # Only use cleaved as input conc else: initConc=initConc*(1-self.cleavage) gain=pcrgain(initConc,400,cycles) finalConc=min(200,initConc*gain) print("Estimated starting concentration in PCR = %.1f nM, running %d cycles -> %.0f nM\n"%(needDil*self.qConc/pcrdil,cycles,finalConc)) nsplit=int(math.ceil(pcrvol*1.0/self.maxPCRVolume)) print("Split each PCR into %d reactions"%nsplit) sampNeeded=pcrvol/pcrdil if self.rtCarryForward and keepCleaved: sampNeeded+=rtCarryForwardVol if keepCleaved and self.rtCarryForward: print("Saving %.1f ul of each pre-PCR sample" % rtCarryForwardVol) self.lastSaved=[Sample("%s.sv"%x.name,self.savePlate) for x in rxs] for i in range(len(rxs)): # Save with rtCarryForwardDil dilution to reduce amount of RT consumed (will have Ct's 2-3 lower than others) self.e.transfer(rtCarryForwardVol,rxs[i],self.lastSaved[i],(False,False)) self.e.transfer(rtCarryForwardVol*(rtCarryForwardDil-1),decklayout.WATER,self.lastSaved[i],(False,True)) # Use pipette mixing -- shaker mixing will be too slow #print "NSplit=",nsplit,", PCR vol=",pcrvol/nsplit,", srcdil=",pcrdil,", input vol=",pcrvol/nsplit/pcrdil minvol=min([r.volume for r in rxs]) maxpcrvol=(minvol-15-1.4*nsplit)*pcrdil if maxpcrvol<pcrvol: print("Reducing PCR volume from %.1ful to %.1ful due to limited input"%(pcrvol, maxpcrvol)) pcrvol=maxpcrvol if keepCleaved: master="MTaqC" else: master="MTaqU" reagents.getsample(master) # Allocate for this before primers if self.barcoding: primers=self.bcprimers[self.rndNum-1] if primers is not None and nsplit>1: primers=primers*nsplit else: primers=None if primers is None: primers=[("T7%sX"%x).replace("T7T7","T7") for x in prefixOut]*nsplit rnddef = self.rnddef[self.rndNum-1] bcout=[] if 'barcode' in rnddef: # Add barcoding primers assert len(rnddef['barcode'])==len(rxs) dil=self.saveSamps(rxs,dil=50,vol=2,plate=decklayout.SAMPLEPLATE) for i in range(len(rxs)): dil[i].conc=Concentration(25,1) for bc in rnddef['barcode'][i]: tgt=Sample("%s.%s"%(rxs[i].name,bc),decklayout.SAMPLEPLATE) bparts=bc.split("/") for b in bparts: if not reagents.isReagent("P-%s"%b): reagents.add(name="P-%s"%b,conc=Concentration(2.67,0.4,'uM'),extraVol=30) print("PCR-%s"%bc) self.e.stage("PCR-%s"%bc,reagents=[reagents.getsample("MTaqBar"),reagents.getsample("P-%s"%bparts[0]),reagents.getsample("P-%s"%bparts[1])],samples=[tgt],sources=[dil[i] ],volume=50,destMix=False) bcout.append(tgt) print(tgt.name,"wellMixed=",tgt.wellMixed) print("Running PCR with master=",master,", primers=",primers) pcr=self.runPCR(src=rxs*nsplit,vol=pcrvol/nsplit,srcdil=pcrdil,ncycles=cycles,primers=primers,usertime=self.usertime if keepCleaved else None,fastCycling=False,inPlace=False,master=master,lowhi=self.lowhi,annealTemp=57) if keepCleaved and self.regenPCRCycles is not None: # Regenerate prefix pcr2=self.runPCR(src=pcr,vol=self.regenPCRVolume,srcdil=self.regenPCRDilution,ncycles=self.regenPCRCycles,primers=None,usertime=None,fastCycling=False,inPlace=False,master="MTaqR",lowhi=self.lowhi,annealTemp=55) # Add BT575p for 1 more cycle for p in pcr2: self.e.transfer(p.volume*0.5/10,reagents.getsample("Unclvd-Stop"),p,(False,False)) # One more cycle cycling=' TEMP@95,30 TEMP@55,30 TEMP@68,30 TEMP@25,2' thermocycler.setpgm('rfin',100,cycling) self.e.runpgm("rfin",5.0,False,max([p.volume for p in pcr2])) pcr=pcr2 # Use 2nd PCR as actual output if len(pcr)<=len(names): # Don't relabel if we've split for i in range(len(pcr)): pcr[i].name=names[i]+".pcr" #print "Volume remaining in PCR input source: [",",".join(["%.1f"%r.volume for r in rxs]),"]" needDil=finalConc/self.qConc print("Projected final concentration = %.0f nM"%(needDil*self.qConc)) for i in range(len(pcr)): pcr[i].conc=Concentration(stock=finalConc,final=None,units='nM') db.popStatus() if self.pcrSave: # Save samples at 1x (move all contents -- can ignore warnings) maxSaveVol=(100 if self.savedilplate else 1500)*1.0/nsplit if self.finalRound and nsplit==1 and self.savedilplate and pcrtgt is None: print("Skipping save of final PCR") sv=pcr else: residual=2.4 # Amount to leave behind to avoid aspirating air sv=self.saveSamps(src=pcr[:len(rxs)],vol=[min([maxSaveVol,x.volume-residual]) for x in pcr[:len(rxs)]],dil=1,plate=(self.savePlate if self.savedilplate else decklayout.EPPENDORFS),tgt=pcrtgt) if nsplit>1: # Combine split for i in range(len(rxs),len(rxs)*nsplit): self.e.transfer(min([maxSaveVol,pcr[i].volume-residual]),pcr[i],sv[i%len(sv)],mix=(False,False)) # Correct concentration (above would've assumed it was diluted) for i in range(len(sv)): sv[i].conc=pcr[i].conc # Shake self.e.shakeSamples(sv) if "pcr" in self.qpcrStages: for i in range(len(sv)): q.addSamples(sv[i],needDil,primers=primerSet[i],names=["%s.pcr"%names[i]]) print("Have %.2f pmoles of product (%.0f ul @ %.1f nM)"%(sv[0].volume*sv[0].conc.stock/1000,sv[0].volume,sv[0].conc.stock)) # Save barcoded products too if len(bcout)>0: print("bcout=",",".join(str(b) for b in bcout)) print("mixed=",bcout[0].isMixed(),", wellMixed=",bcout[0].wellMixed) bcsave=self.saveSamps(src=bcout,vol=[b.volume for b in bcout],dil=1,plate=self.savePlate,mix=(False,False)) if "bc" in self.qpcrStages: print("Doing qPCR of barcoding: ",bcsave) for i in range(len(bcsave)): needDil=640 q.addSamples(src=bcsave[i],needDil=needDil,primers=["T7X","WX","ZX"]+(["MX"] if self.useMX else []),save=False) else: bcsave=[] return sv, bcsave else: assert "pcr" not in self.qpcrStages ## Not implemented return pcr[:len(rxs)], bcout elif self.noPCRCleave: print("Dilution instead of PCR: %.2f"%self.nopcrdil) # Need to add enough t7prefix to compensate for all of the Stop primer currently present, regardless of whether it is for cleaved or uncleaved # Will result in some short transcripts corresponding to the stop primers that are not used for cleaved product, producing just GGG_W_GTCTGC in the next round. These would be reverse-trancribed, but may compete for T7 yield t7prefix=reagents.getsample("BT88") dil=self.extpostdil[self.rndNum-1] # FIXME: Is this correct? Used to have a 'userDil' term stopconc=1000.0/dil bt88conc=t7prefix.conc.stock relbt88=stopconc/bt88conc print("Using EXT with %.0fnM of stop oligo as input to next T7, need %.2ful of BT88@%.0fnM per ul of sample"%(stopconc,relbt88,bt88conc)) for r in rxs: vol=r.volume*relbt88 t7prefix.conc.final=t7prefix.conc.stock*vol/(r.volume+vol) r.conc.final=r.conc.stock*r.volume/(r.volume+vol) self.e.transfer(vol,t7prefix,r,mix=(False,False)) if self.nopcrdil>(1+relbt88): self.diluteInPlace(tgt=rxs,dil=self.nopcrdil/(1.0+relbt88)) #needDil=needDil/self.nopcrdil # needDil not used subsequently print("Dilution of EXT product: %.2fx * %.2fx = %2.fx\n"%(1+relbt88,self.nopcrdil/(1+relbt88),self.nopcrdil)) else: print("Dilution of EXT product: %.2fx\n"%(1+relbt88)) return rxs, [] else: return rxs, []
def runPCR(self,prefix,src,vol,srcdil,tgt=None,ncycles=20,suffix='S',sepPrimers=True,primerDil=4): ## PCR [prefix,src,tgt,vol,srcdil,suffix]=listify([prefix,src,tgt,vol,srcdil,suffix]) for i in range(len(tgt)): if tgt[i] is None: tgt[i]=Sample("%s.P%s%s"%(src[i].name,prefix[i],suffix[i]),src[i].plate) # Adjust source dilution for i in range(len(src)): src[i].conc=Concentration(srcdil[i],1) if sepPrimers: sampvols=[vol[i]/srcdil[i] for i in range(len(src))] mm=reagents.getsample("MPCR") mmvols=[vol[i]/mm.conc.dilutionneeded() for i in range(len(src))] for s in prefix + suffix: if not reagents.isReagent(s): reagents.add(name=s,conc=primerDil,extraVol=30) sprefix=[reagents.getsample(p) for p in prefix] ssuffix=[reagents.getsample(p) for p in suffix] prefixvols=[vol[i]/sprefix[i].conc.dilutionneeded() for i in range(len(src))] suffixvols=[vol[i]/ssuffix[i].conc.dilutionneeded() for i in range(len(src))] watervols=[vol[i]-mmvols[i]-prefixvols[i]-suffixvols[i]-sampvols[i] for i in range(len(src))] print "water=",watervols,", mm=",mmvols,", prefix=",prefixvols,", suffix=",suffixvols,", samp=",sampvols self.e.multitransfer(watervols,decklayout.WATER,tgt,(False,False)) # Transfer water self.e.multitransfer(mmvols,mm,tgt,(False,False)) # PCR master mix sprefixset=set(sprefix) ssuffixset=set(ssuffix) if len(sprefixset)<len(ssuffixset): # Distribute sprefix first for p in sprefixset: self.e.multitransfer([prefixvols[i] for i in range(len(src)) if sprefix[i]==p],p,[tgt[i] for i in range(len(src)) if sprefix[i]==p],(False,False)) # Then individually add ssuffix for i in range(len(src)): self.e.transfer(suffixvols[i],ssuffix[i],tgt[i],(False,False)) else: # Distribute ssuffix first for p in ssuffixset: self.e.multitransfer([suffixvols[i] for i in range(len(src)) if ssuffix[i]==p],p,[tgt[i] for i in range(len(src)) if ssuffix[i]==p],(False,False)) # Then individually add sprefix for i in range(len(src)): self.e.transfer(prefixvols[i],sprefix[i],tgt[i],(False,False)) # Now add templates for i in range(len(src)): self.e.transfer(sampvols[i],src[i],tgt[i],(False,False)) else: primer=[prefix[i]+suffix[i] for i in range(len(prefix))] print "primer=",primer for up in set(primer): s="MPCR%s"%up if not reagents.isReagent(s): reagents.add(name=s,conc=4/3.0,extraVol=30) self.e.stage('PCR%s'%up,[reagents.getsample("MPCR%s"%up)],[src[i] for i in range(len(src)) if primer[i]==up],[tgt[i] for i in range(len(tgt)) if primer[i]==up],[vol[i] for i in range(len(vol)) if primer[i]==up],destMix=False) pgm="PCR%d"%ncycles self.e.shakeSamples(tgt,returnPlate=False) # worklist.pyrun('PTC\\ptcsetpgm.py %s TEMP@95,120 TEMP@95,30 TEMP@55,30 TEMP@72,25 GOTO@2,%d TEMP@72,180 TEMP@16,2'%(pgm,ncycles-1)) worklist.pyrun('PTC\\ptcsetpgm.py %s TEMP@95,120 TEMP@95,10 TEMP@57,10 GOTO@2,%d TEMP@72,120 TEMP@25,2'%(pgm,ncycles-1)) self.e.runpgm(pgm,4.80+1.55*ncycles,False,max(vol),hotlidmode="CONSTANT",hotlidtemp=100) return tgt
from Experiment.sample import Sample from Experiment.experiment import Experiment from Experiment.concentration import Concentration from Experiment import worklist, reagents, decklayout, clock from Experiment import globals import os import sys import math import argparse maxVolumePerWell = 150 reagents.add("MT7", well="A1", conc=2.5, extraVol=30) reagents.add("MPosRT", well="B1", conc=2, extraVol=30) reagents.add("MKlenow", well="C1", conc=2, extraVol=30) reagents.add("MUser", well="D1", conc=2, extraVol=30) reagents.add("MLigBT7W", well="E1", conc=3) reagents.add("MLigase", well="A2", conc=3) reagents.add("MStopXBio", well="B2", conc=2) reagents.add("MStopXSelfExtendW", well="B2", conc=5) reagents.add("MStpX", well="C2", conc=2) reagents.add("MStopXSelfExtendB", well="C2", conc=5) reagents.add("MQREF", well="D2", conc=10.0 / 6) reagents.add("MQAX", well="E2", conc=10.0 / 6) reagents.add("MQBX", well="A3", conc=10.0 / 6) reagents.add("MPCRAX", well="B3", conc=4.0 / 3) reagents.add("MPCRBX", well="C3", conc=4.0 / 3) reagents.add("MQMX", well="D3", conc=10.0 / 6) reagents.add("MQWX", well="E3", conc=10.0 / 6) reagents.add("SSD", well="A4", conc=10.0)