Exemple #1
0
    def pgm(self):
        self.q = QSetup(self, maxdil=16, debug=False, mindilvol=60)

        #  Don't start idler (to minimize tip cross-contamination); last PCR allows plenty of time for doing dilutions without any effect on run time
        # Will start after first constriction PCR is running
        #self.q.debug = True
        # self.e.addIdleProgram(self.q.idler)

        self.q.addReferences(dstep=10, primers=self.qprimers, ref=reagents.getsample("BT5310"),nreplicates=2)

        samps=[r.getsample() for r in self.rsrc]
        for s in samps:
            self.q.addSamples([s],needDil=max(10,s.conc.stock*1e-9/self.qconc),primers=self.qprimers)
        print("### Mixdown #### (%.0f min)" % (clock.elapsed() / 60.0))
        if len(samps)>1:
            mixdown = self.mix(samps, [x['weight'] for x in self.inputs])
        else:
            mixdown=samps[0]
        self.q.addSamples(mixdown, needDil=max(1.0,mixdown.conc.stock * 1e-9 / self.qconc), primers=self.qprimers)
        print("Mixdown final concentration = %.0f pM" % (mixdown.conc.stock * 1000))
        print("### Constriction #### (%.1f min)" % (clock.elapsed() / 60.0))
        constricted = self.constrict(mixdown, mixdown.conc.stock * 1e-9)
        print("### Regeneration #### (%.0f min)" % (clock.elapsed() / 60.0))
        prefixes = set([x['left'][0] for x in self.inputs])
        self.regenerate(constricted * len(prefixes), [p for p in prefixes for _ in constricted])
        print("### qPCR #### (%.0f min)" % (clock.elapsed() / 60.0))
        self.q.run(confirm=False, enzName='EvaGreen', waitForPTC=True)
        print("### qPCR Done #### (%.0f min)" % (clock.elapsed() / 60.0))
        worklist.userprompt("qPCR done -- only need to complete final PCR", 300)
        self.e.waitpgm()
        print("### Final PCR Done #### (%.0f min)" % (clock.elapsed() / 60.0))
Exemple #2
0
    def pgm(self):
        self.q = QSetup(self, maxdil=16, debug=False, mindilvol=60)

        self.q.debug = True
        self.q.addReferences(dstep=10, primers=self.qprimers, ref=reagents.getsample("BT5310"),nreplicates=2)

        print("### Barcoding #### (%.0f min)" % (clock.elapsed() / 60.0))
        self.idbarcoding(self.rsrc, left=[x['left'] for x in self.inputs],
                                 right=[x['right'] for x in self.inputs])
        print("### qPCR #### (%.0f min)" % (clock.elapsed() / 60.0))
        self.q.run(confirm=False, enzName='EvaGreen')
