Esempio n. 1
0
    def __init__ (self, title, set_target):
        self.title = title

        self.target = Property(title = self.title + " Target Temperature", type = int, unit = "C", min = -1000, max = 250, setter = set_target)
        self.mode   = Property(title = self.title + " Mode", type = str)
        self.power  = Stream(title = self.title + " Power", type = int, unit = "W")
        self.temp   = Stream(title = self.title + " Temperature", type = float, unit = "C")
Esempio n. 2
0
    def setup(self, syringe_diameter):
        @defer.inlineCallbacks
        def set_rate(rate):
            # Get the current rate
            try:
                state, result = yield self.protocol.command("RAT")
            except CommandError as e:
                raise

            # Cannot set rate if the pump is running - stop the pump.
            if state in ("I", "W", "A"):
                try:
                    yield self.protocol.command("STP")
                except CommandError as e:
                    if e.type is not CommandError.NOT_APPLICABLE:
                        pass

            # Set the rate
            yield self.protocol.command("RAT{:.3f}".format(
                rate / _rate_unit_factors[self._rate_unit])[:8] +
                                        self._rate_unit)

            # Only start if the rate > 0
            if rate > 0:
                state, result = yield self.protocol.command("RUN")

                if state in ("I", "W"):
                    defer.returnValue("OK")
                else:
                    raise Error("Could not start pump")
            else:
                defer.returnValue("OK")

        def set_direction(direction):
            direction = "WDR" if direction == "withdraw" else "INF"
            return self.protocol.command("DIR" + direction)

        # setup variables
        self.status = Property(title="Status", type=str)
        self.rate = Property(title="Flow rate",
                             type=float,
                             unit="uL/min",
                             setter=set_rate)
        self.direction = Property(title="Direction",
                                  type=str,
                                  options=("infuse", "withdraw"),
                                  setter=set_direction)
        self.dispensed = Stream(title="Volume dispensed",
                                type=float,
                                unit="mL")
        self.withdrawn = Stream(title="Volume withdrawn",
                                type=float,
                                unit="mL")

        self._syringe_diameter = syringe_diameter
        self._vol_unit = "UL"
        self._rate_unit = "MM"

        self.ui = ui(properties=[self.rate])
Esempio n. 3
0
    def setup (self):

        # setup variables
        self.power = Property(title = "Power", type = str, options = ("on", "off"), setter = _set_power(self))
        self.setpoint = Property(title = "Stirrer setpoint", type = float, unit = "rpm", setter = _set_setpoint(self))
        
        self.rpm = Stream(title = "Stirrer Speed", type = float, unit = "rpm")
        self.torque = Stream(title = "Torque", type = float, unit = "Ncm")
Esempio n. 4
0
    def __init__ (self, title, set_target, set_input):
        self.title = title

        self.target   = Property(title = self.title + " Target Flow Rate", type = int, unit = "uL/min", min = 0, max = 99999, setter = set_target)
        self.input    = Property(title = self.title + " Input", type = str, options = ("solvent", "reagent"), setter = set_input)
        self.rate     = Stream(title = self.title + " Flow Rate", type = int, unit = "uL/min")
        self.pressure = Stream(title = self.title + " Pressure", type = int, unit = "mbar")
        self.airlock  = Stream(title = self.title + " Airlock", type = int)
Esempio n. 5
0
    def setup (self):

        # setup variables
        self.heater_power = Property(title = "Heater On", type = str, options = ("on", "off"), setter = _set_heater_power(self))
        self.stirrer_power = Property(title = "Stirrer On", type = str, options = ("on", "off"), setter = _set_stirrer_power(self))
        self.stirrer_setpoint = Property(title = "Stirrer setpoint", type = float, unit = "rpm", setter = _set_stirrer_setpoint(self))
        self.heater_setpoint = Property(title = "Heater setpoint", type = float, unit = "rpm", setter = _set_heater_setpoint(self))
        
        self.external_temperature = Stream(title = "External Temperature", type = float, unit = "C")
        self.hotplate_temperature = Stream(title = "Hotplate Temperature", type = float, unit = "C")
        self.stirrer_speed = Stream(title = "Stirrer Speed", type = float, unit = "rpm")
        self.viscosity = Stream(title = "Viscosity", type = float, unit = "%")
