Example #1
0
 def runpgm(self,pgm,duration,waitForCompletion=True,volume=10,hotlidmode="TRACKING",hotlidtemp=1):
     if self.ptcrunning:
         logging.error("Attempt to start a progam on PTC when it is already running")
     if len(pgm)>8:
         logging.error("PTC program name (%s) too long (max is 8 char)"%pgm)
     # move to thermocycler
     worklist.flushQueue()
     self.lihahome()
     cmt="run %s"%pgm
     worklist.comment(cmt)
     #print "*",cmt
     worklist.pyrun("PTC\\ptclid.py OPEN")
     self.moveplate(decklayout.SAMPLEPLATE,"PTC")
     worklist.vector("Hotel 1 Lid",decklayout.HOTELPOS,worklist.SAFETOEND,True,worklist.DONOTMOVE,worklist.CLOSE)
     worklist.vector("PTC200lid",decklayout.PTCPOS,worklist.SAFETOEND,True,worklist.DONOTMOVE,worklist.OPEN)
     worklist.romahome()
     worklist.pyrun("PTC\\ptclid.py CLOSE")
     #        pgm="PAUSE30"  # For debugging
     assert hotlidmode=="TRACKING" or hotlidmode=="CONSTANT"
     assert (hotlidmode=="TRACKING" and hotlidtemp>=0 and hotlidtemp<=45) or (hotlidmode=="CONSTANT" and hotlidtemp>30)
     worklist.pyrun('PTC\\ptcrun.py %s CALC %s,%d %d'%(pgm,hotlidmode,hotlidtemp,volume))
     self.pgmStartTime=clock.pipetting
     self.pgmEndTime=duration*60+clock.pipetting
     self.ptcrunning=True
     Sample.addallhistory("{%s}"%pgm,addToEmpty=False,onlyplate=decklayout.SAMPLEPLATE.name)
     if waitForCompletion:
         self.waitpgm()
Example #2
0
    def dispose(self, volume, src,  mix=False, getDITI=True, dropDITI=True):
        'Dispose of a given volume by aspirating and not dispensing (will go to waste during next wash)'
        if self.ptcrunning and src.plate==decklayout.SAMPLEPLATE:
            self.waitpgm()
        if volume>self.MAXVOLUME:
            reuseTip=False   # Since we need to wash to get rid of it
            print "Splitting large transfer of %.1f ul into smaller chunks < %.1f ul "%(volume,self.MAXVOLUME),
            if reuseTip:
                print "with tip reuse"
            else:
                print "without tip reuse"
            self.dispose(self.MAXVOLUME,src,mix,getDITI,dropDITI)
            self.dispose(volume-self.MAXVOLUME,src,False,getDITI,dropDITI)
            return

        cmt="Remove and dispose of %.1f ul from %s"%(volume, src.name)
        ditivolume=volume+src.inliquidLC.singletag
        if mix and not src.isMixed():
            cmt=cmt+" with src mix"
            ditivolume=max(ditivolume,src.volume)
        if self.useDiTis:
            tipMask=4
            if getDITI:
                worklist.getDITI(tipMask&self.DITIMASK,ditivolume)
        else:
            tipMask=self.cleantip()
        #print "*",cmt
        worklist.comment(cmt)

        if mix and not src.isMixed():
            src.mix(tipMask)
        src.aspirate(tipMask,volume)

        if self.useDiTis and dropDITI:
            worklist.dropDITI(tipMask&self.DITIMASK,decklayout.WASTE)
Example #3
0
    def multitransfer(self, volumes, src, dests,mix=(True,False),getDITI=True,dropDITI=True,ignoreContents=False,extraFrac=0.05):
        'Multi pipette from src to multiple dest.  mix is (src,dest) mixing -- only mix src if needed though'
        #print "multitransfer(",volumes,",",src,",",dests,",",mix,",",getDITI,",",dropDITI,")"
        if self.ptcrunning and (src.plate==decklayout.SAMPLEPLATE or len([1 for d in dests if d.plate==decklayout.SAMPLEPLATE])>0):
            self.waitpgm()

        if isinstance(volumes,(int,long,float)):
            # Same volume for each dest
            volumes=[volumes for i in range(len(dests))]
        assert len(volumes)==len(dests)
        #        if len([d.volume for d in dests if d.conc!=None])==0:
        if len([dests[i].volume for i in range(0,len(dests)) if dests[i].conc != None and volumes[i]>0.01])==0:
            maxval=0
        else:
            maxval=max([dests[i].volume for i in range(0,len(dests)) if dests[i].conc != None and volumes[i]>0.01])
            #         maxval=max([d.volume for d in dests if d.conc != None])
        #print "volumes=",[d.volume for d in dests],", conc=",[str(d.conc) for d in dests],", maxval=",maxval
        if not mix[1] and len(volumes)>1 and ( maxval<.01 or ignoreContents):
            if sum(volumes)*(1+extraFrac)>self.MAXVOLUME:
                #print "sum(volumes)=%.1f, MAXVOL=%.1f"%(sum(volumes),self.MAXVOLUME)
                for i in range(1,len(volumes)):
                    if sum(volumes[0:i+1])*(1+extraFrac)>self.MAXVOLUME:
                        destvol=max([d.volume for d in dests[0:i]])
                        reuseTip=destvol<=0
                        # print "Splitting multi with total volume of %.1f ul into smaller chunks < %.1f ul after %d dispenses "%(sum(volumes),self.MAXVOLUME,i),
                        # if reuseTip:
                        #     print "with tip reuse"
                        # else:
                        #     print "without tip reuse"
                        self.multitransfer(volumes[0:i],src,dests[0:i],mix,getDITI,not reuseTip,extraFrac=extraFrac)
                        self.multitransfer(volumes[i:],src,dests[i:],(False,mix[1]),not reuseTip,dropDITI,extraFrac=extraFrac)
                        return

            if self.useDiTis:
                tipMask=4
                if  getDITI:
                    ditivol=sum(volumes)*(1+extraFrac)+src.inliquidLC.multicond+src.inliquidLC.multiexcess
                    worklist.getDITI(tipMask&self.DITIMASK,min(self.MAXVOLUME,ditivol),True,True)
            else:
                tipMask=self.cleantip()

            cmt="Multi-add  %s to samples %s"%(src.name,",".join("%s[%.1f]"%(dests[i].name,volumes[i]) for i in range(len(dests))))
            #print "*",cmt
            worklist.comment(cmt)

            if mix[0] and not src.isMixed():
                if src.plate==decklayout.SAMPLEPLATE or src.plate==decklayout.DILPLATE:
                    self.shakeSamples([src])
                else:
                    src.mix(tipMask)
            src.aspirate(tipMask,sum(volumes)*(1+extraFrac),True)	# Aspirate extra
            for i in range(len(dests)):
                if volumes[i]>0.01:
                    dests[i].dispense(tipMask,volumes[i],src)
            if self.useDiTis and dropDITI:
                worklist.dropDITI(tipMask&self.DITIMASK,decklayout.WASTE)
        else:
            for i in range(len(dests)):
                if volumes[i]>0.01:
                    self.transfer(volumes[i],src,dests[i],(mix[0] and i==0,mix[1]),getDITI,dropDITI)
