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 addReferences(self,mindil=1,nsteps=6,dstep=4,nreplicates=1,ref=None,primers=None): """Add all needed references""" #print "addReferences(mindil=",mindil,", nsteps=",nsteps,", dstep=",dstep,", nrep=", nreplicates, ", ref=",ref,")" # Make sure the ref reagent is loaded if ref is None: ref=reagents.getsample("QPCRREF") if primers is None: primers=self.allprimers() dils=[1.0] for i in range(nsteps): needDil=mindil*math.pow(dstep,i) srcDil=1 src=[ref] for j in range(len(dils)): if needDil/dils[j] <= self.MAXDIL: srcDil=dils[j] if srcDil==1: src=[ref] else: srcname=diluteName(ref.name,srcDil) src=[Sample.lookup(srcname)] if src[0] is None: logging.error("%s not found"%srcname) break tmp=self.MINDILVOL self.MINDILVOL=75 # Make sure there's enough for resuing dilutions self.addSamples(src=src,needDil=needDil/srcDil,primers=primers,nreplicates=nreplicates,save=needDil/srcDil>self.MAXDIL,saveVol=75) self.MINDILVOL=tmp dils.append(needDil) self.addSamples(src=[self.dilutant],needDil=1,primers=primers,nreplicates=nreplicates,save=False)
def runRxInPlace(self,src,vol,master,master2=None,master3=None,returnPlate=True,finalx=1.0): 'Run reaction on beads in given total volume' [vol,src,master,master2,master3]=listify([vol,src,master,master2,master3]) mastervol=[vol[i]*finalx/master[i].conc.dilutionneeded() for i in range(len(vol))] master2vol=[0 if master2[i] is None else vol[i]*finalx/master2[i].conc.dilutionneeded() for i in range(len(vol))] master3vol=[0 if master3[i] is None else vol[i]*finalx/master3[i].conc.dilutionneeded() for i in range(len(vol))] watervol=[vol[i]-src[i].volume-mastervol[i]-master2vol[i]-master3vol[i] for i in range(len(vol))] if any([w < -0.02 for w in watervol]): logging.error("runRxInPlace: negative amount of water needed: %.2f"%min(watervol)) for i in range(len(src)): if watervol[i]+src[i].volume>=4.0 and watervol[i]>0.1: self.e.transfer(watervol[i],decklayout.WATER,src[i],(False,False)) watervol[i]=0 for i in range(len(src)): self.e.transfer(mastervol[i],master[i],src[i],(True,False)) for i in range(len(src)): if master2vol[i]>0: self.e.transfer(master2vol[i],master2[i],src[i],(True,False)) if master3vol[i]>0: self.e.transfer(master3vol[i],master3[i],src[i],(True,False)) for i in range(len(src)): if watervol[i]>=0.1: self.e.transfer(watervol[i],decklayout.WATER,src[i],(False,False)) self.e.shakeSamples(src,returnPlate=returnPlate)
def run(self,confirm=False,enzName="EvaUSER",waitForPTC=True): """Run the dilutions and QPCR setup""" # Setup qPCRs #self.jobq.dump() self.idler(100000) if waitForPTC: self.trp.e.waitpgm() # May still need to wait for TC to complete before able to do final jobs self.idler(100000) worklist.flushQueue() if self.jobq.len()>0: logging.error( "Blocked jobs remain on queue:") self.jobq.dump() assert False if len(self.dilProds)==0: return if confirm: worklist.userprompt('Continue to setup qPCR') worklist.comment('Starting qPCR setup') self.trp.e.sanitize(force=True) if all([allp in p for allp in self.allprimers() for p in self.primers]): print("All samples use same qPCR primers") # This allows the Eva to be distributed all at once self.trp.runQPCR(src=self.dilProds,vol=self.volume,primers=self.allprimers(),nreplicates=self.nreplicates,enzName=enzName) else: for p in self.allprimers(): # Build list of relevant entries ind=[ i for i in range(len(self.dilProds)) if p in self.primers[i]] self.trp.runQPCR(src=[self.dilProds[i] for i in ind],vol=self.volume,primers=[p],nreplicates=[self.nreplicates[i] for i in ind],enzName=enzName)
def finish(self): self.e.lihahome() worklist.userprompt("Process complete. Continue to turn off reagent cooler") self.e.setreagenttemp(None) #Sample.printallsamples("At completion") hasError=False for s in Sample.getAllOnPlate(): if s.volume<1.0 and s.conc is not None and not s.emptied: logging.error("Insufficient volume for %s: need at least %.1f ul additional"%(s.name,1.0-s.volume),fatal=False) #hasError=True elif s.volume<2.5 and s.conc is not None and not s.emptied: logging.warning("Low final volume for "+ s.name) elif s.volume>s.plate.maxVolume: logging.erorr("Excess final volume (%.1f) for %s: maximum is %.1f ul"%(s.volume,s.name,s.plate.maxVolume),fatal=False) hasError=True if hasError: logging.error("NO OUTPUT DUE TO ERRORS") print "Wells used: samples: %d, dilutions: %d, qPCR: %d"%(Sample.numSamplesOnPlate(decklayout.SAMPLEPLATE),Sample.numSamplesOnPlate(decklayout.DILPLATE),Sample.numSamplesOnPlate(decklayout.QPCRPLATE)) # Save worklist to a file #e.saveworklist("trp1.gwl") (scriptname,ext)=os.path.splitext(sys.argv[0]) self.e.savegem(scriptname+".gem") self.e.savesummary(scriptname+".txt") Sample.savematlab(scriptname+".m")
def diluteInPlace(self,tgt,dil=None,finalvol=None): # Dilute in place # e.g.: trp.diluteInPlace(tgt=rt1,dil=2) [tgt,dil,finalvol]=listify([tgt,dil,finalvol]) dilutant=decklayout.WATER for i in range(len(tgt)): if finalvol[i] is not None and dil[i] is None: self.e.transfer(finalvol[i]-tgt[i].volume,dilutant,tgt[i],mix=(False,False)) elif finalvol[i] is None and dil[i] is not None: self.e.transfer(tgt[i].volume*(dil[i]-1),dilutant,tgt[i],mix=(False,False)) else: logging.error("diluteInPlace: cannot specify both dil and finalvol") #print "after dilute, tgt[0]=",str(tgt[0]),",mixed=",tgt[0].isMixed() return tgt # The name of the samples are unchanged -- the predilution names
def run(self): """Run the dilutions and QPCR setup""" # Setup qPCRs # self.jobq.dump() self.idler(100000) self.trp.e.waitpgm() # May still need to wait for TC to complete before able to do final jobs self.idler(100000) if self.jobq.len() > 0: logging.error("Blocked jobs remain on queue:") self.jobq.dump() assert False tgt1 = Sample("Barcoded.Mixdown1", decklayout.EPPENDORFS) for i in range(1, len(self.dilProds)): self.e.transfer(12.5 * 1.2 * 2 / 1.5, self.dilProds[i], tgt1, mix=(False, False))
def run(self): 'Run the dilutions and QPCR setup' # Setup qPCRs #self.jobq.dump() self.idler(100000) self.trp.e.waitpgm() # May still need to wait for PTC to complete before able to do final jobs self.idler(100000) if self.jobq.len()>0: logging.error( "Blocked jobs remain on queue:",fatal=False) self.jobq.dump() assert False worklist.comment('Starting qPCR setup') for p in self.allprimers(): # Build list of relevant entries ind=[ i for i in range(len(self.dilProds)) if p in self.primers[i]] self.trp.runQPCR(src=[self.dilProds[i] for i in ind],vol=self.volume,primers=[p],nreplicates=[self.nreplicates[i] for i in ind])
def runT7Setup(self,src,vol,srcdil,ligands=None,tgt=None,rlist=["MT7"]): if isinstance(ligands,bool): if not ligands: ligands=None else: assert('runT7Setup: ligands arg should be ligand samples or None, not True') [ligands,src,tgt,srcdil]=listify([ligands,src,tgt,srcdil]) for i in range(len(src)): if tgt[i] is None: if ligands[i] is not None: tgt[i]=Sample("%s.T+%s"%(src[i].name,ligands[i].name),decklayout.SAMPLEPLATE) else: tgt[i]=Sample("%s.T-"%src[i].name,decklayout.SAMPLEPLATE) worklist.comment("runT7: source=%s"%[str(s) for s in src]) rvols=[reagents.getsample(x).conc.volneeded(vol) for x in rlist] rtotal=sum(rvols) sourcevols=[vol*1.0/s for s in srcdil] ligandvols=[0 for s in srcdil] watervols=[0 for s in srcdil] for i in range(len(srcdil)): if ligands[i] is not None: ligandvols[i]=vol*1.0/ligands[i].conc.dilutionneeded() watervols[i]=vol-ligandvols[i]-sourcevols[i]-rtotal else: watervols[i]=vol-sourcevols[i]-rtotal if any([w<-.01 for w in watervols]): logging.error("runT7Setup: Negative amount of water required: "+str(watervols)) if sum(watervols)>0.01: self.e.multitransfer(watervols,decklayout.WATER,tgt) for ir in range(len(rlist)): self.e.multitransfer([rvols[ir] for s in tgt],reagents.getsample(rlist[ir]),tgt) for i in range(len(ligands)): if ligandvols[i] > 0.01: self.e.transfer(ligandvols[i],ligands[i],tgt[i]) for i in range(len(src)): self.e.transfer(sourcevols[i],src[i],tgt[i]) self.e.shakeSamples(tgt,returnPlate=True) for t in tgt: t.ingredients['BIND']=1e-20*sum(t.ingredients.values()) return tgt
def runIncubation(self,src=None,vol=None,srcdil=None,tgt=None,enzymes=None,incTemp=37,incTime=15,hiTemp=None,hiTime=0,inPlace=False): if len(enzymes)!=1: logging.error("runIncubation only supports a single master mix") if inPlace: if tgt is not None: logging.error("tgt specified for in-place incubation") elif tgt is None: tgt=[Sample("%s.%s"%(src[i].name,enzymes[0].name),decklayout.SAMPLEPLATE) for i in range(len(src))] if srcdil==None: # Minimum dilution (no water) srcdil=1/(1-sum([1/e.conc.dilutionneeded() for e in enzymes])) if vol is None and inPlace: vol=[s.volume*srcdil for s in src] [src,tgt,vol,srcdil]=listify([src,tgt,vol,srcdil]) # Adjust source dilution for i in range(len(src)): src[i].conc=Concentration(srcdil[i],1) if inPlace: self.runRxInPlace(src,vol,enzymes[0],returnPlate=False) tgt=src else: self.e.stage('Incubation',enzymes,src,tgt,vol,destMix=False) self.e.shakeSamples(tgt,returnPlate=(incTime is None)) if incTime is None: print "Setup only of incubation with %s"%enzymes[0].name else: if hiTemp is None: worklist.pyrun('PTC\\ptcsetpgm.py INC TEMP@%.0f,%.0f TEMP@25,30'%(incTemp,incTime*60)) print "Incubating at %dC for %d minutes without heat inactivation"%(incTemp, incTime) hiTime=0 else: assert(hiTime>0) worklist.pyrun('PTC\\ptcsetpgm.py INC TEMP@%.0f,%.0f TEMP@%.0f,%.0f TEMP@25,30'%(incTemp,incTime*60,hiTemp,hiTime*60)) print "Incubating at %dC for %d minutes followed by heat inactivate at %dC for %d minutes"%(incTemp,incTime,hiTemp,hiTime) self.e.runpgm("INC",incTime+hiTime+2,False,max(vol),hotlidmode="TRACKING",hotlidtemp=10) return tgt
def beadSupernatant(self,src,tgt=None,sepTime=None,residualVolume=0.1,plate=None): if plate is None: plate=decklayout.SAMPLEPLATE if tgt is None: tgt=[] for i in range(len(src)): tgt.append(Sample("%s.SN"%src[i].name,plate)) [src,tgt]=listify([src,tgt]) if any([s.plate!=src[0].plate for s in src]): logging.error("beadSupernatant: Attempt to magsep on multiple plates at the same time") self.e.moveplate(src[0].plate,"Magnet") # Move to magnet self.sepWait(src,sepTime) for i in range(len(src)): self.e.transfer(src[i].amountToRemove(residualVolume),src[i],tgt[i],(False,False)) # Transfer elution to new tube self.e.moveplate(src[0].plate,"Home") return tgt
def run(self): 'Run the dilutions and QPCR setup' # Setup qPCRs #self.jobq.dump() self.idler(100000) self.trp.e.waitpgm( ) # May still need to wait for PTC to complete before able to do final jobs self.idler(100000) if self.jobq.len() > 0: logging.error("Blocked jobs remain on queue:", fatal=False) self.jobq.dump() assert False tgt1 = Sample("Barcoded.Mixdown1", decklayout.EPPENDORFS) for i in range(1, len(self.dilProds)): self.e.transfer(12.5 * 1.2 * 2 / 1.5, self.dilProds[i], tgt1, mix=(False, False))
def run(self,confirm=False,enzName="EvaUSER"): 'Run the dilutions and QPCR setup' # Setup qPCRs #self.jobq.dump() self.idler(100000) self.trp.e.waitpgm() # May still need to wait for PTC to complete before able to do final jobs self.idler(100000) worklist.flushQueue() if self.jobq.len()>0: logging.error( "Blocked jobs remain on queue:",fatal=False) self.jobq.dump() assert False if confirm: worklist.userprompt('Continue to setup qPCR') worklist.comment('Starting qPCR setup') self.trp.e.sanitize(force=True) for p in self.allprimers(): # Build list of relevant entries ind=[ i for i in range(len(self.dilProds)) if p in self.primers[i]] self.trp.runQPCR(src=[self.dilProds[i] for i in ind],vol=self.volume,primers=[p],nreplicates=[self.nreplicates[i] for i in ind],enzName=enzName)
def bindBeads(self,src,beads=None,beadConc=None,beadDil=None,bbuffer=None,incTime=60,addBuffer=False): if beads is None: beads=reagents.getsample("Dynabeads") if bbuffer is None: bbuffer=reagents.getsample("BeadBuffer") [src,beads,bbuffer,beadConc,beadDil]=listify([src,beads,bbuffer,beadConc,beadDil]) for s in src: if s.plate!=decklayout.SAMPLEPLATE: logging.error( "runBeadCleanup: src "+s.name+" is not in sample plate.") s.conc=None # Can't track concentration of beads self.e.moveplate(src[0].plate,"Home") # Make sure we do this off the magnet # Calculate volumes needed beadDil=[beads[i].conc.stock/(beads[i].conc.final if beadConc[i] is None else beadConc[i]) if beadDil[i] is None else beadDil[i] for i in range(len(beads))] if addBuffer: totalvol=[s.volume/(1-1.0/beadDil-1.0/bbuffer[i].conc.dilutionneeded()) for s in src] buffervol=[totalvol[i]/bbuffer[i].conc.dilutionneeded() for i in range(len(src))] # Add binding buffer to bring to 1x (beads will already be in 1x, so don't need to provide for them) for i in range(len(src)): self.e.transfer(buffervol[i],bbuffer[i],src[i]) else: buffervol=[0.0 for i in range(len(src))] totalvol=[src[i].volume/(1-1.0/beadDil[i]) for i in range(len(src))] beadvol=[totalvol[i]/beadDil[i] for i in range(len(totalvol))] # Transfer the beads for i in range(len(src)): self.e.transfer(beadvol[i],beads[i],src[i],(True,False)) # Mix beads before self.e.shakeSamples(src,dur=incTime,returnPlate=False)
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 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()
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)
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