Esempio n. 6
0
    def setup(self):

        # setup variables
        self.power = Property(title="Power",
                              type=str,
                              options=("on", "off"),
                              setter=_set_power_s(self))
        self.target = Property(title="Target flowrate",
                               type=float,
                               unit="mL/min",
                               setter=_set_setpoint_s(self))

        self.flowrate = Stream(title="Flow rate", type=float, unit="mL/min")
        self.pressure = Stream(title="Pressure", type=float, unit="bar")
Esempio n. 7
0
class CGQ(Machine):
    """
    Control class for a Aquila CGQ, via the CGQuant software.
    The software connects via a Named Pipe at \\.\pipe\CGQuantDataPipe
    """

    protocolFactory = Factory.forProtocol(CGQuantLineReceiver)
    name = "CGQuant"

    def setup(self):

        # setup variables
        self.backscatter = Stream(title="Backscatter", type=float, unit="au")
        self.temperature = Stream(title="Temperature", type=float, unit="C")
        self.shakingspeed = Stream(title="Shaking speed",
                                   type=float,
                                   unit="rpm")
        self.growthrate = Stream(title="Growth rate", type=float, unit="1/h")

    def start(self):
        def receive_packet(packet: CGQuantDataPacket):
            self.backscatter._push(packet.backscatter)
            self.temperature._push(packet.temperature)
            self.shakingspeed._push(packet.shakingspeed)
            self.growthrate._push(packet.growthrate)

        self.protocol.setListener(receive_packet)

    def stop(self):
        self.protocol.setListener(None)
Esempio n. 8
0
    def setup(self):

        # setup variables
        self.power = Property(title="Power",
                              type=str,
                              options=("on", "off"),
                              setter=_set_power(self))
        self.setpoint = Property(title="Setpoint",
                                 type=int,
                                 unit="C",
                                 setter=_set_setpoint(self))

        self.bath_temp = Stream(title="Bath Temperature", type=float, unit="C")
        self.external_temp = Stream(title="External Temperature",
                                    type=float,
                                    unit="C")
Esempio n. 9
0
    def setup(self):

        # setup variables
        self.backscatter = Stream(title="Backscatter", type=float, unit="au")
        self.temperature = Stream(title="Temperature", type=float, unit="C")
        self.shakingspeed = Stream(title="Shaking speed",
                                   type=float,
                                   unit="rpm")
        self.growthrate = Stream(title="Growth rate", type=float, unit="1/h")
Esempio n. 10
0
    def setup (self, **kwargs):

        # setup variables
        self.status = Property(title = "Status", type = str)
        self.power  = Property(title = "System Power", type = str, options = ("on", "off"), setter = _set_power(self))
        self.pressure = Stream(title = "System Pressure", type = int, unit = "mbar")
        self.pressure_limit = Property(title = "System Pressure Limit", type = int, unit = "mbar", min = 1000, max = 50000, setter = _set_pressure_limit(self))
        self.output = Property(title = "Output", type = str, options = ("waste", "collect"), setter = _set_output(self))

        self.pump1 = R2Pump("Pump A", _set_pump_target(self, 0), _set_pump_input(self, 0))
        self.pump2 = R2Pump("Pump B", _set_pump_target(self, 1), _set_pump_input(self, 1))

        self.loop1 = Property(title = "Loop A Position", type = str, options = ("load", "inject"), setter = _set_loop(self, 0))
        self.loop2 = Property(title = "Loop B Position", type = str, options = ("load", "inject"), setter = _set_loop(self, 1))

        self.heater1 = R4Heater("Heater A", _set_heater_target(self, 0))
        self.heater2 = R4Heater("Heater B", _set_heater_target(self, 1))
        self.heater3 = R4Heater("Heater C", _set_heater_target(self, 2))
        self.heater4 = R4Heater("Heater D", _set_heater_target(self, 3))

        self.ui = ui(
            traces = [{
                "title": "Pressure",
                "unit":  self.pressure.unit,
                "traces": [self.pressure, self.pump1.pressure, self.pump2.pressure],
                "colours": ["#0c4", "#F70", "#50a"]
            }, {
                "title": "Temperature",
                "unit":  self.heater1.temp.unit,
                "traces": [self.heater1.temp, self.heater2.temp, self.heater3.temp, self.heater4.temp],
                "colours": ["#0c4", "#F70", "#50a", "#921"]
            }],
            properties = [
                self.pressure,
                self.pump1.pressure,
                self.pump2.pressure,
                self.pump1.rate,
                self.pump2.rate,
                self.pump1.input,
                self.pump2.input,
                self.heater1.temp,
                self.heater2.temp,
                self.heater3.temp,
                self.heater4.temp
            ]
        )
