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
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
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)
def setreagenttemp(self,temp=None): if temp is None: worklist.pyrun("RIC\\ricset.py IDLE") decklayout.REAGENTPLATE.liquidTemp=22.7 else: worklist.variable("dewpoint",temp,userprompt="Enter dewpoint",minval=0,maxval=20) worklist.variable("rictemp","~dewpoint~+2") worklist.pyrun("RIC\\ricset.py ~rictemp~") decklayout.REAGENTPLATE.liquidTemp=temp+2 # Assumes that temp is the one used
def setreagenttemp(self, temp=None): if temp is None: worklist.pyrun("RIC\\ricset.py IDLE") decklayout.REAGENTPLATE.liquidTemp = 22.7 else: worklist.variable("dewpoint", temp, userprompt="Enter dewpoint", minval=0, maxval=20) worklist.variable("rictemp", "~dewpoint~+2") worklist.pyrun("RIC\\ricset.py ~rictemp~") decklayout.REAGENTPLATE.liquidTemp = temp + 2 # Assumes that temp is the one used
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
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()
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
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()
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)
def shake(self, plate, dur=60, speed=None, accel=5, returnPlate=True, samps=None): if self.ptcrunning and plate == decklayout.SAMPLEPLATE: self.waitpgm() # Move the plate to the shaker, run for the given time, and bring plate back allsamps = Sample.getAllOnPlate(plate) if samps is None: samps = allsamps if all([x.isMixed() for x in samps]): print "No need to shake ", plate maxvol = max([x.volume for x in allsamps]) minvol = min([x.volume for x in samps if not x.isMixed()] + [200]) (minspeed, maxspeed) = plate.getmixspeeds( minvol * 0.95, maxvol + 5) # Assume volumes could be off if minspeed > maxspeed: print "minspeed(", minspeed, ") > maxspeed (", maxspeed, ")" if speed is None: if minspeed < maxspeed: speed = (maxspeed + minspeed) / 2 else: speed = maxspeed warned = False if speed > maxspeed: print "WARNING: %s plate contains wells with up to %.2f ul, which may spill at %d RPM: " % ( plate.name, maxvol, speed), for x in samps: tmp = plate.getmixspeeds(x.volume, x.volume) if tmp[1] < speed: print "%s[%.1ful, max=%.0f RPM] " % (x.name, x.volume, tmp[1]), print warned = True if globals.verbose and speed < minspeed: print "NOTICE: %s plate contains unmixed wells that may not be mixed at %d RPM: " % ( plate.name, speed), for x in samps: if x.isMixed(): continue tmp = plate.getmixspeeds(x.volume * 0.95, x.volume + 5) if speed < tmp[0]: print "%s[%.1ful, min=%.0f RPM, max=%.0f RPM] " % ( x.name, x.volume, tmp[0], tmp[1]), print warned = True if warned or globals.verbose: print " Mixing %s at %.0f RPM (min unmixed vol=%.0ful -> min RPM=%.0f; max vol=%.0ful -> max RPM=%.f)" % ( plate.name, speed, minvol, minspeed, maxvol, maxspeed) oldloc = plate.curloc self.moveplate(plate, "Shaker", returnHome=False) global __shakerActive __shakerActive = True worklist.pyrun("BioShake\\bioexec.py setElmLockPos") worklist.pyrun("BioShake\\bioexec.py setShakeTargetSpeed%d" % speed) worklist.pyrun("BioShake\\bioexec.py setShakeAcceleration%d" % accel) worklist.pyrun("BioShake\\bioexec.py shakeOn") self.starttimer() Sample.shaken(plate.name, speed) Sample.addallhistory("(S%d@%.0f)" % (dur, speed), onlyplate=plate.name) self.waittimer(dur) worklist.pyrun("BioShake\\bioexec.py shakeOff") self.starttimer() self.waittimer(accel + 4) worklist.pyrun("BioShake\\bioexec.py setElmUnlockPos") __shakerActive = False if returnPlate: self.moveplate(plate, oldloc)
def shake(self,plate,dur=60,speed=None,accel=5,returnPlate=True,samps=None,force=False): if self.ptcrunning and plate==decklayout.SAMPLEPLATE: self.waitpgm() # Move the plate to the shaker, run for the given time, and bring plate back allsamps=Sample.getAllOnPlate(plate) if samps is None: samps=allsamps if all([x.isMixed() for x in samps]) and not force: logging.notice( "No need to shake "+plate.name+", but doing so anyway.") minspeed=0 maxspeed=2000 for x in samps: (a,b)=x.getmixspeeds() minspeed=max([a,minspeed]) maxspeed=min([b,maxspeed]) if speed is None: if minspeed<maxspeed: speed=max((maxspeed+minspeed)/2,maxspeed-50) # Mix as fast as safely possible (but always above minspeed) else: speed=maxspeed if speed<minspeed-2 or speed>maxspeed+2: others="" for x in allsamps: (a,b)=x.getmixspeeds() if b<minspeed or a>maxspeed: if a is not None and a>0: others+=" {%s: %.1ful,G=%.2f%%,min=%.0f,max=%.0f}"%(x.name,x.volume,x.glycerolfrac()*100,a,b) else: others+=" {%s: %.1ful,G=%.2f%%,max=%.0f}"%(x.name,x.volume,x.glycerolfrac()*100,b) logging.mixwarning("Mixing %s at %.0f RPM; minspeed(%.0f) > maxspeed(%.0f), limits=[%s]"%(plate.name,speed,minspeed,maxspeed,others)) else: logging.notice("Mixing %s at %.0f RPM ( min RPM=%.0f, max RPM=%.f)"%(plate.name, speed, minspeed, maxspeed)) oldloc=plate.curloc self.moveplate(plate,"Shaker",returnHome=False) global __shakerActive __shakerActive=True worklist.pyrun("BioShake\\bioexec.py setElmLockPos") worklist.pyrun("BioShake\\bioexec.py setShakeTargetSpeed%d"%speed) worklist.pyrun("BioShake\\bioexec.py setShakeAcceleration%d"%accel) worklist.pyrun("BioShake\\bioexec.py shakeOn") self.starttimer() Sample.shaken(plate.name,speed) Sample.addallhistory("(S%d@%.0f)"%(dur,speed),onlyplate=plate.name) self.waittimer(dur) worklist.pyrun("BioShake\\bioexec.py shakeOff") self.starttimer() self.waittimer(accel+4) worklist.pyrun("BioShake\\bioexec.py setElmUnlockPos") __shakerActive=False if returnPlate: self.moveplate(plate,oldloc)
def shake(self,plate,dur=60,speed=None,accel=5,returnPlate=True,samps=None): if self.ptcrunning and plate==decklayout.SAMPLEPLATE: self.waitpgm() # Move the plate to the shaker, run for the given time, and bring plate back allsamps=Sample.getAllOnPlate(plate) if samps is None: samps=allsamps if all([x.isMixed() for x in samps]): print "No need to shake ",plate maxvol=max([x.volume for x in allsamps]) minvol=min([x.volume for x in samps if not x.isMixed() ]+[200]) (minspeed,maxspeed)=plate.getmixspeeds(minvol*0.95,maxvol+5) # Assume volumes could be off if minspeed>maxspeed: print "minspeed(",minspeed,") > maxspeed (",maxspeed,")" if speed is None: if minspeed<maxspeed: speed=(maxspeed+minspeed)/2 else: speed=maxspeed warned=False if speed>maxspeed: print "WARNING: %s plate contains wells with up to %.2f ul, which may spill at %d RPM: "%(plate.name, maxvol, speed), for x in samps: tmp=plate.getmixspeeds(x.volume,x.volume) if tmp[1]<speed: print "%s[%.1ful, max=%.0f RPM] "%(x.name,x.volume,tmp[1]), print warned=True if globals.verbose and speed<minspeed: print "NOTICE: %s plate contains unmixed wells that may not be mixed at %d RPM: "%(plate.name, speed), for x in samps: if x.isMixed(): continue tmp=plate.getmixspeeds(x.volume*0.95,x.volume+5) if speed<tmp[0]: print "%s[%.1ful, min=%.0f RPM, max=%.0f RPM] "%(x.name,x.volume,tmp[0],tmp[1]), print warned=True if warned or globals.verbose: print " Mixing %s at %.0f RPM (min unmixed vol=%.0ful -> min RPM=%.0f; max vol=%.0ful -> max RPM=%.f)"%(plate.name, speed, minvol, minspeed, maxvol, maxspeed) oldloc=plate.curloc self.moveplate(plate,"Shaker",returnHome=False) global __shakerActive __shakerActive=True worklist.pyrun("BioShake\\bioexec.py setElmLockPos") worklist.pyrun("BioShake\\bioexec.py setShakeTargetSpeed%d"%speed) worklist.pyrun("BioShake\\bioexec.py setShakeAcceleration%d"%accel) worklist.pyrun("BioShake\\bioexec.py shakeOn") self.starttimer() Sample.shaken(plate.name,speed) Sample.addallhistory("(S%d@%.0f)"%(dur,speed),onlyplate=plate.name) self.waittimer(dur) worklist.pyrun("BioShake\\bioexec.py shakeOff") self.starttimer() self.waittimer(accel+4) worklist.pyrun("BioShake\\bioexec.py setElmUnlockPos") __shakerActive=False if returnPlate: self.moveplate(plate,oldloc)
def shake(self, plate, dur=60, speed=None, accel=5, returnPlate=True, samps=None, force=False): if self.ptcrunning and plate == decklayout.SAMPLEPLATE: self.waitpgm() # Move the plate to the shaker, run for the given time, and bring plate back allsamps = Sample.getAllOnPlate(plate) if samps is None: samps = allsamps if all([x.isMixed() for x in samps]) and not force: logging.notice("No need to shake " + plate.name + ", but doing so anyway.") minspeed = 0 maxspeed = 2000 for x in samps: (a, b) = x.getmixspeeds() minspeed = max([a, minspeed]) for x in allsamps: (a, b) = x.getmixspeeds() maxspeed = min([b, maxspeed]) if speed is None: if minspeed < maxspeed: speed = max( (maxspeed + minspeed) / 2, maxspeed - 50 ) # Mix as fast as safely possible (but always above minspeed) else: speed = maxspeed if speed < minspeed - 2 or speed > maxspeed + 2: others = "" for x in allsamps: (a, b) = x.getmixspeeds() if b < minspeed or a > maxspeed: if a is not None and a > 0: others += " {%s: %.1ful,G=%.2f%%,min=%.0f,max=%.0f}" % ( x.name, x.volume, x.glycerolfrac() * 100, a, b) else: others += " {%s: %.1ful,G=%.2f%%,max=%.0f}" % ( x.name, x.volume, x.glycerolfrac() * 100, b) logging.mixwarning( "Mixing %s at %.0f RPM; minspeed(%.0f) > maxspeed(%.0f), limits=[%s]" % (plate.name, speed, minspeed, maxspeed, others)) else: logging.notice( "Mixing %s at %.0f RPM ( min RPM=%.0f, max RPM=%.f)" % (plate.name, speed, minspeed, maxspeed)) oldloc = plate.curloc self.moveplate(plate, "Shaker", returnHome=False) global __shakerActive __shakerActive = True worklist.pyrun("BioShake\\bioexec.py setElmLockPos") worklist.pyrun("BioShake\\bioexec.py setShakeTargetSpeed%d" % speed) worklist.pyrun("BioShake\\bioexec.py setShakeAcceleration%d" % accel) worklist.pyrun("BioShake\\bioexec.py shakeOn") self.starttimer() Sample.shaken(plate.name, speed) Sample.addallhistory("(S%d@%.0f)" % (dur, speed), onlyplate=plate.name, type="shake") self.waittimer(dur) worklist.pyrun("BioShake\\bioexec.py shakeOff") self.starttimer() self.waittimer(accel + 4) worklist.pyrun("BioShake\\bioexec.py setElmUnlockPos") __shakerActive = False if returnPlate: self.moveplate(plate, oldloc)