Exemple #3
0
    def pgm(self):
        q = QSetup(self,maxdil=16,debug=False,mindilvol=60)
        self.e.addIdleProgram(q.idler)
        t7in = [s.getsample()  for s in self.srcs]
        
        if "negative" in self.qpcrStages:
            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
        self.rndNum=0
        self.nextID=self.firstID
        curPrefix=[inp['prefix'] for inp in self.inputs]

        while self.rndNum<self.nrounds:
            self.rndNum=self.rndNum+1
                
            prefixOut=["A" if p=="W" else "B" if p=="A" else "W" if p=="B" else "BADPREFIX" for p in curPrefix]
            if self.rndNum==1:
                self.t7vol1=self.t7vol1a
            else:
                self.t7vol1=max(20,self.pmolesIn*1000/min([inp.conc.final for inp in t7in])) # New input volueme
            r1=self.oneround(q,t7in,prefixOut,prefixIn=curPrefix,keepCleaved=False,rtvol=self.rtvol1,t7vol=self.t7vol1,cycles=self.pcrcycles1,pcrdil=self.pcrdil1,pcrvol=self.pcrvol1,dolig=self.allLig)
            # pcrvol is set to have same diversity as input 
            for i in range(len(r1)):
                r1[i].name="%s_%d_R%dU_%s"%(curPrefix[i],self.nextID,self.inputs[i]['round']+self.rndNum,self.inputs[i]['ligand'])
                self.nextID+=1
                r1[i].conc.final=r1[i].conc.stock*self.templateDilution
            if self.rndNum>=self.nrounds:
                logging.warning("Warning: ending on an uncleaved round")
                break
            
            self.rndNum=self.rndNum+1
            print "prefixIn=",curPrefix
            print "prefixOut=",prefixOut
            
            self.t7vol2=max(20,self.pmolesIn*1000/min([inp.conc.final for inp in r1]))
            r2=self.oneround(q,r1,prefixOut,prefixIn=curPrefix,keepCleaved=True,rtvol=self.rtvol2,t7vol=self.t7vol2,cycles=self.pcrcycles2,pcrdil=self.pcrdil2,pcrvol=self.pcrvol2,dolig=True)
            # pcrvol is set to have same diversity as input = (self.t7vol2*self.templateDilution/rnagain*stopdil*rtdil*extdil*exodil*pcrdil)
            for i in range(len(self.inputs)):
                r2[i].name="%s_%d_R%dC_%s"%(prefixOut[i],self.nextID,self.inputs[i]['round']+self.rndNum,self.inputs[i]['ligand'])
                self.nextID+=1
                r2[i].conc.final=r2[i].conc.stock*self.templateDilution
            t7in=r2
            curPrefix=prefixOut
        if "finalpcr" in self.qpcrStages:
            for i in range(len(r2)):
                q.addSamples(src=r2[i],needDil=r2[i].conc.stock/self.qConc,primers=["T7X","T7"+prefixOut[i]+"X"])
            
        print "######### qPCR ###########"
        #q.addReferences(mindil=4,nsteps=6,primers=["T7X","MX","T7AX"])
        if self.qpcrWait:
            worklist.userprompt('Continue to setup qPCR')
        q.run()
Exemple #4
0
    def pgm(self):
        self.q = QSetup(self, maxdil=16, debug=False, mindilvol=100)
        self.e.addIdleProgram(self.q.idler)

        if self.doqpcr:
            self.q.addReferences(dstep=10, primers=self.qprimers, ref=reagents.getsample("BT5310"))

        print("### Barcoding #### (%.0f min)" % (clock.elapsed() / 60.0))
        bcout = self.barcoding(names=[x['name'] for x in self.inputs], left=[x['left'] for x in self.inputs],
                               right=[x['right'] for x in self.inputs])

        for i in range(len(self.inputs)):
            x = self.inputs[i]
            if 'bconc' in x and x['bconc'] is not None:
                print("Resetting concentration of %s from expected %.1f to bconc setting of %.1f nM" % \
                      (x['name'], bcout[i].conc.stock, x['bconc']))
                bcout[i].conc.stock = x['bconc']

        print("### qPCR #### (%.0f min)" % (clock.elapsed() / 60.0))
        self.q.run(confirm=False, enzName='EvaGreen')
        print("### qPCR Done #### (%.0f min)" % (clock.elapsed() / 60.0))
        print("### Final PCR Done #### (%.0f min)" % (clock.elapsed() / 60.0))
        worklist.flushQueue()

        if all(['bconc' in x and x['bconc'] is not None for x in self.inputs]):
            print("### Mixdown #### (%.0f min)" % (clock.elapsed() / 60.0))
            worklist.flushQueue()
            worklist.comment('Start mixdown only at this point')
            self.e.sanitize(force=True)
            # mixdown = self.mix(bcout, [x['weight'] for x in self.inputs])
            # Set default mix number to 1
            for x in self.inputs:
                if 'mix' not in x:
                    x['mix']=1
            mixes=set([x['mix'] for x in self.inputs])
            for m in mixes:
                sel=[ i for i in range(len(self.inputs)) if self.inputs[i]['mix']==m] 
                print("sel=",sel)
                mixdown = self.mix([bcout[i] for i in sel], [self.inputs[i]['weight'] for i in sel],prefix="Mix%d_"%m)
                mixdown.name="Mix%d_Final"%m
            # self.q.addSamples(mixdown, needDil=mixdown.conc.stock * 1e-9 / self.qconc, primers=self.qprimers,nreplicates=3)
        else:
            print("### Not doing mixdown as bconc not set in all inputs")