Esempio n. 11
0
class Sartorious(Machine):

    protocolFactory = Factory.forProtocol(QueuedLineReceiver)
    name = "Sartorious Balance"

    def setup(self):

        # setup variables
        self.weight = Stream(title="Weight", type=float, unit="g")

    def start(self):
        def interpret_weight(result: str) -> float:

            result_value = float((result[-14:-4]).replace(" ", ""))

            self.weight._push(result_value)

        to_monitor = []

        def addMonitor(command, fn, variable: Stream):
            def interpret(result):
                variable._push(fn(result), now())

            to_monitor.append((command, interpret))

        addMonitor("P", interpret_weight, self.weight)

        def monitor():
            for cmd, fn in to_monitor:
                self.protocol.write(cmd).addCallback(fn)

        self._monitor = self._tick(monitor, 1)

    def stop(self):
        self._stopTicks()

    def reset(self):
        return defer.succeed('OK')

    def tare(self):
        return self.protocol.write("T", expectReply=False, wait=5)
Esempio n. 12
0
    def setup(self):

        # setup variables
        self.power = Property(title="Power",
                              type=str,
                              options=("on", "off"),
                              setter=_set_power(self))
        self.percentage_setpoint = Property(
            title="Setpoint",
            type=float,
            unit="%",
            setter=_set_percentage_setpoint(self))
        self.pressure_setpoint = Property(title="Setpoint",
                                          type=float,
                                          unit="bar",
                                          setter=_set_pressure_setpoint(self))

        self.percentage_pressure = Stream(title="Flow rate",
                                          type=float,
                                          unit="%")
        self.pressure = Stream(title="Flow rate", type=float, unit="bar")
Esempio n. 13
0
    def setup(self):

        # setup variables
        self.power = Property(title="Power",
                              type=str,
                              options=("on", "off"),
                              setter=_set_power_l(self))
        self.target = Property(title="Target speed",
                               type=float,
                               unit="1/min",
                               setter=_set_setpoint_l(self))

        self.speed = Stream(title="Speed", type=float, unit="1/min")
