예제 #1
0
    def runQPCR(self,src,vol,primers,nreplicates=1,enzName="EvaUSER"):
        ## QPCR setup
        worklist.comment("runQPCR: primers=%s, source=%s"%([p for p in primers],[s.name for s in src]))
        [src,vol,nreplicates]=listify([src,vol,nreplicates])
        self.e.shakeSamples(src,returnPlate=True)

        # Build a list of sets to be run
        torun=[]
        for repl in range(max(nreplicates)):
            for p in primers:
                for i in range(len(src)):
                    if nreplicates[i]<=repl:
                        continue
                    if repl==0:
                        sampname="%s.Q%s"%(src[i].name,p)
                    else:
                        sampname="%s.Q%s.%d"%(src[i].name,p,repl+1)
                    s=Sample(sampname,decklayout.QPCRPLATE)
                    torun=torun+[(src[i],s,p,vol[i])]

        # Add enzyme
        e=reagents.getsample(enzName)
        v=[a[3]/e.conc.dilutionneeded() for a in torun]
        t=[a[1] for a in torun]
        self.e.multitransfer(v,e,t)

        # Make the target have 'none' concentration so we can multiadd to it again
        for s in t:
            s.conc=None

        # Fill the master mixes
        dil={}
        for p in primers:
            mname="P-%s"%p
            if not reagents.isReagent(mname):
                reagents.add(name=mname,conc=4,extraVol=30)
            mq=reagents.getsample(mname)
            t=[a[1] for a in torun if a[2]==p]
            v=[a[3]/mq.conc.dilutionneeded() for a in torun if a[2]==p]
            assert(v>0)
            self.e.multitransfer(v,mq,t,(False,False))
            dil[p]=1.0/(1-1/e.conc.dilutionneeded()-1/mq.conc.dilutionneeded())
            
        # Add the samples
        self.e.sanitize()		# In case we are aligned
        for a in torun:
            s=a[0]
            t=a[1]
            p=a[2]
            v=a[3]/dil[p]
            t.conc=None		# Concentration of master mix is irrelevant now
            self.e.transfer(v,s,t)
            
        return [a[1] for a in torun]
예제 #2
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
예제 #3
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