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)
def __init__(self, name, plate, well=None, conc=None, volume=0, hasBeads=False, extraVol=50, mixLC=liquidclass.LCMixBottom, firstWell=None, extrainfo=[], ingredients=None, atEnd=False): while True: # wrap with a loop to allow use of backupPlate # If firstWell is not None, then it is a hint of the first well position that should be used if well != None and well != -1: if not isinstance(well, int): well = plate.wellnumber(well) if well not in plate.wells: logging.warning( "Attempt to assign sample %s to well %d (%s) which is not legal on plate %s" % (name, well, plate.wellname(well), plate.name)) for s in __allsamples: if s.well == well and s.plate == plate: logging.warning( "Attempt to assign sample %s to plate %s, well %s that already contains %s" % (name, str(plate), plate.wellname(well), s.name)) if firstWell is None: firstWell = well well = None break if well is None: # Find first unused well found = False if firstWell is not None: # First check only wells>=firstWell for well in plate.wells: if well < firstWell: continue found = True for s in __allsamples: if s.plate == plate and s.well == well: well = well + 1 found = False break if found: break if not found: well = max(plate.wells) if atEnd else min(plate.wells) while (well >= 0) if atEnd else (well <= max(plate.wells)): found = True for s in __allsamples: if s.plate == plate and s.well == well: well = well + (-1 if atEnd else 1) found = False break if found: break elif well == -1: well = None if well >= plate.nx * plate.ny: # Overflow if plate.backupPlate is not None: # Overflow onto backup plate logging.warning( "Overflow of %s plate, moving %s to %s plate -- verify carefully!" % (plate.name, name, plate.backupPlate.name)) plate = plate.backupPlate well = None continue else: logging.error("Overflow of plate %s while adding %s" % (str(plate), name)) break for s in __allsamples: if s.plate == plate and s.well == well: logging.error( "Attempt to assign sample %s to plate %s, well %s that already contains %s" % (name, str(plate), plate.wellname(well), s.name)) if name in [s.name for s in __allsamples]: while name in [s.name for s in __allsamples]: name = name + "#" logging.notice("renaming sample to %s" % name) self.name = name self.plate = plate self.well = well if isinstance(conc, Concentration) or conc is None: self.conc = conc else: self.conc = Concentration(conc) self.volume = volume self.initVol = volume if volume > 0: if ingredients is None: self.ingredients = {name: volume} else: self.ingredients = ingredients.copy() total = sum([v for v in ingredients.values()]) for k in self.ingredients: self.ingredients[k] = self.ingredients[k] * volume / total self.lastvolcheck = None else: self.ingredients = {} self.lastvolcheck = 0 # Assume that it has already been checked for 0 (since it can't be any less...) self.checkingredients() if plate.pierce: self.bottomLC = liquidclass.LCWaterPierce self.bottomSideLC = self.bottomLC # Can't use side with piercing self.inliquidLC = self.bottomLC # Can't use liquid detection when piercing else: self.bottomLC = liquidclass.LCWaterBottom self.bottomSideLC = liquidclass.LCWaterBottomSide self.inliquidLC = liquidclass.LCWaterInLiquid self.beadsLC = liquidclass.LCWaterBottomBeads self.mixLC = mixLC self.airLC = liquidclass.LCAir # Same as bottom for now self.emptyLC = self.bottomLC self.history = "" __allsamples.append(self) if hasBeads: self.lastMixed = None else: self.lastMixed = clock.elapsed( ) - 20 * 60 # Assume it was last mixed an 20 min before start of run self.wellMixed = True self.initHasBeads = hasBeads self.hasBeads = hasBeads # Setting this to true overrides the manual conditioning self.extraVol = extraVol # Extra volume to provide self.evap = 0 # Amount that has evaporated if self.plate.name == "Samples": self.lastevapupdate = clock.pipetting else: self.lastevapupdate = clock.elapsed() self.extrainfo = extrainfo self.emptied = False
def __init__(self, name, plate, well=None, conc=None, volume=0, hasBeads=False, extraVol=50, mixLC=liquidclass.LCMixBottom): if well != None and well != -1: if not isinstance(well, int): well = plate.wellnumber(well) if well not in plate.wells: print "Attempt to assign sample %s to well %d (%s) which is not legal on plate %s" % ( name, well, plate.wellname(well), plate.name) for s in __allsamples: if s.well == well and s.plate == plate: print "Attempt to assign sample %s to plate %s, well %s that already contains %s" % ( name, str(plate), plate.wellname(well), s.name) well = None break if well is None: # Find first unused well found = False for well in plate.wells: found = True for s in __allsamples: if s.plate == plate and s.well == well: well = well + 1 found = False break if found: break elif well == -1: well = None for s in __allsamples: if s.plate == plate and s.well == well: print "Attempt to assign sample %s to plate %s, well %s that already contains %s" % ( name, str(plate), plate.wellname(well), s.name) # print "Aliasing %s as %s"%(s.name,name) assert False if name in [s.name for s in __allsamples]: while name in [s.name for s in __allsamples]: name = name + "#" print "NOTICE: renaming sample to %s" % name self.name = name self.plate = plate if well >= plate.nx * plate.ny: print "Overflow of plate %s" % str(plate) for s in __allsamples: if s.plate == plate: print s assert False self.well = well if isinstance(conc, Concentration) or conc is None: self.conc = conc else: self.conc = Concentration(conc) self.volume = volume if volume > 0: self.ingredients = {name: volume} else: self.ingredients = {} if plate.pierce: self.bottomLC = liquidclass.LCWaterPierce self.bottomSideLC = self.bottomLC # Can't use side with piercing self.inliquidLC = self.bottomLC # Can't use liquid detection when piercing else: self.bottomLC = liquidclass.LCWaterBottom self.bottomSideLC = liquidclass.LCWaterBottomSide self.inliquidLC = liquidclass.LCWaterInLiquid self.beadsLC = liquidclass.LCWaterBottomBeads self.mixLC = mixLC self.airLC = liquidclass.LCAir # Same as bottom for now self.emptyLC = self.bottomLC self.history = "" __allsamples.append(self) if hasBeads: self.lastMixed = None else: self.lastMixed = clock.elapsed( ) - 20 * 60 # Assume it was last mixed an 20 min before start of run self.wellMixed = True self.initHasBeads = hasBeads self.hasBeads = hasBeads # Setting this to true overrides the manual conditioning self.extraVol = extraVol # Extra volume to provide self.evap = 0 # Amount that has evaporated if self.plate.name == "Samples": self.lastevapupdate = clock.pipetting else: self.lastevapupdate = clock.elapsed()