Exemple #5
0
    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)
Exemple #6
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)
Exemple #7
0
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"]

        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 pgm(self):
        self.q = QSetup(self, maxdil=16, debug=False, mindilvol=60)

        #  Don't start idler (to minimize tip cross-contamination); last PCR allows plenty of time for doing dilutions without any effect on run time
        # Will start after first constriction PCR is running
        #self.q.debug = True
        # self.e.addIdleProgram(self.q.idler)

        self.q.addReferences(dstep=10, primers=self.qprimers, ref=reagents.getsample("BT5310"),nreplicates=2)

        samps=[r.getsample() for r in self.rsrc]
        for s in samps:
            self.q.addSamples([s],needDil=max(10,s.conc.stock*1e-9/self.qconc),primers=self.qprimers)
        print("### Mixdown #### (%.0f min)" % (clock.elapsed() / 60.0))
        if len(samps)>1:
            mixdown = self.mix(samps, [x['weight'] for x in self.inputs])
        else:
            mixdown=samps[0]
        self.q.addSamples(mixdown, needDil=max(1.0,mixdown.conc.stock * 1e-9 / self.qconc), primers=self.qprimers)
        print("Mixdown final concentration = %.0f pM" % (mixdown.conc.stock * 1000))
        print("### Constriction #### (%.1f min)" % (clock.elapsed() / 60.0))
        constricted = self.constrict(mixdown, mixdown.conc.stock * 1e-9)
        print("### Regeneration #### (%.0f min)" % (clock.elapsed() / 60.0))
        prefixes = set([x['left'][0] for x in self.inputs])
        self.regenerate(constricted * len(prefixes), [p for p in prefixes for _ in constricted])
        print("### qPCR #### (%.0f min)" % (clock.elapsed() / 60.0))
        self.q.run(confirm=False, enzName='EvaGreen', waitForPTC=True)
        print("### qPCR Done #### (%.0f min)" % (clock.elapsed() / 60.0))
        worklist.userprompt("qPCR done -- only need to complete final PCR", 300)
        self.e.waitpgm()
        print("### Final PCR Done #### (%.0f min)" % (clock.elapsed() / 60.0))

    def mix(self, inp, weights,mixvol=100,tgtconc=None,maxinpvol=20):
        """Mix given inputs according to weights (by moles -- use conc.stock of each input)"""
        vol = [weights[i] *1.0 / inp[i].conc.stock for i in range(len(inp))]
        scale = mixvol / sum(vol)
        conc=sum([inp[i].conc.stock * scale * vol[i] for i in range(len(inp))]) / mixvol

        if tgtconc is not None and conc>tgtconc:
            scale*=tgtconc*1.0/conc
        if max(vol)*scale<4.0:
            scale=4.1/max(vol)   # At least one input with 4ul input
        vol = [x * scale for x in vol]  # Mix to make planned total without water

        for i in range(len(vol)):
            # Check if this would require more than available of any input
            newscale= min(maxinpvol,inp[i].volume-inp[i].plate.unusableVolume()-2)/vol[i]
            if newscale<1:
                vol = [x * 1.0 * newscale for x in vol]
                if tgtconc is not None:
                    mixvol *= newscale   # Maintain same target concentration by reducing total volume
                    
        if min(vol) < 4.0:
            # Some components are too small; split mixing
            lowvol=[i for i in range(len(inp)) if vol[i]<4.0]
            highvol=[i for i in range(len(inp)) if i not in lowvol]
            assert len(highvol)>0
            assert len(lowvol)>0
            lowtgtconc=sum([inp[i].conc.stock *1.0/ weights[i] for i in highvol])/len(highvol)*sum([weights[i] for i in lowvol])
            print("Running premix of samples "+",".join(["%d"%ind for ind in lowvol])+" with target concentration of %.4f"%lowtgtconc)
            mix1=self.mix([inp[i] for i in lowvol],[weights[i] for i in lowvol],tgtconc=lowtgtconc,mixvol=mixvol,maxinpvol=maxinpvol)
            wt1=sum([weights[i] for i in lowvol])
            mix2=self.mix([inp[i] for i in highvol]+[mix1],[weights[i] for i in highvol]+[wt1],tgtconc=tgtconc,mixvol=mixvol,maxinpvol=maxinpvol)
            return mix2


        print("Mixing into %.0ful with tgtconc of %s, dil=%.2f"%(mixvol,"None" if tgtconc is None else "%.4f"%tgtconc,mixvol/sum(vol)))
        for i in range(len(inp)):
            print("%-30.30s %6.3fnM wt=%5.2f v=%5.2ful"%(inp[i].name,inp[i].conc.stock,weights[i],vol[i]))

        watervol = mixvol - sum(vol)
        #print "Mixdown: vols=[", ",".join(["%.2f " % v for v in vol]), "], water=", watervol, ", total=", mixvol, " ul"
        mixdown = Sample('mixdown', plate=decklayout.SAMPLEPLATE)

        if watervol < -0.1:
            print("Total mixdown is %.1f ul, more than planned %.0f ul" % (sum(vol), mixvol))
            assert False
        elif watervol >= 4.0:   # Omit if too small
            self.e.transfer(watervol, decklayout.WATER, mixdown, (False, False))
        else:
            pass
        ordering=sorted(list(range(len(inp))),key=lambda i: vol[i],reverse=True)
        for i in ordering:
            inp[i].conc.final = inp[i].conc.stock * vol[i] / mixvol  # Avoid warnings about concentrations not adding up
            self.e.transfer(vol[i], inp[i], mixdown, (False, False))
        self.e.shakeSamples([mixdown])
        if not mixdown.wellMixed:
            self.e.mix(mixdown)
        mixdown.conc = Concentration(stock=sum([inp[i].conc.stock * vol[i] for i in range(len(inp))]) / mixvol,
                                     final=None, units='nM')
        print("Mix product, %s, is in well %s with %.1ful @ %.2f nM"%(mixdown.name,mixdown.plate.wellname(mixdown.well),mixdown.volume,mixdown.conc.stock))
        print("----------")
        return mixdown

    def constrict(self, constrictin, conc):
        """Constrict sample with concentration given by conc (in M)"""
        # noinspection PyPep8Naming
        AN = 6.022e23

        dil = conc * (self.con_pcr1inputvol * 1e-6) * AN / self.nmolecules
        nstages = int(math.ceil(math.log(dil) / math.log(self.con_maxdilperstage)))
        dilperstage = math.pow(dil, 1.0 / nstages)
        print("Diluting by %.0fx in %.0f stages of %.1f" % (dil, nstages, dilperstage))

        s = [decklayout.WATER] + [constrictin] * self.nconstrict + [decklayout.SSDDIL]
        self.e.sanitize(3, 50)  # Heavy sanitize

        for j in range(nstages):
            print("Stage ", j, ", conc=", conc)
            if conc <= self.qconc * 1e-9:
                self.q.addSamples(s, needDil=1.0, primers=self.qprimers, save=False)
            s = self.runQPCRDIL(s, self.con_dilvol, dilperstage, dilPlate=True)
            conc /= dilperstage

        cycles = int(
            math.log(self.con_pcr1tgtconc / conc * self.con_pcr1vol / self.con_pcr1inputvol) / math.log(self.pcreff) + 0.5)
        pcr1finalconc = conc * self.con_pcr1inputvol / self.con_pcr1vol * self.pcreff ** cycles
        print("Running %d cycle PCR1 -> %.1f pM" % (cycles, pcr1finalconc * 1e12))
        s = s + [decklayout.WATER]  # Extra control of just water added to PCR mix
        pcr = self.runPCR(primers=None, src=s, vol=self.con_pcr1vol,
                          srcdil=self.con_pcr1vol * 1.0 / self.con_pcr1inputvol,
                          ncycles=cycles, master="MConstrict", kapa=True)
        for p in pcr:
            p.conc = Concentration(stock=pcr1finalconc * 1e9, final=pcr1finalconc / self.con_pcr2dil, units='nM')
        self.e.addIdleProgram(self.q.idler)  # Now that constriction is done, can start on qPCR setup

        needDil = max(4, pcr1finalconc / self.qconc)
        print("Running qPCR of PCR1 products using %.1fx dilution" % needDil)
        self.q.addSamples(pcr, needDil=needDil, primers=self.qprimers, save=True)
        pcr = pcr[1:-2]  # Remove negative controls
        cycles2 = int(math.log(self.con_pcr2tgtconc / pcr1finalconc * self.con_pcr2dil) / math.log(self.pcreff) + 0.5)
        pcr2finalconc = pcr1finalconc / self.con_pcr2dil * self.pcreff ** cycles2

        if cycles2 > 0:
            print("Running %d cycle PCR2 -> %.1f nM" % (cycles2, pcr2finalconc * 1e9))

            pcr2 = self.runPCR(primers="End", src=pcr, vol=self.con_pcr2vol, srcdil=self.con_pcr2dil,
                               ncycles=cycles2, master="MKapa", kapa=True)
            self.q.addSamples(pcr2, needDil=pcr2finalconc / self.qconc, primers=self.qprimers, save=True)
            for p in pcr2:
                p.conc = Concentration(stock=pcr2finalconc * 1e9, units='nM')
            self.e.waitpgm()
            return pcr2
        else:
            return pcr

    def regenerate(self, inp, prefix):
        """Regenerate T7 templates without barcodes with each of the given prefixes"""
        print("Regen Predilute: %.1f nM by %.1fx to %.2f nM" % (
            inp[0].conc.stock, self.regen_predil, inp[0].conc.stock / self.regen_predil))
        d1 = self.runQPCRDIL(inp, self.regen_predilvol, self.regen_predil, dilPlate=True)
        inconc = inp[0].conc.stock / self.regen_predil / self.regen_dil
        print("Regen PCR:  %.3f nM with %d cycles -> %.1f nM" % (
            inconc, self.regen_cycles, inconc * self.pcreff ** self.regen_cycles))
        res = self.runPCR(src=d1, srcdil=self.regen_dil, vol=self.regen_vol,
                          ncycles=self.regen_cycles,
                          primers=["T7%sX" % p for p in prefix], fastCycling=False, master="MKapa", kapa=True)
        return res
