def mix(self,tipMask,preaspirateAir=False,nmix=4): if self.isMixed() and self.wellMixed: logging.notice( "mix() called for sample %s, which is already mixed"%self.name) return False logging.mixwarning("Pipette mixing of %s may introduce bubbles"%self.name) self.volcheck(tipMask,[self.well],0) blowvol=5 mstr="" extraspace=blowvol+0.1 if preaspirateAir: extraspace+=5 mixvol=self.volume # -self.plate.unusableVolume; # Can mix entire volume, if air is aspirated, it will just be dispensed first without making a bubble if self.volume>MAXVOLUME-extraspace: mixvol=MAXVOLUME-extraspace logging.mixwarning("Mix of %s limited to %.0f ul instead of full volume of %.0ful"%(self.name,mixvol,self.volume)) well=[self.well if self.well!=None else 2**(tipMask-1)-1 ] mixprefillvol=5 if mixvol<self.plate.unusableVolume-mixprefillvol: logging.notice("Not enough volume in sample %s (%.1f) to mix"%(self.name,self.volume)) self.history+="(UNMIXED)" return False else: if preaspirateAir: # Aspirate some air to avoid mixing with excess volume aspirated into pipette from source in previous transfer self.aspirateAir(tipMask,5) if False: # this results in losing mixprefillvol of sample which was not mixed; remainder has different concentration than planned worklist.aspirateNC(tipMask,well,self.inliquidLC,mixprefillvol,self.plate) self.volume-=mixprefillvol self.addhistory("(PRE)",-mixprefillvol,tipMask) worklist.mix(tipMask,well,self.mixLC,mixvol,self.plate,nmix) mstr="(MB)" elif False: # self.volume>=MINLIQUIDDETECTVOLUME: # Another short-lived strategy worklist.mix(tipMask,well,self.inliquidLC,mixvol,self.plate,nmix) self.history+="(MLD)" else: height=self.plate.getliquidheight(self.volume) if height is None: worklist.mix(tipMask,well,self.mixLC,mixvol,self.plate,nmix) mstr="(MB)" else: mixheight=math.floor(height-1) # At least 1mm below liquid height if mixheight<2: mixheight=2 # print 'Vol=%.1f ul, height=%.1f mm, mix=%d, blow=%d'%(self.volume,height,mixheight,blowheight) mixLC=liquidclass.LCMix[min(12,mixheight)] if blowvol>0: blowoutLC=liquidclass.LCBlowoutLD worklist.aspirateNC(tipMask,well,self.airLC,(blowvol+0.1),self.plate) if self.volume<30: worklist.mix(tipMask,well,self.mixLC,mixvol,self.plate,nmix) mstr="(MB)" else: for _ in range(nmix): worklist.aspirateNC(tipMask,well,mixLC,mixvol,self.plate) worklist.dispense(tipMask,well,mixLC,mixvol,self.plate) mstr="(M@%d)"%(mixheight) if blowvol>0: worklist.dispense(tipMask,well,blowoutLC,blowvol,self.plate) worklist.dispense(tipMask,well,liquidclass.LCDip,0.1,self.plate) self.volume-=MIXLOSS self.addhistory(mstr,-MIXLOSS,tipMask) self.lastMixed=clock.elapsed() self.wellMixed=True return True
def dispense(self,tipMask,volume,src): self.evapcheck('dispense') if self.plate.curloc=='PTC': logging.error("Dispense to PTC!, loc=(%d,%d)"%(self.plate.grid,self.plate.pos)) if volume<0.1: logging.warning("attempt to dispense only %.1f ul to %s ignored"%(volume,self.name)) return if self.volume+volume < MINDEPOSITVOLUME: logging.warning("Dispense of %.1ful into %s results in total of %.1ful which is less than minimum deposit volume of %.1f ul"%(volume,self.name,self.volume+volume,MINDEPOSITVOLUME)) #well=[self.well if self.well!=None else 2**(tipMask-1)-1 ] well=[self.well if self.well!=None else int(math.log(tipMask,2)) ] if self.well is None: logging.warning("Dispense with well is None, not sure what right logic is..., using well=%d"%well[0]) if self.volume+volume > self.plate.maxVolume: logging.error("Dispense of %.1ful into %s results in total of %.1ful which is more than the maximum volume of %.1f ul"%(volume,self.name,self.volume+volume,self.plate.maxVolume)) if self.hasBeads and self.plate.curloc=="Magnet": worklist.dispense(tipMask,well,self.beadsLC,volume,self.plate) elif self.volume>=MINLIQUIDDETECTVOLUME: worklist.dispense(tipMask,well,self.inliquidLC,volume,self.plate) elif self.volume+volume>=MINSIDEDISPENSEVOLUME: worklist.dispense(tipMask,well,self.bottomSideLC,volume,self.plate) else: worklist.dispense(tipMask,well,self.bottomLC,volume,self.plate) # Assume we're diluting the contents if self.conc is None and src.conc is None: pass elif src.conc is None or volume==0: if self.volume==0: self.conc=None else: self.conc=self.conc.dilute((self.volume+volume)/self.volume) elif self.conc is None or self.volume==0 or self.conc.final is None or src.conc.final is None: self.conc=src.conc.dilute((self.volume+volume)/volume) else: # Both have concentrations, they should match c1=self.conc.dilute((self.volume+volume)/self.volume) c2=src.conc.dilute((self.volume+volume)/volume) if abs(c1.stock/c1.final-c2.stock/c2.final)>.01: logging.warning("Dispense of %.1ful of %s@%.2fx into %.1ful of %s@%.2fx does not equalize concentrations"%(volume,src.name,src.conc.dilutionneeded(),self.volume,self.name,self.conc.dilutionneeded())) #assert abs(c1.stock/c1.final-c2.stock/c2.final)<.01 self.conc=None else: self.conc=Concentration(c1.stock/c1.final,1.0,'x') # Since there are multiple ingredients express concentration as x # Set to not mixed after second ingredient added if self.volume>0: self.lastMixed=None self.wellMixed=False if src.hasBeads and src.plate.curloc!="Magnet": #print "Set %s to have beads since %s does\n"%(self.name,src.name) self.hasBeads=True self.volume=self.volume+volume self.emptied=False #self.addhistory("%06x %s"%(self.getHash(w)&0xffffff,src.name),volume,tipMask) self.addhistory(src.name,volume,tipMask) self.addingredients(src,volume)
import worklist import plate #aspirate(1,"LC",[1,3,4],1,2,3,"wells") plate1=plate.Plate("Samples",4,3,12,8) worklist.aspirate(7,['B3','D3','E3'],"Water",[10,20,30],plate1) worklist.aspirate(7,['B4','D4','F4'],"Water",[10,20,30],plate1) worklist.aspirate(1,['B1'],"Water",[10],plate1) worklist.dispense(2,['B1'],"Water",[10],plate1) worklist.mix(2,['B1'],"Water",[10],plate1,7) worklist.vector("ROMAVector",plate1,worklist.SAFETOEND,True,worklist.OPEN,worklist.CLOSE) worklist.execute("python test",True,"result") worklist.userprompt("Script done") worklist.dump()
def mix(self, tipMask, preaspirateAir=False, nmix=4): if self.isMixed() and self.wellMixed: logging.notice( "mix() called for sample %s, which is already mixed" % self.name) return False logging.mixwarning("Pipette mixing of %s may introduce bubbles" % self.name) self.volcheck(tipMask, [self.well], 0) blowvol = 5 mstr = "" extraspace = blowvol + 0.1 if preaspirateAir: extraspace += 5 mixvol = self.volume # -self.plate.unusableVolume; # Can mix entire volume, if air is aspirated, it will just be dispensed first without making a bubble if self.volume > MAXVOLUME - extraspace: mixvol = MAXVOLUME - extraspace logging.mixwarning( "Mix of %s limited to %.0f ul instead of full volume of %.0ful" % (self.name, mixvol, self.volume)) well = [self.well if self.well != None else 2**(tipMask - 1) - 1] mixprefillvol = 5 if mixvol < self.plate.unusableVolume - mixprefillvol: logging.notice("Not enough volume in sample %s (%.1f) to mix" % (self.name, self.volume)) self.history += "(UNMIXED)" return False else: if preaspirateAir: # Aspirate some air to avoid mixing with excess volume aspirated into pipette from source in previous transfer self.aspirateAir(tipMask, 5) if False: # this results in losing mixprefillvol of sample which was not mixed; remainder has different concentration than planned worklist.aspirateNC(tipMask, well, self.inliquidLC, mixprefillvol, self.plate) self.removeVolume(mixprefillvol) self.addhistory("(PRE)", -mixprefillvol, tipMask) worklist.mix(tipMask, well, self.mixLC, mixvol, self.plate, nmix) mstr = "(MB)" elif False: # self.volume>=MINLIQUIDDETECTVOLUME: # Another short-lived strategy worklist.mix(tipMask, well, self.inliquidLC, mixvol, self.plate, nmix) self.history += "(MLD)" else: height = self.plate.getliquidheight(self.volume) if height is None: worklist.mix(tipMask, well, self.mixLC, mixvol, self.plate, nmix) mstr = "(MB)" else: mixheight = math.floor( height - 1) # At least 1mm below liquid height if mixheight < 2: mixheight = 2 # print 'Vol=%.1f ul, height=%.1f mm, mix=%d, blow=%d'%(self.volume,height,mixheight,blowheight) mixLC = liquidclass.LCMix[min(12, mixheight)] if blowvol > 0: blowoutLC = liquidclass.LCBlowoutLD worklist.aspirateNC(tipMask, well, self.airLC, (blowvol + 0.1), self.plate) if self.volume < 30: worklist.mix(tipMask, well, self.mixLC, mixvol, self.plate, nmix) mstr = "(MB)" else: for _ in range(nmix): worklist.aspirateNC(tipMask, well, mixLC, mixvol, self.plate) worklist.dispense(tipMask, well, mixLC, mixvol, self.plate) mstr = "(M@%d)" % (mixheight) if blowvol > 0: worklist.dispense(tipMask, well, blowoutLC, blowvol, self.plate) worklist.dispense(tipMask, well, liquidclass.LCDip, 0.1, self.plate) self.removeVolume(MIXLOSS) self.addhistory(mstr, -MIXLOSS, tipMask) self.lastMixed = clock.elapsed() self.wellMixed = True return True
def dispense(self, tipMask, volume, src): self.evapcheck('dispense') if self.plate.curloc == 'PTC': logging.error("Dispense to PTC!, loc=(%d,%d)" % (self.plate.grid, self.plate.pos)) if volume < 0.1: logging.warning("attempt to dispense only %.1f ul to %s ignored" % (volume, self.name)) return if self.volume + volume < MINDEPOSITVOLUME: logging.warning( "Dispense of %.1ful into %s results in total of %.1ful which is less than minimum deposit volume of %.1f ul" % (volume, self.name, self.volume + volume, MINDEPOSITVOLUME)) #well=[self.well if self.well!=None else 2**(tipMask-1)-1 ] well = [self.well if self.well != None else int(math.log(tipMask, 2))] if self.well is None: logging.warning( "Dispense with well is None, not sure what right logic is..., using well=%d" % well[0]) if self.volume + volume > self.plate.maxVolume: logging.error( "Dispense of %.1ful into %s results in total of %.1ful which is more than the maximum volume of %.1f ul" % (volume, self.name, self.volume + volume, self.plate.maxVolume)) if self.hasBeads and self.plate.curloc == "Magnet": worklist.dispense(tipMask, well, self.beadsLC, volume, self.plate) elif self.volume >= MINLIQUIDDETECTVOLUME: worklist.dispense(tipMask, well, self.inliquidLC, volume, self.plate) elif self.volume + volume >= MINSIDEDISPENSEVOLUME: worklist.dispense(tipMask, well, self.bottomSideLC, volume, self.plate) else: worklist.dispense(tipMask, well, self.bottomLC, volume, self.plate) # Assume we're diluting the contents if self.conc is None and src.conc is None: pass elif src.conc is None or volume == 0: if self.volume == 0: self.conc = None else: self.conc = self.conc.dilute( (self.volume + volume) / self.volume) elif self.conc is None or self.volume == 0 or self.conc.final is None or src.conc.final is None: self.conc = src.conc.dilute((self.volume + volume) / volume) else: # Both have concentrations, they should match c1 = self.conc.dilute((self.volume + volume) / self.volume) c2 = src.conc.dilute((self.volume + volume) / volume) if abs(c1.stock / c1.final - c2.stock / c2.final) > .01: logging.warning( "Dispense of %.1ful of %s@%.2fx into %.1ful of %s@%.2fx does not equalize concentrations" % (volume, src.name, src.conc.dilutionneeded(), self.volume, self.name, self.conc.dilutionneeded())) #assert abs(c1.stock/c1.final-c2.stock/c2.final)<.01 self.conc = None else: self.conc = Concentration( c1.stock / c1.final, 1.0, 'x' ) # Since there are multiple ingredients express concentration as x # Set to not mixed after second ingredient added if self.volume > 0: self.lastMixed = None self.wellMixed = False if src.hasBeads and src.plate.curloc != "Magnet": #print "Set %s to have beads since %s does\n"%(self.name,src.name) self.hasBeads = True self.volume = self.volume + volume self.emptied = False #self.addhistory("%06x %s"%(self.getHash(w)&0xffffff,src.name),volume,tipMask) self.addhistory(src.name, volume, tipMask) self.addingredients(src, volume)
import worklist import plate #aspirate(1,"LC",[1,3,4],1,2,3,"wells") plate1 = plate.Plate("Samples", 4, 3, 12, 8) worklist.aspirate(7, ['B3', 'D3', 'E3'], "Water", [10, 20, 30], plate1) worklist.aspirate(7, ['B4', 'D4', 'F4'], "Water", [10, 20, 30], plate1) worklist.aspirate(1, ['B1'], "Water", [10], plate1) worklist.dispense(2, ['B1'], "Water", [10], plate1) worklist.mix(2, ['B1'], "Water", [10], plate1, 7) worklist.vector("ROMAVector", plate1, worklist.SAFETOEND, True, worklist.OPEN, worklist.CLOSE) worklist.execute("python test", True, "result") worklist.userprompt("Script done") worklist.dump()