Example #4
0
    def __init__(self):
        'Create a new experiment with given sample locations for water and WASTE;  totalTime is expected run time in seconds, if known'
        worklist.comment("Generated %s" % (datetime.now().ctime()))
        worklist.userprompt(
            "The following reagent tubes should be present: %s" %
            Sample.getAllLocOnPlate(decklayout.REAGENTPLATE))
        worklist.userprompt(
            "The following eppendorf tubes should be present: %s" %
            Sample.getAllLocOnPlate(decklayout.EPPENDORFS))
        worklist.email(dest='*****@*****.**',
                       subject='Run started (Generate: %s)' %
                       (datetime.now().ctime()))
        worklist.email(dest='*****@*****.**',
                       subject='Tecan error',
                       onerror=1)
        self.cleanTips = 0
        # self.sanitize()  # Not needed, TRP does it, also first use of tips will do this
        self.useDiTis = False
        self.ptcrunning = False
        self.overrideSanitize = False
        self.pgmStartTime = None
        self.pgmEndTime = None

        # Access PTC and RIC early to be sure they are working
        worklist.pyrun("PTC\\ptctest.py")
        #        worklist.periodicWash(15,4)
        worklist.userprompt(
            "Verify that PTC thermocycler lid pressure is set to '2'.")
        self.idlePgms = []
        self.timerStartTime = [None] * 8
Example #5
0
    def __init__(self):
        'Create a new experiment with given sample locations for water and WASTE;  totalTime is expected run time in seconds, if known'
        self.checksum=md5sum(sys.argv[0])
        self.checksum=self.checksum[-4:]
        pyTecan=os.path.dirname(os.path.realpath(__file__))
        self.gitlabel=strip(subprocess.check_output(["git", "describe","--always"],cwd=pyTecan))
        worklist.comment("Generated %s (%s-%s pyTecan-%s)"%(datetime.now().ctime(),sys.argv[0],self.checksum,self.gitlabel))
        worklist.userprompt("The following reagent tubes should be present: %s"%Sample.getAllLocOnPlate(decklayout.REAGENTPLATE))
        worklist.userprompt("The following eppendorf tubes should be present: %s"%Sample.getAllLocOnPlate(decklayout.EPPENDORFS))
        worklist.email(dest='*****@*****.**',subject='Run started (Generate: %s) expected runtime %.0f minutes'%(datetime.now().ctime(),clock.totalTime/60.0 if clock.totalTime is not None else 0.0 ) )
        worklist.email(dest='*****@*****.**',subject='Tecan error',onerror=1)
        self.cleanTips=0
        # self.sanitize()  # Not needed, TRP does it, also first use of tips will do this
        self.useDiTis=False
        self.ptcrunning=False
        self.overrideSanitize=False
        self.pgmStartTime=None
        self.pgmEndTime=None

        # Access PTC and RIC early to be sure they are working
        worklist.pyrun("PTC\\ptctest.py")
        #        worklist.periodicWash(15,4)
        worklist.userprompt("Verify that PTC thermocycler lid pressure is set to '2'.")
        self.idlePgms=[]
        self.timerStartTime=[None]*8
Example #6
0
    def waitpgm(self, sanitize=True):
        if not self.ptcrunning:
            return
        #print "* Wait for PTC to finish"
        if sanitize:
            self.sanitize()   # Sanitize tips before waiting for this to be done
        worklist.comment("Wait for PTC")
        while self.pgmEndTime-clock.pipetting > 120:
            # Run any idle programs
            oldElapsed=clock.pipetting
            for ip in self.idlePgms:
                if self.pgmEndTime-clock.pipetting > 120:
                    #print "Executing idle program with %.0f seconds"%(self.pgmEndTime-clock.pipetting)
                    ip(self.pgmEndTime-clock.pipetting-120)
            if oldElapsed==clock.pipetting:
                # Nothing was done
                break
            worklist.flushQueue()		# Just in case

        clock.pipandthermotime+=(clock.pipetting-self.pgmStartTime)
        clock.thermotime+=(self.pgmEndTime-clock.pipetting)
        clock.pipetting=self.pgmStartTime

        #print "Waiting for PTC with %.0f seconds expected to remain"%(self.pgmEndTime-clock.pipetting)
        self.lihahome()
        worklist.pyrun('PTC\\ptcwait.py')
        worklist.pyrun("PTC\\ptclid.py OPEN")
        #        worklist.pyrun('PTC\\ptcrun.py %s CALC ON'%"COOLDOWN")
        #        worklist.pyrun('PTC\\ptcwait.py')
        worklist.vector("PTC200lid",decklayout.PTCPOS,worklist.SAFETOEND,True,worklist.DONOTMOVE,worklist.CLOSE)
        worklist.vector("Hotel 1 Lid",decklayout.HOTELPOS,worklist.SAFETOEND,True,worklist.DONOTMOVE,worklist.OPEN)

        worklist.vector("PTC200WigglePos",decklayout.PTCPOS,worklist.SAFETOEND,False,worklist.DONOTMOVE,worklist.DONOTMOVE)
        worklist.vector("PTC200Wiggle",decklayout.PTCPOS,worklist.SAFETOEND,False,worklist.DONOTMOVE,worklist.CLOSE,True)
        worklist.vector("PTC200Wiggle",decklayout.PTCPOS,worklist.ENDTOSAFE,False,worklist.DONOTMOVE,worklist.OPEN,True)
        worklist.vector("PTC200WigglePos",decklayout.PTCPOS,worklist.ENDTOSAFE,False,worklist.DONOTMOVE,worklist.DONOTMOVE)

        worklist.vector("PTC200Wiggle2Pos",decklayout.PTCPOS,worklist.SAFETOEND,False,worklist.DONOTMOVE,worklist.DONOTMOVE)
        worklist.vector("PTC200Wiggle2",decklayout.PTCPOS,worklist.SAFETOEND,False,worklist.DONOTMOVE,worklist.CLOSE,True)
        worklist.vector("PTC200Wiggle2",decklayout.PTCPOS,worklist.ENDTOSAFE,False,worklist.DONOTMOVE,worklist.OPEN,True)
        worklist.vector("PTC200Wiggle2Pos",decklayout.PTCPOS,worklist.ENDTOSAFE,False,worklist.DONOTMOVE,worklist.DONOTMOVE)

        worklist.vector("PTC200WigglePos",decklayout.PTCPOS,worklist.SAFETOEND,False,worklist.DONOTMOVE,worklist.DONOTMOVE)
        worklist.vector("PTC200Wiggle",decklayout.PTCPOS,worklist.SAFETOEND,False,worklist.DONOTMOVE,worklist.CLOSE,True)
        worklist.vector("PTC200Wiggle",decklayout.PTCPOS,worklist.ENDTOSAFE,False,worklist.DONOTMOVE,worklist.OPEN,True)
        worklist.vector("PTC200WigglePos",decklayout.PTCPOS,worklist.ENDTOSAFE,False,worklist.DONOTMOVE,worklist.DONOTMOVE)

        self.ptcrunning=False
        self.moveplate(decklayout.SAMPLEPLATE,"Home")
        # Mark all samples on plate as unmixed (due to condensation)
        Sample.notMixed(decklayout.SAMPLEPLATE.name)
        # Verify plate is in place
        worklist.vector(decklayout.SAMPLEPLATE.vectorName,decklayout.SAMPLEPLATE,worklist.SAFETOEND,False,worklist.DONOTMOVE,worklist.CLOSE)
        worklist.vector(decklayout.SAMPLEPLATE.vectorName,decklayout.SAMPLEPLATE,worklist.ENDTOSAFE,False,worklist.OPEN,worklist.DONOTMOVE)
        worklist.romahome()
        #worklist.userprompt("Plate should be back on deck. Press return to continue")
        # Wash tips again to remove any drips that may have formed while waiting for PTC
        worklist.wash(15,1,5,True)
Example #7
0
    def mix(self, src, nmix=4):
        if self.ptcrunning and src.plate == decklayout.SAMPLEPLATE:
            self.waitpgm()

        cmt = "Mix %s" % (src.name)
        tipMask = self.cleantip()
        worklist.comment(cmt)
        src.lastMixed = None  # Force a mix
        src.mix(tipMask, False, nmix=nmix)
Example #8
0
    def mix(self, src, nmix=4):
        if self.ptcrunning and src.plate==decklayout.SAMPLEPLATE:
            self.waitpgm()

        cmt="Mix %s"%(src.name)
        tipMask=self.cleantip()
        worklist.comment(cmt)
        src.lastMixed=None	# Force a mix
        src.mix(tipMask,False,nmix=nmix)
