Esempio n. 1
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)
Esempio n. 2
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)