def set_units(self, units: str): '''Set the pump units Arguments: units: One of the unit strings in the note Note: Possible units are: mL/min, mL/hr, uL/min, uL/hr Calling this function will also update the internal rate and volume to match the new untis ''' #validation try: unit_number = self.units_dict[units] except KeyError: raise ValueError( "Invalid unit: {}." "Please specify one of the following units: mL/min, mL/hr, uL/min, uL/hr" .format(units)) #Set units cmd = "set units {}".format(unit_number) expected_response = "units = {}".format(unit_number) sio_write(self.sio, cmd, output=True, exp=expected_response, ctx=self.name, timeout=self.retry) #Update internal variable self.units = units if self.volume: self.volume = self._convert_volume(self.volume) self.rate = self._convert_rate(self.rate) return self.units
def set_syringe(self, manufacturer: str, volume: float, inner_diameter: float = None): """Set diameter of syringe on the pump Args: manufacturer: Syringe manufacturer volume: Syringe total volume in mL inner_diameter: Inner diameter of the syringe in mm (optional) """ #Try to get syringe diameter from database self.diameter = self.sdb.find_diameter(manufacturer=manufacturer, volume=volume) if not self.diameter and inner_diameter: self.diameter = inner_diameter elif not self.diameter: raise ValueError( "{} {}mL syringe not in the database. " " To use a custom syringe, pass inner_diameter.".format( manufacturer, volume)) #Send command and check response cmd = 'set diameter %0.3f\x0D' % (self.diameter) expected_response = 'diameter = %0.3f\x0D' % (self.diameter) sio_write(self.sio, cmd, output=True, exp=expected_response, ctx=self.name, timeout=self.retry) #Change internal variables volume = self._convert_volume({'value': volume, 'units': 'mL'}) self.volume = volume
def set_rate(self, rate, direction=None): """Set the flowrate of the pump Note: To run a pump, first call set_rate and then call run. See :meth:`chemios.components.pumps.Chemyx.set_rate`for units format. Args: rate (obj:'value', 'units'): {'value': pump flowrate, 'units': UM} direction (str): Direction of pump. INF for infuse or WDR for withdraw (optional) Note: The only way to set direction on Chemyx pumps is by changing the volume. Currently, the software resets the volume to the max volume of the syringe. """ #Check if syringe volume has been set if not self.volume: raise ValueError("Please set the syringe before calling set_rate.") #Convert units if necessary if rate['units'] != self.units: rate = self._convert_rate(rate) #Set rate self.ser.flushOutput() cmd = 'set rate %0.3f\x0D' % (rate['value']) expected_response = 'rate = %0.3f\x0D' % (rate['value']) sio_write(self.sio, cmd, output=True, exp=expected_response, ctx=self.name, timeout=self.retry) time.sleep(0.1) #Set direction using the volume if direction: if direction == 'INF': cmd = "set volume %0.3f\x0D" % (self.volume['value']) elif direction == 'WDR': cmd = "set volume %0.3f\x0D" % (-1 * self.volume['value']) else: raise ValueError( 'Must choose INF for infuse or WDR for withdraw') serial_write(self.ser, cmd) #Change internal variable self.rate = rate
def get_info(self): """ Get info about the current pump Yields: obj: model, address, syringe_diameter, rate """ info = { 'name': self.name, 'model': self.model, 'syringe_diameter': self.diameter, 'rate': self.rate } try: response = sio_write(self.sio, "view parameter\x0D", True, timeout=self.retry) #Invert key, value mapping on units dict unit_table = {v: k for k, v in self.units_dict.items()} #Get rate match1 = re.search(r'(?<=rate = )\d+.(\d+)?', response, re.M) value = match1.group() match2 = re.search(r'(?<=unit = )\d', response, re.M) unit_number = match2[0] unit = unit_table[unit_number] info['rate'] = {'value': value, 'units': unit} except Exception as e: logging.warning(e) return info
def __init__(self, model: str, ser: serial.Serial, name='HarvardApparatus', units='mL/min'): self.name = name self.model = model #model self.ser = ser #serial object self.units = units #Internal variables self.sio = io.TextIOWrapper(io.BufferedRWPair(self.ser, self.ser)) self.rate = {'value': None, 'units': None} self.direction = None #INF for infuse or WDR for withdraw self.sdb = SyringeData('../../../data/syringe_db.json') self.volume = None self.diameter = None self.units_dict = { 'mL/min': '0', 'mL/hr': '1', 'uL/min': '2', 'uL/hr': 3 } self.timeout = 1 #Validation------------------------------------------------------------ #Check that the model is one of the available models models = ['Phd-Ultra'] if self.model not in models: raise ValueError( '{} is not one of the currently available pump models'.format( self.model)) #Connection------------------------------------------------------------ logging.debug("Connecting to {} pump".format(self.name)) #Check that it's plugged into this port #and the right type of commands are being used response = sio_write(self.sio, "CMD\x0D", True, timeout=1) if self.model == 'Phd-Ultra': match = re.search(r'(Ultra)', response, re.M) if match is None: status_text = "Pump not set to Ultra command set" raise IOError(status_text)
def __init__(self, model, address, syringe_type={}, ser=None, bus=None): self.pump_models = {'names': ['NE-1000', 'DIY', 'Chemyx', 'HA-PHD-Ultra']} self.address = address #Adress for the pump self.model = model #model self.syringe_type = syringe_type self.ser = ser #serial object self.bus = bus #i2c bus object #Validation if self.model not in self.pump_models['names']: raise ValueError('Please choose one of the listed pumps'+ json.dumps(self.pump_models,indent=2)) if self.model == 'NE-1000' and self.ser is None: raise ValueError('Serial object must be provided for communication with the NE-1000.') if self.model == 'DIY' and self.bus is None: raise ValueError('i2C bus must be provided for communication with the DIY pump.') if self.model == 'Chemyx' and self.ser is None: raise ValueError('Serial object must be provided for communication with the NE-1000.') if self.model == 'HA-PHD-Ultra' and self.ser is None: raise ValueError('Serial object must be provided for communication with Harvard Apparatus PHD Ultra') #Internal variables self.sio = io.TextIOWrapper(io.BufferedRWPair(self.ser, self.ser)) self.rate = {'value': None,'units': None} self.direction = None #INF for infuse or WDR for withdraw self.sleep_time = 0.1 try: #rate limits in microliters/hr self.rate_limits = self.syringe_type['rate_limits'] self.diameter = self.syringe_type['diameter'] #Volume in mL if self.syringe_type['volume'][1] != 'ml': raise ValueError("Volume must be in ml") self.volume = self.syringe_type['volume'][0] except KeyError: self.rate_limits = {} self.diameter = None self.volume = None if self.model == 'Chemyx': raise ValueError("Please pass diameter, volume and rate limits array in syringe_type") else: pass #Set up pumps using serial if self.model == 'NE-1000': #Set NE-1000 continuous pumping (i.e., 0 volume to dispense) serial_write(self.ser, construct_cmd("VOL0\x0D", self.address), "setup continuous pumping") time.sleep(0.5) self.ser.flush() if self.model == 'Chemyx': #Check pump address by units (i.e., I'm setting pump_1 units to 1 and pump_2 units to 2) response = sio_write(self.sio, "view parameter\x0D", True, timeout =5) try: match2 = re.search(r'(?<=unit = )\d', response, re.M) unit_number = match2.group(0) except Exception: raise IOError("Wrong pump address") #raise IOError("Wrong pump address") if int(unit_number) != int(address): raise IOError("Wrong pump address") if self.diameter is not None: cmd = 'set diameter %0.3f\x0D'%(self.diameter) diameter = serial_write(self.ser, cmd, "set_diameter", True) self.ser.flush() #Set up PHD Ultra if self.model == 'HA-PHD-Ultra': #Set the syringe type try: #Check that it's plugged into this port #and the right type of commands are being used # for i in range(3): self.ser.flush() # response = sio_write(self.sio, "CMD", True, timeout=5) # match = re.search(r'(Ultra)', response, re.M) # if match is None: # status_text = "Pump not set to Ultra command set" # raise IOError(status_text) cmd = "syrm {} {} {}\x0D".format( syringe_type["code"], syringe_type['volume'][0], syringe_type['volume'][1] ) for i in range(3): self.ser.flush() sio_write(self.sio, cmd, False, timeout=1) time.sleep(0.1) #Check back on that the manfacturer was set correctly for i in range(3): self.ser.flush() output = sio_write(self.sio, "syrm\x0D", True, timeout = 2) logging.debug("Output from setting syringe manufacture: {}".format(output)) except ValueError as e: logging.debug(e)