Example #9
0
    def transfer(self,
                 volume,
                 src,
                 dest,
                 mix=(True, False),
                 getDITI=True,
                 dropDITI=True):
        if self.ptcrunning and (src.plate == decklayout.SAMPLEPLATE
                                or dest.plate == decklayout.SAMPLEPLATE) > 0:
            self.waitpgm()

        if volume > self.MAXVOLUME:
            destvol = dest.volume
            reuseTip = destvol <= 0
            print "Splitting large transfer of %.1f ul into smaller chunks < %.1f ul " % (
                volume, self.MAXVOLUME),
            if reuseTip:
                print "with tip reuse"
            else:
                print "without tip reuse"
            self.transfer(self.MAXVOLUME, src, dest, mix, getDITI, False)
            self.transfer(volume - self.MAXVOLUME, src, dest,
                          (mix[0] and not reuseTip, mix[1]), False, dropDITI)
            return

        cmt = "Add %.1f ul of %s to %s" % (volume, src.name, dest.name)
        ditivolume = volume + src.inliquidLC.singletag
        if mix[0] and not src.isMixed():
            cmt = cmt + " with src mix"
            ditivolume = max(ditivolume, src.volume)
        if mix[1] and dest.volume > 0 and not src.isMixed():
            cmt = cmt + " with dest mix"
            ditivolume = max(ditivolume, volume + dest.volume)
            #            print "Mix volume=%.1f ul"%(ditivolume)
        if self.useDiTis:
            tipMask = 4
            if getDITI:
                worklist.getDITI(tipMask & self.DITIMASK, ditivolume)
        else:
            tipMask = self.cleantip()
        #print "*",cmt
        worklist.comment(cmt)

        if mix[0] and not src.isMixed():
            if src.plate == decklayout.SAMPLEPLATE or src.plate == decklayout.DILPLATE:
                self.shakeSamples([src])
            else:
                src.mix(tipMask)
        src.aspirate(tipMask, volume)
        dest.dispense(tipMask, volume, src)
        if mix[1]:
            dest.mix(tipMask, True)

        if self.useDiTis and dropDITI:
            worklist.dropDITI(tipMask & self.DITIMASK, decklayout.WASTE)
Example #10
0
    def stage(self,stagename,reagents,sources,samples,volume,finalx=1.0,destMix=True,dilutant=None):
        # Add water to sample wells as needed (multi)
        # Pipette reagents into sample wells (multi)
        # Pipette sources into sample wells
        # Concs are in x (>=1)

        # Sample.printallsamples("Before "+stagename)
        # print "\nStage: ", stagename, "reagents=",[str(r) for r in reagents], ",sources=",[str(s) for s in sources],",samples=",[str(s) for s in samples],str(volume)

        if len(samples)==0:
            logging.notice("No samples")
            return

        if dilutant is None:
            dilutant=decklayout.WATER

        worklist.comment("Stage: "+stagename)
        if not isinstance(volume,list):
            volume=[volume for i in range(len(samples))]
        for i in range(len(volume)):
            assert volume[i]>0
            volume[i]=float(volume[i])

        reagentvols=[1.0/x.conc.dilutionneeded()*finalx for x in reagents]
        if len(sources)>0:
            sourcevols=[volume[i]*1.0/sources[i].conc.dilutionneeded()*finalx for i in range(len(sources))]
            while len(sourcevols)<len(samples):
                sourcevols.append(0)
            watervols=[volume[i]*(1-sum(reagentvols))-samples[i].volume-sourcevols[i] for i in range(len(samples))]
        else:
            watervols=[volume[i]*(1-sum(reagentvols))-samples[i].volume for i in range(len(samples))]

        if min(watervols)<-0.01:
            msg="Error: Ingredients add up to more than desired volume by %.1f ul"%(-min(watervols))
            for s in samples:
                if s.volume>0:
                    msg=msg+" Note: %s already contains %.1f ul\n"%(s.name,s.volume)
            logging.error(msg)

        watervols2=[w if w<=2 else 0 for w in watervols]   # Move later since volume is low
        watervols=[w if w>2 else 0 for w in watervols]  # Only move>=2 at beginning
        if any([w>0.01 for w in watervols]):
            self.multitransfer(watervols,dilutant,samples,(False,destMix and (len(reagents)+len(sources)==0)))

        for i in range(len(reagents)):
            self.multitransfer([reagentvols[i]*v for v in volume],reagents[i],samples,(True,destMix and (len(sources)==0 and i==len(reagents)-1)))

        if any([w>0.01 for w in watervols2]):
            self.multitransfer(watervols2,dilutant,samples,(False,destMix and (len(reagents)+len(sources)==0)))

        if len(sources)>0:
            assert len(sources)<=len(samples)
            for i in range(len(sources)):
                self.transfer(sourcevols[i],sources[i],samples[i],(True,destMix))
Example #11
0
    def moveplate(self,plate,dest="Home",returnHome=True):
        if self.ptcrunning and plate==decklayout.SAMPLEPLATE:
            self.waitpgm()

        # move to given destination (one of "Home","Magnet","Shaker","PTC" )
        if plate!=decklayout.SAMPLEPLATE and plate!=decklayout.DILPLATE:
            print "Only able to move %s or %s plates, not %s"%(decklayout.SAMPLEPLATE.name,decklayout.DILPLATE.name,plate.name)
            assert False

        if plate.curloc==dest:
            #print "Plate %s is already at %s"%(plate.name,dest)
            return

        #print "Move plate %s from %s to %s"%(plate.name,plate.curloc,dest)
        worklist.flushQueue()
        self.lihahome()
        cmt="moveplate %s %s"%(plate.name,dest)
        worklist.comment(cmt)
        if plate.curloc=="Home":
            worklist.vector(plate.vectorName,plate,worklist.SAFETOEND,True,worklist.DONOTMOVE,worklist.CLOSE)
        elif plate.curloc=="Magnet":
            worklist.vector("Magplate",decklayout.MAGPLATELOC,worklist.SAFETOEND,True,worklist.DONOTMOVE,worklist.CLOSE)
        elif plate.curloc=="Shaker":
            worklist.vector("Shaker",decklayout.SHAKERPLATELOC,worklist.SAFETOEND,True,worklist.DONOTMOVE,worklist.CLOSE)
        elif plate.curloc=="PTC":
            worklist.vector("PTC200",decklayout.PTCPOS,worklist.SAFETOEND,True,worklist.DONOTMOVE,worklist.CLOSE)
        else:
            print "Plate %s is in unknown location: %s"%(plate.name,plate.curloc)
            assert False

        if dest=="Home":
            plate.movetoloc(dest)
            worklist.vector(plate.vectorName,plate,worklist.SAFETOEND,True,worklist.DONOTMOVE,worklist.OPEN)
        elif dest=="Magnet":
            plate.movetoloc(dest,decklayout.MAGPLATELOC)
            worklist.vector("Magplate",decklayout.MAGPLATELOC,worklist.SAFETOEND,True,worklist.DONOTMOVE,worklist.OPEN)
        elif dest=="Shaker":
            plate.movetoloc(dest,decklayout.SHAKERPLATELOC)
            worklist.vector("Shaker",decklayout.SHAKERPLATELOC,worklist.SAFETOEND,True,worklist.DONOTMOVE,worklist.OPEN)
        elif dest=="PTC":
            plate.movetoloc(dest,decklayout.PTCPOS)
            worklist.vector("PTC200",decklayout.PTCPOS,worklist.SAFETOEND,True,worklist.DONOTMOVE,worklist.OPEN)
        else:
            print "Attempt to move plate %s to unknown location: %s"%(plate.name,dest)
            assert False

        Sample.addallhistory("{->%s}"%dest,onlyplate=plate.name)
        if returnHome:
            worklist.romahome()
