def pgm(self): q = QSetup(self, maxdil=16, debug=False, mindilvol=60) self.e.addIdleProgram(q.idler) input = [s.getsample() for s in self.srcs] # Save RT product from first (uncleaved) round and then use it during 2nd (cleaved) round for ligation and qPCR measurements prefixIn = [inp['prefix'] for inp in self.inputs] prefixOut = [ "A" if p == "W" else "B" if p == "A" else "W" if p == "B" else "BADPREFIX" for p in prefixIn ] qpcrPrimers = ["REF", "MX", "T7X"] if "W" in prefixIn + prefixOut: qpcrPrimers += ["T7WX"] if "A" in prefixIn + prefixOut: qpcrPrimers += ["T7AX"] if "B" in prefixIn + prefixOut: qpcrPrimers += ["T7BX"] q.addSamples(decklayout.SSDDIL, 1, qpcrPrimers, save=False) # Negative controls print "Starting new cleavage round, will add prefix: ", prefixOut names = [i.name for i in input] print "######## T7 ###########" print "Inputs: (t7vol=%.2f)" % self.t7vol for inp in input: print " %s: %.1ful@%.1f nM, use %.1f ul (%.3f pmoles)" % ( inp.name, inp.volume, inp.conc.stock, self.t7vol / inp.conc.dilutionneeded(), self.t7vol * inp.conc.final / 1000) print "input[0]=", input[0] needDil = max([inp.conc.final for inp in input]) * 1.0 / self.qConc if self.directT7: # Just add MT7 and possibly water to each well mconc = reagents.getsample("MT7").conc.dilutionneeded() for i in range(len(input)): watervol = self.t7vol * (1 - 1 / mconc) - input[i].volume if watervol > 0.1: self.e.transfer(watervol, decklayout.WATER, input[i], mix=(False, False)) self.e.transfer(self.t7vol / mconc, reagents.getsample("MT7"), input[i], mix=(False, False)) assert (input[i].volume == self.t7vol) rxs = input else: rxs = self.runT7Setup( src=input, vol=self.t7vol, srcdil=[inp.conc.dilutionneeded() for inp in input]) print "input[0]=", input[0] #for i in range(len(rxs)): # q.addSamples(src=rxs],needDil=needDil,primers=["T7"+prefixIn[i]+"X","MX","T7X","REF"],names=["%s.T-"%names[i]]) self.runT7Pgm(dur=self.t7dur, vol=self.t7vol) print "Template conc=%.1f nM, estimated RNA concentration in T7 reaction at %.0f nM" % ( self.tmplFinalConc, self.rnaConc) print "######## Stop ###########" self.e.lihahome() print "Have %.1f ul before stop" % rxs[0].volume preStopVolume = rxs[0].volume self.addEDTA(tgt=rxs, finalconc=2) # Stop to 2mM EDTA final stopDil = rxs[0].volume / preStopVolume if self.saveRNA: self.saveSamps( src=rxs, vol=5, dil=2, plate=decklayout.DILPLATE, dilutant=reagents.getsample("TE8"), mix=(False, False)) # Save to check [RNA] on Qubit, bioanalyzer stop = [ "A-Stop" if n == "A" else "B-Stop" if n == "B" else "W-Stop" if n == "W" else "BADPREFIX" for n in prefixOut ] for i in range(len(rxs)): rxs[i].name = rxs[i].name + "." + stop[i] needDil = self.rnaConc / self.qConc / stopDil #q.addSamples(src=rxs,needDil=needDil,primers=["T7AX","MX","T7X","REF"],names=["%s.stopped"%r.name for r in rxs]) print "######## RT Setup ###########" rtDil = 4 hiTemp = 95 rtDur = 20 rxin = rxs rxs = self.runRT(src=rxs, vol=self.rtvol, srcdil=rtDil, heatInactivate=True, hiTemp=hiTemp, dur=rtDur, incTemp=50, stop=[reagents.getsample(s) for s in stop ]) # Heat inactivate also allows splint to fold print "RT volume= ", [x.volume for x in rxs] for r in rxin: if r.volume > 20: print "Have more T7 reaction remaining than needed: %s has %.1f ul" % ( r.name, r.volume) needDil /= rtDil rtPostDil = 5 if rtPostDil != 1: self.diluteInPlace(tgt=rxs, dil=rtPostDil) needDil /= rtPostDil #q.addSamples(src=rxs,needDil=needDil,primers=["T7AX","MX","REF"],names=["%s.rt"%r.name for r in rxs]) print "######## Ligation setup ###########" extdil = 5.0 / 4 reagents.getsample("MLigase").conc = Concentration(5) extvol = 20 print "Extension volume=", extvol rxs = self.runLig(rxs, vol=extvol) print "Ligation volume= ", [x.volume for x in rxs] needDil = needDil / extdil extpostdil = 4 if extpostdil > 1: print "Dilution after extension: %.2f" % extpostdil self.diluteInPlace(tgt=rxs, dil=extpostdil) needDil = needDil / extpostdil if not self.doexo: self.pcrdil = self.pcrdil / extpostdil 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, decklayout.DILPLATE) for n in names], mix=(False, True)) # Save cDNA product for subsequent NGS for i in range(len(rxs)): q.addSamples(src=[ext[i]], needDil=needDil / self.saveDil, primers=[ "T7" + prefixIn[i] + "X", "T7" + prefixOut[i] + "X", "MX", "T7X", "REF" ], names=["%s.ext" % names[i]]) else: for i in range(len(rxs)): q.addSamples(src=[rxs[i]], needDil=needDil, primers=[ "T7" + prefixIn[i] + "X", "T7" + prefixOut[i] + "X", "MX", "T7X", "REF" ], names=["%s.ext" % names[i]]) if self.doexo: print "######## Exo ###########" prevvol = rxs[0].volume rxs = self.runExo(rxs, incTime=30, inPlace=True) exoDil = rxs[0].volume / prevvol needDil /= exoDil needDil /= 7 # Anecdotal based on Ct's -- large components (MX) reduced by exo digestion q.addSamples(src=rxs, needDil=needDil, primers=["T7AX", "T7BX", "MX", "T7X", "REF"], names=["%s.exo" % names[i] for i in range(len(rxs))]) #exo=self.saveSamps(src=rxs,vol=10*exoDil,dil=2/exoDil,dilutant=reagents.getsample("TE8"),tgt=[Sample("%s.exo"%n,decklayout.SAMPLEPLATE) for n in names]) # Save cDNA product else: exoDil = 1 exo = [] if self.doampure: print "######## Ampure Cleanup ###########" ratio = 1.5 elutionVol = 30 cleanIn = ext + exo + user needDil = needDil * cleanIn[0].volume / elutionVol clean = self.runAmpure(src=cleanIn, ratio=ratio, elutionVol=elutionVol) q.addSamples(src=[clean[i] for i in range(len(rxs))], needDil=needDil, primers=["T7AX", "MX", "T7X", "REF"]) rxs = rxs + clean # Use the cleaned products for PCR totalDil = stopDil * rtDil * rtPostDil * extdil * extpostdil * exoDil fracRetained = rxs[0].volume / (self.t7vol * totalDil) print "Total dilution from T7 to Pre-pcr Product = %.2f*%.2f*%.2f*%.2f*%.2f*%.2f = %.2f, fraction retained=%.0f%%" % ( stopDil, rtDil, rtPostDil, extdil, extpostdil, exoDil, totalDil, fracRetained * 100) if self.dopcr: print "######### PCR #############" print "PCR Volume: %.1f, Dilution: %.1f, volumes available for PCR: [%s]" % ( self.pcrvol, self.pcrdil, ",".join( ["%.1f" % r.volume for r in rxs])) maxSampleVolume = 100 # Maximum sample volume of each PCR reaction (thermocycler limit, and mixing limit) initConc = needDil * self.qConc / self.pcrdil if self.doexo: initConc = initConc * 7 * self.cleavage # Back out 7x dilution in exo step, but only use cleaved as input conc else: initConc = initConc * self.cleavage # Only use cleaved as input conc gain = pcrgain(initConc, 400, self.pcrcycles) finalConc = initConc * gain print "Estimated starting concentration in PCR = %.1f nM, running %d cycles -> %.0f nM\n" % ( needDil * self.qConc, self.pcrcycles, finalConc) pcr = self.runPCR(src=rxs, vol=self.pcrvol, srcdil=self.pcrdil, ncycles=self.pcrcycles, primers=["T7%sX" % x for x in prefixOut], usertime=self.usertime, fastCycling=True) needDil = finalConc / self.qConc pcrpostdil = 2 if pcrpostdil > 1: self.diluteInPlace(pcr, pcrpostdil) needDil = needDil / pcrpostdil print "Projected final concentration = %.0f nM (after %.1fx dilution)" % ( needDil * self.qConc, pcrpostdil) for i in range(len(pcr)): pcr[i].conc = Concentration(stock=finalConc / pcrpostdil, final=None, units='nM') if self.pcrSave: # Save samples at 1x if self.savedilplate: sv = self.saveSamps( src=pcr[:len(rxs)], vol=[x.volume - 16.4 for x in pcr[:len(rxs)]], dil=1, plate=decklayout.DILPLATE) else: sv = self.saveSamps( src=pcr[:len(rxs)], vol=[x.volume - 16.4 for x in pcr[:len(rxs)]], dil=1, plate=decklayout.EPPENDORFS) # for i in range(len(pcr)): # q.addSamples(pcr,needDil,["T7%sX"%prefixOut[i]]) processEff = 0.5 # Estimate of overall efficiency of process print "Saved %.2f pmoles of product (%.0f ul @ %.1f nM)" % ( sv[0].volume * sv[0].conc.stock / 1000, sv[0].volume, sv[0].conc.stock) print "######### qPCR ###########" #q.addReferences(mindil=4,nsteps=6,primers=["T7X","MX","T7AX"]) q.run(confirm=False)
def pgm(self): q = QSetup(self,maxdil=16,debug=False,mindilvol=60) self.e.addIdleProgram(q.idler) input = [s.getsample() for s in self.srcs] qpcrPrimers=["REF","MX","T7X","T7AX","T7BX","T7WX"] q.addSamples(decklayout.SSDDIL,1,qpcrPrimers,save=False) # Negative controls # Save RT product from first (uncleaved) round and then use it during 2nd (cleaved) round for ligation and qPCR measurements prefixIn=[inp['prefix'] for inp in self.inputs] prefixOut=["A" if p=="W" else "B" if p=="A" else "W" if p=="B" else "BADPREFIX" for p in prefixIn] print "Starting new cleavage round, will add prefix: ",prefixOut names=[i.name for i in input] print "######## T7 ###########" print "Inputs: (t7vol=%.2f)"%self.t7vol for inp in input: print " %s: %.1ful@%.1f nM, use %.1f ul (%.3f pmoles)"%(inp.name,inp.volume,inp.conc.stock,self.t7vol/inp.conc.dilutionneeded(), self.t7vol*inp.conc.final/1000) print "input[0]=",input[0] needDil = max([inp.conc.final for inp in input])*1.0/self.qConc if self.directT7: # Just add MT7 and possibly water to each well mconc=reagents.getsample("MT7").conc.dilutionneeded() for i in range(len(input)): watervol=self.t7vol*(1-1/mconc)-input[i].volume if watervol>0.1: self.e.transfer(watervol,decklayout.WATER,input[i],mix=(False,False)) self.e.transfer(self.t7vol/mconc,reagents.getsample("MT7"),input[i],mix=(False,False)) assert(input[i].volume==self.t7vol) rxs=input else: rxs = self.runT7Setup(src=input,vol=self.t7vol,srcdil=[inp.conc.dilutionneeded() for inp in input]) print "input[0]=",input[0] #for i in range(len(rxs)): # q.addSamples(src=rxs],needDil=needDil,primers=["T7"+prefixIn[i]+"X","MX","T7X","REF"],names=["%s.T-"%names[i]]) self.runT7Pgm(dur=self.t7dur,vol=self.t7vol) print "Template conc=%.1f nM, estimated RNA concentration in T7 reaction at %.0f nM"%(self.tmplFinalConc,self.rnaConc) print "######## Stop ###########" #self.saveSamps(src=rxs,vol=5,dil=10,plate=decklayout.EPPENDORFS,dilutant=reagents.getsample("TE8"),mix=(False,False)) # Save to check [RNA] on Qubit, bioanalyzer self.e.lihahome() print "Have %.1f ul before stop"%rxs[0].volume preStopVolume=rxs[0].volume self.addEDTA(tgt=rxs,finalconc=2) # Stop to 2mM EDTA final stop=[ "A-Stop" if n=="A" else "B-Stop" if n=="B" else "W-Stop" if n=="W" else "BADPREFIX" for n in prefixOut] for i in range(len(rxs)): rxs[i].name=rxs[i].name+"."+stop[i] stopDil=rxs[0].volume/preStopVolume needDil = self.rnaConc/self.qConc/stopDil #q.addSamples(src=rxs,needDil=needDil,primers=["T7AX","MX","T7X","REF"],names=["%s.stopped"%r.name for r in rxs]) print "######## RT Setup ###########" rtDil=4 hiTemp=95 rtDur=20 rxin=rxs rxs=self.runRT(src=rxs,vol=self.rtvol,srcdil=rtDil,heatInactivate=True,hiTemp=hiTemp,dur=rtDur,incTemp=50,stop=[reagents.getsample(s) for s in stop]) # Heat inactivate also allows splint to fold print "RT volume= ",[x.volume for x in rxs] for r in rxin: if r.volume>20: print "Have more T7 reaction remaining than needed: %s has %.1f ul"%(r.name,r.volume) needDil /= rtDil rtPostDil=5 if rtPostDil!=1: self.diluteInPlace(tgt=rxs,dil=rtPostDil) needDil /= rtPostDil #q.addSamples(src=rxs,needDil=needDil,primers=["T7AX","MX","REF"],names=["%s.rt"%r.name for r in rxs]) print "######## Ligation setup ###########" extdil=5.0/4 reagents.getsample("MLigase").conc=Concentration(5) extvol=20; print "Extension volume=",extvol rxs=self.runLig(rxs,vol=extvol) print "Ligation volume= ",[x.volume for x in rxs] needDil=needDil/extdil extpostdil=4 if extpostdil>1: print "Dilution after extension: %.2f"%extpostdil self.diluteInPlace(tgt=rxs,dil=extpostdil) needDil=needDil/extpostdil if not self.doexo: self.pcrdil=self.pcrdil/extpostdil 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,decklayout.DILPLATE) for n in names],mix=(False,True)) # Save cDNA product for subsequent NGS for i in range(len(rxs)): q.addSamples(src=[ext[i]],needDil=needDil/self.saveDil,primers=["T7"+prefixIn[i]+"X","T7"+prefixOut[i]+"X","MX","T7X","REF"],names=["%s.ext"%names[i]]) else: for i in range(len(rxs)): q.addSamples(src=[rxs[i]],needDil=needDil,primers=["T7"+prefixIn[i]+"X","T7"+prefixOut[i]+"X","MX","T7X","REF"],names=["%s.ext"%names[i]]) if self.doexo: print "######## Exo ###########" prevvol=rxs[0].volume rxs=self.runExo(rxs,incTime=30,inPlace=True) exoDil=rxs[0].volume/prevvol needDil/=exoDil needDil/=7 # Anecdotal based on Ct's -- large components (MX) reduced by exo digestion q.addSamples(src=rxs,needDil=needDil,primers=["T7AX","T7BX","MX","T7X","REF"],names=["%s.exo"%names[i] for i in range(len(rxs))]) #exo=self.saveSamps(src=rxs,vol=10*exoDil,dil=2/exoDil,dilutant=reagents.getsample("TE8"),tgt=[Sample("%s.exo"%n,decklayout.SAMPLEPLATE) for n in names]) # Save cDNA product else: exoDil=1 exo=[] if self.doampure: print "######## Ampure Cleanup ###########" ratio=1.5 elutionVol=30 cleanIn=ext+exo+user needDil=needDil*cleanIn[0].volume/elutionVol clean=self.runAmpure(src=cleanIn,ratio=ratio,elutionVol=elutionVol) q.addSamples(src=[clean[i] for i in range(len(rxs))],needDil=needDil,primers=["T7AX","MX","T7X","REF"]) rxs=rxs+clean # Use the cleaned products for PCR totalDil=stopDil*rtDil*rtPostDil*extdil*extpostdil*exoDil fracRetained=rxs[0].volume/(self.t7vol*totalDil) print "Total dilution from T7 to Pre-pcr Product = %.2f*%.2f*%.2f*%.2f*%.2f*%.2f = %.2f, fraction retained=%.0f%%"%(stopDil,rtDil,rtPostDil,extdil,extpostdil,exoDil,totalDil,fracRetained*100) if self.dopcr: print "######### PCR #############" print "PCR Volume: %.1f, Dilution: %.1f, volumes available for PCR: [%s]"%(self.pcrvol, self.pcrdil,",".join(["%.1f"%r.volume for r in rxs])) maxSampleVolume=100 # Maximum sample volume of each PCR reaction (thermocycler limit, and mixing limit) initConc=needDil*self.qConc/self.pcrdil if self.doexo: initConc=initConc*7*self.cleavage # Back out 7x dilution in exo step, but only use cleaved as input conc else: initConc=initConc*self.cleavage # Only use cleaved as input conc gain=pcrgain(initConc,400,self.pcrcycles) finalConc=initConc*gain print "Estimated starting concentration in PCR = %.1f nM, running %d cycles -> %.0f nM\n"%(needDil*self.qConc,self.pcrcycles,finalConc) pcr=self.runPCR(src=rxs,vol=self.pcrvol,srcdil=self.pcrdil,ncycles=self.pcrcycles,primers=["T7%sX"%x for x in prefixOut],usertime=self.usertime,fastCycling=True) needDil=finalConc/self.qConc pcrpostdil=2 if pcrpostdil>1: self.diluteInPlace(pcr,pcrpostdil) needDil=needDil/pcrpostdil print "Projected final concentration = %.0f nM (after %.1fx dilution)"%(needDil*self.qConc,pcrpostdil) for i in range(len(pcr)): pcr[i].conc=Concentration(stock=finalConc/pcrpostdil,final=None,units='nM') if self.pcrSave: # Save samples at 1x if self.savedilplate: sv=self.saveSamps(src=pcr[:len(rxs)],vol=[x.volume-16.4 for x in pcr[:len(rxs)]],dil=1,plate=decklayout.DILPLATE) else: sv=self.saveSamps(src=pcr[:len(rxs)],vol=[x.volume-16.4 for x in pcr[:len(rxs)]],dil=1,plate=decklayout.EPPENDORFS) # for i in range(len(pcr)): # q.addSamples(pcr,needDil,["T7%sX"%prefixOut[i]]) processEff=0.5 # Estimate of overall efficiency of process print "Saved %.2f pmoles of product (%.0f ul @ %.1f nM)"%(sv[0].volume*sv[0].conc.stock/1000,sv[0].volume,sv[0].conc.stock) print "######### qPCR ###########" #q.addReferences(mindil=4,nsteps=6,primers=["T7X","MX","T7AX"]) #worklist.userprompt('Continue to setup qPCR') q.run()
def oneround(self, q, input, prefixOut, stop, prefixIn, keepCleaved, t7vol, rtvol, pcrdil, cycles, pcrvol, dolig): primerSet = [ set(["MX", "REF", "T7X", prefixIn[i] + "X", prefixOut[i] + "X"]) for i in range(len(prefixIn)) ] 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=", t7vol, ",rtvol=", rtvol, ",pcrdil=", pcrdil, ",cycles=", cycles, ",dolig=", dolig if self.rtCarryForward: assert (dolig) names = [i.name for i in input] if self.rnaInput: rxs = input stopDil = 1 else: print "######## T7 ########### %.0f min" % (clock.elapsed() / 60) print "Inputs: (t7vol=%.2f)" % t7vol inconc = [inp.conc.final for inp in input] for inp in input: 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) needDil = max([inp.conc.stock for inp in input]) * 1.0 / self.qConc else: print " %s: %.1ful@%.1f %s, use %.1f ul" % ( inp.name, inp.volume, inp.conc.stock, inp.conc.units, t7vol / inp.conc.dilutionneeded()) needDil = 100 / self.qConc # Assume 100nM # inp.conc.final=inp.conc.stock*self.templateDilution if self.directT7 and self.rndNum == 1: # Just add ligands and MT7 to each well if not keepCleaved: for i in range(len(input)): if self.inputs[i]['ligand'] is not None: ligand = reagents.getsample( self.inputs[i]['ligand']) self.e.transfer(t7vol / ligand.conc.dilutionneeded(), ligand, input[i], mix=(False, False)) names[i] += "+" mconc = reagents.getsample("MT7").conc.dilutionneeded() for i in range(len(input)): watervol = t7vol * (1 - 1 / mconc) - input[i].volume if watervol > 0.1: self.e.transfer(watervol, decklayout.WATER, input[i], mix=(False, False)) self.e.transfer(t7vol / mconc, reagents.getsample("MT7"), input[i], mix=(False, False)) assert (abs(input[i].volume - t7vol) < 0.1) rxs = input elif self.rndNum == len( self.rounds) and self.finalPlus and keepCleaved: rxs = self.runT7Setup( src=input, vol=t7vol, srcdil=[inp.conc.dilutionneeded() for inp in input]) for i in range(len(input)): inp = input[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( src=input, vol=t7vol, srcdil=[inp.conc.dilutionneeded() for inp in input]) else: rxs = self.runT7Setup( ligands=[ reagents.getsample(inp['ligand']) for inp in self.inputs ], src=input, vol=t7vol, srcdil=[inp.conc.dilutionneeded() for inp in input]) 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]]) needDil = needDil * max( [inp.conc.dilutionneeded() for inp in input]) self.runT7Pgm(dur=self.t7dur, vol=t7vol) for i in range(len(rxs)): rxs[i].name = "%s.t7" % names[i] print "Estimate usable RNA concentration in T7 reaction at %.0f nM" % self.rnaConc print "######## Stop ########### %.0f min" % (clock.elapsed() / 60) self.e.lihahome() print "Have %.1f ul before stop" % rxs[0].volume preStopVolume = rxs[0].volume self.addEDTA(tgt=rxs, finalconc=2) # Stop to 2mM EDTA final stopDil = rxs[0].volume / preStopVolume if self.saveRNA: self.saveSamps( src=rxs, vol=5, dil=self.saveRNADilution, plate=decklayout.DILPLATE, 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) 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] if self.rtSave: rtsv = self.saveSamps( src=rxs, vol=self.rtSaveVol, dil=self.rtSaveDil, plate=decklayout.DILPLATE, 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) if dolig: print "######## Ligation setup ########### %.0f min" % ( clock.elapsed() / 60) 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, decklayout.DILPLATE) 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)) q.addSamples(src=[ext[i]], needDil=min(maxdil, needDil / self.saveDil), primers=primerSet[i], names=["%s.ext" % names[i]], save=False) else: if "ext" in self.qpcrStages: print "needDil=", needDil for i in range(len(names)): q.addSamples(src=[rxs[i]], needDil=needDil, primers=primerSet[i], 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]) 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(input): # Have extra samples due when self.finalPlus is True rxs = rxs[0:len(input)] # Only keep -target products prefixOut = prefixOut[0:len(input)] prefixIn = prefixIn[0:len(input)] stop = stop[0:len(input)] if self.dopcr and not (keepCleaved and self.noPCRCleave): print "######### PCR ############# %.0f min" % (clock.elapsed() / 60) maxvol = max([r.volume for r in rxs]) 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 minsrcdil = 1 / (1 - 1.0 / 3 - 1.0 / 4) sampNeeded = pcrvol / pcrdil if self.rtCarryForward and keepCleaved: sampNeeded += rtCarryForwardVol maxvol = max([r.volume for r in rxs]) minvol = min([r.volume for r in rxs]) if keepCleaved and self.rtCarryForward: assert (len(rxs) == len(rtCarryForward)) print "Saving %.1f ul of each pre-PCR sample" % ( rtCarryForwardVol) self.lastSaved = [ Sample("%s.sv" % x.name, decklayout.DILPLATE) 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" 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 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' worklist.pyrun('PTC\\ptcsetpgm.py rfin %s' % (cycling)) self.e.runpgm("rfin", 5.0, False, max([p.volume for p in pcr2]), hotlidmode="CONSTANT", hotlidtemp=100) 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') 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: print "Skipping save of final PCR" sv = pcr else: sv = self.saveSamps( src=pcr[:len(rxs)], vol=[ min([maxSaveVol, x.volume]) for x in pcr[:len(rxs)] ], dil=1, plate=(decklayout.DILPLATE if self.savedilplate else decklayout.EPPENDORFS), atEnd=self.savePCRAtEnd) if nsplit > 1: # Combine split for i in range(len(rxs), len(rxs) * nsplit): self.e.transfer(min([maxSaveVol, pcr[i].volume]), pcr[i], sv[i % len(sv)], mix=(False, i >= len(rxs) * (nsplit - 1))) # Correct concentration (above would've assumed it was diluted) for i in range(len(sv)): sv[i].conc = pcr[i].conc if "pcr" in self.qpcrStages: for i in range(len(sv)): q.addSamples(sv[i], needDil, primers=primerSet[i], names=["%s.pcr" % names[i]]) processEff = 0.5 # Estimate of overall efficiency of process 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) return sv else: assert "pcr" not in self.qpcrStages ## Not implemented return pcr[:len(rxs)] 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] * userDil 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 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 oneround(self,q,input,prefixOut,prefixIn,keepCleaved,t7vol,rtvol,pcrdil,cycles,pcrvol,dolig): if keepCleaved: print "Starting new cleavage round, will add prefix: ",prefixOut assert(dolig) else: print "Starting new uncleaved round, will retain prefix: ",prefixIn if self.rtSave: assert(dolig) names=[i.name for i in input] print "######## T7 ###########" print "Inputs: (t7vol=%.2f)"%t7vol inconc=[inp.conc.final for inp in input] for inp in input: print " %s: %.1ful@%.1f nM, use %.1f ul (%.3f pmoles)"%(inp.name,inp.volume,inp.conc.stock,t7vol/inp.conc.dilutionneeded(), t7vol*inp.conc.final/1000) # inp.conc.final=inp.conc.stock*self.templateDilution needDil = max([inp.conc.stock for inp in input])*1.0/self.qConc if self.directT7 and self.rndNum==1: # Just add ligands and MT7 to each well for i in range(len(input)): ligand=reagents.getsample(self.inputs[i]['ligand']) self.e.transfer(t7vol/ligand.conc.dilutionneeded(),ligand,input[i],mix=(False,False)) mconc=reagents.getsample("MT7").conc.dilutionneeded() for i in range(len(input)): watervol=t7vol*(1-1/mconc)-input[i].volume if watervol>0.1: self.e.transfer(watervol,decklayout.WATER,input[i],mix=(False,False)) self.e.transfer(t7vol/mconc,reagents.getsample("MT7"),input[i],mix=(False,False)) assert(abs(input[i].volume-t7vol)<0.1) rxs=input elif self.rndNum==self.nrounds and self.finalPlus: rxs = self.runT7Setup(src=input,vol=t7vol,srcdil=[inp.conc.dilutionneeded() for inp in input]) rxs += self.runT7Setup(ligands=[reagents.getsample(inp['ligand']) for inp in self.inputs],src=input,vol=t7vol,srcdil=[inp.conc.dilutionneeded() for inp in input]) prefixIn+=prefixIn prefixOut+=prefixOut names+=["%s+"%n for n in names] elif keepCleaved: rxs = self.runT7Setup(src=input,vol=t7vol,srcdil=[inp.conc.dilutionneeded() for inp in input]) else: rxs = self.runT7Setup(ligands=[reagents.getsample(inp['ligand']) for inp in self.inputs],src=input,vol=t7vol,srcdil=[inp.conc.dilutionneeded() for inp in input]) for i in range(len(rxs)): rxs[i].name="%s.rx"%names[i] 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=["T7X","REF","T7"+prefixIn[i]+"X"],names=["%s.T-"%names[i]]) needDil = needDil*max([inp.conc.dilutionneeded() for inp in input]) t7dur=30 self.runT7Pgm(dur=t7dur,vol=t7vol) print "Estimate RNA concentration in T7 reaction at %.0f nM"%self.rnaConc self.rnaConc=min(40,inconc)*t7dur*65/30 print "######## Stop ###########" #self.saveSamps(src=rxs,vol=5,dil=10,plate=decklayout.EPPENDORFS,dilutant=reagents.getsample("TE8"),mix=(False,False)) # Save to check [RNA] on Qubit, bioanalyzer self.e.lihahome() print "Have %.1f ul before stop"%rxs[0].volume preStopVolume=rxs[0].volume self.addEDTA(tgt=rxs,finalconc=2) # Stop to 2mM EDTA final stop=["Unclvd-Stop" if (not dolig) else "A-Stop" if n=="A" else "B-Stop" if n=="B" else "W-Stop" if n=="W" else "BADPREFIX" for n in prefixOut] stopDil=rxs[0].volume/preStopVolume needDil = self.rnaConc/self.qConc/stopDil if "stopped" in self.qpcrStages: q.addSamples(src=rxs,needDil=needDil,primers=["T7AX","MX","T7X","REF"],names=["%s.stopped"%r.name for r in rxs]) print "######## RT Setup ###########" rtDil=4 hiTemp=95 rtDur=20 rxs=self.runRT(src=rxs,vol=rtvol,srcdil=rtDil,heatInactivate=True,hiTemp=hiTemp,dur=rtDur,incTemp=50,stop=[reagents.getsample(s) for s in stop]) # Heat inactivate also allows splint to fold print "RT volume= ",[x.volume for x in rxs] needDil /= rtDil if "rt" in self.qpcrStages: q.addSamples(src=rxs,needDil=needDil,primers=["T7AX","MX","REF"],names=["%s.rt"%r.name for r in rxs]) rtSaveDil=10 rtSaveVol=3.5 if self.rtSave 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) if dolig: print "######## Ligation setup ###########" extdil=5.0/4 reagents.getsample("MLigase").conc=Concentration(5) rxs=self.runLig(rxs,inPlace=True) print "Ligation volume= ",[x.volume for x in rxs] needDil=needDil/extdil extpostdil=2 if extpostdil>1: print "Dilution after extension: %.2f"%extpostdil self.diluteInPlace(tgt=rxs,dil=extpostdil) needDil=needDil/extpostdil if not self.doexo: pcrdil=pcrdil/extpostdil 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,decklayout.DILPLATE) 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)) q.addSamples(src=[ext[i]],needDil=min(maxdil,needDil/self.saveDil),primers=["T7"+prefixIn[i]+"X","T7"+prefixOut[i]+"X","MX","T7X","REF"],names=["%s.ext"%names[i]],save=False) else: if "ext" in self.qpcrStages: for i in range(len(input)): q.addSamples(src=[rxs[i]],needDil=needDil,primers=["T7"+prefixIn[i]+"X","T7"+prefixOut[i]+"X","MX","T7X","REF"],names=["%s.ext"%names[i]]) isave=i+len(input) if isave<len(rxs): # samples restored q.addSamples(src=[rxs[isave]],needDil=needDil/rtSaveDil,primers=["T7"+rxs[isave].name[0]+"X","T7"+("B" if rxs[isave].name[0]=="A" else "W" if rxs[isave].name[0]=="B" else "A")+"X","MX","T7X","REF"]) if self.doexo: print "######## Exo ###########" prevvol=rxs[0].volume rxs=self.runExo(rxs,incTime=30,inPlace=True) exoDil=rxs[0].volume/prevvol needDil/=exoDil needDil/=7 # Anecdotal based on Ct's -- large components (MX) reduced by exo digestion if "exo" in self.qpcrStages: q.addSamples(src=[rxs[i] for i in self.trackIndices],needDil=needDil,primers=["T7AX","T7BX","MX","T7X","REF"],names=["%s.exo"%names[i] for i in self.trackIndices]) exo=self.saveSamps(src=rxs,vol=10*exoDil,dil=2/exoDil,dilutant=reagents.getsample("TE8"),tgt=[Sample("%s.exo"%n,decklayout.SAMPLEPLATE) for n in names]) # Save cDNA product else: exoDil=1 exo=[] else: extdil=1 extpostdil=1 exoDil=1 if self.doampure: print "######## Ampure Cleanup ###########" ratio=1.5 elutionVol=30 cleanIn=ext+exo+user needDil=needDil*cleanIn[0].volume/elutionVol clean=self.runAmpure(src=cleanIn,ratio=ratio,elutionVol=elutionVol) if "ampure" in self.qpcrStages: q.addSamples(src=[clean[i] for i in self.trackIndices],needDil=needDil,primers=["T7AX","MX","T7X","REF"]) rxs=rxs+clean # Use the cleaned products for PCR totalDil=stopDil*rtDil*extdil*extpostdil*exoDil 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,rtDil,extdil,extpostdil,exoDil,totalDil,fracRetained*100) if self.rtSave 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(input): rxs=rxs[0:len(input)] # Only keep -target products prefixOut=prefixOut[0:len(input)] prefixIn=prefixIn[0:len(input)] if self.dopcr: print "######### PCR #############" print "PCR Volume: %.1f, Dilution: %.1f, volumes available for PCR: [%s]"%(pcrvol, pcrdil,",".join(["%.1f"%r.volume for r in rxs])) maxSampleVolume=100 # Maximum sample volume of each PCR reaction (thermocycler limit, and mixing limit) initConc=needDil*self.qConc/pcrdil if keepCleaved: if self.doexo: initConc=initConc*7*self.cleavage # Back out 7x dilution in exo step, but only use cleaved as input conc else: initConc=initConc*self.cleavage # Only use cleaved as input conc else: initConc=initConc*(1-self.cleavage) gain=pcrgain(initConc,400,cycles) finalConc=initConc*gain print "Estimated starting concentration in PCR = %.1f nM, running %d cycles -> %.0f nM\n"%(needDil*self.qConc,cycles,finalConc) nsplit=int(math.ceil(pcrvol*1.0/maxSampleVolume)) print "Split each PCR into %d reactions"%nsplit srcdil=(1-1.0/3-1.0/4) sampNeeded=pcrvol/pcrdil if self.rtSave and keepCleaved: sampNeeded+=rtSaveVol maxvol=max([r.volume for r in rxs]); minvol=min([r.volume for r in rxs]); predil=min(75/maxvol,(40+1.4*nsplit)/(minvol-sampNeeded)) # Dilute to have 40ul left -- keeps enough sample to allow good mixing if keepCleaved and self.rtSave and predil>rtSaveDil: print "Reducing predil from %.1f to %.1f (rtSaveDil)"%(predil, rtSaveDil) predil=rtSaveDil if predil>1: self.diluteInPlace(rxs,predil) self.e.shakeSamples(rxs) print "Pre-diluting by %.1fx into [%s] ul"%(predil,",".join(["%.1f"%r.volume for r in rxs])) if keepCleaved and self.rtSave: assert(len(rxs)==len(rtSave)) print "Saving %.1f ul of each pre-PCR sample (@%.1f*%.1f dilution)"%(rtSaveVol ,predil, rtSaveDil/predil) self.lastSaved=[Sample("%s.sv"%x.name,decklayout.DILPLATE) for x in rxs] for i in range(len(rxs)): # Save with rtSaveDil dilution to reduce amount of RT consumed (will have Ct's 2-3 lower than others) self.e.transfer(rtSaveVol*predil,rxs[i],self.lastSaved[i],(False,False)) self.e.transfer(rtSaveVol*(rtSaveDil/predil-1),decklayout.WATER,self.lastSaved[i],(False,True)) # Use pipette mixing -- shaker mixing will be too slow pcr=self.runPCR(src=rxs*nsplit,vol=pcrvol/nsplit,srcdil=pcrdil*1.0/predil,ncycles=cycles,primers=["T7%sX"%x for x in (prefixOut if keepCleaved else prefixIn)]*nsplit,usertime=self.usertime if keepCleaved else None,fastCycling=True,inPlace=False) 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') if self.pcrSave: # Save samples at 1x (move all contents -- can ignore warnings) if self.savedilplate: sv=self.saveSamps(src=pcr[:len(rxs)],vol=[x.volume for x in pcr[:len(rxs)]],dil=1,plate=decklayout.DILPLATE,atEnd=True) else: sv=self.saveSamps(src=pcr[:len(rxs)],vol=[x.volume for x in pcr[:len(rxs)]],dil=1,plate=decklayout.EPPENDORFS) if nsplit>1: # Combine split for i in range(len(rxs),len(rxs)*nsplit): self.e.transfer(pcr[i].volume-16.4,pcr[i],sv[i%len(sv)],mix=(False,i>=len(rxs)*(nsplit-1))) # Correct concentration (above would've assumed it was diluted) for i in range(len(sv)): sv[i].conc=pcr[i].conc if "pcr" in self.qpcrStages: for i in range(len(pcr)): q.addSamples(pcr,needDil,["T7%sX"%prefixOut[i]]) processEff=0.5 # Estimate of overall efficiency of process print "Saved %.2f pmoles of product (%.0f ul @ %.1f nM)"%(sv[0].volume*sv[0].conc.stock/1000,sv[0].volume,sv[0].conc.stock) return sv else: return pcr[:len(rxs)] else: return rxs