Esempio n. 14
0
class Aladdin(Machine):

    protocolFactory = protocol.Factory.forProtocol(SinglePumpReceiver)
    name = "World Precision Instruments Aladdin Syringe Pump"

    def setup(self, syringe_diameter):
        @defer.inlineCallbacks
        def set_rate(rate):
            # Get the current rate
            try:
                state, result = yield self.protocol.command("RAT")
            except CommandError as e:
                raise

            # Cannot set rate if the pump is running - stop the pump.
            if state in ("I", "W", "A"):
                try:
                    yield self.protocol.command("STP")
                except CommandError as e:
                    if e.type is not CommandError.NOT_APPLICABLE:
                        pass

            # Set the rate
            yield self.protocol.command("RAT{:.3f}".format(
                rate / _rate_unit_factors[self._rate_unit])[:8] +
                                        self._rate_unit)

            # Only start if the rate > 0
            if rate > 0:
                state, result = yield self.protocol.command("RUN")

                if state in ("I", "W"):
                    defer.returnValue("OK")
                else:
                    raise Error("Could not start pump")
            else:
                defer.returnValue("OK")

        def set_direction(direction):
            direction = "WDR" if direction == "withdraw" else "INF"
            return self.protocol.command("DIR" + direction)

        # setup variables
        self.status = Property(title="Status", type=str)
        self.rate = Property(title="Flow rate",
                             type=float,
                             unit="uL/min",
                             setter=set_rate)
        self.direction = Property(title="Direction",
                                  type=str,
                                  options=("infuse", "withdraw"),
                                  setter=set_direction)
        self.dispensed = Stream(title="Volume dispensed",
                                type=float,
                                unit="mL")
        self.withdrawn = Stream(title="Volume withdrawn",
                                type=float,
                                unit="mL")

        self._syringe_diameter = syringe_diameter
        self._vol_unit = "UL"
        self._rate_unit = "MM"

        self.ui = ui(properties=[self.rate])

    def start(self):

        ## To set:
        # SAF50
        # VER = version
        # DIA = syringe diameter (only not during program)

        ## To call
        # VOL = volume to be dispensed (only not during program)
        # CLD = clear dispensed volume (only not during program)

        ## To monitor:
        # DIR = pumping direction (INF/WDR/REV)
        # DIS = volume dispensed
        # RAT = pumping rate (stored if not during program)

        ## Phase Programming... todo?
        # RUN = run pumping program
        # STP = stop pumping program
        # LOC = keyboard lockout (only during program)
        # ...

        # Setup monitor on a tick to update variables
        def interpretDispensed(result):
            if result is None:
                return

            status, result = result

            self.status._push(_aladdin_status[status])

            vol_unit = result[12:14]
            unit = _vol_unit_factors[vol_unit]

            self._vol_unit = vol_unit
            self.dispensed._push(unit * float(result[1:6]))
            self.withdrawn._push(unit * float(result[7:12]))

        def interpretRate(result):
            if result is None:
                return

            status, result = result

            rate_unit = result[5:7]
            unit = _rate_unit_factors[rate_unit]

            self._rate_unit = rate_unit
            self.rate._push(unit * float(result[0:5]))

        def interpretDirection(result):
            if result is None:
                return

            self.direction._push("infuse" if result[1] ==
                                 "INF" else "withdraw")

        def monitor():
            return defer.gatherResults([
                self.protocol.command("DIS").addCallback(
                    interpretDispensed).addErrback(lambda f: self.log.failure(
                        "While getting dispensed volume", f)),
                self.protocol.command("RAT").addCallback(
                    interpretRate).addErrback(
                        lambda f: self.log.failure("While getting rate", f)),
                self.protocol.command("DIR").addCallback(
                    interpretDirection).addErrback(lambda f: self.log.failure(
                        "While getting direction", f))
            ])

        def setMonitor(result):
            self._tick(monitor, 1)

        return defer.gatherResults([
            self.protocol.command("STP").addErrback(
                lambda f: self.log.failure("While stopping pump", f)),
            self.protocol.command("SAF50"),
            self.protocol.command("VER"),
            self.protocol.command("DIA{:.3f}".format(
                self._syringe_diameter)[:8]),
            monitor().addCallback(setMonitor)
        ])

    def stop(self):
        # Disable safe mode to prevent timeout error.
        self._stopTicks()
        self.protocol.command("SAF0")

    def reset(self):
        # Setup a single program phase with unlimited volume
        # Default to stopped (0 rate) and infuse direction.
        return defer.gatherResults([
            self.protocol.command("STP").addErrback(
                lambda f: self.log.failure("While stopping pump", f)),
            self.protocol.command("PHN01"),
            self.protocol.command("FUNRAT"),
            self.protocol.command("VOL0"),
            self.protocol.command("RAT0"),
            self.protocol.command("DIRINF")
        ])

    def pause(self):
        self._pauseState = self.rate.value
        return self.rate.set(0)

    def resume(self):
        try:
            return self.rate.set(self._pauseState)
        except AttributeError:
            return defer.succeed()