Example #12
0
    def transfer(self, volume, src, dest, mix=(True,False), getDITI=True, dropDITI=True):
        if self.ptcrunning and (src.plate==decklayout.SAMPLEPLATE or dest.plate==decklayout.SAMPLEPLATE)>0:
            self.waitpgm()
            
        if volume>self.MAXVOLUME:
            destvol=dest.volume
            reuseTip=destvol<=0
            print "Splitting large transfer of %.1f ul into smaller chunks < %.1f ul "%(volume,self.MAXVOLUME),
            if reuseTip:
                print "with tip reuse"
            else:
                print "without tip reuse"
            self.transfer(self.MAXVOLUME,src,dest,mix,getDITI,False)
            self.transfer(volume-self.MAXVOLUME,src,dest,(mix[0] and not reuseTip,mix[1]),False,dropDITI)
            return

        cmt="Add %.1f ul of %s to %s"%(volume, src.name, dest.name)
        ditivolume=volume+src.inliquidLC.singletag
        if mix[0] and not src.isMixed():
            cmt=cmt+" with src mix"
            ditivolume=max(ditivolume,src.volume)
        if mix[1] and dest.volume>0 and not src.isMixed():
            cmt=cmt+" with dest mix"
            ditivolume=max(ditivolume,volume+dest.volume)
            #            print "Mix volume=%.1f ul"%(ditivolume)
        if self.useDiTis:
            tipMask=4
            if getDITI:
                worklist.getDITI(tipMask&self.DITIMASK,ditivolume)
        else:
            tipMask=self.cleantip()
        #print "*",cmt
        worklist.comment(cmt)

        if mix[0] and not src.isMixed():
            if src.plate==decklayout.SAMPLEPLATE or src.plate==decklayout.DILPLATE:
                self.shakeSamples([src])
            else:
                src.mix(tipMask)
        src.aspirate(tipMask,volume)
        dest.dispense(tipMask,volume,src)
        if mix[1]:
            dest.mix(tipMask,True)

        if self.useDiTis and dropDITI:
            worklist.dropDITI(tipMask&self.DITIMASK,decklayout.WASTE)
Example #13
0
 def runpgm(self,
            pgm,
            duration,
            waitForCompletion=True,
            volume=10,
            hotlidmode="TRACKING",
            hotlidtemp=1):
     if self.ptcrunning:
         logging.error(
             "Attempt to start a progam on PTC when it is already running")
     if len(pgm) > 8:
         logging.error("PTC program name (%s) too long (max is 8 char)" %
                       pgm)
     # move to thermocycler
     worklist.flushQueue()
     self.lihahome()
     cmt = "run %s" % pgm
     worklist.comment(cmt)
     #print "*",cmt
     worklist.pyrun("PTC\\ptclid.py OPEN")
     self.moveplate(decklayout.SAMPLEPLATE, "PTC")
     worklist.vector("Hotel 1 Lid", decklayout.HOTELPOS, worklist.SAFETOEND,
                     True, worklist.DONOTMOVE, worklist.CLOSE)
     worklist.vector("PTC200lid", decklayout.PTCPOS, worklist.SAFETOEND,
                     True, worklist.DONOTMOVE, worklist.OPEN)
     worklist.romahome()
     worklist.pyrun("PTC\\ptclid.py CLOSE")
     #        pgm="PAUSE30"  # For debugging
     assert hotlidmode == "TRACKING" or hotlidmode == "CONSTANT"
     assert (hotlidmode == "TRACKING" and hotlidtemp >= 0
             and hotlidtemp <= 45) or (hotlidmode == "CONSTANT"
                                       and hotlidtemp > 30)
     worklist.pyrun('PTC\\ptcrun.py %s CALC %s,%d %d' %
                    (pgm, hotlidmode, hotlidtemp, volume))
     self.pgmStartTime = clock.pipetting
     self.pgmEndTime = duration * 60 + clock.pipetting
     self.ptcrunning = True
     Sample.addallhistory("{%s}" % pgm,
                          addToEmpty=False,
                          onlyplate=decklayout.SAMPLEPLATE.name,
                          type="ptc")
     if waitForCompletion:
         self.waitpgm()
Example #14
0
    def __init__(self):
        'Create a new experiment with given sample locations for water and WASTE;  totalTime is expected run time in seconds, if known'
        worklist.comment("Generated %s"%(datetime.now().ctime()))
        worklist.userprompt("The following reagent tubes should be present: %s"%Sample.getAllLocOnPlate(decklayout.REAGENTPLATE))
        worklist.userprompt("The following eppendorf tubes should be present: %s"%Sample.getAllLocOnPlate(decklayout.EPPENDORFS))
        worklist.email(dest='*****@*****.**',subject='Run started (Generate: %s)'%(datetime.now().ctime()))
        worklist.email(dest='*****@*****.**',subject='Tecan error',onerror=1)
        self.cleanTips=0
        # self.sanitize()  # Not needed, TRP does it, also first use of tips will do this
        self.useDiTis=False
        self.ptcrunning=False
        self.overrideSanitize=False
        self.pgmStartTime=None
        self.pgmEndTime=None

        # Access PTC and RIC early to be sure they are working
        worklist.pyrun("PTC\\ptctest.py")
        #        worklist.periodicWash(15,4)
        worklist.userprompt("Verify that PTC thermocycler lid pressure is set to '2'.")
        self.idlePgms=[]
        self.timerStartTime=[None]*8
Example #15
0
    def __init__(self):
        'Create a new experiment with given sample locations for water and WASTE;  totalTime is expected run time in seconds, if known'
        self.checksum = md5sum(sys.argv[0])
        self.checksum = self.checksum[-4:]
        pyTecan = os.path.dirname(os.path.realpath(__file__))
        self.gitlabel = strip(
            subprocess.check_output(["git", "describe", "--always"],
                                    cwd=pyTecan))
        worklist.comment("Generated %s (%s-%s pyTecan-%s)" %
                         (datetime.now().ctime(), sys.argv[0], self.checksum,
                          self.gitlabel))
        worklist.userprompt(
            "The following reagent tubes should be present: %s" %
            Sample.getAllLocOnPlate(decklayout.REAGENTPLATE))
        worklist.userprompt(
            "The following eppendorf tubes should be present: %s" %
            Sample.getAllLocOnPlate(decklayout.EPPENDORFS))
        worklist.email(
            dest='*****@*****.**',
            subject='Run started (Generate: %s) expected runtime %.0f minutes'
            % (datetime.now().ctime(),
               clock.totalTime / 60.0 if clock.totalTime is not None else 0.0))
        worklist.email(dest='*****@*****.**',
                       subject='Tecan error',
                       onerror=1)
        self.cleanTips = 0
        # self.sanitize()  # Not needed, TRP does it, also first use of tips will do this
        self.useDiTis = False
        self.ptcrunning = False
        self.overrideSanitize = False
        self.pgmStartTime = None
        self.pgmEndTime = None

        # Access PTC and RIC early to be sure they are working
        worklist.pyrun("PTC\\ptctest.py")
        #        worklist.periodicWash(15,4)
        worklist.userprompt(
            "Verify that PTC thermocycler lid pressure is set to '2'.")
        self.idlePgms = []
        self.timerStartTime = [None] * 8