Exemple #8
0
    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()
Exemple #9
0
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"]
        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 pgm(self):
        self.q = QSetup(self, maxdil=16, debug=False, mindilvol=100)
        self.e.addIdleProgram(self.q.idler)

        if self.doqpcr:
            self.q.addReferences(dstep=10, primers=self.qprimers, ref=reagents.getsample("BT5310"))

        print("### Barcoding #### (%.0f min)" % (clock.elapsed() / 60.0))
        bcout = self.barcoding(names=[x['name'] for x in self.inputs], left=[x['left'] for x in self.inputs],
                               right=[x['right'] for x in self.inputs])

        for i in range(len(self.inputs)):
            x = self.inputs[i]
            if 'bconc' in x and x['bconc'] is not None:
                print("Resetting concentration of %s from expected %.1f to bconc setting of %.1f nM" % \
                      (x['name'], bcout[i].conc.stock, x['bconc']))
                bcout[i].conc.stock = x['bconc']

        print("### qPCR #### (%.0f min)" % (clock.elapsed() / 60.0))
        self.q.run(confirm=False, enzName='EvaGreen')
        print("### qPCR Done #### (%.0f min)" % (clock.elapsed() / 60.0))
        print("### Final PCR Done #### (%.0f min)" % (clock.elapsed() / 60.0))
        worklist.flushQueue()

        if all(['bconc' in x and x['bconc'] is not None for x in self.inputs]):
            print("### Mixdown #### (%.0f min)" % (clock.elapsed() / 60.0))
            worklist.flushQueue()
            worklist.comment('Start mixdown only at this point')
            self.e.sanitize(force=True)
            # mixdown = self.mix(bcout, [x['weight'] for x in self.inputs])
            # Set default mix number to 1
            for x in self.inputs:
                if 'mix' not in x:
                    x['mix']=1
            mixes=set([x['mix'] for x in self.inputs])
            for m in mixes:
                sel=[ i for i in range(len(self.inputs)) if self.inputs[i]['mix']==m] 
                print("sel=",sel)
                mixdown = self.mix([bcout[i] for i in sel], [self.inputs[i]['weight'] for i in sel],prefix="Mix%d_"%m)
                mixdown.name="Mix%d_Final"%m
            # self.q.addSamples(mixdown, needDil=mixdown.conc.stock * 1e-9 / self.qconc, primers=self.qprimers,nreplicates=3)
        else:
            print("### Not doing mixdown as bconc not set in all inputs")

    def mix(self, inp, weights, tgtdil=1.0, maxusefrac=0.75, prefix="Mix"):
        """Mix given inputs according to weights (by moles -- use conc.stock of each input)"""
        print("Mix: tgtdil=%.2f, inp=" % tgtdil, ",".join(
            ["%s@%.2f" % (inp[i].name, weights[i]) for i in range(len(inp))]))
        relvol = [weights[i] * 1.0 / inp[i].conc.stock for i in range(len(inp))]
        stages=mixsplit(vols=relvol,samps=inp,avail=[(i.volume-15.0)*maxusefrac-1.4 for i in inp],minvol=4.0,minmix=100.0,maxmix=100.0,plate=decklayout.SAMPLEPLATE,debug=False,prefix=prefix)
        for s in stages:
            dest=s[0]
            moles=0
            for i in range(len(s[1])-1,-1,-1):
                src=s[1][i]
                vol=s[2][i]
                self.e.transfer(vol,src,dest,(True,False))
                if src.conc is not None:
                    moles+=src.conc.stock*vol
            newconc=moles/sum(s[2])
            print("Adjusting concentration of %s from %s to %.2f nM"%(dest.name,str(dest.conc) if dest.conc is not None else -1,newconc))
            dest.conc=Concentration(newconc,newconc,units='nM')
            print(s[0].name,'\n =',"\n + ".join(['%5.1fuL %5.2f %s %s'%(s[2][i],s[1][i].conc.stock if s[1][i].conc is not None else 0,s[1][i].conc.units if s[1][i].conc is not None else "  ",s[1][i].name) for i in range(len(s[1]))]),"\n-> %5.1ful %5.2f %s %s"%(dest.volume,dest.conc.stock,dest.conc.units,dest.name))
        print()
        return stages[0][0]

    def oldmix(self, inp, weights, tgtdil=1.0):
        """Mix given inputs according to weights (by moles -- use conc.stock of each input)"""
        print("Mix: tgtdil=%.2f, inp=" % tgtdil, ",".join(
            ["%s@%.2f" % (inp[i].name, weights[i]) for i in range(len(inp))]))
        mixvol = 100.0
        if len(inp) == 1:
            if tgtdil > 1.0:
                vol = [mixvol / tgtdil]
                if vol[0] < 4.0:
                    vol[0] = 4.0
            else:
                # Special case, just dilute 10x
                vol = [mixvol / 10]
        else:
            relvol = [weights[i] * 1.0 / inp[i].conc.stock for i in range(len(inp))]
            scale = mixvol / sum(relvol)
            for i in range(len(inp)):
                if relvol[i] * scale > inp[i].volume - 16.4:
                    scale = (inp[i].volume - 16.4) / relvol[i]
            vol = [x * scale for x in relvol]
            if min(vol) > 4.0 and tgtdil > 1.0:
                scale = max(1.0 / tgtdil, 4.0 / min(vol))
                print("Rescale volumes by %.2f to get closer to target dilution of %.2f" % (scale, tgtdil))
                vol = [x * scale for x in vol]

        print("Mix1: vols=[", ",".join(["%.3f" % v for v in vol]), "]")
        if min(vol) < 4.0:
            logging.info("Minimum volume into mixing would be only %.2f ul - staging..." % min(vol))
            if max(vol) < 4.0:
                # All volumes are low, just too much
                # Split into 2 stages
                sel = list(range(int(len(inp) / 2)))
                nsel = list(range(int(len(inp) / 2), len(inp)))
            else:
                # Choose a splitting threshold
                mindilution = 4.0 / min(vol)
                thresh = np.median(vol)
                while mixvol / sum([v for v in vol if v < thresh]) < mindilution:
                    thresh = thresh * 0.8
                print("Using %.2f as threshold to split mixdown" % thresh)
                sel = [i for i in range(len(inp)) if vol[i] < thresh]
                nsel = [i for i in range(len(inp)) if vol[i] >= thresh]
            print("Mixing ", ",".join([inp[i].name for i in sel]), " with vols [", ",".join(
                ["%.2f" % vol[i] for i in sel]), "] in separate stage.")
            tgtdil = float(np.median([vol[i] for i in nsel]) / sum([vol[i] for i in sel]))
            print("tgtdil=%.2f" % tgtdil)
            mix1 = self.mix([inp[i] for i in sel], [weights[i] for i in sel], tgtdil)
            mix2 = self.mix([inp[i] for i in nsel] + [mix1],
                            [weights[i] for i in nsel] + [sum([weights[i] for i in sel])])
            return mix2
        watervol = mixvol - sum(vol)
        print("Mixdown: vols=[", ",".join(["%.2f " % v for v in vol]), "], water=", watervol, ", total=", mixvol, " ul")
        mixdown = Sample('mixdown', plate=decklayout.SAMPLEPLATE)

        if watervol < -0.1:
            print("Total mixdown is %.1f ul, more than planned %.0f ul" % (sum(vol), mixvol))
            assert False
        elif watervol > 0.0:
            self.e.transfer(watervol, decklayout.WATER, mixdown, (False, False))
        else:
            pass
        for i in range(len(inp)):
            inp[i].conc.final = inp[i].conc.stock * vol[i] / mixvol  # Avoid warnings about concentrations not adding up
            self.e.transfer(vol[i], inp[i], mixdown, (False, i == len(inp) - 1))
        self.e.shakeSamples([mixdown])
        mixdown.conc = Concentration(stock=sum([inp[i].conc.stock * vol[i] for i in range(len(inp))]) / mixvol,
                                     final=None, units='nM')
        print("Mixdown final concentration = %.1f nM" % mixdown.conc.stock)
        return mixdown

    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
Exemple #10
0
class IDPrep(TRP):
    # Barcode multiple samples
    pcreff = 1.98

    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):
        self.q = QSetup(self, maxdil=16, debug=False, mindilvol=60)

        self.q.debug = True
        self.q.addReferences(dstep=10, primers=self.qprimers, ref=reagents.getsample("BT5310"),nreplicates=2)

        print("### Barcoding #### (%.0f min)" % (clock.elapsed() / 60.0))
        self.idbarcoding(self.rsrc, left=[x['left'] for x in self.inputs],
                                 right=[x['right'] for x in self.inputs])
        print("### qPCR #### (%.0f min)" % (clock.elapsed() / 60.0))
        self.q.run(confirm=False, enzName='EvaGreen')

    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
Exemple #11
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 '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()