Esempio n. 15
0
class R2R4 (Machine):

    title = "Vapourtec R2+/R4"
    protocolFactory = R2ProtocolFactory()

    def setup (self, **kwargs):

        # setup variables
        self.status = Property(title = "Status", type = str)
        self.power  = Property(title = "System Power", type = str, options = ("on", "off"), setter = _set_power(self))
        self.pressure = Stream(title = "System Pressure", type = int, unit = "mbar")
        self.pressure_limit = Property(title = "System Pressure Limit", type = int, unit = "mbar", min = 1000, max = 50000, setter = _set_pressure_limit(self))
        self.output = Property(title = "Output", type = str, options = ("waste", "collect"), setter = _set_output(self))

        self.pump1 = R2Pump("Pump A", _set_pump_target(self, 0), _set_pump_input(self, 0))
        self.pump2 = R2Pump("Pump B", _set_pump_target(self, 1), _set_pump_input(self, 1))

        self.loop1 = Property(title = "Loop A Position", type = str, options = ("load", "inject"), setter = _set_loop(self, 0))
        self.loop2 = Property(title = "Loop B Position", type = str, options = ("load", "inject"), setter = _set_loop(self, 1))

        self.heater1 = R4Heater("Heater A", _set_heater_target(self, 0))
        self.heater2 = R4Heater("Heater B", _set_heater_target(self, 1))
        self.heater3 = R4Heater("Heater C", _set_heater_target(self, 2))
        self.heater4 = R4Heater("Heater D", _set_heater_target(self, 3))

        self.ui = ui(
            traces = [{
                "title": "Pressure",
                "unit":  self.pressure.unit,
                "traces": [self.pressure, self.pump1.pressure, self.pump2.pressure],
                "colours": ["#0c4", "#F70", "#50a"]
            }, {
                "title": "Temperature",
                "unit":  self.heater1.temp.unit,
                "traces": [self.heater1.temp, self.heater2.temp, self.heater3.temp, self.heater4.temp],
                "colours": ["#0c4", "#F70", "#50a", "#921"]
            }],
            properties = [
                self.pressure,
                self.pump1.pressure,
                self.pump2.pressure,
                self.pump1.rate,
                self.pump2.rate,
                self.pump1.input,
                self.pump2.input,
                self.heater1.temp,
                self.heater2.temp,
                self.heater3.temp,
                self.heater4.temp
            ]
        )

    def gsioc (self, id):
        d = defer.Deferred()

        def interpret (response):
            if response[:13] == 'GSIOC reply: ':
                return response[13:]

            if response == 'GSIOC command failed' or response == 'GSIOC timed out':
                raise GSIOCNoDevice(id)

            if response == 'GSIOC command OK':
                return True

        def immediate_command (line):
            return self.protocol.write(
                    "TG i %d %s" % (id, line)
                ).addCallback(interpret)

        def buffered_command (line):
            return self.protocol.write(
                    "TG b %d %s" % (id, line)
                ).addCallback(interpret)

        def r (result):
            d.callback(GSIOCSlave(
                immediate_command,
                buffered_command,
                name = "%s(GSIOC:%s)" % (
                    self.protocol.connection_name, id
                )
            ))
            return result

        self.ready.addCallback(r)
        return d

    def start (self):
        # setup monitor on a tick to update variables

        self._timeZero = now() # in seconds

        def handleClearHistory (result):
            if result == 'OK':
                self._timeZero = now()

        def clearHistory ():
            return self.protocol.write("HR").addCallback(handleClearHistory)

        heaterMode = {
            "U": "off",
            "C": "cooling",
            "H": "heating",
            "S": "stable unheated",
            "F": "stable heated"
        }

        status = (
            "off", "running",
            "system overpressure",
            "pump 1 overpressure", "pump 2 overpressure",
            "system underpressure",
            "pump 1 underpressure", "pump 2 underpressure"
        )

        def heaterTemp (input):
            if input == "-1000":
                return 0
            else:
                return float(input) / 10

        def interpretPressure (result, sendTime):
            if result == "OK":
                return

            result = [x.split(",") for x in result.split("&")]

            # Compensate for difference between clocks.
            #
            # Expect the last time returned to have some delay:
            #   At least 0.1s (frequency of collection)
            #   + 1/2 round-trip communication time
            #
            # Any other difference is due to slow/fast clock,
            # which can be re-zeroed from time to time.
            #
            # Algorithm:
            #   lastTime = self._timeZero + (float(result[-1][0]) / 10)
            #   roundTripTime = now() - sendTime
            #   expectedDiff = 0.1 + (roundTripTime / 2)
            #   timeDiff = (lastTime - now()) - expectedDiff

            timeDiff = self._timeZero + (float(result[-1][0]) * 0.1) - 0.1 - (now() * 1.5) + (sendTime * 0.5)

            if timeDiff < -0.05:
                self._timeZero -= timeDiff

            for v in result:
                if len(v) < 4:
                    return

                time = self._timeZero + (float(v[0]) / 10)
                self.pressure._push(int(v[1]) * 10, time)
                self.pump1.pressure._push(int(v[2]) * 10, time)
                self.pump2.pressure._push(int(v[3]) * 10, time)

        def interpretHistory (result):
            if result == "OK":
                return


            for type, parts in [x.split("{") for x in result[:-1].split("}")]:
                data = [x.split(",") for x in parts.split("&")]

                if type == "T":
                    for v in data:
                        if len(v) < 9:
                            continue

                        time = self._timeZero + (float(v[0]) / 10)
                        self.heater1.mode._push(heaterMode[v[1]], time)
                        self.heater1.temp._push(heaterTemp(v[2]), time)
                        self.heater2.mode._push(heaterMode[v[3]], time)
                        self.heater2.temp._push(heaterTemp(v[4]), time)
                        self.heater3.mode._push(heaterMode[v[5]], time)
                        self.heater3.temp._push(heaterTemp(v[6]), time)
                        self.heater4.mode._push(heaterMode[v[7]], time)
                        self.heater4.temp._push(heaterTemp(v[8]), time)

                if type == "W":
                    for v in data:
                        if len(v) < 5:
                            continue

                        time = self._timeZero + (float(v[0]) / 10)
                        self.heater1.power._push(int(v[1]), time)
                        self.heater2.power._push(int(v[2]), time)
                        self.heater3.power._push(int(v[3]), time)
                        self.heater4.power._push(int(v[4]), time)

                if type == "F":
                    for v in data:
                        if len(v) < 3:
                            continue

                        time = self._timeZero + (float(v[0]) / 10)
                        self.pump1.rate._push(int(v[1]), time)
                        self.pump2.rate._push(int(v[2]), time)

                if type == "V":
                    for v in data:
                        if len(v) < 2:
                            continue

                        time = self._timeZero + (float(v[0]) / 10)
                        v = int(v[1])

                        self.pump1.input._push("reagent" if v & 1 else "solvent", time)
                        self.pump2.input._push("reagent" if v & 2 else "solvent", time)
                        self.loop1._push("inject" if v & 4 else "load", time)
                        self.loop2._push("inject" if v & 8 else "load", time)
                        self.output._push("collect" if v & 16 else "waste", time)

            # Reset the R2's internal clock before it runs out
            # of numbers for timing (v[0] ~ 2**15 ?)
            if now() > self._timeZero + 2500:
                clearHistory()

        def interpretStatus (result):
            v = result.split(" ")

            if len(v) < 11:
                return

            time = now()

            self.power._push("on" if v[0] == "1" else "off", time)
            self.status._push(status[int(v[0])], time)
            self.pump1.target._push(int(v[1]), time)
            self.pump2.target._push(int(v[2]), time)
            self.pump1.airlock._push(int(v[3]), time)
            self.pump2.airlock._push(int(v[4]), time)
            self.pressure_limit._push(float(v[5]) / 100, time)
            self.heater1.target._push(int(v[7]), time)
            self.heater2.target._push(int(v[8]), time)
            self.heater3.target._push(int(v[9]), time)
            self.heater4.target._push(int(v[10]), time)

        def monitorPressure ():
            self.protocol.write("HP").addCallback(interpretPressure, now())

        def monitorStatus ():
            self.protocol.write("HH").addCallback(interpretHistory)
            self.protocol.write("GA").addCallback(interpretStatus)

        def startMonitors (result):
            self._tick(monitorPressure, 0.1)
            self._tick(monitorStatus, 1)

        clearHistory().addCallback(startMonitors)

    def stop (self):
        self._stopTicks()

    def reset (self):
        return defer.gatherResults([
            self.power.set("off"),
            self.pressure_limit.set(15000),
            self.output.set("waste"),
            self.loop1.set("load"),
            self.loop2.set("load"),
            self.pump1.input.set("solvent"),
            self.pump2.input.set("solvent"),
            self.pump1.target.set(0),
            self.pump2.target.set(0),
            self.heater1.target.set(-1000),
            self.heater2.target.set(-1000),
            self.heater3.target.set(-1000),
            self.heater4.target.set(-1000)
        ])

    def pause (self):
        self._pauseState = self.power.value
        return self.power.set("off")

    def resume (self):
        return self.power.set(self._pauseState)
Esempio n. 16
0
    def setup(self):

        # setup variables
        self.weight = Stream(title="Weight", type=float, unit="g")