Example #16
0
    def dispose(self, volume, src, mix=False, getDITI=True, dropDITI=True):
        'Dispose of a given volume by aspirating and not dispensing (will go to waste during next wash)'
        if self.ptcrunning and src.plate == decklayout.SAMPLEPLATE:
            self.waitpgm()
        if volume > self.MAXVOLUME:
            reuseTip = False  # Since we need to wash to get rid of it
            msg = "Splitting large transfer of %.1f ul into smaller chunks < %.1f ul " % (
                volume, self.MAXVOLUME),
            if reuseTip:
                msg += "with tip reuse"
            else:
                msg += "without tip reuse"
            logging.notice(msg)
            self.dispose(self.MAXVOLUME, src, mix, getDITI, dropDITI)
            self.dispose(volume - self.MAXVOLUME, src, False, getDITI,
                         dropDITI)
            return

        cmt = "Remove and dispose of %.1f ul from %s" % (volume, src.name)
        ditivolume = volume + src.inliquidLC.singletag
        if mix and not src.isMixed():
            cmt = cmt + " with src mix"
            ditivolume = max(ditivolume, src.volume)
        if self.useDiTis:
            tipMask = 4
            if getDITI:
                worklist.getDITI(tipMask & self.DITIMASK, ditivolume)
        else:
            tipMask = self.cleantip()
        #print "*",cmt
        worklist.comment(cmt)

        if mix and not src.isMixed():
            src.mix(tipMask)
        src.aspirate(tipMask, volume)

        if self.useDiTis and dropDITI:
            worklist.dropDITI(tipMask & self.DITIMASK, decklayout.WASTE)
Example #17
0
    def transfer(self, volume, src, dest, mix=(True,False), getDITI=True, dropDITI=True):
        if self.ptcrunning and (src.plate==decklayout.SAMPLEPLATE or dest.plate==decklayout.SAMPLEPLATE)>0:
            self.waitpgm()

        if volume>self.MAXVOLUME:
            destvol=dest.volume
            reuseTip=destvol<=0
            msg="Splitting large transfer of %.1f ul into smaller chunks < %.1f ul "%(volume,self.MAXVOLUME)
            if reuseTip:
                msg+= "with tip reuse"
            else:
                msg+= "without tip reuse"
            logging.notice(msg)
            self.transfer(self.MAXVOLUME,src,dest,mix,getDITI,False)
            self.transfer(volume-self.MAXVOLUME,src,dest,(mix[0] and not reuseTip,mix[1]),False,dropDITI)
            return

        cmt="Add %.1f ul of %s to %s"%(volume, src.name, dest.name)
        ditivolume=volume+src.inliquidLC.singletag
        if mix[0] and not src.isMixed():
            cmt=cmt+" with src mix"
            ditivolume=max(ditivolume,src.volume)
        if mix[1] and dest.volume>0 and not src.isMixed():
            cmt=cmt+" with dest mix"
            ditivolume=max(ditivolume,volume+dest.volume)
            #            print "Mix volume=%.1f ul"%(ditivolume)
        if mix[0] and not src.isMixed() and (src.plate==decklayout.SAMPLEPLATE or src.plate==decklayout.DILPLATE):
            worklist.comment("shaking for src mix of "+src.name)
            self.shakeSamples([src])  # Need to do this before allocating a tip since washing during this will modify the tip clean states

        if self.useDiTis:
            tipMask=4
            if getDITI:
                worklist.getDITI(tipMask&self.DITIMASK,ditivolume)
        else:
            tipMask=self.cleantip()
        #print "*",cmt
        worklist.comment(cmt)

        if mix[0] and (not src.isMixed() or not src.wellMixed):
            if (src.plate==decklayout.SAMPLEPLATE or src.plate==decklayout.DILPLATE):
                logging.notice("Forcing pipette mix of "+src.name)
            worklist.comment("pipette mix for src mix of "+src.name)
            src.mix(tipMask)	# Manual mix (after allocating a tip for this)
            
        src.aspirate(tipMask,volume)
        dest.dispense(tipMask,volume,src)
        if mix[1]:
            dest.mix(tipMask,True)

        if self.useDiTis and dropDITI:
            worklist.dropDITI(tipMask&self.DITIMASK,decklayout.WASTE)
Example #18
0
 def sanitize(self,nmix=1,deepvol=20,force=False):
     'Deep wash including RNase-Away treatment'
     fixedTips=(~self.DITIMASK)&15
     worklist.flushQueue()
     if not force and fixedTips==self.cleanTips:
         # print no sanitize needed
         worklist.comment("Sanitize not needed cleanTips=%d"%self.cleanTips)
         return
     worklist.comment("Sanitize (cleanTips=%d)"%self.cleanTips)
     worklist.wash(15,1,2)
     fixedWells=[]
     if not self.overrideSanitize:
         for i in range(4):
             if (fixedTips & (1<<i)) != 0:
                 fixedWells.append(i)
                 decklayout.BLEACH.addhistory("SANITIZE",0,1<<i)
         worklist.mix(fixedTips,fixedWells,decklayout.BLEACH.mixLC,200,decklayout.BLEACH.plate,nmix,False)
         worklist.wash(fixedTips,1,deepvol,True)
     self.cleanTips|=fixedTips
     # print "* Sanitize"
     worklist.comment(clock.statusString())
Example #19
0
 def sanitize(self, nmix=1, deepvol=20, force=False):
     'Deep wash including RNase-Away treatment'
     fixedTips = (~self.DITIMASK) & 15
     worklist.flushQueue()
     if not force and fixedTips == self.cleanTips:
         # print no sanitize needed
         worklist.comment("Sanitize not needed cleanTips=%d" %
                          self.cleanTips)
         return
     worklist.comment("Sanitize (cleanTips=%d)" % self.cleanTips)
     worklist.wash(15, 1, 2)
     fixedWells = []
     if not self.overrideSanitize:
         for i in range(4):
             if (fixedTips & (1 << i)) != 0:
                 fixedWells.append(i)
                 decklayout.BLEACH.addhistory("SANITIZE", 0, 1 << i)
         worklist.mix(fixedTips, fixedWells, decklayout.BLEACH.mixLC, 200,
                      decklayout.BLEACH.plate, nmix, False)
         worklist.wash(fixedTips, 1, deepvol, True)
     self.cleanTips |= fixedTips
     # print "* Sanitize"
     worklist.comment(clock.statusString())
Example #20
0
    def stage(self,
              stagename,
              reagents,
              sources,
              samples,
              volume,
              finalx=1.0,
              destMix=True,
              dilutant=None):
        # Add water to sample wells as needed (multi)
        # Pipette reagents into sample wells (multi)
        # Pipette sources into sample wells
        # Concs are in x (>=1)

        # Sample.printallsamples("Before "+stagename)
        # print "\nStage: ", stagename, "reagents=",[str(r) for r in reagents], ",sources=",[str(s) for s in sources],",samples=",[str(s) for s in samples],str(volume)

        if len(samples) == 0:
            print "No samples\n"
            return

        if dilutant is None:
            dilutant = decklayout.WATER

        worklist.comment("Stage: " + stagename)
        if not isinstance(volume, list):
            volume = [volume for i in range(len(samples))]
        for i in range(len(volume)):
            assert volume[i] > 0
            volume[i] = float(volume[i])

        reagentvols = [
            1.0 / x.conc.dilutionneeded() * finalx for x in reagents
        ]
        if len(sources) > 0:
            sourcevols = [
                volume[i] * 1.0 / sources[i].conc.dilutionneeded() * finalx
                for i in range(len(sources))
            ]
            while len(sourcevols) < len(samples):
                sourcevols.append(0)
            watervols = [
                volume[i] * (1 - sum(reagentvols)) - samples[i].volume -
                sourcevols[i] for i in range(len(samples))
            ]
        else:
            watervols = [
                volume[i] * (1 - sum(reagentvols)) - samples[i].volume
                for i in range(len(samples))
            ]

        if min(watervols) < -0.01:
            print "Error: Ingredients add up to more than desired volume by %.1f ul" % (
                -min(watervols))
            for s in samples:
                if s.volume > 0:
                    print "Note: %s already contains %.1f ul\n" % (s.name,
                                                                   s.volume)
            assert False

        if sum(watervols) > 0.01:
            self.multitransfer(watervols, dilutant, samples,
                               (False, destMix and
                                (len(reagents) + len(sources) == 0)))

        for i in range(len(reagents)):
            self.multitransfer(
                [reagentvols[i] * v for v in volume], reagents[i], samples,
                (True, destMix and
                 (len(sources) == 0 and i == len(reagents) - 1)))

        if len(sources) > 0:
            assert len(sources) <= len(samples)
            for i in range(len(sources)):
                self.transfer(sourcevols[i], sources[i], samples[i],
                              (True, destMix))
