예제 #1
0
파일: light.py 프로젝트: bensondaled/puffs
class Light(object):
    OFF,ON = 0,1
    def __init__(self, port='ao0', saver=None):
        self.port = port
        self.saver = saver
        self.daq = DAQ(DAQ.ANALOG_OUT, ports=[self.port])
        self.trig = Trigger(5.0, dtype=np.float64)
        self.end_trig = Trigger(0.0, dtype=np.float64)

        self.is_on = False
    def on(self):
        if self.is_on:
            return
        
        self.daq.trigger(self.trig, clear=False)
        if self.saver:
            self.saver.write('light', [self.ON])
        self.is_on = True
    def off(self):
        if not self.is_on:
            return

        self.daq.trigger(self.end_trig, clear=False)
        if self.saver:
            self.saver.write('light', [self.OFF])
        self.is_on = False
    def end(self):
        self.daq.release()
예제 #2
0
class AnalogReader(object):
    READ_BUF_SIZE = 10
    ACCUM_SIZE = 1000

    def __init__(
        self, ports=["ai0", "ai1", "ai5", "ai6"], runtime_ports=[0, 1], saver=None, lick_thresh=6.0, holding_thresh=1.0
    ):
        # IMPORTANT: NUMBER OF PORTS MUST MATCH VALUE IN EXPTS/DTYPES.PY
        self.ports = ports
        self.runtime_ports = runtime_ports  # to be used in accumulator and lick/holding variable
        self.saver = saver
        self.thresh = lick_thresh
        self.daq = DAQ(DAQ.ANALOG_IN, ports=self.ports, read_buffer_size=self.READ_BUF_SIZE)
        self.holding_thresh = int(holding_thresh * self.daq.sample_rate)

        # runtime vars
        self.licked_ = np.zeros(len(self.runtime_ports))
        self.accum = np.zeros((len(self.runtime_ports), self.ACCUM_SIZE))
        self.holding = np.array([False, False])
        self.lock = threading.Lock()
        self.accum_lock = threading.Lock()
        self.SAVING = False
        self.start()

    def start(self):
        # begin reading
        self.on = True
        th = threading.Thread(target=self.continuous_read)
        th.start()

    def get_accum(self):
        with self.accum_lock:
            return self.accum.copy()

    def continuous_read(self):
        while self.on:

            # read new data
            with self.accum_lock:
                self.accum = np.roll(self.accum, -self.READ_BUF_SIZE, axis=1)
                newdat_ts, newdat = (
                    self.daq.get()
                )  # important that "get" function locks thread, otherwise update line below would repeat logic on identical data
                assert newdat.shape == (len(self.ports), self.READ_BUF_SIZE)
                self.accum[:, -self.READ_BUF_SIZE :] = newdat[self.runtime_ports, :]

            # update logic
            with self.lock:
                self.licked_ += np.any(
                    newdat[self.runtime_ports, :] >= self.thresh, axis=1
                )  # is this really picking up the number of licks? no, it really represents the number of times this class queried and received a "at least 1 lick" response
                self.holding = np.all(self.accum[:, -self.holding_thresh :] > self.thresh, axis=1)

            if not self.on:  # b/c session can end b/t start of this loop iteration and this point
                break
            if self.saver and self.SAVING:
                self.saver.write("analogreader", newdat, ts=newdat_ts)
        self.release()

    def begin_saving(self):
        self.SAVING = True

    def licked(self):
        with self.lock:
            ret = self.licked_.copy()
            self.licked_ = np.zeros(len(self.runtime_ports))
            return ret

    def end(self):
        self.SAVING = False
        self.on = False

    def release(self):
        self.daq.release()