Beispiel #1
0
 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
Beispiel #2
0
    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
Beispiel #3
0
    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
Beispiel #4
0
    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
Beispiel #5
0
    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)
Beispiel #6
0
    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)