Example #21
0
 def savegem(self, filename):
     worklist.comment("Completed (%s-%s)" % (sys.argv[0], self.checksum))
     worklist.flushQueue()
     worklist.savegem(decklayout.headerfile, filename)
Example #22
0
    def multitransfer(self,
                      volumes,
                      src,
                      dests,
                      mix=(True, False),
                      getDITI=True,
                      dropDITI=True,
                      ignoreContents=False,
                      extraFrac=0.05):
        'Multi pipette from src to multiple dest.  mix is (src,dest) mixing -- only mix src if needed though'
        #print "multitransfer(",volumes,",",src,",",dests,",",mix,",",getDITI,",",dropDITI,")"
        if self.ptcrunning and (src.plate == decklayout.SAMPLEPLATE or len(
            [1 for d in dests if d.plate == decklayout.SAMPLEPLATE]) > 0):
            self.waitpgm()

        if isinstance(volumes, (int, long, float)):
            # Same volume for each dest
            volumes = [volumes for i in range(len(dests))]
        assert len(volumes) == len(dests)
        #        if len([d.volume for d in dests if d.conc!=None])==0:
        if len([
                dests[i].volume for i in range(0, len(dests))
                if dests[i].conc != None and volumes[i] > 0.01
        ]) == 0:
            maxval = 0
        else:
            maxval = max([
                dests[i].volume for i in range(0, len(dests))
                if dests[i].conc != None and volumes[i] > 0.01
            ])
            #         maxval=max([d.volume for d in dests if d.conc != None])
        #print "volumes=",[d.volume for d in dests],", conc=",[str(d.conc) for d in dests],", maxval=",maxval
        if not mix[1] and len(volumes) > 1 and (maxval < .01
                                                or ignoreContents):
            if sum(volumes) * (1 + extraFrac) > self.MAXVOLUME:
                #print "sum(volumes)=%.1f, MAXVOL=%.1f"%(sum(volumes),self.MAXVOLUME)
                for i in range(1, len(volumes)):
                    if sum(volumes[0:i + 1]) * (1 +
                                                extraFrac) > self.MAXVOLUME:
                        destvol = max([d.volume for d in dests[0:i]])
                        reuseTip = destvol <= 0
                        # print "Splitting multi with total volume of %.1f ul into smaller chunks < %.1f ul after %d dispenses "%(sum(volumes),self.MAXVOLUME,i),
                        # if reuseTip:
                        #     print "with tip reuse"
                        # else:
                        #     print "without tip reuse"
                        self.multitransfer(volumes[0:i],
                                           src,
                                           dests[0:i],
                                           mix,
                                           getDITI,
                                           not reuseTip,
                                           extraFrac=extraFrac)
                        self.multitransfer(volumes[i:],
                                           src,
                                           dests[i:], (False, mix[1]),
                                           not reuseTip,
                                           dropDITI,
                                           extraFrac=extraFrac)
                        return

            if self.useDiTis:
                tipMask = 4
                if getDITI:
                    ditivol = sum(volumes) * (
                        1 + extraFrac
                    ) + src.inliquidLC.multicond + src.inliquidLC.multiexcess
                    worklist.getDITI(tipMask & self.DITIMASK,
                                     min(self.MAXVOLUME, ditivol), True, True)
            else:
                tipMask = self.cleantip()

            cmt = "Multi-add  %s to samples %s" % (src.name, ",".join(
                "%s[%.1f]" % (dests[i].name, volumes[i])
                for i in range(len(dests))))
            #print "*",cmt
            worklist.comment(cmt)

            if mix[0] and not src.isMixed():
                if src.plate == decklayout.SAMPLEPLATE or src.plate == decklayout.DILPLATE:
                    self.shakeSamples([src])
                else:
                    src.mix(tipMask)
            src.aspirate(tipMask,
                         sum(volumes) * (1 + extraFrac),
                         True)  # Aspirate extra
            for i in range(len(dests)):
                if volumes[i] > 0.01:
                    dests[i].dispense(tipMask, volumes[i], src)
            if self.useDiTis and dropDITI:
                worklist.dropDITI(tipMask & self.DITIMASK, decklayout.WASTE)
        else:
            for i in range(len(dests)):
                if volumes[i] > 0.01:
                    self.transfer(volumes[i], src, dests[i],
                                  (mix[0] and i == 0, mix[1]), getDITI,
                                  dropDITI)
Example #23
0
    def volcheck(self,tipMask,well,volToRemove):
        '''Check if the well contains the expected volume'''
        if self.lastvolcheck is not None:
            # Decide if a volume check is needed
            if volToRemove==0:
                # No need to check if not removing anything and it has been checked previously (i.e. lastvolcheck is not None)
                return
            if self.volume-volToRemove > max(30,self.lastvolcheck-200) or self.volume-volToRemove>200:
                # Not needed
                return
        self.lastvolcheck=self.volume
        height=self.plate.getliquidheight(self.volume)
        gemvol=self.plate.getgemliquidvolume(height)	# Volume that would be reported by Gemini for this height
        if gemvol is None:
            logging.warning( "No volume equation for %s, skipping initial volume check"%self.name)
            return

        volwarn=self.volume*0.80
        heightwarn=min(self.plate.getliquidheight(volwarn),height-1.0)	# threshold is lower of 1mm or 80%
        gemvolwarn=self.plate.getgemliquidvolume(heightwarn)	# Volume that would be reported by Gemini for this height

        volcrit=self.plate.unusableVolume*0.8+volToRemove
        heightcrit=self.plate.getliquidheight(volcrit)
        gemvolcrit=self.plate.getgemliquidvolume(heightcrit)	# Volume that would be reported by Gemini for this height
    
        worklist.flushQueue()
        worklist.comment( "Check that %s contains %.1f ul (warn< %.1f, crit<%.1f), (gemvol=%.1f (warn<%.1f,crit<%.1f); height=%.1f (>%.1f) )"%(self.name,self.volume,volwarn,volcrit,gemvol,gemvolwarn,gemvolcrit,height,heightwarn))
        tipnum=0
        tm=tipMask
        while tm>0:
            tm=tm>>1
            tipnum+=1

        volvar='detected_volume_%d'%tipnum
        worklist.variable(volvar,-2)
        worklist.detectLiquid(tipMask,well,self.inliquidLC,self.plate)
        doneLabel=worklist.getlabel()
        worklist.condition(volvar,">",gemvolwarn,doneLabel)
        ptmp=clock.pipetting;
        warnLabel=worklist.getlabel()
        worklist.condition(volvar,">",gemvolcrit,warnLabel)
        worklist.moveliha(worklist.WASHLOC)	# Get LiHa out of the way
        msg="Failed volume check of %s - should have  %.0f ul (gemvol=~%s~, crit=%.0f)"%(self.name,self.volume,volvar,gemvolcrit)
        worklist.email(dest='*****@*****.**',subject=msg)
        worklist.stringvariable("response","retry",msg+" Enter 'ignore' to ignore and continue, otherwise will retry.")
        worklist.condition("response","==","ignore",doneLabel)
        # Retry
        worklist.detectLiquid(tipMask,well,self.inliquidLC,self.plate)
        worklist.condition(volvar,">",gemvolcrit,doneLabel)
        worklist.stringvariable("response","retry","Still have <%.0f. Enter 'ignore' to ignore and continue, otherwise will retry."%self.volume)
        worklist.condition("response","==","ignore",doneLabel)
        # Retry again
        worklist.detectLiquid(tipMask,well,self.inliquidLC,self.plate)
        worklist.condition(volvar,">",gemvolcrit,doneLabel)
        worklist.stringvariable("response","ignore","Still have <%.0f. Will continue regardless."%self.volume)
        worklist.condition("response","!=","warn",doneLabel)

        worklist.comment(warnLabel)
        msg="Warning: volume check of %s - should have  %.0f ul (gemvol=~%s~, warn=%.0f, crit=%.0f)"%(self.name,self.volume,volvar,gemvolwarn,gemvolcrit)
        worklist.email(dest='*****@*****.**',subject=msg)
        worklist.comment(doneLabel)
        clock.pipetting=ptmp   # All the retries don't usually happen, so don't count in total time
        self.addhistory("LD",0,tipMask)
Example #24
0
 def savegem(self,filename):
     worklist.comment("Completed (%s-%s)"%(sys.argv[0],self.checksum))
     worklist.flushQueue()
     worklist.savegem(decklayout.headerfile,filename)
Example #25
0
    def moveplate(self, plate, dest="Home", returnHome=True):
        if self.ptcrunning and plate == decklayout.SAMPLEPLATE:
            self.waitpgm()

        # move to given destination (one of "Home","Magnet","Shaker","PTC" )
        if plate != decklayout.SAMPLEPLATE and plate != decklayout.DILPLATE:
            print "Only able to move %s or %s plates, not %s" % (
                decklayout.SAMPLEPLATE.name, decklayout.DILPLATE.name,
                plate.name)
            assert False

        if plate.curloc == dest:
            #print "Plate %s is already at %s"%(plate.name,dest)
            return

        #print "Move plate %s from %s to %s"%(plate.name,plate.curloc,dest)
        worklist.flushQueue()
        self.lihahome()
        cmt = "moveplate %s %s" % (plate.name, dest)
        worklist.comment(cmt)
        if plate.curloc == "Home":
            worklist.vector(plate.vectorName, plate, worklist.SAFETOEND, True,
                            worklist.DONOTMOVE, worklist.CLOSE)
        elif plate.curloc == "Magnet":
            worklist.vector("Magplate", decklayout.MAGPLATELOC,
                            worklist.SAFETOEND, True, worklist.DONOTMOVE,
                            worklist.CLOSE)
        elif plate.curloc == "Shaker":
            worklist.vector("Shaker", decklayout.SHAKERPLATELOC,
                            worklist.SAFETOEND, True, worklist.DONOTMOVE,
                            worklist.CLOSE)
        elif plate.curloc == "PTC":
            worklist.vector("PTC200", decklayout.PTCPOS, worklist.SAFETOEND,
                            True, worklist.DONOTMOVE, worklist.CLOSE)
        else:
            print "Plate %s is in unknown location: %s" % (plate.name,
                                                           plate.curloc)
            assert False

        if dest == "Home":
            plate.movetoloc(dest)
            worklist.vector(plate.vectorName, plate, worklist.SAFETOEND, True,
                            worklist.DONOTMOVE, worklist.OPEN)
        elif dest == "Magnet":
            plate.movetoloc(dest, decklayout.MAGPLATELOC)
            worklist.vector("Magplate", decklayout.MAGPLATELOC,
                            worklist.SAFETOEND, True, worklist.DONOTMOVE,
                            worklist.OPEN)
        elif dest == "Shaker":
            plate.movetoloc(dest, decklayout.SHAKERPLATELOC)
            worklist.vector("Shaker", decklayout.SHAKERPLATELOC,
                            worklist.SAFETOEND, True, worklist.DONOTMOVE,
                            worklist.OPEN)
        elif dest == "PTC":
            plate.movetoloc(dest, decklayout.PTCPOS)
            worklist.vector("PTC200", decklayout.PTCPOS, worklist.SAFETOEND,
                            True, worklist.DONOTMOVE, worklist.OPEN)
        else:
            print "Attempt to move plate %s to unknown location: %s" % (
                plate.name, dest)
            assert False

        Sample.addallhistory("{->%s}" % dest, onlyplate=plate.name)
        if returnHome:
            worklist.romahome()
Example #26
0
    def volcheck(self, tipMask, well, volToRemove):
        '''Check if the well contains the expected volume'''
        if self.lastvolcheck is not None:
            # Decide if a volume check is needed
            if volToRemove == 0:
                # No need to check if not removing anything and it has been checked previously (i.e. lastvolcheck is not None)
                return
            if self.volume - volToRemove > max(
                    30, self.lastvolcheck -
                    200) or self.volume - volToRemove > 200:
                # Not needed
                return
        self.lastvolcheck = self.volume
        height = self.plate.getliquidheight(self.volume)
        gemvol = self.plate.getgemliquidvolume(
            height)  # Volume that would be reported by Gemini for this height
        if gemvol is None:
            logging.warning(
                "No volume equation for %s, skipping initial volume check" %
                self.name)
            return

        volcrit = self.plate.unusableVolume * 0.8 + volToRemove
        volwarn = min(volcrit, self.volume * 0.80)

        heightwarn = min(self.plate.getliquidheight(volwarn),
                         height - 1.0)  # threshold is lower of 1mm or 80%
        gemvolwarn = self.plate.getgemliquidvolume(
            heightwarn
        )  # Volume that would be reported by Gemini for this height

        heightcrit = self.plate.getliquidheight(volcrit)
        gemvolcrit = self.plate.getgemliquidvolume(
            heightcrit
        )  # Volume that would be reported by Gemini for this height

        worklist.flushQueue()
        worklist.comment(
            "Check that %s contains %.1f ul (warn< %.1f, crit<%.1f), (gemvol=%.1f (warn<%.1f,crit<%.1f); height=%.1f (>%.1f) )"
            % (self.name, self.volume, volwarn, volcrit, gemvol, gemvolwarn,
               gemvolcrit, height, heightwarn))
        tipnum = 0
        tm = tipMask
        while tm > 0:
            tm = tm >> 1
            tipnum += 1

        volvar = 'detected_volume_%d' % tipnum
        worklist.variable(volvar, -2)
        worklist.detectLiquid(tipMask, well, self.inliquidLC, self.plate)
        doneLabel = worklist.getlabel()
        worklist.condition(volvar, ">", gemvolwarn, doneLabel)
        ptmp = clock.pipetting
        warnLabel = worklist.getlabel()
        worklist.condition(volvar, ">", gemvolcrit, warnLabel)
        worklist.moveliha(worklist.WASHLOC)  # Get LiHa out of the way
        msg = "Failed volume check of %s - should have  %.0f ul (gemvol=~%s~, crit=%.0f)" % (
            self.name, self.volume, volvar, gemvolcrit)
        worklist.email(dest='*****@*****.**', subject=msg)
        worklist.stringvariable(
            "response", "retry", msg +
            " Enter 'ignore' to ignore and continue, otherwise will retry.")
        worklist.condition("response", "==", "ignore", doneLabel)
        # Retry
        worklist.detectLiquid(tipMask, well, self.inliquidLC, self.plate)
        worklist.condition(volvar, ">", gemvolcrit, doneLabel)
        worklist.stringvariable(
            "response", "retry",
            "Still have <%.0f. Enter 'ignore' to ignore and continue, otherwise will retry."
            % self.volume)
        worklist.condition("response", "==", "ignore", doneLabel)
        # Retry again
        worklist.detectLiquid(tipMask, well, self.inliquidLC, self.plate)
        worklist.condition(volvar, ">", gemvolcrit, doneLabel)
        worklist.stringvariable(
            "response", "ignore",
            "Still have <%.0f. Will continue regardless." % self.volume)
        worklist.condition("response", "!=", "warn", doneLabel)

        worklist.comment(warnLabel)
        msg = "Warning: volume check of %s - should have  %.0f ul (gemvol=~%s~, warn=%.0f, crit=%.0f)" % (
            self.name, self.volume, volvar, gemvolwarn, gemvolcrit)
        worklist.email(dest='*****@*****.**', subject=msg)
        worklist.comment(doneLabel)
        clock.pipetting = ptmp  # All the retries don't usually happen, so don't count in total time
        self.addhistory("LD", 0, tipMask, "detect")
Example #27
0
    def waitpgm(self, sanitize=True):
        if not self.ptcrunning:
            return
        #print "* Wait for PTC to finish"
        if sanitize:
            self.sanitize()  # Sanitize tips before waiting for this to be done
        worklist.comment("Wait for PTC")
        while self.pgmEndTime - clock.pipetting > 120:
            # Run any idle programs
            oldElapsed = clock.pipetting
            for ip in self.idlePgms:
                if self.pgmEndTime - clock.pipetting > 120:
                    #print "Executing idle program with %.0f seconds"%(self.pgmEndTime-clock.pipetting)
                    ip(self.pgmEndTime - clock.pipetting - 120)
            if oldElapsed == clock.pipetting:
                # Nothing was done
                break
            worklist.flushQueue()  # Just in case

        clock.pipandthermotime += (clock.pipetting - self.pgmStartTime)
        clock.thermotime += (self.pgmEndTime - clock.pipetting)
        clock.pipetting = self.pgmStartTime

        #print "Waiting for PTC with %.0f seconds expected to remain"%(self.pgmEndTime-clock.pipetting)
        worklist.pyrun('PTC\\ptcwait.py')
        worklist.pyrun("PTC\\ptclid.py OPEN")
        #        worklist.pyrun('PTC\\ptcrun.py %s CALC ON'%"COOLDOWN")
        #        worklist.pyrun('PTC\\ptcwait.py')
        worklist.vector("PTC200lid", decklayout.PTCPOS, worklist.SAFETOEND,
                        True, worklist.DONOTMOVE, worklist.CLOSE)
        worklist.vector("Hotel 1 Lid", decklayout.HOTELPOS, worklist.SAFETOEND,
                        True, worklist.DONOTMOVE, worklist.OPEN)

        worklist.vector("PTC200WigglePos", decklayout.PTCPOS,
                        worklist.SAFETOEND, False, worklist.DONOTMOVE,
                        worklist.DONOTMOVE)
        worklist.vector("PTC200Wiggle", decklayout.PTCPOS, worklist.SAFETOEND,
                        False, worklist.DONOTMOVE, worklist.CLOSE, True)
        worklist.vector("PTC200Wiggle", decklayout.PTCPOS, worklist.ENDTOSAFE,
                        False, worklist.DONOTMOVE, worklist.OPEN, True)
        worklist.vector("PTC200WigglePos", decklayout.PTCPOS,
                        worklist.ENDTOSAFE, False, worklist.DONOTMOVE,
                        worklist.DONOTMOVE)

        worklist.vector("PTC200Wiggle2Pos", decklayout.PTCPOS,
                        worklist.SAFETOEND, False, worklist.DONOTMOVE,
                        worklist.DONOTMOVE)
        worklist.vector("PTC200Wiggle2", decklayout.PTCPOS, worklist.SAFETOEND,
                        False, worklist.DONOTMOVE, worklist.CLOSE, True)
        worklist.vector("PTC200Wiggle2", decklayout.PTCPOS, worklist.ENDTOSAFE,
                        False, worklist.DONOTMOVE, worklist.OPEN, True)
        worklist.vector("PTC200Wiggle2Pos", decklayout.PTCPOS,
                        worklist.ENDTOSAFE, False, worklist.DONOTMOVE,
                        worklist.DONOTMOVE)

        worklist.vector("PTC200WigglePos", decklayout.PTCPOS,
                        worklist.SAFETOEND, False, worklist.DONOTMOVE,
                        worklist.DONOTMOVE)
        worklist.vector("PTC200Wiggle", decklayout.PTCPOS, worklist.SAFETOEND,
                        False, worklist.DONOTMOVE, worklist.CLOSE, True)
        worklist.vector("PTC200Wiggle", decklayout.PTCPOS, worklist.ENDTOSAFE,
                        False, worklist.DONOTMOVE, worklist.OPEN, True)
        worklist.vector("PTC200WigglePos", decklayout.PTCPOS,
                        worklist.ENDTOSAFE, False, worklist.DONOTMOVE,
                        worklist.DONOTMOVE)

        self.ptcrunning = False
        self.moveplate(decklayout.SAMPLEPLATE, "Home")
        # Mark all samples on plate as unmixed (due to condensation)
        Sample.notMixed(decklayout.SAMPLEPLATE.name)
        # Verify plate is in place
        worklist.vector(decklayout.SAMPLEPLATE.vectorName,
                        decklayout.SAMPLEPLATE, worklist.SAFETOEND, False,
                        worklist.DONOTMOVE, worklist.CLOSE)
        worklist.vector(decklayout.SAMPLEPLATE.vectorName,
                        decklayout.SAMPLEPLATE, worklist.ENDTOSAFE, False,
                        worklist.OPEN, worklist.DONOTMOVE)
        worklist.romahome()
        #worklist.userprompt("Plate should be back on deck. Press return to continue")
        # Wash tips again to remove any drips that may have formed while waiting for PTC
        worklist.wash(15, 1, 5, True)
Example #28
0
    def transfer(self,
                 volume,
                 src,
                 dest,
                 mix=(True, False),
                 getDITI=True,
                 dropDITI=True):
        if self.ptcrunning and (src.plate == decklayout.SAMPLEPLATE
                                or dest.plate == decklayout.SAMPLEPLATE) > 0:
            self.waitpgm()

        if volume > self.MAXVOLUME:
            destvol = dest.volume
            reuseTip = destvol <= 0
            msg = "Splitting large transfer of %.1f ul into smaller chunks < %.1f ul " % (
                volume, self.MAXVOLUME)
            if reuseTip:
                msg += "with tip reuse"
            else:
                msg += "without tip reuse"
            logging.notice(msg)
            self.transfer(self.MAXVOLUME, src, dest, mix, getDITI, False)
            self.transfer(volume - self.MAXVOLUME, src, dest,
                          (mix[0] and not reuseTip, mix[1]), False, dropDITI)
            return

        cmt = "Add %.1f ul of %s to %s" % (volume, src.name, dest.name)
        ditivolume = volume + src.inliquidLC.singletag
        if mix[0] and not src.isMixed():
            cmt = cmt + " with src mix"
            ditivolume = max(ditivolume, src.volume)
        if mix[1] and dest.volume > 0 and not src.isMixed():
            cmt = cmt + " with dest mix"
            ditivolume = max(ditivolume, volume + dest.volume)
            #            print "Mix volume=%.1f ul"%(ditivolume)
        if mix[0] and not src.isMixed() and (
                src.plate == decklayout.SAMPLEPLATE
                or src.plate == decklayout.DILPLATE):
            worklist.comment("shaking for src mix of " + src.name)
            self.shakeSamples(
                [src]
            )  # Need to do this before allocating a tip since washing during this will modify the tip clean states

        if self.useDiTis:
            tipMask = 4
            if getDITI:
                worklist.getDITI(tipMask & self.DITIMASK, ditivolume)
        else:
            tipMask = self.cleantip()
        #print "*",cmt
        worklist.comment(cmt)

        if mix[0] and (not src.isMixed() or not src.wellMixed):
            if (src.plate == decklayout.SAMPLEPLATE
                    or src.plate == decklayout.DILPLATE):
                logging.notice("Forcing pipette mix of " + src.name)
            worklist.comment("pipette mix for src mix of " + src.name)
            src.mix(tipMask)  # Manual mix (after allocating a tip for this)

        src.aspirate(tipMask, volume)
        dest.dispense(tipMask, volume, src)
        if mix[1]:
            dest.mix(tipMask, True)

        if self.useDiTis and dropDITI:
            worklist.dropDITI(tipMask & self.DITIMASK, decklayout.WASTE)