示例#1
0
    def __init__(self, param=DefaultParam):

        self.param = param
        self.experiment = self.param['experiment']
        self.experiment_time = self.param['experiment_time']
        self.time_start = time.time()

        # Set up Phidget channels
        self.aout_channel_yaw = 0
        self.aout_channel_x = 1
        self.aout_channel_yaw_gain = 2
        self.aout_channel_y = 3
        self.aout_max_volt = 10.0
        self.aout_min_volt = 0.0

        # Setup analog output YAW
        self.aout_yaw = VoltageOutput()
        self.aout_yaw.setChannel(self.aout_channel_yaw)
        self.aout_yaw.openWaitForAttachment(5000)
        self.aout_yaw.setVoltage(0.0)

        # Setup analog output X
        self.aout_x = VoltageOutput()
        self.aout_x.setChannel(self.aout_channel_x)
        self.aout_x.openWaitForAttachment(5000)
        self.aout_x.setVoltage(0.0)

        # Setup analog output YAW gain
        self.aout_yaw_gain = VoltageOutput()
        self.aout_yaw_gain.setChannel(self.aout_channel_yaw_gain)
        self.aout_yaw_gain.openWaitForAttachment(5000)
        self.aout_yaw_gain.setVoltage(0.0)

        # Setup analog output Y
        self.aout_y = VoltageOutput()
        self.aout_y.setChannel(self.aout_channel_y)
        self.aout_y.openWaitForAttachment(5000)
        self.aout_y.setVoltage(0.0)

        self.print = True

        # Set up socket info
        self.HOST = '127.0.0.1'  # The (receiving) host IP address (sock_host)
        self.PORT = 65432  # The (receiving) host port (sock_port)

        self.done = False

        self.gain_yaw = 1
        self.heading_with_gain = 0

        self.jump = True
        self.time_between_jumps = 90
        self.jump_size = 0

        #set up logger to save hd5f file
        self.logger = H5Logger(
            filename=self.param['logfile_name'],
            auto_incr=self.param['logfile_auto_incr'],
            auto_incr_format=self.param['logfile_auto_incr_format'],
            param_attr=self.param)
示例#2
0
    def __init__(self, param=DefaultParam):

        self.param = param
        self.experiment = self.param['experiment']
        self.experiment_time = self.param['experiment_time']
        self.time_start = time.time(
        )  # get the current time and use it as a ref for elapsed time

        #get gain for the panels and wind
        self.gain_panels = self.param['gain_panels']
        self.gain_wind = self.param['gain_wind']

        # Set up Phidget serial numbers for using two devices
        self.phidget_vision = 525577  # written on the back of the Phidget
        self.phidget_wind = 589946  # for sending the position of the motor to NI-DAQ

        # Set up Phidget channels in device 1 for vision (0-index)
        self.aout_channel_yaw = 0
        self.aout_channel_x = 1
        self.aout_channel_yaw_gain = 2
        self.aout_channel_y = 3
        self.aout_max_volt = 10.0
        self.aout_min_volt = 0.0

        # Setup analog output YAW
        self.aout_yaw = VoltageOutput()
        self.aout_yaw.setDeviceSerialNumber(self.phidget_vision)
        self.aout_yaw.setChannel(self.aout_channel_yaw)
        self.aout_yaw.openWaitForAttachment(5000)
        self.aout_yaw.setVoltage(0.0)

        # Setup analog output X
        self.aout_x = VoltageOutput()
        self.aout_x.setDeviceSerialNumber(self.phidget_vision)
        self.aout_x.setChannel(self.aout_channel_x)
        self.aout_x.openWaitForAttachment(5000)
        self.aout_x.setVoltage(0.0)

        # Setup analog output YAW gain
        self.aout_yaw_gain = VoltageOutput()
        self.aout_yaw_gain.setDeviceSerialNumber(self.phidget_vision)
        self.aout_yaw_gain.setChannel(self.aout_channel_yaw_gain)
        self.aout_yaw_gain.openWaitForAttachment(5000)
        self.aout_yaw_gain.setVoltage(0.0)

        # Setup analog output Y
        self.aout_y = VoltageOutput()
        self.aout_y.setDeviceSerialNumber(self.phidget_vision)
        self.aout_y.setChannel(self.aout_channel_y)
        self.aout_y.openWaitForAttachment(5000)
        self.aout_y.setVoltage(0.0)

        # Set up Phidget channels in device 2 for wind (0-index)
        self.aout_channel_motor = 0
        self.aout_channel_wind_valve = 2

        # Setup analog output motor
        self.aout_motor = VoltageOutput()
        self.aout_motor.setDeviceSerialNumber(self.phidget_wind)
        self.aout_motor.setChannel(self.aout_channel_motor)
        self.aout_motor.openWaitForAttachment(5000)
        self.aout_motor.setVoltage(0.0)

        # Setup analog output wind valve
        self.aout_wind_valve = VoltageOutput()
        self.aout_wind_valve.setDeviceSerialNumber(self.phidget_wind)
        self.aout_wind_valve.setChannel(self.aout_channel_wind_valve)
        self.aout_wind_valve.openWaitForAttachment(5000)
        self.aout_wind_valve.setVoltage(0.0)

        self.print = True

        # Set up socket info for connecting with the FicTrac
        self.HOST = '127.0.0.1'  # The (receiving) host IP address (sock_host)
        self.PORT = 65432  # The (receiving) host port (sock_port)

        # Set up Arduino connection
        self.COM = 'COM4'  # serial port
        self.baudrate = 115200  # 9600
        self.serialTimeout = 0.001  # blocking timeout for readline()

        # flag for indicating when the trial is done
        self.done = False

        #initialize heading with respect to panels to be starting position
        self.motor_command = 0
        self.bar_position = np.deg2rad(360 - self.param['offset'])

        self.jump = True
        self.time_between_jumps = 90  # [s]
        self.jump_mag = 90  # [deg] jump magnitude
        self.jump_size = 0  # default value is zero

        #set up logger to save hd5f file
        self.logger_fictrac = H5Logger(
            filename=self.param['logfile_name'],
            auto_incr=self.param['logfile_auto_incr'],
            auto_incr_format=self.param['logfile_auto_incr_format'],
            param_attr=self.param)

        #set up logger to save hd5f file
        self.logger_arduino = H5Logger(
            filename=(self.param['logfile_name']).replace(
                '.hdf5', '_arduino.hdf5'),
            auto_incr=self.param['logfile_auto_incr'],
            auto_incr_format=self.param['logfile_auto_incr_format'],
            param_attr=self.param)

        #specify a variable for the first message being read
        self.first_time_in_loop = True
示例#3
0
def endheatersignal():
    voltageOutput0 = VoltageOutput()
    voltageOutput0.close()
示例#4
0
class SocketClient(object):

    DefaultParam = {
        'experiment': 1,
        'experiment_time': 30,
        'logfile_name': 'Z:/Wilson Lab/Mel/FlyOnTheBall/data',
        'logfile_auto_incr': True,
        'logfile_auto_incr_format': '{0:06d}',
        'logfile_dt': 0.01,
        'offset': 0
    }

    def __init__(self, param=DefaultParam):

        self.param = param
        self.experiment = self.param['experiment']
        self.experiment_time = self.param['experiment_time']
        self.time_start = time.time(
        )  # get the current time and use it as a ref for elapsed time

        #get gain for the panels and wind
        self.gain_panels = self.param['gain_panels']
        self.gain_wind = self.param['gain_wind']

        # Set up Phidget serial numbers for using two devices
        self.phidget_vision = 525577  # written on the back of the Phidget
        self.phidget_wind = 589946  # for sending the position of the motor to NI-DAQ

        # Set up Phidget channels in device 1 for vision (0-index)
        self.aout_channel_yaw = 0
        self.aout_channel_x = 1
        self.aout_channel_yaw_gain = 2
        self.aout_channel_y = 3
        self.aout_max_volt = 10.0
        self.aout_min_volt = 0.0

        # Setup analog output YAW
        self.aout_yaw = VoltageOutput()
        self.aout_yaw.setDeviceSerialNumber(self.phidget_vision)
        self.aout_yaw.setChannel(self.aout_channel_yaw)
        self.aout_yaw.openWaitForAttachment(5000)
        self.aout_yaw.setVoltage(0.0)

        # Setup analog output X
        self.aout_x = VoltageOutput()
        self.aout_x.setDeviceSerialNumber(self.phidget_vision)
        self.aout_x.setChannel(self.aout_channel_x)
        self.aout_x.openWaitForAttachment(5000)
        self.aout_x.setVoltage(0.0)

        # Setup analog output YAW gain
        self.aout_yaw_gain = VoltageOutput()
        self.aout_yaw_gain.setDeviceSerialNumber(self.phidget_vision)
        self.aout_yaw_gain.setChannel(self.aout_channel_yaw_gain)
        self.aout_yaw_gain.openWaitForAttachment(5000)
        self.aout_yaw_gain.setVoltage(0.0)

        # Setup analog output Y
        self.aout_y = VoltageOutput()
        self.aout_y.setDeviceSerialNumber(self.phidget_vision)
        self.aout_y.setChannel(self.aout_channel_y)
        self.aout_y.openWaitForAttachment(5000)
        self.aout_y.setVoltage(0.0)

        # Set up Phidget channels in device 2 for wind (0-index)
        self.aout_channel_motor = 0
        self.aout_channel_wind_valve = 2

        # Setup analog output motor
        self.aout_motor = VoltageOutput()
        self.aout_motor.setDeviceSerialNumber(self.phidget_wind)
        self.aout_motor.setChannel(self.aout_channel_motor)
        self.aout_motor.openWaitForAttachment(5000)
        self.aout_motor.setVoltage(0.0)

        # Setup analog output wind valve
        self.aout_wind_valve = VoltageOutput()
        self.aout_wind_valve.setDeviceSerialNumber(self.phidget_wind)
        self.aout_wind_valve.setChannel(self.aout_channel_wind_valve)
        self.aout_wind_valve.openWaitForAttachment(5000)
        self.aout_wind_valve.setVoltage(0.0)

        self.print = True

        # Set up socket info for connecting with the FicTrac
        self.HOST = '127.0.0.1'  # The (receiving) host IP address (sock_host)
        self.PORT = 65432  # The (receiving) host port (sock_port)

        # Set up Arduino connection
        self.COM = 'COM4'  # serial port
        self.baudrate = 115200  # 9600
        self.serialTimeout = 0.001  # blocking timeout for readline()

        # flag for indicating when the trial is done
        self.done = False

        #initialize heading with respect to panels to be starting position
        self.motor_command = 0
        self.bar_position = np.deg2rad(360 - self.param['offset'])

        self.jump = True
        self.time_between_jumps = 90  # [s]
        self.jump_mag = 90  # [deg] jump magnitude
        self.jump_size = 0  # default value is zero

        #set up logger to save hd5f file
        self.logger_fictrac = H5Logger(
            filename=self.param['logfile_name'],
            auto_incr=self.param['logfile_auto_incr'],
            auto_incr_format=self.param['logfile_auto_incr_format'],
            param_attr=self.param)

        #set up logger to save hd5f file
        self.logger_arduino = H5Logger(
            filename=(self.param['logfile_name']).replace(
                '.hdf5', '_arduino.hdf5'),
            auto_incr=self.param['logfile_auto_incr'],
            auto_incr_format=self.param['logfile_auto_incr_format'],
            param_attr=self.param)

        #specify a variable for the first message being read
        self.first_time_in_loop = True

    def run(self):
        # connect to socket via UDP, not TCP!
        # connect to Arduino via serial
        with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock,\
         serial.Serial(self.COM, self.baudrate, timeout=self.serialTimeout) as ser:
            sock.bind((self.HOST,
                       self.PORT))  # takes one argument, give it as a tuple
            sock.setblocking(False)  # make it non-blocking

            # Keep receiving data from socket until FicTrac closes
            data = ""
            timeout_in_seconds = 1

            while not self.done:  # main loop
                self.aout_wind_valve.setVoltage(
                    5.0)  # keep the wind on for the duration of the trial

                motor_pos = np.nan
                self.motor_pos_rad = np.nan  # default value before receiving the data
                # listening to Arduino
                msg = ser.readline()  # read from serial until there's a \n
                self.time_arduino = time.time() - self.time_start  # (s)
                if msg:  # received a non-empty message
                    try:
                        arduino_line = msg.decode(
                            'utf-8')[:-2]  # decode and remove \r and \n
                        #motor_info = arduino_line.split(", ")
                        #log_arduino = str("{:.7f}".format(time_now)) + "," + motor_info[0] + "\n"  # first element is the current motor position (0-360 deg)
                        #f_arduino.writelines(log_arduino)
                        motor_pos = int(
                            arduino_line)  # current motor position (0-360 deg)
                        self.motor_pos_rad = np.deg2rad(motor_pos)

                        # Set analog output voltage of Phidget so that it could be recorded using NI-DAQ
                        output_voltage_motor = self.motor_pos_rad * (
                            self.aout_max_volt - self.aout_min_volt) / (2 *
                                                                        np.pi)
                        self.aout_motor.setVoltage(output_voltage_motor)

                        # write to HDF5 file
                        self.write_logfile_arduino()

                    except:
                        print("message from Arduino is not a number:", msg)

                # ask the OS whether the socket is readable
                # give 3 lists of sockets for reading, writing, and checking for errors; we only care about the first one
                # https://docs.python.org/3/howto/sockets.html#socket-programming-howto
                ready = select.select(
                    [sock], [], [], timeout_in_seconds
                )  # returns the subset of sockets that are actually readable

                # Only try to receive data if there is data waiting
                if ready[0]:
                    # Receive one data frame
                    new_data = sock.recv(
                        1024
                    )  # buffer size, should be a relatively small power of 2

                    # Uh oh?
                    if not new_data:
                        break

                    # Decode received data
                    data += new_data.decode('UTF-8')
                    self.time_elapsed = time.time() - self.time_start  # (s)

                    # Find the first frame of data
                    endline = data.find("\n")
                    line = data[:endline]  # copy first frame
                    data = data[endline + 1:]  # delete first frame

                    # Tokenise
                    toks = line.split(", ")

                    # Check that we have sensible tokens
                    if ((len(toks) < 24) | (toks[0] != "FT")):
                        print('Bad read')
                        continue

                    # Extract FicTrac variables
                    # (see https://github.com/rjdmoore/fictrac/blob/master/doc/data_header.txt for descriptions)
                    self.frame = int(toks[1])  # frame counter
                    self.posx = float(toks[15])  # integrated x position (rad)
                    self.posy = float(toks[16])  # integrated y position (rad)
                    self.intx = float(
                        toks[20]
                    )  # integrated x position (rad) of the sphere in lab coord neglecting heading
                    self.inty = float(
                        toks[21]
                    )  # integrated y position (rad) of the sphere in lab coord neglecting heading
                    self.timestamp = float(
                        toks[22])  # frame capture time (ms) since epoch

                    # calculate delta heading by comparing it to the previous value
                    if self.first_time_in_loop:
                        self.prev_heading = float(toks[17])
                        self.first_time_in_loop = False
                    else:
                        self.prev_heading = self.heading
                    self.heading = float(
                        toks[17]
                    )  # integrated heading direction of the animal in lab coords (rad)
                    self.deltaheading = self.heading - self.prev_heading

                    # Set analog output voltage YAW_gain
                    #set value depending on how much time has elapsed
                    if ((self.time_elapsed > 1)
                            and ((math.floor(self.time_elapsed) %
                                  self.time_between_jumps) == 0)
                            and (self.jump == True)):
                        #choose randomly between -120 and 120 jumps
                        self.jump_size = random.choice([
                            np.deg2rad(-self.jump_mag),
                            np.deg2rad(self.jump_mag)
                        ])
                        self.jump = False
                    else:
                        self.jump_size = 0

                #reset self.jump 1 sec before the gain change
                    if (((math.floor(self.time_elapsed + 1) %
                          self.time_between_jumps) == 0)
                            and (self.jump == False)):
                        self.jump = True

                    # send the heading signal to Arduino
                    self.motor_command = (self.motor_command +
                                          self.deltaheading +
                                          self.jump_size) % (2 * np.pi)
                    #animal_heading_360 = int(self.heading * (360 / (2 * np.pi)))  # convert from rad to deg
                    arduino_str = "H " + str(
                        360 - np.rad2deg(self.motor_command)
                    ) + "\n"  # "H is a command used in the Arduino code to indicate heading
                    arduino_byte = arduino_str.encode(
                    )  # convert unicode string to byte string
                    ser.write(arduino_byte)  # send to serial port

                    ## Set Phidget voltages using FicTrac data
                    # Set analog output voltage X
                    wrapped_intx = (self.intx % (2 * np.pi))
                    output_voltage_x = wrapped_intx * (
                        self.aout_max_volt - self.aout_min_volt) / (2 * np.pi)
                    self.aout_x.setVoltage(output_voltage_x)

                    # Set analog output voltage YAW
                    self.bar_position = (self.bar_position +
                                         self.deltaheading * self.gain_panels
                                         ) % (2 * np.pi)  # wrap around
                    self.output_voltage_yaw = (self.bar_position) * (
                        self.aout_max_volt - self.aout_min_volt) / (2 * np.pi)
                    self.aout_yaw.setVoltage(self.output_voltage_yaw)
                    self.aout_yaw_gain.setVoltage(self.output_voltage_yaw)

                    # Set analog output voltage Y
                    wrapped_inty = self.inty % (2 * np.pi)
                    output_voltage_y = wrapped_inty * (
                        self.aout_max_volt - self.aout_min_volt) / (2 * np.pi)
                    self.aout_y.setVoltage(output_voltage_y)

                    # Save fictrac data in HDF5 file
                    self.write_logfile_fictrac()

                    # Display status message
                    if self.print:
                        print(f'time elapsed: {self.time_elapsed: 1.3f}',
                              end='')
                        print(
                            f'  motor command: {np.rad2deg(self.motor_command):3.0f}',
                            end='')
                        print(f'  motor pos: {motor_pos:3.0f}', end='')
                        print(
                            f'  bar pos: {np.rad2deg(self.bar_position):3.0f}')
                        #print(f'  delta heading: {np.rad2deg(self.deltaheading):3.0f}')

                    if self.time_elapsed > self.experiment_time:
                        self.done = True
                        break

            # go back to 0 deg at the end of the trial
            arduino_str = "H " + str(
                0
            ) + "\n"  # "H is a command used in the Arduino code to indicate heading
            arduino_byte = arduino_str.encode(
            )  # convert unicode string to byte string
            ser.write(arduino_byte)  # send to serial port

            self.aout_wind_valve.setVoltage(
                0.0)  # turn the wind off at the end of the trial

            print('Trial finished - quitting!')

    #define function to log data to hdf5 file
    def write_logfile_fictrac(self):
        log_data = {
            'time': self.time_elapsed,
            'frame': self.frame,
            'posx': self.posx,
            'posy': self.posy,
            'intx': self.intx,
            'inty': self.inty,
            'heading': self.heading,
            'deltaheading': self.deltaheading,
            'motor': self.motor_pos_rad,
            'motor_command': self.motor_command,
            'bar_position': self.bar_position,
            'out_voltage_yaw': self.output_voltage_yaw
        }
        self.logger_fictrac.add(log_data)

    def write_logfile_arduino(self):
        log_data = {'time': self.time_arduino, 'motor': self.motor_pos_rad}
        self.logger_arduino.add(log_data)
示例#5
0
class PneumaticFrame2:
    def __init__(self, master, initial_name, top_name, color, sol, reg_pwr,
                 reg_set, reg_get, PSI):
        self.frame = Frame(master, borderwidth=2, relief=SUNKEN, bg=color)
        self.frame.pack()
        self.master = master
        self.frame_name = StringVar()
        self.frame_name.set(initial_name)
        self.state = 0
        self.fontType = "Comic Sans"
        self.activeColor = 'SpringGreen4'
        self.frameColor = color

        self.pressure = IntVar()
        self.lock_flag = IntVar()
        self.pressure.set("")

        self.power = Button(self.frame,
                            text="PWR",
                            activebackground=self.activeColor,
                            command=lambda: self.toggle_pwr())
        self.set_label = Button(self.frame,
                                text="SET LABEL",
                                font=(self.fontType, 7),
                                command=lambda: self.get_label_input())
        self.observed_pressure = Entry(self.frame,
                                       width=5,
                                       state="readonly",
                                       textvariable=self.pressure)
        if self.frame_name.get() == "Hydro":
            self.set_pressure_scale = Scale(self.frame,
                                            orient=HORIZONTAL,
                                            from_=0,
                                            to=92,
                                            resolution=0.5,
                                            bg=color,
                                            label="Set Pressure (PSI)",
                                            highlightthickness=0,
                                            command=self.set_pressure)
        else:
            self.set_pressure_scale = Scale(self.frame,
                                            orient=HORIZONTAL,
                                            from_=0,
                                            to=50,
                                            resolution=0.5,
                                            bg=color,
                                            label="Set Pressure (PSI)",
                                            highlightthickness=0,
                                            command=self.set_pressure)
        self.custom_label = Label(self.frame,
                                  textvariable=self.frame_name,
                                  font=(self.fontType, 14),
                                  bg=color)
        self.label = Label(self.frame, text=initial_name, bg=color)
        self.lock = Checkbutton(self.frame,
                                text="LOCK",
                                bg=color,
                                variable=self.lock_flag,
                                command=self.lock)
        self.frame_name.set(top_name)

        # Init the pressure scale to the default value.
        self.set_pressure_scale.set(PSI)
        # Lock hydo at startup
        if initial_name == "Hydro":
            self.lock.select()
            self.set_pressure_scale.config(state="disabled")
            self.power.config(state="disable")

        self.frame.rowconfigure(0, minsize=30)
        self.custom_label.grid(row=0, column=0, columnspan=2, sticky=S)
        self.set_label.grid(column=0, row=1, columnspan=2)
        self.frame.rowconfigure(2, minsize=50)
        self.power.grid(column=0, row=2)
        self.observed_pressure.grid(column=1, row=2)
        self.set_pressure_scale.grid(column=0, row=3, columnspan=2, padx=20)
        self.frame.rowconfigure(4, minsize=5)
        self.label.grid(column=0, row=5)
        self.lock.grid(column=1, row=5)

        # Connect to Phidget Solid State Relay for solinoid control
        if self.frame_name.get() == "Hydro":
            self.solenoid_switch = DigitalOutput()
            self.solenoid_switch.setDeviceSerialNumber(sol[0])
            self.solenoid_switch.setIsHubPortDevice(False)
            self.solenoid_switch.setHubPort(sol[1])
            self.solenoid_switch.setChannel(sol[2])
            self.solenoid_switch.openWaitForAttachment(5000)

        #Connect to Phidget Solid State Relay for regulator power control
        self.reg_switch = DigitalOutput()
        self.reg_switch.setDeviceSerialNumber(reg_pwr[0])
        self.reg_switch.setIsHubPortDevice(False)
        self.reg_switch.setHubPort(reg_pwr[1])
        self.reg_switch.setChannel(reg_pwr[2])
        self.reg_switch.openWaitForAttachment(5000)

        #Connect to Phidget Voltage Ouptut for pressure control
        self.pressure_ctrl = VoltageOutput()
        self.pressure_ctrl.setDeviceSerialNumber(reg_set[0])
        self.pressure_ctrl.setIsHubPortDevice(False)
        self.pressure_ctrl.setHubPort(reg_set[1])
        self.pressure_ctrl.setChannel(reg_set[2])
        self.pressure_ctrl.openWaitForAttachment(5000)

        #Connect to Phidget Analog Input for pressure reading
        self.pressure_reading = VoltageRatioInput()
        self.pressure_reading.setDeviceSerialNumber(reg_get[0])

        #One of the VINT Hubs on the SBC is used and needs special configuration
        if reg_get[0] == SBCH:
            self.pressure_reading.setIsHubPortDevice(True)
            self.pressure_reading.setHubPort(0)

        self.pressure_reading.setChannel(reg_get[1])
        self.pressure_reading.openWaitForAttachment(5000)

    def toggle_pwr(self):
        #Turn on air channel
        if self.state == 0:
            #Turn on power to regulator and show active button color
            self.power.config(bg=self.activeColor)
            self.reg_switch.setState(True)
            if self.frame_name.get() == "Hydro":
                self.solenoid_switch.setState(True)

            #Start monitoring air pressure
            self.update_pressure()

            #Change state of air channel
            self.state = 1

        #Turn off air channel
        elif self.state == 1:
            remember_state = self.set_pressure_scale.get()
            if self.frame_name.get() != "Hydro":
                messagebox.showinfo(
                    self.frame_name.get() + " Warning",
                    "Pressure will be set to zero. Acknowledge that " +
                    self.frame_name.get() + " is in a safe configuration")

            # Change pressure to zero
            self.set_pressure_scale.set(0)
            self.set_pressure(0)
            time.sleep(0.5)
            self.frame.update()
            self.reg_switch.setState(False)
            time.sleep(0.5)
            self.set_pressure_scale.set(remember_state)
            if self.frame_name.get() == "Hydro":
                self.solenoid_switch.setState(False)
                self.lock.select()
                self.set_pressure_scale.config(state="disabled")
                self.power.config(state="disable")

            #Turn off power to reguluator and remove active button color
            self.power.config(bg="SystemButtonFace")

            #Update air channel state
            self.state = 0

    def get_label_input(self):
        self.window = popupWindow(self.master)
        self.set_label.config(state=DISABLED)
        self.master.wait_window(self.window.top)
        self.set_label.config(state=NORMAL)

        #If the user does not enter a value exception will be produced
        try:
            if len(self.window.value) > 12:
                self.frame_name.set("SET ERROR")
            else:
                self.frame_name.set(self.window.value)
        except:
            self.frame_name.set("SET ERROR")

    def set_pressure(self, val):
        # Pressure Range
        range = MAXPR - MINPR
        # Calculate volts/PSI
        ratio = 5 / range
        self.pressure_ctrl.setVoltage(float(val) * ratio)

    def update_pressure(self):
        if self.reg_switch.getState():
            try:
                val = float(self.pressure_reading.getSensorValue())
                PSI = val * 165.63 - 30.855
                PSI = round(PSI, 2)
                self.pressure.set(PSI)
                #Low pressure check
                if PSI < (self.set_pressure_scale.get() - 3):
                    if self.frame.cget('bg') == "Red":
                        self.frame.config(bg=self.frameColor)
                        self.set_pressure_scale.config(bg=self.frameColor)
                        self.custom_label.config(bg=self.frameColor)
                        self.label.config(bg=self.frameColor)
                        self.lock.config(bg=self.frameColor)
                    else:
                        self.frame.config(bg='Red')
                        self.set_pressure_scale.config(bg="Red")
                        self.custom_label.config(bg="Red")
                        self.label.config(bg="Red")
                        self.lock.config(bg="Red")
                if PSI > (self.set_pressure_scale.get() - 3):
                    if self.frame.cget('bg') == "Red":
                        self.frame.config(bg=self.frameColor)
                        self.set_pressure_scale.config(bg=self.frameColor)
                        self.custom_label.config(bg=self.frameColor)
                        self.label.config(bg=self.frameColor)
                        self.lock.config(bg=self.frameColor)
            except:
                print("Init Air Pressure")
            root.after(200, self.update_pressure)
        else:
            self.pressure.set("")

    def lock(self):
        if self.lock_flag.get() == True:
            self.set_pressure_scale.config(state="disabled")
            self.power.config(state="disable")
        elif self.lock_flag.get() == False:
            self.set_pressure_scale.config(state="normal")
            self.power.config(state="normal")
示例#6
0
class SocketClient(object):

    DefaultParam = {
        'experiment': 1,
        'stim_speed': 20,
        'turn_type': 'clockwise',
        'bar_offset': 0,
        'experiment_time': 30,
        'logfile_name': 'Z:/Wilson Lab/Mel/FlyOnTheBall/data',
        'logfile_auto_incr': True,
        'logfile_auto_incr_format': '{0:06d}',
        'logfile_dt': 0.01,
    }

    def __init__(self, param=DefaultParam):

        self.param = param
        self.experiment = self.param['experiment']
        self.stim_speed = self.param['stim_speed']
        self.turn_type = self.param['turn_type']
        self.bar_offset = self.param[
            'bar_offset']  # bar relative to wind [deg]
        self.experiment_time = self.param['experiment_time']
        self.time_start = time.time(
        )  # get the current time and use it as a ref for elapsed time
        self.stim_dir = 0
        self.offset_adjust = 15  # use this offset to make bars perfectly aligned to wind, hard coded (deg)
        self.fly_heading = 0  # for calculating heading of the fly (rad)
        self.first_time_in_loop = True

        self.print = True  # for printing the current values on the console

        # specify the time epochs in the experiment
        self.time_baseline = 10  # [s] baseline period
        self.epoch_dur = 200  # [s] duration of an individual epoch
        self.epoch_num = 6  # total number of epochs

        # set voltage range for Phidget
        self.aout_max_volt = 10.0
        self.aout_min_volt = 0.0

        # set up two Phidgets
        self.phidget_vision = 525577  # for writing Fictrac x, y, and panels (yaw_gain)
        self.phidget_wind = 589946  # for sending the position of the motor to NI-DAQ, actual animal yaw

        # Set up Phidget channels in device 1 for vision (0-index)
        self.aout_channel_ydimension = 0
        self.aout_channel_x = 1
        self.aout_channel_y = 3
        self.aout_channel_yaw_gain = 2

        # Setup analog output X
        self.aout_x = VoltageOutput()
        self.aout_x.setDeviceSerialNumber(self.phidget_vision)
        self.aout_x.setChannel(self.aout_channel_x)
        self.aout_x.openWaitForAttachment(5000)
        self.aout_x.setVoltage(0.0)

        # Setup analog output Y
        self.aout_y = VoltageOutput()
        self.aout_y.setDeviceSerialNumber(self.phidget_vision)
        self.aout_y.setChannel(self.aout_channel_y)
        self.aout_y.openWaitForAttachment(5000)
        self.aout_y.setVoltage(0.0)

        # Setup analog output YAW (use this channel to turn panels on and off)
        self.aout_ydim = VoltageOutput()
        self.aout_ydim.setDeviceSerialNumber(self.phidget_vision)
        self.aout_ydim.setChannel(self.aout_channel_ydimension)
        self.aout_ydim.openWaitForAttachment(5000)
        self.aout_ydim.setVoltage(0.0)

        # Setup analog output YAW gain (use this channel to control panel bar position)
        self.aout_yaw_gain = VoltageOutput()
        self.aout_yaw_gain.setDeviceSerialNumber(self.phidget_vision)
        self.aout_yaw_gain.setChannel(self.aout_channel_yaw_gain)
        self.aout_yaw_gain.openWaitForAttachment(5000)
        self.aout_yaw_gain.setVoltage(0.0)

        # Set up Phidget channels in device 2 for wind (0-index)
        self.aout_channel_motor = 0
        self.aout_channel_yaw = 1  # for recording the actual yaw of the fly
        self.aout_channel_wind_valve = 2

        # Setup analog output motor
        self.aout_motor = VoltageOutput()
        self.aout_motor.setDeviceSerialNumber(self.phidget_wind)
        self.aout_motor.setChannel(self.aout_channel_motor)
        self.aout_motor.openWaitForAttachment(5000)
        self.aout_motor.setVoltage(0.0)

        # Setup analog output for yaw
        self.aout_yaw = VoltageOutput()
        self.aout_yaw.setDeviceSerialNumber(self.phidget_wind)
        self.aout_yaw.setChannel(self.aout_channel_yaw)
        self.aout_yaw.openWaitForAttachment(5000)
        self.aout_yaw.setVoltage(0.0)

        # Setup analog output wind valve
        self.aout_wind_valve = VoltageOutput()
        self.aout_wind_valve.setDeviceSerialNumber(self.phidget_wind)
        self.aout_wind_valve.setChannel(self.aout_channel_wind_valve)
        self.aout_wind_valve.openWaitForAttachment(5000)
        self.aout_wind_valve.setVoltage(0.0)

        # Set up socket info for connecting with the FicTrac
        self.HOST = '127.0.0.1'  # The (receiving) host IP address (sock_host)
        self.PORT = 65432  # The (receiving) host port (sock_port)

        # Set up Arduino connection
        self.COM = 'COM4'  # serial port
        self.baudrate = 115200  # 9600
        self.serialTimeout = 0.001  # blocking timeout for readline()

        # flag for indicating when the trial is done
        self.done = False

        #set up logger to save hd5f file
        self.logger_fictrac = H5Logger(
            filename=self.param['logfile_name'],
            auto_incr=self.param['logfile_auto_incr'],
            auto_incr_format=self.param['logfile_auto_incr_format'],
            param_attr=self.param)

        #set up logger to save hd5f file
        self.logger_arduino = H5Logger(
            filename=(self.param['logfile_name']).replace(
                '.hdf5', '_arduino.hdf5'),
            auto_incr=self.param['logfile_auto_incr'],
            auto_incr_format=self.param['logfile_auto_incr_format'],
            param_attr=self.param)

    def run(self, gain_x=1):
        # connect to socket via UDP, not TCP!
        # connect to Arduino via serial
        with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock,\
         serial.Serial(self.COM, self.baudrate, timeout=self.serialTimeout) as ser:
            sock.bind((self.HOST,
                       self.PORT))  # takes one argument, give it as a tuple
            sock.setblocking(False)  # make it non-blocking

            # Keep receiving data from socket until FicTrac closes
            data = ""
            timeout_in_seconds = 1
            self.time_end = time.time()  #initialize turn time

            while not self.done:  # main loop

                motor_pos = np.nan
                self.motor_pos_rad = np.nan  # default value before receiving the data
                # listening to Arduino
                msg = ser.readline()  # read from serial until there's a \n
                self.time_arduino = time.time() - self.time_start  # (s)
                if msg:  # received a non-empty message
                    try:
                        arduino_line = msg.decode(
                            'utf-8')[:-2]  # decode and remove \r and \n
                        motor_pos = int(
                            arduino_line)  # current motor position (0-360 deg)
                        self.motor_pos_rad = np.deg2rad(motor_pos)

                        # Set analog output voltage of Phidget for recording the current motor position
                        output_voltage_motor = self.motor_pos_rad * (
                            self.aout_max_volt - self.aout_min_volt) / (2 *
                                                                        np.pi)
                        self.aout_motor.setVoltage(output_voltage_motor)

                        # write to HDF5 file
                        self.write_logfile_arduino()

                    except:
                        print("message from Arduino is not a number:", msg)

                # ask the OS whether the socket is readable
                # give 3 lists of sockets for reading, writing, and checking for errors; we only care about the first one
                # https://docs.python.org/3/howto/sockets.html#socket-programming-howto
                ready = select.select(
                    [sock], [], [], timeout_in_seconds
                )  # returns the subset of sockets that are actually readable

                # Only try to receive data if there is data waiting
                if ready[0]:
                    # Receive one data frame
                    new_data = sock.recv(
                        1024
                    )  # buffer size, should be a relatively small power of 2

                    if not new_data:
                        break

                    # Decode received data
                    data += new_data.decode('UTF-8')
                    self.time_elapsed = time.time() - self.time_start  # (s)

                    # Find the first frame of data
                    endline = data.find("\n")
                    line = data[:endline]  # copy first frame
                    data = data[endline + 1:]  # delete first frame

                    # Tokenise
                    toks = line.split(", ")

                    # Check that we have sensible tokens
                    if ((len(toks) < 24) | (toks[0] != "FT")):
                        print('Bad read')
                        continue

                    # Extract FicTrac variables
                    # (see https://github.com/rjdmoore/fictrac/blob/master/doc/data_header.txt for descriptions)
                    self.frame = int(toks[1])  # frame counter
                    self.posx = float(toks[15])  # integrated x position (rad)
                    self.posy = float(toks[16])  # integrated y position (rad)
                    #self.heading = float(toks[17])  # integrated heading direction of the animal in lab coords (rad)
                    self.intx = float(
                        toks[20]
                    )  # integrated x position (rad) of the sphere in lab coord neglecting heading
                    self.inty = float(
                        toks[21]
                    )  # integrated y position (rad) of the sphere in lab coord neglecting heading
                    self.timestamp = float(
                        toks[22])  # frame capture time (ms) since epoch

                    self.time_step = time.time(
                    ) - self.time_end  # difference between now and the previous time step [s]
                    if self.turn_type == 'clockwise':
                        self.stim_dir = (
                            self.stim_dir +
                            (self.time_step * self.stim_speed)) % 360
                    elif self.turn_type == 'counterclockwise':
                        self.stim_dir = (
                            self.stim_dir -
                            (self.time_step * self.stim_speed)) % 360

                    self.time_end = time.time()  # save the current time step

                    # prepare the outputs based on the epoch
                    if self.time_elapsed < self.time_baseline:
                        self.epoch_counter = 0
                    else:
                        self.epoch_counter = int((
                            (self.time_elapsed - self.time_baseline) //
                            self.epoch_dur) + 1)

                    if self.epoch_counter == 0:  # baseline
                        wind_voltage = 0.0  # wind off
                        self.current_wind_dir = 0  # wind tube stationary at 0 deg
                        y_dim_voltage = 5.0  # bar off
                        self.current_bar_pos = 0

                    elif self.epoch_counter == 1:  # bar only
                        wind_voltage = 0.0  # wind off
                        self.current_wind_dir = 0  # wind tube stationary at 0 deg
                        y_dim_voltage = 9.0  # bar on
                        self.current_bar_pos = self.stim_dir

                    elif self.epoch_counter == 2:  # wind only
                        wind_voltage = 5.0  # wind on
                        self.current_wind_dir = self.stim_dir
                        y_dim_voltage = 5.0  # bar off
                        self.current_bar_pos = 0  # bar is off anyways

                    elif self.epoch_counter == 3:  # both rotating in sync
                        wind_voltage = 5.0  # wind on
                        self.current_wind_dir = self.stim_dir
                        y_dim_voltage = 9.0  # bar on
                        self.current_bar_pos = self.stim_dir

                    elif self.epoch_counter == 4:
                        wind_voltage = 5.0  # wind on
                        self.current_wind_dir = 0  # wind tube stationary at 0 deg
                        y_dim_voltage = 9.0  # bar on
                        self.current_bar_pos = self.stim_dir

                    elif self.epoch_counter == 5:  # both rotating in sync
                        wind_voltage = 5.0  # wind on
                        self.current_wind_dir = self.stim_dir
                        y_dim_voltage = 9.0  # bar on
                        self.current_bar_pos = self.stim_dir

                    elif self.epoch_counter == 6:  # stationary bar
                        wind_voltage = 5.0  # wind on
                        self.current_wind_dir = self.stim_dir
                        y_dim_voltage = 9.0  # bar on
                        self.current_bar_pos = 0

                    else:
                        self.done = True  # end of the experiment

                    # configure the outputs
                    self.aout_ydim.setVoltage(y_dim_voltage)
                    self.aout_wind_valve.setVoltage(
                        wind_voltage
                    )  # turn the wind off at the end of the trial

                    # send the wind direction to Arduino
                    arduino_str = "H " + str(
                        self.current_wind_dir
                    ) + "\n"  # "H is a command used in the Arduino code to indicate heading
                    arduino_byte = arduino_str.encode(
                    )  # convert unicode string to byte string
                    ser.write(arduino_byte)  # send to serial port

                    # set analog output voltage of Phidget so that the motor position could be recorded on NI-DAQ
                    output_voltage_motor = (self.current_wind_dir / 360) * (
                        self.aout_max_volt - self.aout_min_volt
                    )  # convert from deg to V
                    self.aout_motor.setVoltage(output_voltage_motor)

                    # open-loop bar: set analog output voltage YAW GAIN (note the sign flip)
                    self.current_bar_pos_adjusted = (
                        360 - self.current_bar_pos - self.bar_offset +
                        self.offset_adjust) % 360
                    output_voltage_yaw = self.current_bar_pos_adjusted * (
                        self.aout_max_volt - self.aout_min_volt) / 360
                    self.aout_yaw_gain.setVoltage(
                        output_voltage_yaw)  # yaw gain, not yaw!

                    ## Write FicTrac data to Phidget
                    # Set analog output voltage X
                    wrapped_intx = (self.intx % (2 * np.pi))
                    output_voltage_x = wrapped_intx * (
                        self.aout_max_volt - self.aout_min_volt) / (2 * np.pi)
                    self.aout_x.setVoltage(output_voltage_x)

                    # Set analog output voltage Y
                    wrapped_inty = self.inty % (2 * np.pi)
                    output_voltage_y = wrapped_inty * (
                        self.aout_max_volt - self.aout_min_volt) / (2 * np.pi)
                    self.aout_y.setVoltage(output_voltage_y)

                    # Set analog output voltage YAW (on the wind Phidget, not vision Phidget)
                    if self.first_time_in_loop:
                        self.prev_heading = float(toks[17])
                        self.first_time_in_loop = False
                    else:
                        self.prev_heading = self.heading
                    self.heading = float(
                        toks[17]
                    )  # integrated heading direction of the animal in lab coords (rad)
                    self.deltaheading = self.heading - self.prev_heading
                    self.fly_heading = (self.fly_heading + self.deltaheading
                                        ) % (2 * np.pi)  # wrap around
                    self.output_voltage_yaw = (self.fly_heading) * (
                        self.aout_max_volt - self.aout_min_volt) / (2 * np.pi)
                    self.aout_yaw.setVoltage(self.output_voltage_yaw)

                    # Save fictrac data in HDF5 file
                    self.write_logfile_fictrac()

                    # Display status message
                    if self.print:
                        print(f'epoch: {self.epoch_counter}', end='')
                        print(f'\t time elapsed: {self.time_elapsed: 1.3f} s',
                              end='')
                        print(f'\t wind dir: {self.current_wind_dir:3.0f} deg',
                              end='')
                        print(f'\t bar pos: {self.current_bar_pos:3.0f} deg',
                              end='')
                        print(f'\t y_dim: {y_dim_voltage:3.0f} V')

            # go back to 0 deg at the end of the trial
            arduino_str = "H " + str(
                0
            ) + "\n"  # "H is a command used in the Arduino code to indicate heading
            arduino_byte = arduino_str.encode(
            )  # convert unicode string to byte string
            ser.write(arduino_byte)  # send to serial port

            self.aout_wind_valve.setVoltage(
                0.0)  # turn the wind off at the end of the trial

            print('Trial finished - quitting!')

    #define function to log data to hdf5 file
    def write_logfile_fictrac(self):
        log_data = {
            'time': self.time_elapsed,
            'frame': self.frame,
            'posx': self.posx,
            'posy': self.posy,
            'intx': self.intx,
            'inty': self.inty,
            'heading': self.heading,
            'motor': self.motor_pos_rad
        }
        self.logger_fictrac.add(log_data)

    def write_logfile_arduino(self):
        log_data = {'time': self.time_arduino, 'motor': self.motor_pos_rad}
        self.logger_arduino.add(log_data)
示例#7
0
class SocketClientCueDisappears(object):

    DefaultParam = {
        'experiment': 1,
        'experiment_time': 30,
        'logfile_name': 'Z:/Wilson Lab/Mel/FlyOnTheBall/data',
        'logfile_auto_incr': True,
        'logfile_auto_incr_format': '{0:06d}',
        'logfile_dt': 0.01,
        'offset': 0
    }

    def __init__(self, param=DefaultParam):

        self.param = param
        self.experiment = self.param['experiment']
        self.experiment_time = self.param['experiment_time']
        self.time_start = time.time()

        # Set up Phidget channels
        self.aout_channel_ydimension = 0
        self.aout_channel_x = 1
        self.aout_channel_yaw_gain = 2
        self.aout_channel_y = 3
        self.aout_max_volt = 10.0
        self.aout_min_volt = 0.0

        # Set up Phidget serial numbers for using two devices
        self.phidget_vision = 525577  # written on the back of the Phidget
        self.phidget_heading = 589946

        # Setup analog output y dim, to change the y dimension of the stimulus
        self.aout_ydim = VoltageOutput()
        self.aout_ydim.setDeviceSerialNumber(self.phidget_vision)
        self.aout_ydim.setChannel(self.aout_channel_ydimension)
        self.aout_ydim.openWaitForAttachment(5000)
        self.aout_ydim.setVoltage(0.0)

        # Setup analog output X
        self.aout_x = VoltageOutput()
        self.aout_x.setDeviceSerialNumber(self.phidget_vision)
        self.aout_x.setChannel(self.aout_channel_x)
        self.aout_x.openWaitForAttachment(5000)
        self.aout_x.setVoltage(0.0)

        # Setup analog output YAW gain
        self.aout_yaw_gain = VoltageOutput()
        self.aout_yaw_gain.setDeviceSerialNumber(self.phidget_vision)
        self.aout_yaw_gain.setChannel(self.aout_channel_yaw_gain)
        self.aout_yaw_gain.openWaitForAttachment(5000)
        self.aout_yaw_gain.setVoltage(0.0)

        # Setup analog output Y
        self.aout_y = VoltageOutput()
        self.aout_y.setDeviceSerialNumber(self.phidget_vision)
        self.aout_y.setChannel(self.aout_channel_y)
        self.aout_y.openWaitForAttachment(5000)
        self.aout_y.setVoltage(9.0)

        # Set up Phidget channels in device 2 to save the heading
        self.aout_heading_channel = 1

        # Setup analog output motor
        self.aout_heading = VoltageOutput()
        self.aout_heading.setDeviceSerialNumber(self.phidget_heading)
        self.aout_heading.setChannel(self.aout_heading_channel)
        self.aout_heading.openWaitForAttachment(5000)
        self.aout_heading.setVoltage(0.0)

        self.print = True

        # Set up socket info
        self.HOST = '127.0.0.1'  # The (receiving) host IP address (sock_host)
        self.PORT = 65432  # The (receiving) host port (sock_port)

        # Set up Arduino connection
        self.COM = 'COM4'  # serial port
        self.baudrate = 115200  # 9600
        self.serialTimeout = 0.001  # blocking timeout for readline()

        self.done = False

        self.gain_yaw = 1
        self.heading_with_gain = 0

        self.bar_jump = True
        self.bar_jump_size = 0

        #initialize the bar on
        self.bar = True
        self.bar_moving = True

        #define times when bar will be turned off
        self.turn_off_times = np.linspace(900, 3525, 26)
        #self.turn_off_times = np.linspace(30,300,7)   #uncomment for testing

        #initialize heading with respect to panels to be starting position
        self.bar_position = np.deg2rad(360 - self.param['offset'])

        #set up logger to save hd5f file
        self.logger_fictrac = H5Logger(
            filename=self.param['logfile_name'],
            auto_incr=self.param['logfile_auto_incr'],
            auto_incr_format=self.param['logfile_auto_incr_format'],
            param_attr=self.param)

        #specify a variable for the first message being read
        self.first_time_in_loop = True

    def run(self):

        # UDP
        # Open the connection (ctrl-c / ctrl-break to quit)
        with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock,\
         serial.Serial(self.COM, self.baudrate, timeout=self.serialTimeout) as ser:
            sock.bind((self.HOST,
                       self.PORT))  # takes one argument, give it as a tuple
            sock.setblocking(False)  # make it non-blocking

            # Keep receiving data until FicTrac closes
            data = ""
            timeout_in_seconds = 1

            while not self.done:

                # Check to see whether there is data waiting
                ready = select.select([sock], [], [], timeout_in_seconds)

                # Only try to receive data if there is data waiting
                if ready[0]:
                    # Receive one data frame
                    new_data = sock.recv(1024)

                    # Uh oh?
                    if not new_data:
                        break

                    # Decode received data
                    data += new_data.decode('UTF-8')
                    #get time
                    time_now = time.time()
                    self.time_elapsed = time_now - self.time_start

                    # Find the first frame of data
                    endline = data.find("\n")
                    line = data[:endline]  # copy first frame
                    data = data[endline + 1:]  # delete first frame

                    # Tokenise
                    toks = line.split(", ")

                    # Check that we have sensible tokens
                    if ((len(toks) < 24) | (toks[0] != "FT")):
                        print('Bad read')
                        continue

                    # Extract FicTrac variables
                    # (see https://github.com/rjdmoore/fictrac/blob/master/doc/data_header.txt for descriptions)
                    self.frame = int(toks[1])
                    self.posx = float(toks[15])
                    self.posy = float(toks[16])
                    self.heading = float(toks[17])
                    self.intx = float(toks[20])
                    self.inty = float(toks[21])
                    self.timestamp = float(toks[22])

                    # calculate delta heading by comparing it to the previous value
                    #if self.first_time_in_loop:
                    #  self.prev_heading = float(toks[17])
                    # self.first_time_in_loop = False
                    #else:
                    #   self.prev_heading = self.heading
                    #self.deltaheading = self.heading - self.prev_heading
                    #I had to comment the above lines because they weren't working well.
                    self.deltaheading = float(toks[8])

                    #Set Phidget voltages using FicTrac data

                    #Set the voltages that don't depend on the time of the experiment
                    # Set analog output voltage X
                    wrapped_intx = (self.intx % (2 * np.pi))
                    output_voltage_x = wrapped_intx * (
                        self.aout_max_volt - self.aout_min_volt) / (2 * np.pi)
                    self.aout_x.setVoltage(output_voltage_x)

                    # Set analog output voltage Y
                    wrapped_inty = self.inty % (2 * np.pi)
                    output_voltage_y = wrapped_inty * (
                        self.aout_max_volt - self.aout_min_volt) / (2 * np.pi)
                    self.aout_y.setVoltage(output_voltage_y)

                    #At the right intervals, stop the stimulus and turn it off
                    if ((math.floor(self.time_elapsed) in self.turn_off_times)
                            and (self.bar == True)
                            and (self.bar_moving == True)):
                        self.bar = False
                        self.bar_moving = False
                        self.bar_jump = True  #resetting bar jump

                    #At the right intervals, make the stimulus jump 90 deg from its previous position and turn it on
                    if ((math.floor(self.time_elapsed - 15)
                         in self.turn_off_times) and (self.bar == False)
                            and (self.bar_moving == False)
                            and (self.bar_jump == True)):
                        self.bar_moving = True
                        self.bar = True
                        #self.bar_jump_size = random.choice([math.radians(-90),math.radians(90)])
                        self.bar_jump_size = 0
                        self.bar_jump = False
                    else:
                        self.bar_jump_size = 0

                    if self.bar_moving == True:
                        self.heading_with_gain = (
                            self.heading_with_gain + self.deltaheading *
                            self.gain_yaw + self.bar_jump_size) % (2 * np.pi)

                    output_voltage_yaw_gain = (self.heading_with_gain) * (
                        self.aout_max_volt - self.aout_min_volt) / (2 * np.pi)
                    self.aout_yaw_gain.setVoltage(10 - output_voltage_yaw_gain)

                    #store heading data
                    output_voltage_heading = self.heading
                    self.aout_heading.setVoltage(output_voltage_heading)

                    if self.bar == False:
                        y_dim_voltage = 5.0
                    else:
                        y_dim_voltage = 9.0

                    self.aout_ydim.setVoltage(y_dim_voltage)

                    # Save fictrac data in HDF5 file
                    self.write_logfile_fictrac()

                    # Display status message
                    if self.print:
                        print(f'time elapsed: {self.time_elapsed: 1.3f}',
                              end='')
                        print(
                            f'  bar pos: {np.rad2deg(self.heading_with_gain):3.0f}'
                        )
                        print(f'  ydim volt: {y_dim_voltage:3.0f}')
                        print(
                            f'  delta heading: {np.rad2deg(self.deltaheading):3.0f}'
                        )

                    if self.time_elapsed > self.experiment_time:
                        self.done = True
                        break

            print('Trial finished - quitting!')

    #define function to log data to hdf5 file
    def write_logfile_fictrac(self):
        log_data = {
            'time': self.time_elapsed,
            'frame': self.frame,
            'posx': self.posx,
            'posy': self.posy,
            'intx': self.intx,
            'inty': self.inty,
            'heading': self.heading,
            'deltaheading': self.deltaheading,
            'bar_position': self.heading_with_gain,
        }
        self.logger_fictrac.add(log_data)
示例#8
0
    def __init__(self, param=DefaultParam):

        self.param = param
        self.experiment = self.param['experiment']
        self.experiment_time = self.param['experiment_time']
        self.time_start = time.time()

        # Set up Phidget channels
        self.aout_channel_ydimension = 0  #I'm setting up a channel such that I can change the y dimension of the panels sending a signal through here
        self.aout_channel_x = 1
        self.aout_channel_yaw_gain = 2
        self.aout_channel_y = 3
        self.aout_max_volt = 10.0
        self.aout_min_volt = 0.0

        # Set up Phidget serial numbers for using two devices
        self.phidget_vision = 525577  # written on the back of the Phidget
        self.phidget_wind = 589946  # for sending the position of the motor to NI-DAQ

        # Setup analog output YAW
        self.aout_ydim = VoltageOutput()
        self.aout_ydim.setDeviceSerialNumber(self.phidget_vision)
        self.aout_ydim.setChannel(self.aout_channel_ydimension)
        self.aout_ydim.openWaitForAttachment(5000)
        self.aout_ydim.setVoltage(0.0)

        # Setup analog output X
        self.aout_x = VoltageOutput()
        self.aout_x.setDeviceSerialNumber(self.phidget_vision)
        self.aout_x.setChannel(self.aout_channel_x)
        self.aout_x.openWaitForAttachment(5000)
        self.aout_x.setVoltage(0.0)

        # Setup analog output YAW gain
        self.aout_yaw_gain = VoltageOutput()
        self.aout_yaw_gain.setDeviceSerialNumber(self.phidget_vision)
        self.aout_yaw_gain.setChannel(self.aout_channel_yaw_gain)
        self.aout_yaw_gain.openWaitForAttachment(5000)
        self.aout_yaw_gain.setVoltage(0.0)

        # Setup analog output Y
        self.aout_y = VoltageOutput()
        self.aout_y.setDeviceSerialNumber(self.phidget_vision)
        self.aout_y.setChannel(self.aout_channel_y)
        self.aout_y.openWaitForAttachment(5000)
        self.aout_y.setVoltage(9.0)

        # Set up Phidget channels in device 2 for wind
        self.aout_channel_motor = 0
        self.aout_channel_wind_valve = 2

        # Setup analog output motor
        self.aout_motor = VoltageOutput()
        self.aout_motor.setDeviceSerialNumber(self.phidget_wind)
        self.aout_motor.setChannel(self.aout_channel_motor)
        self.aout_motor.openWaitForAttachment(5000)
        self.aout_motor.setVoltage(0.0)

        # Setup analog output wind valve
        self.aout_wind_valve = VoltageOutput()
        self.aout_wind_valve.setDeviceSerialNumber(self.phidget_wind)
        self.aout_wind_valve.setChannel(self.aout_channel_wind_valve)
        self.aout_wind_valve.openWaitForAttachment(5000)
        self.aout_wind_valve.setVoltage(0.0)

        self.print = True

        # Set up socket info
        self.HOST = '127.0.0.1'  # The (receiving) host IP address (sock_host)
        self.PORT = 65432  # The (receiving) host port (sock_port)

        # Set up Arduino connection
        self.COM = 'COM4'  # serial port
        self.baudrate = 115200  # 9600
        self.serialTimeout = 0.001  # blocking timeout for readline()

        self.done = False

        self.gain_yaw = 1
        self.heading_with_gain = 0

        self.bar_jump = True
        self.bar_jump_size = 0
        self.wind_jump = True
        self.wind_jump_size = 0

        #initialize the bar on and the wind off
        self.bar = False
        self.wind = True

        #initialize heading with respect to panels to be starting position
        self.motor_command = 0
        self.bar_position = np.deg2rad(360 - self.param['offset'])

        #set up logger to save hd5f file
        self.logger_fictrac = H5Logger(
            filename=self.param['logfile_name'],
            auto_incr=self.param['logfile_auto_incr'],
            auto_incr_format=self.param['logfile_auto_incr_format'],
            param_attr=self.param)

        #set up logger to save hd5f file
        self.logger_arduino = H5Logger(
            filename=(self.param['logfile_name']).replace(
                '.hdf5', '_arduino.hdf5'),
            auto_incr=self.param['logfile_auto_incr'],
            auto_incr_format=self.param['logfile_auto_incr_format'],
            param_attr=self.param)

        #specify a variable for the first message being read
        self.first_time_in_loop = True
示例#9
0
    def __init__(self, master, colorArray):
        frame1 = Frame(master, borderwidth=2, relief=SUNKEN)
        frame2 = Frame(master, borderwidth=2, relief=SUNKEN)
        frame3 = Frame(master, borderwidth=2, relief=SUNKEN)
        frame4 = Frame(master, borderwidth=2, relief=SUNKEN)
        frame5 = Frame(master, borderwidth=2, relief=SUNKEN)
        frame6 = Frame(master, borderwidth=2, relief=SUNKEN)
        frame7 = Frame(master, borderwidth=2, relief=SUNKEN)
        camera_frame_1 = Frame(master, borderwidth=2, relief=SUNKEN, bg='LightSkyBlue2')
        camera_frame_2 = Frame(master, borderwidth=2, relief=SUNKEN, bg='light goldenrod yellow')

        frame1.grid(row=1, column=0)
        frame2.grid(row=1, column=1)
        frame3.grid(row=1, column=2)
        frame4.grid(row=1, column=3)
        frame5.grid(row=1, column=4)
        frame6.grid(row=1, column=5)
        frame7.grid(row=1, column=6)
        camera_frame_1.grid(row=3, column=0, columnspan=7, sticky=NSEW)
        camera_frame_2.grid(row=4, column=0, columnspan=7, sticky=NSEW)

        self.out1 = AxisFrame(frame1, "BASE CIRC", "VESSEL RIGHT", "VESSEL LEFT", HUB1, 5, colorArray[0], 3.3, 0.55)
        self.out2 = AxisFrame(frame2, "BASE AUX", "CW/IN", "CCW/OUT", HUB2, 0, colorArray[1], 2.2, 0.11)
        self.out3 = AxisFrame(frame3, "VARD ROT", "CW", "CCW", HUB1, 3, colorArray[2], 2.2, 0.15)
        self.out4 = AxisFrame(frame4, "VARD VERT", "UP", "DOWN", HUB1, 4, colorArray[3], 7.8, 0.54)
        self.out5 = AxisFrame(frame5, "DA MAST", "UP", "DOWN", HUB1, 0, colorArray[4], 8, 0.86)
        self.out6 = AxisFrame(frame6, "DA PAN", "CW", "CCW", HUB1, 2, colorArray[5], 3.0, 0.30)
        self.out7 = AxisFrame(frame7, "DA TILT", "UP", "DOWN", HUB1, 1, colorArray[6], 3.6, 0.57)

        # RJ Camera Control: Code Tool Camera
        self.invert_tilt_1 = BooleanVar()
        self.invert_pan_1 = BooleanVar()
        self.btn_power_1 = Button(camera_frame_1, text="PWR", font="Courier, 12", command=self.toggle_power_1)
        self.btn_near_1 = Button(camera_frame_1, text="NEAR", font="Courier, 12", width=7)
        self.btn_far_1 = Button(camera_frame_1, text="FAR", font="Courier, 12", width=7)
        self.btn_wide_1 = Button(camera_frame_1, text="WIDE", font="Courier, 12", width=7)
        self.btn_tele_1 = Button(camera_frame_1, text="TELE", font="Courier, 12", width=7)
        self.btn_ms_1 = Button(camera_frame_1, text="MS", font="Courier, 12", width=7)
        self.left_light_scale_1 = Scale(camera_frame_1, orient=VERTICAL, from_=0, to=0.45, resolution=0.01,
                                        command=self.update_left_intensity_1, bg='LightSkyBlue2', highlightthickness=0)
        self.right_light_scale_1 = Scale(camera_frame_1, orient=VERTICAL, from_=0, to=0.45, resolution=0.01,
                                         command=self.update_right_intensity_1, bg='LightSkyBlue2',
                                         highlightthickness=0)
        self.label_lights_1 = Label(camera_frame_1, text="  Light Intensity", bg='LightSkyBlue2')
        self.label_camera_type_1 = Label(camera_frame_1, text="TOOL CAMERA", font=("TkDefaultFont", 14),
                                         bg='LightSkyBlue2')
        self.btn_tilt_up_1 = Button(camera_frame_1, text="TILT UP", font="Courier, 12", width=10)
        self.btn_tilt_down_1 = Button(camera_frame_1, text="TILT DOWN", font="Courier, 12", width=10)
        self.btn_pan_right_1 = Button(camera_frame_1, text="PAN RIGHT", font="Courier, 12", width=10)
        self.btn_pan_left_1 = Button(camera_frame_1, text="PAN LEFT", font="Courier, 12", width=10)
        self.tilt_speed_1 = Scale(camera_frame_1, orient=HORIZONTAL, from_=0.01, to=.5, resolution=0.01,
                                  bg='LightSkyBlue2', highlightthickness=0)
        self.pan_speed_1 = Scale(camera_frame_1, orient=HORIZONTAL, from_=0.01, to=.5, resolution=0.01,
                                 bg='LightSkyBlue2', highlightthickness=0)
        self.ckbx_invert_tilt_1 = Checkbutton(camera_frame_1, text="Invert Tilt", variable=self.invert_tilt_1,
                                              bg='LightSkyBlue2')
        self.ckbx_invert_pan_1 = Checkbutton(camera_frame_1, text="Invert Pan", variable=self.invert_pan_1,
                                             bg='LightSkyBlue2')
        self.activeColor_1 = 'SpringGreen4'

        self.tilt_speed_1.set(0.15)
        self.pan_speed_1.set(0.15)

        # RJ Camera Control: Overview Camera
        self.invert_tilt_2 = BooleanVar()
        self.invert_pan_2 = BooleanVar()
        self.btn_power_2 = Button(camera_frame_2, text="PWR", font="Courier, 12", command=self.toggle_power_2)
        self.btn_near_2 = Button(camera_frame_2, text="NEAR", font="Courier, 12", width=7)
        self.btn_far_2 = Button(camera_frame_2, text="FAR", font="Courier, 12", width=7)
        self.btn_wide_2 = Button(camera_frame_2, text="WIDE", font="Courier, 12", width=7)
        self.btn_tele_2 = Button(camera_frame_2, text="TELE", font="Courier, 12", width=7)
        self.btn_ms_2 = Button(camera_frame_2, text="MS", font="Courier, 12", width=7)
        self.left_light_scale_2 = Scale(camera_frame_2, orient=VERTICAL, from_=0, to=0.45, resolution=0.01,
                                        command=self.update_left_intensity_2, bg='light goldenrod yellow',
                                        highlightthickness=0)
        self.right_light_scale_2 = Scale(camera_frame_2, orient=VERTICAL, from_=0, to=0.45, resolution=0.01,
                                         command=self.update_right_intensity_2, bg='light goldenrod yellow',
                                         highlightthickness=0)
        self.label_lights_2 = Label(camera_frame_2, text="  Light Intensity", bg='light goldenrod yellow')
        self.label_camera_type_2 = Label(camera_frame_2, text="OVERVIEW CAMERA", font=("TkDefaultFont", 14),
                                         bg='light goldenrod yellow')
        self.btn_tilt_up_2 = Button(camera_frame_2, text="TILT UP", font="Courier, 12", width=10)
        self.btn_tilt_down_2 = Button(camera_frame_2, text="TILT DOWN", font="Courier, 12", width=10)
        self.btn_pan_right_2 = Button(camera_frame_2, text="PAN RIGHT", font="Courier, 12", width=10)
        self.btn_pan_left_2 = Button(camera_frame_2, text="PAN LEFT", font="Courier, 12", width=10)
        self.tilt_speed_2 = Scale(camera_frame_2, orient=HORIZONTAL, from_=0.01, to=.5, resolution=0.01,
                                  bg='light goldenrod yellow', highlightthickness=0)
        self.pan_speed_2 = Scale(camera_frame_2, orient=HORIZONTAL, from_=0.01, to=.5, resolution=0.01,
                                 bg='light goldenrod yellow', highlightthickness=0)
        self.ckbx_invert_tilt_2 = Checkbutton(camera_frame_2, text="Invert Tilt", variable=self.invert_tilt_2,
                                              bg='light goldenrod yellow')
        self.ckbx_invert_pan_2 = Checkbutton(camera_frame_2, text="Invert Pan", variable=self.invert_pan_2,
                                             bg='light goldenrod yellow')
        self.activeColor_2 = 'SpringGreen4'

        self.tilt_speed_2.set(0.15)
        self.pan_speed_2.set(0.15)

        # Grid the Tool Camera Controls
        self.btn_power_1.grid(row=0, column=0, padx=60)
        self.btn_ms_1.grid(row=1, column=0, padx=5, pady=5)
        self.btn_near_1.grid(row=0, column=2, padx=20, pady=10)
        self.btn_far_1.grid(row=1, column=2, padx=20, pady=10)
        self.btn_tele_1.grid(row=0, column=3, padx=20, pady=10)
        self.btn_wide_1.grid(row=1, column=3, padx=20, pady=10)
        self.label_camera_type_1.grid(row=2, column=0, columnspan=4)
        self.left_light_scale_1.grid(row=0, column=4, rowspan=3, padx=20, pady=5)
        self.right_light_scale_1.grid(row=0, column=5, rowspan=3, padx=45, pady=5)
        self.label_lights_1.grid(row=3, column=4, columnspan=2, padx=45, sticky=N)
        self.btn_tilt_up_1.grid(row=0, column=6, padx=20, pady=5)
        self.btn_tilt_down_1.grid(row=1, column=6, padx=20, pady=5)
        self.btn_pan_right_1.grid(row=0, column=8, padx=20, pady=5, rowspan=2)
        self.btn_pan_left_1.grid(row=0, column=7, padx=20, pady=5, rowspan=2)
        self.tilt_speed_1.grid(row=2, column=6)
        self.pan_speed_1.grid(row=2, column=7, columnspan=2)
        self.ckbx_invert_tilt_1.grid(row=3, column=6)
        self.ckbx_invert_pan_1.grid(row=3, column=7, columnspan=2)

        # Grid the Overview Camera Controls
        self.btn_power_2.grid(row=0, column=0, padx=60)
        self.btn_ms_2.grid(row=1, column=0, padx=5, pady=5)
        self.btn_near_2.grid(row=0, column=2, padx=20, pady=10)
        self.btn_far_2.grid(row=1, column=2, padx=20, pady=10)
        self.btn_tele_2.grid(row=0, column=3, padx=20, pady=10)
        self.btn_wide_2.grid(row=1, column=3, padx=20, pady=10)
        self.label_camera_type_2.grid(row=2, column=0, columnspan=4)
        self.left_light_scale_2.grid(row=0, column=4, rowspan=3, padx=20, pady=5)
        self.right_light_scale_2.grid(row=0, column=5, rowspan=3, padx=45, pady=5)
        self.label_lights_2.grid(row=3, column=4, columnspan=2, padx=45, sticky=N)
        self.btn_tilt_up_2.grid(row=0, column=6, padx=20, pady=5)
        self.btn_tilt_down_2.grid(row=1, column=6, padx=20, pady=5)
        self.btn_pan_right_2.grid(row=0, column=8, padx=20, pady=5, rowspan=2)
        self.btn_pan_left_2.grid(row=0, column=7, padx=20, pady=5, rowspan=2)
        self.tilt_speed_2.grid(row=2, column=6)
        self.pan_speed_2.grid(row=2, column=7, columnspan=2)
        self.ckbx_invert_tilt_2.grid(row=3, column=6)
        self.ckbx_invert_pan_2.grid(row=3, column=7, columnspan=2)

        # Connect to Phidget Devices for Tool Camera
        self.power_1 = DigitalOutput()
        self.power_1.setDeviceSerialNumber(HUB2)
        self.power_1.setIsHubPortDevice(False)
        self.power_1.setHubPort(1)
        self.power_1.setChannel(0)
        try:
            self.power_1.openWaitForAttachment(1000)
        except PhidgetException as e:
            print("Failed to open (CAM POWER): " + e.details)

        self.manual_select_1 = DigitalOutput()
        self.manual_select_1.setDeviceSerialNumber(HUB2)
        self.manual_select_1.setIsHubPortDevice(False)
        self.manual_select_1.setHubPort(1)
        self.manual_select_1.setChannel(1)
        try:
            self.manual_select_1.openWaitForAttachment(1000)
        except PhidgetException as e:
            print("Failed to open (Manual Select): " + e.details)

        self.near_1 = DigitalOutput()
        self.near_1.setDeviceSerialNumber(HUB2)
        self.near_1.setIsHubPortDevice(False)
        self.near_1.setHubPort(1)
        self.near_1.setChannel(2)
        try:
            self.near_1.openWaitForAttachment(1000)
        except PhidgetException as e:
            print("Failed to open (NEAR): " + e.details)

        self.far_1 = DigitalOutput()
        self.far_1.setDeviceSerialNumber(HUB2)
        self.far_1.setIsHubPortDevice(False)
        self.far_1.setHubPort(1)
        self.far_1.setChannel(3)
        try:
            self.far_1.openWaitForAttachment(1000)
        except PhidgetException as e:
            print("Failed to open (FAR): " + e.details)

        self.wide_1 = DigitalOutput()
        self.wide_1.setDeviceSerialNumber(HUB2)
        self.wide_1.setIsHubPortDevice(False)
        self.wide_1.setHubPort(1)
        self.wide_1.setChannel(4)
        try:
            self.wide_1.openWaitForAttachment(1000)
        except PhidgetException as e:
            print("Failed to open (WIDE): " + e.details)

        self.tele_1 = DigitalOutput()
        self.tele_1.setDeviceSerialNumber(HUB2)
        self.tele_1.setIsHubPortDevice(False)
        self.tele_1.setHubPort(1)
        self.tele_1.setChannel(5)
        try:
            self.tele_1.openWaitForAttachment(1000)
        except PhidgetException as e:
            print("Failed to open (TELE): " + e.details)

        self.left_light_1 = VoltageOutput()
        self.left_light_1.setDeviceSerialNumber(HUB2)
        self.left_light_1.setIsHubPortDevice(False)
        self.left_light_1.setHubPort(2)
        self.left_light_1.setChannel(0)
        try:
            self.left_light_1.openWaitForAttachment(1000)
        except PhidgetException as e:
            print("Failed to open (LEFT LIGHT): " + e.details)

        self.right_light_1 = VoltageOutput()
        self.right_light_1.setDeviceSerialNumber(HUB2)
        self.right_light_1.setIsHubPortDevice(False)
        self.right_light_1.setHubPort(3)
        self.right_light_1.setChannel(0)
        try:
            self.right_light_1.openWaitForAttachment(1000)
        except PhidgetException as e:
            print("Failed to open (RIGHT LIGHT): " + e.details)

        self.pan_1 = VoltageOutput()
        self.pan_1.setDeviceSerialNumber(HUB2)
        self.pan_1.setIsHubPortDevice(False)
        self.pan_1.setHubPort(5)
        self.pan_1.setChannel(0)
        try:
            self.pan_1.openWaitForAttachment(1000)
        except PhidgetException as e:
            print("Failed to open (PAN): " + e.details)

        self.tilt_1 = VoltageOutput()
        self.tilt_1.setDeviceSerialNumber(HUB2)
        self.tilt_1.setIsHubPortDevice(False)
        self.tilt_1.setHubPort(4)
        self.tilt_1.setChannel(0)
        try:
            self.tilt_1.openWaitForAttachment(1000)
        except PhidgetException as e:
            print("Failed to open (TILT): " + e.details)

        self.btn_near_1.bind('<ButtonPress-1>', lambda event: self.focus_1("+"))
        self.btn_near_1.bind('<ButtonRelease-1>', lambda event: self.focus_1("0"))
        self.btn_far_1.bind('<ButtonPress-1>', lambda event: self.focus_1("-"))
        self.btn_far_1.bind('<ButtonRelease-1>', lambda event: self.focus_1("0"))
        self.btn_wide_1.bind('<ButtonPress-1>', lambda event: self.zoom_1("-"))
        self.btn_wide_1.bind('<ButtonRelease-1>', lambda event: self.zoom_1("0"))
        self.btn_tele_1.bind('<ButtonPress-1>', lambda event: self.zoom_1("+"))
        self.btn_tele_1.bind('<ButtonRelease-1>', lambda event: self.zoom_1("0"))
        self.btn_ms_1.bind('<ButtonPress-1>', lambda event: self.focus_type_1("ON"))
        self.btn_ms_1.bind('<ButtonRelease-1>', lambda event: self.focus_type_1("OFF"))

        self.btn_tilt_up_1.bind('<ButtonPress-1>', lambda event: self.tilt_move_1("-"))
        self.btn_tilt_up_1.bind('<ButtonRelease-1>', lambda event: self.tilt_move_1("0"))
        self.btn_tilt_down_1.bind('<ButtonPress-1>', lambda event: self.tilt_move_1("+"))
        self.btn_tilt_down_1.bind('<ButtonRelease-1>', lambda event: self.tilt_move_1("0"))
        self.btn_pan_right_1.bind('<ButtonPress-1>', lambda event: self.pan_move_1("R"))
        self.btn_pan_right_1.bind('<ButtonRelease-1>', lambda event: self.pan_move_1("0"))
        self.btn_pan_left_1.bind('<ButtonPress-1>', lambda event: self.pan_move_1("L"))
        self.btn_pan_left_1.bind('<ButtonRelease-1>', lambda event: self.pan_move_1("0"))

        # Connect to Phidget Devices for Overview Camera
        self.power_2 = DigitalOutput()
        self.power_2.setDeviceSerialNumber(HUB2)
        self.power_2.setIsHubPortDevice(False)
        self.power_2.setHubPort(1)
        self.power_2.setChannel(0)
        try:
            self.power_2.openWaitForAttachment(1000)
        except PhidgetException as e:
            print("Failed to open (CAM POWER): " + e.details)

        self.manual_select_2 = DigitalOutput()
        self.manual_select_2.setDeviceSerialNumber(HUB2)
        self.manual_select_2.setIsHubPortDevice(False)
        self.manual_select_2.setHubPort(1)
        self.manual_select_2.setChannel(1)
        try:
            self.manual_select_2.openWaitForAttachment(1000)
        except PhidgetException as e:
            print("Failed to open (Manual Select): " + e.details)

        self.near_2 = DigitalOutput()
        self.near_2.setDeviceSerialNumber(HUB2)
        self.near_2.setIsHubPortDevice(False)
        self.near_2.setHubPort(1)
        self.near_2.setChannel(2)
        try:
            self.near_2.openWaitForAttachment(1000)
        except PhidgetException as e:
            print("Failed to open (NEAR): " + e.details)

        self.far_2 = DigitalOutput()
        self.far_2.setDeviceSerialNumber(HUB2)
        self.far_2.setIsHubPortDevice(False)
        self.far_2.setHubPort(1)
        self.far_2.setChannel(3)
        try:
            self.far_2.openWaitForAttachment(1000)
        except PhidgetException as e:
            print("Failed to open (FAR): " + e.details)

        self.wide_2 = DigitalOutput()
        self.wide_2.setDeviceSerialNumber(HUB2)
        self.wide_2.setIsHubPortDevice(False)
        self.wide_2.setHubPort(1)
        self.wide_2.setChannel(4)
        try:
            self.wide_2.openWaitForAttachment(1000)
        except PhidgetException as e:
            print("Failed to open (WIDE): " + e.details)

        self.tele_2 = DigitalOutput()
        self.tele_2.setDeviceSerialNumber(HUB2)
        self.tele_2.setIsHubPortDevice(False)
        self.tele_2.setHubPort(1)
        self.tele_2.setChannel(5)
        try:
            self.tele_2.openWaitForAttachment(1000)
        except PhidgetException as e:
            print("Failed to open (TELE): " + e.details)

        self.left_light_2 = VoltageOutput()
        self.left_light_2.setDeviceSerialNumber(HUB2)
        self.left_light_2.setIsHubPortDevice(False)
        self.left_light_2.setHubPort(2)
        self.left_light_2.setChannel(0)
        try:
            self.left_light_2.openWaitForAttachment(1000)
        except PhidgetException as e:
            print("Failed to open (LEFT LIGHT): " + e.details)

        self.right_light_2 = VoltageOutput()
        self.right_light_2.setDeviceSerialNumber(HUB2)
        self.right_light_2.setIsHubPortDevice(False)
        self.right_light_2.setHubPort(3)
        self.right_light_2.setChannel(0)
        try:
            self.right_light_2.openWaitForAttachment(1000)
        except PhidgetException as e:
            print("Failed to open (RIGHT LIGHT): " + e.details)

        self.pan_2 = VoltageOutput()
        self.pan_2.setDeviceSerialNumber(HUB2)
        self.pan_2.setIsHubPortDevice(False)
        self.pan_2.setHubPort(5)
        self.pan_2.setChannel(0)
        try:
            self.pan_2.openWaitForAttachment(1000)
        except PhidgetException as e:
            print("Failed to open (PAN): " + e.details)

        self.tilt_2 = VoltageOutput()
        self.tilt_2.setDeviceSerialNumber(HUB2)
        self.tilt_2.setIsHubPortDevice(False)
        self.tilt_2.setHubPort(4)
        self.tilt_2.setChannel(0)
        try:
            self.tilt_2.openWaitForAttachment(1000)
        except PhidgetException as e:
            print("Failed to open (TILT): " + e.details)
示例#10
0
#!/usr/bin/env python3

from Phidget22.Phidget import *
from Phidget22.Devices.VoltageOutput import *
import sys
import time

experiment_time = float(sys.argv[1]) + 2.0  # adding two extra seconds

phidget_wind = 589946  # for sending the position of the motor to NI-DAQ
aout_channel_wind_valve = 2

aout_wind_valve = VoltageOutput()
aout_wind_valve.setDeviceSerialNumber(phidget_wind)
aout_wind_valve.setChannel(aout_channel_wind_valve)
aout_wind_valve.openWaitForAttachment(5000)
aout_wind_valve.setVoltage(0.0)

time_start = time.time() 

print(f'Turning MFC on for {experiment_time} seconds')

while True:
    time_elapsed = time.time() - time_start
    aout_wind_valve.setVoltage(5.0)
    if time_elapsed > experiment_time:
        aout_wind_valve.setVoltage(0.0)
        print('Turning MFC off')
        break
# The following is from the 'init' part of analogout.py (https://github.com/jennyl617/fly_experiments/blob/master/fictrac_2d/analogout.py)

# *********** Set up aout params ***********

rate_to_volt_const = 50,
aout_max_volt = 10.0,
aout_min_volt = 0.0,
aout_max_volt_vel = 10.0,
aout_min_volt_vel = 0.0,
lowpass_cutoff = 0.5,

# *********** Set up analog output channels ***********

# Setup analog output 'runSpeed' - inst. running speed in rads/frame
aout_runSpeed = VoltageOutput()
aout_runSpeed.setChannel(0)
aout_runSpeed.openWaitForAttachment(5000)
aout_runSpeed.setVoltage(0.0)
aout_runSpeed.setDeviceSerialNumber(525438)

# Setup analog output 'animalheading360' -- this will be fly heading in degrees (0-3.6V) as in open loop trials
aout_animalheading360 = VoltageOutput()
aout_animalheading360.setChannel(1)
aout_animalheading360.openWaitForAttachment(5000)
aout_animalheading360.setVoltage(0.0)
aout_animalheading360.setDeviceSerialNumber(525438)

# xpos command to controller
aout_xposcmd = VoltageOutput()
aout_xposcmd.setChannel(2)
示例#12
0
def get_device_channel(serial_number, channel):
    try:
        """
        * Allocate a new Phidget Channel object
        """
        ch = VoltageOutput()
        """
        * Set matching parameters to specify which channel to open
        """
        #You may remove this line and hard-code the addressing parameters to fit your application

        ch.setDeviceSerialNumber(serial_number)
        ch.setIsHubPortDevice(False)
        ch.setChannel(channel)
        """
        * Add event handlers before calling open so that no events are missed.
        """
        print("\n--------------------------------------")
        print("\nSetting OnAttachHandler...")
        ch.setOnAttachHandler(onAttachHandler)

        print("Setting OnDetachHandler...")
        ch.setOnDetachHandler(onDetachHandler)

        print("Setting OnErrorHandler...")
        ch.setOnErrorHandler(onErrorHandler)
        """
        * Open the channel with a timeout
        """
        print("\nOpening and Waiting for Attachment...")

        try:
            ch.openWaitForAttachment(5000)
        except PhidgetException as e:
            PrintOpenErrorMessage(e, ch)
            raise EndProgramSignal("Program Terminated: Open Failed")

        # ch.setVoltage(voltage)
        '''
        * Perform clean up and exit
        '''

        return ch

    except:
        pass
示例#13
0
    def __init__(self, param=DefaultParam):

        self.param = param
        self.experiment = self.param['experiment']
        self.experiment_time = self.param['experiment_time']
        self.time_start = time.time()

        # Set up Phidget channels
        self.aout_channel_yaw = 0
        self.aout_channel_x = 1
        self.aout_channel_yaw_gain = 2
        self.aout_channel_y = 3
        self.aout_max_volt = 10.0
        self.aout_min_volt = 0.0

        # Set up Phidget serial numbers for using two devices
        self.phidget_vision = 525577  # written on the back of the Phidget
        self.phidget_wind = 589946  # for sending the position of the motor to NI-DAQ

        # Setup analog output YAW
        self.aout_yaw = VoltageOutput()
        self.aout_yaw.setDeviceSerialNumber(self.phidget_vision)
        self.aout_yaw.setChannel(self.aout_channel_yaw)
        self.aout_yaw.openWaitForAttachment(5000)
        self.aout_yaw.setVoltage(0.0)

        # Setup analog output X
        self.aout_x = VoltageOutput()
        self.aout_x.setDeviceSerialNumber(self.phidget_vision)
        self.aout_x.setChannel(self.aout_channel_x)
        self.aout_x.openWaitForAttachment(5000)
        self.aout_x.setVoltage(0.0)

        # Setup analog output YAW gain
        self.aout_yaw_gain = VoltageOutput()
        self.aout_yaw_gain.setDeviceSerialNumber(self.phidget_vision)
        self.aout_yaw_gain.setChannel(self.aout_channel_yaw_gain)
        self.aout_yaw_gain.openWaitForAttachment(5000)
        self.aout_yaw_gain.setVoltage(0.0)

        # Setup analog output Y
        self.aout_y = VoltageOutput()
        self.aout_y.setDeviceSerialNumber(self.phidget_vision)
        self.aout_y.setChannel(self.aout_channel_y)
        self.aout_y.openWaitForAttachment(5000)
        self.aout_y.setVoltage(0.0)

        self.print = True

        # Set up socket info
        self.HOST = '127.0.0.1'  # The (receiving) host IP address (sock_host)
        #self.HOST = '10.119.97.141'
        self.PORT = 65432  # The (receiving) host port (sock_port)

        self.done = False

        # Set initial bar position
        self.bar_position = np.deg2rad(
            360 - self.param['offset'])  # right to the fly is +90 deg

        #set up logger to save hd5f file
        self.logger = H5Logger(
            filename=self.param['logfile_name'],
            auto_incr=self.param['logfile_auto_incr'],
            auto_incr_format=self.param['logfile_auto_incr_format'],
            param_attr=self.param)

        #specify a variable for the first message being read
        self.first_time_in_loop = True
示例#14
0
class SocketClientGainChange(object):

    DefaultParam = {
        'experiment': 1,
        'experiment_time': 30,
        'logfile_name': 'Z:/Wilson Lab/Mel/FlyOnTheBall/data',
        'logfile_auto_incr': True,
        'logfile_auto_incr_format': '{0:06d}',
        'logfile_dt': 0.01,
    }

    def __init__(self, param=DefaultParam):

        self.param = param
        self.experiment = self.param['experiment']
        self.experiment_time = self.param['experiment_time']
        self.time_start = time.time()

        self.phidget_vision = 525577  # written on the back of the Phidget

        # Set up Phidget channels
        self.aout_channel_yaw = 0
        self.aout_channel_x = 1
        self.aout_channel_yaw_gain = 2
        self.aout_channel_y = 3
        self.aout_max_volt = 10.0
        self.aout_min_volt = 0.0

        # Setup analog output YAW
        self.aout_yaw = VoltageOutput()
        self.aout_yaw.setDeviceSerialNumber(self.phidget_vision)
        self.aout_yaw.setChannel(self.aout_channel_yaw)
        self.aout_yaw.openWaitForAttachment(5000)
        self.aout_yaw.setVoltage(0.0)

        # Setup analog output X
        self.aout_x = VoltageOutput()
        self.aout_x.setDeviceSerialNumber(self.phidget_vision)
        self.aout_x.setChannel(self.aout_channel_x)
        self.aout_x.openWaitForAttachment(5000)
        self.aout_x.setVoltage(0.0)

        # Setup analog output YAW gain
        self.aout_yaw_gain = VoltageOutput()
        self.aout_yaw_gain.setDeviceSerialNumber(self.phidget_vision)
        self.aout_yaw_gain.setChannel(self.aout_channel_yaw_gain)
        self.aout_yaw_gain.openWaitForAttachment(5000)
        self.aout_yaw_gain.setVoltage(0.0)

        # Setup analog output Y
        self.aout_y = VoltageOutput()
        self.aout_y.setDeviceSerialNumber(self.phidget_vision)
        self.aout_y.setChannel(self.aout_channel_y)
        self.aout_y.openWaitForAttachment(5000)
        self.aout_y.setVoltage(0.0)

        self.print = True

        # Set up socket info
        self.HOST = '127.0.0.1'  # The (receiving) host IP address (sock_host)
        self.PORT = 65432  # The (receiving) host port (sock_port)

        self.done = False

        self.gain_yaw = 1
        self.gain_change = True
        self.heading_with_gain = 0

        #set up logger to save hd5f file
        self.logger = H5Logger(
            filename=self.param['logfile_name'],
            auto_incr=self.param['logfile_auto_incr'],
            auto_incr_format=self.param['logfile_auto_incr_format'],
            param_attr=self.param)

    def run(self):

        # UDP
        # Open the connection (ctrl-c / ctrl-break to quit)
        with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:
            sock.bind((self.HOST, self.PORT))
            sock.setblocking(0)

            # Keep receiving data until FicTrac closes
            data = ""
            timeout_in_seconds = 1

            while not self.done:
                # Check to see whether there is data waiting
                ready = select.select([sock], [], [], timeout_in_seconds)

                # Only try to receive data if there is data waiting
                if ready[0]:
                    # Receive one data frame
                    new_data = sock.recv(1024)

                    # Uh oh?
                    if not new_data:
                        break

                    # Decode received data
                    data += new_data.decode('UTF-8')
                    #get time
                    time_now = time.time()
                    self.time_elapsed = time_now - self.time_start

                    # Find the first frame of data
                    endline = data.find("\n")
                    line = data[:endline]  # copy first frame
                    data = data[endline + 1:]  # delete first frame

                    # Tokenise
                    toks = line.split(", ")

                    # Check that we have sensible tokens
                    if ((len(toks) < 24) | (toks[0] != "FT")):
                        print('Bad read')
                        continue

                    # Extract FicTrac variables
                    # (see https://github.com/rjdmoore/fictrac/blob/master/doc/data_header.txt for descriptions)
                    self.frame = int(toks[1])
                    self.posx = float(toks[15])
                    self.posy = float(toks[16])
                    self.heading = float(toks[17])
                    self.deltaheading = float(toks[8])
                    self.intx = float(toks[20])
                    self.inty = float(toks[21])
                    self.timestamp = float(toks[22])

                    #Set Phidget voltages using FicTrac data

                    # Set analog output voltage yaw
                    output_voltage_yaw = (self.heading) * (
                        self.aout_max_volt - self.aout_min_volt) / (2 * np.pi)
                    self.aout_yaw.setVoltage(output_voltage_yaw)

                    # Set analog output voltage X
                    wrapped_intx = (self.intx % (2 * np.pi))
                    output_voltage_x = wrapped_intx * (
                        self.aout_max_volt - self.aout_min_volt) / (2 * np.pi)
                    self.aout_x.setVoltage(output_voltage_x)

                    # Set analog output voltage YAW_gain
                    #set yaw gain depending on how much time has elapsed
                    if ((self.time_elapsed > 200)
                            and (self.gain_change == True)):
                        self.gain_yaw = -1
                        self.gain_change = False
                    elif self.time_elapsed > 1000:
                        self.gain_yaw = 1

                    self.heading_with_gain = (
                        self.heading_with_gain +
                        self.deltaheading * self.gain_yaw) % (2 * np.pi)
                    output_voltage_yaw_gain = (self.heading_with_gain) * (
                        self.aout_max_volt - self.aout_min_volt) / (2 * np.pi)
                    self.aout_yaw_gain.setVoltage(10 - output_voltage_yaw_gain)

                    # Set analog output voltage Y
                    wrapped_inty = self.inty % (2 * np.pi)
                    output_voltage_y = wrapped_inty * (
                        self.aout_max_volt - self.aout_min_volt) / (2 * np.pi)
                    self.aout_y.setVoltage(output_voltage_y)

                    # Save data in log file
                    self.write_logfile()

                    # Display status message
                    if self.print:
                        print('frame:  {0}'.format(self.frame))
                        print('time elapsed:   {0:1.3f}'.format(
                            self.time_elapsed))
                        print('gain yaw: {0}'.format(self.gain_yaw))
                        print('gain change: {0}'.format(self.gain_change))
                        print('yaw:   {0:1.3f}'.format(self.heading * 360 /
                                                       (2 * np.pi)))
                        print(
                            'volt:   {0:1.3f}'.format(output_voltage_yaw_gain))
                        print('int x:   {0:1.3f}'.format(wrapped_intx))
                        print('volt:   {0:1.3f}'.format(output_voltage_x))
                        print('int y:   {0:1.3f}'.format(wrapped_inty))
                        print('volt:   {0:1.3f}'.format(output_voltage_y))
                        print()

                    if self.time_elapsed > self.experiment_time:
                        self.done = True
                        break

            # END OF EXPERIMENT
            print('Trial finished - quitting!')

    #define function to log data to hdf5 file
    def write_logfile(self):
        log_data = {
            'time': self.time_elapsed,
            'frame': self.frame,
            'posx': self.posx,
            'posy': self.posy,
            'intx': self.intx,
            'inty': self.inty,
            'heading': self.heading,
            'heading_with_gain': self.heading_with_gain,
            'deltaheading': self.deltaheading,
            'gain_yaw': self.gain_yaw
        }
        self.logger.add(log_data)
示例#15
0
    def __init__(self, param=DefaultParam):

        self.param = param
        self.experiment = self.param['experiment']
        self.experiment_time = self.param['experiment_time']
        self.time_start = time.time()

        # Set up Phidget channels
        self.aout_channel_ydimension = 0
        self.aout_channel_x = 1
        self.aout_channel_yaw_gain = 2
        self.aout_channel_y = 3
        self.aout_max_volt = 10.0
        self.aout_min_volt = 0.0

        # Set up Phidget serial numbers for using two devices
        self.phidget_vision = 525577  # written on the back of the Phidget
        self.phidget_heading = 589946

        # Setup analog output y dim, to change the y dimension of the stimulus
        self.aout_ydim = VoltageOutput()
        self.aout_ydim.setDeviceSerialNumber(self.phidget_vision)
        self.aout_ydim.setChannel(self.aout_channel_ydimension)
        self.aout_ydim.openWaitForAttachment(5000)
        self.aout_ydim.setVoltage(0.0)

        # Setup analog output X
        self.aout_x = VoltageOutput()
        self.aout_x.setDeviceSerialNumber(self.phidget_vision)
        self.aout_x.setChannel(self.aout_channel_x)
        self.aout_x.openWaitForAttachment(5000)
        self.aout_x.setVoltage(0.0)

        # Setup analog output YAW gain
        self.aout_yaw_gain = VoltageOutput()
        self.aout_yaw_gain.setDeviceSerialNumber(self.phidget_vision)
        self.aout_yaw_gain.setChannel(self.aout_channel_yaw_gain)
        self.aout_yaw_gain.openWaitForAttachment(5000)
        self.aout_yaw_gain.setVoltage(0.0)

        # Setup analog output Y
        self.aout_y = VoltageOutput()
        self.aout_y.setDeviceSerialNumber(self.phidget_vision)
        self.aout_y.setChannel(self.aout_channel_y)
        self.aout_y.openWaitForAttachment(5000)
        self.aout_y.setVoltage(9.0)

        # Set up Phidget channels in device 2 to save the heading
        self.aout_heading_channel = 1

        # Setup analog output motor
        self.aout_heading = VoltageOutput()
        self.aout_heading.setDeviceSerialNumber(self.phidget_heading)
        self.aout_heading.setChannel(self.aout_heading_channel)
        self.aout_heading.openWaitForAttachment(5000)
        self.aout_heading.setVoltage(0.0)

        self.print = True

        # Set up socket info
        self.HOST = '127.0.0.1'  # The (receiving) host IP address (sock_host)
        self.PORT = 65432  # The (receiving) host port (sock_port)

        # Set up Arduino connection
        self.COM = 'COM4'  # serial port
        self.baudrate = 115200  # 9600
        self.serialTimeout = 0.001  # blocking timeout for readline()

        self.done = False

        self.gain_yaw = 1
        self.heading_with_gain = 0

        self.bar_jump = True
        self.bar_jump_size = 0

        #initialize the bar on
        self.bar = True
        self.bar_moving = True

        #define times when bar will be turned off
        self.turn_off_times = np.linspace(900, 3525, 26)
        #self.turn_off_times = np.linspace(30,300,7)   #uncomment for testing

        #initialize heading with respect to panels to be starting position
        self.bar_position = np.deg2rad(360 - self.param['offset'])

        #set up logger to save hd5f file
        self.logger_fictrac = H5Logger(
            filename=self.param['logfile_name'],
            auto_incr=self.param['logfile_auto_incr'],
            auto_incr_format=self.param['logfile_auto_incr_format'],
            param_attr=self.param)

        #specify a variable for the first message being read
        self.first_time_in_loop = True
示例#16
0
class SocketClientWindBarJump(object):

    DefaultParam = {
        'experiment': 1,
        'experiment_time': 30,
        'logfile_name': 'Z:/Wilson Lab/Mel/FlyOnTheBall/data',
        'logfile_auto_incr': True,
        'logfile_auto_incr_format': '{0:06d}',
        'logfile_dt': 0.01,
        'offset': 0
    }

    def __init__(self, param=DefaultParam):

        self.param = param
        self.experiment = self.param['experiment']
        self.experiment_time = self.param['experiment_time']
        self.time_start = time.time()

        # Set up Phidget channels
        self.aout_channel_ydimension = 0  #I'm setting up a channel such that I can change the y dimension of the panels sending a signal through here
        self.aout_channel_x = 1
        self.aout_channel_yaw_gain = 2
        self.aout_channel_y = 3
        self.aout_max_volt = 10.0
        self.aout_min_volt = 0.0

        # Set up Phidget serial numbers for using two devices
        self.phidget_vision = 525577  # written on the back of the Phidget
        self.phidget_wind = 589946  # for sending the position of the motor to NI-DAQ

        # Setup analog output YAW
        self.aout_ydim = VoltageOutput()
        self.aout_ydim.setDeviceSerialNumber(self.phidget_vision)
        self.aout_ydim.setChannel(self.aout_channel_ydimension)
        self.aout_ydim.openWaitForAttachment(5000)
        self.aout_ydim.setVoltage(0.0)

        # Setup analog output X
        self.aout_x = VoltageOutput()
        self.aout_x.setDeviceSerialNumber(self.phidget_vision)
        self.aout_x.setChannel(self.aout_channel_x)
        self.aout_x.openWaitForAttachment(5000)
        self.aout_x.setVoltage(0.0)

        # Setup analog output YAW gain
        self.aout_yaw_gain = VoltageOutput()
        self.aout_yaw_gain.setDeviceSerialNumber(self.phidget_vision)
        self.aout_yaw_gain.setChannel(self.aout_channel_yaw_gain)
        self.aout_yaw_gain.openWaitForAttachment(5000)
        self.aout_yaw_gain.setVoltage(0.0)

        # Setup analog output Y
        self.aout_y = VoltageOutput()
        self.aout_y.setDeviceSerialNumber(self.phidget_vision)
        self.aout_y.setChannel(self.aout_channel_y)
        self.aout_y.openWaitForAttachment(5000)
        self.aout_y.setVoltage(9.0)

        # Set up Phidget channels in device 2 for wind
        self.aout_channel_motor = 0
        self.aout_channel_wind_valve = 2

        # Setup analog output motor
        self.aout_motor = VoltageOutput()
        self.aout_motor.setDeviceSerialNumber(self.phidget_wind)
        self.aout_motor.setChannel(self.aout_channel_motor)
        self.aout_motor.openWaitForAttachment(5000)
        self.aout_motor.setVoltage(0.0)

        # Setup analog output wind valve
        self.aout_wind_valve = VoltageOutput()
        self.aout_wind_valve.setDeviceSerialNumber(self.phidget_wind)
        self.aout_wind_valve.setChannel(self.aout_channel_wind_valve)
        self.aout_wind_valve.openWaitForAttachment(5000)
        self.aout_wind_valve.setVoltage(0.0)

        self.print = True

        # Set up socket info
        self.HOST = '127.0.0.1'  # The (receiving) host IP address (sock_host)
        self.PORT = 65432  # The (receiving) host port (sock_port)

        # Set up Arduino connection
        self.COM = 'COM4'  # serial port
        self.baudrate = 115200  # 9600
        self.serialTimeout = 0.001  # blocking timeout for readline()

        self.done = False

        self.gain_yaw = 1
        self.heading_with_gain = 0

        self.bar_jump = True
        self.bar_jump_size = 0
        self.wind_jump = True
        self.wind_jump_size = 0

        #initialize the bar on and the wind off
        self.bar = False
        self.wind = True

        #initialize heading with respect to panels to be starting position
        self.motor_command = 0
        self.bar_position = np.deg2rad(360 - self.param['offset'])

        #set up logger to save hd5f file
        self.logger_fictrac = H5Logger(
            filename=self.param['logfile_name'],
            auto_incr=self.param['logfile_auto_incr'],
            auto_incr_format=self.param['logfile_auto_incr_format'],
            param_attr=self.param)

        #set up logger to save hd5f file
        self.logger_arduino = H5Logger(
            filename=(self.param['logfile_name']).replace(
                '.hdf5', '_arduino.hdf5'),
            auto_incr=self.param['logfile_auto_incr'],
            auto_incr_format=self.param['logfile_auto_incr_format'],
            param_attr=self.param)

        #specify a variable for the first message being read
        self.first_time_in_loop = True

    def run(self):

        # UDP
        # Open the connection (ctrl-c / ctrl-break to quit)
        with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock,\
         serial.Serial(self.COM, self.baudrate, timeout=self.serialTimeout) as ser:
            sock.bind((self.HOST,
                       self.PORT))  # takes one argument, give it as a tuple
            sock.setblocking(False)  # make it non-blocking

            # Keep receiving data until FicTrac closes
            data = ""
            timeout_in_seconds = 1

            while not self.done:

                motor_pos = np.nan
                self.motor_pos_rad = np.nan  # default value before receiving the data
                # listening to Arduino
                msg = ser.readline()  # read from serial until there's a \n
                self.time_arduino = time.time() - self.time_start  # (s)
                if msg:  # received a non-empty message
                    try:
                        arduino_line = msg.decode(
                            'utf-8')[:-2]  # decode and remove \r and \n
                        #motor_info = arduino_line.split(", ")
                        #log_arduino = str("{:.7f}".format(time_now)) + "," + motor_info[0] + "\n"  # first element is the current motor position (0-360 deg)
                        #f_arduino.writelines(log_arduino)
                        motor_pos = int(
                            arduino_line)  # current motor position (0-360 deg)
                        self.motor_pos_rad = np.deg2rad(motor_pos)

                        # Set analog output voltage of Phidget so that it could be recorded using NI-DAQ
                        output_voltage_motor = self.motor_pos_rad * (
                            self.aout_max_volt - self.aout_min_volt) / (2 *
                                                                        np.pi)
                        self.aout_motor.setVoltage(output_voltage_motor)

                        # write to HDF5 file
                        self.write_logfile_arduino()

                    except:
                        print("message from Arduino is not a number:", msg)

                # Check to see whether there is data waiting
                ready = select.select([sock], [], [], timeout_in_seconds)

                # Only try to receive data if there is data waiting
                if ready[0]:
                    # Receive one data frame
                    new_data = sock.recv(1024)

                    # Uh oh?
                    if not new_data:
                        break

                    # Decode received data
                    data += new_data.decode('UTF-8')
                    #get time
                    time_now = time.time()
                    self.time_elapsed = time_now - self.time_start

                    # Find the first frame of data
                    endline = data.find("\n")
                    line = data[:endline]  # copy first frame
                    data = data[endline + 1:]  # delete first frame

                    # Tokenise
                    toks = line.split(", ")

                    # Check that we have sensible tokens
                    if ((len(toks) < 24) | (toks[0] != "FT")):
                        print('Bad read')
                        continue

                    # Extract FicTrac variables
                    # (see https://github.com/rjdmoore/fictrac/blob/master/doc/data_header.txt for descriptions)
                    self.frame = int(toks[1])
                    self.posx = float(toks[15])
                    self.posy = float(toks[16])
                    self.heading = float(toks[17])
                    self.intx = float(toks[20])
                    self.inty = float(toks[21])
                    self.timestamp = float(toks[22])

                    # calculate delta heading by comparing it to the previous value
                    #if self.first_time_in_loop:
                    #  self.prev_heading = float(toks[17])
                    # self.first_time_in_loop = False
                    #else:
                    #   self.prev_heading = self.heading
                    #self.deltaheading = self.heading - self.prev_heading
                    #I had to comment the above lines because they weren't working well.
                    self.deltaheading = float(toks[8])

                    #Set Phidget voltages using FicTrac data

                    #Set the voltages that don't depend on the time of the experiment

                    # Set analog output voltage X
                    wrapped_intx = (self.intx % (2 * np.pi))
                    output_voltage_x = wrapped_intx * (
                        self.aout_max_volt - self.aout_min_volt) / (2 * np.pi)
                    self.aout_x.setVoltage(output_voltage_x)

                    # Set analog output voltage Y
                    wrapped_inty = self.inty % (2 * np.pi)
                    output_voltage_y = wrapped_inty * (
                        self.aout_max_volt - self.aout_min_volt) / (2 * np.pi)
                    self.aout_y.setVoltage(output_voltage_y)

                    # Specify the time conditions to set the other voltages
                    # Specify the bar jumps
                    if ((math.floor(self.time_elapsed) == 1860)
                            and (self.bar_jump == True)):
                        self.bar_jump_size = math.radians(-120)
                        self.bar_jump = False
                    else:
                        self.bar_jump_size = 0

                    self.heading_with_gain = (
                        self.heading_with_gain + self.deltaheading *
                        self.gain_yaw + self.bar_jump_size) % (2 * np.pi)
                    output_voltage_yaw_gain = (self.heading_with_gain) * (
                        self.aout_max_volt - self.aout_min_volt) / (2 * np.pi)
                    self.aout_yaw_gain.setVoltage(10 - output_voltage_yaw_gain)

                    # Specify the wind jumps
                    if ((math.floor(self.time_elapsed) == 1380
                         or math.floor(self.time_elapsed) == 2340)
                            and (self.wind_jump == True)):
                        self.wind_jump_size = math.radians(120)
                        self.wind_jump = False
                    else:
                        self.wind_jump_size = 0

                #reset self.jump 1 sec before the wind jump has to happen
                    if ((math.floor(self.time_elapsed) == 2339)
                            and (self.wind_jump == False)):
                        self.wind_jump = True

                    # send the heading signal to Arduino
                    self.motor_command = (self.motor_command +
                                          self.deltaheading +
                                          self.wind_jump_size) % (2 * np.pi)
                    #animal_heading_360 = int(self.heading * (360 / (2 * np.pi)))  # convert from rad to deg
                    arduino_str = "H " + str(
                        np.rad2deg(self.motor_command)
                    ) + "\n"  # "H is a command used in the Arduino code to indicate heading
                    #I had to remove the 360- from the above line to make the gain = 1, and I'm not sure why, since in the other codes it works the other way
                    arduino_byte = arduino_str.encode(
                    )  # convert unicode string to byte string
                    ser.write(arduino_byte)  # send to serial port

                    # Specify the changes in bar intensity
                    #turn off the bar
                    if ((math.floor(self.time_elapsed) == 1020
                         or math.floor(self.time_elapsed) == 1500
                         or math.floor(self.time_elapsed) == 1980
                         or math.floor(self.time_elapsed) == 2460
                         or math.floor(self.time_elapsed) == 2700)
                            and (self.bar == True)):
                        self.bar = False
                    #turn on the bar
                    if ((math.floor(self.time_elapsed) == 600
                         or math.floor(self.time_elapsed) == 1140
                         or math.floor(self.time_elapsed) == 1620
                         or math.floor(self.time_elapsed) == 2100
                         or math.floor(self.time_elapsed) == 2580)
                            and (self.bar == False)):
                        self.bar = True

                    if self.bar == False:
                        y_dim_voltage = 5.0
                    else:
                        y_dim_voltage = 9.0

                    self.aout_ydim.setVoltage(y_dim_voltage)

                    # Specify the changes in wind inensity
                    #turn on the wind
                    if ((math.floor(self.time_elapsed) == 900
                         or math.floor(self.time_elapsed) == 1260
                         or math.floor(self.time_elapsed) == 1740
                         or math.floor(self.time_elapsed) == 2220)
                            and (self.wind == False)):
                        self.wind = True
                    #turn off the wind
                    if ((math.floor(self.time_elapsed) == 600
                         or math.floor(self.time_elapsed) == 1140
                         or math.floor(self.time_elapsed) == 1620
                         or math.floor(self.time_elapsed) == 2100
                         or math.floor(self.time_elapsed) == 2580)
                            and (self.wind == True)):
                        self.wind = False

                    if self.wind == False:
                        wind_valve = 0.0
                    else:
                        wind_valve = 5.0

                    self.aout_wind_valve.setVoltage(wind_valve)

                    # Save fictrac data in HDF5 file
                    self.write_logfile_fictrac()

                    # Display status message
                    if self.print:
                        print(f'time elapsed: {self.time_elapsed: 1.3f}',
                              end='')
                        print(
                            f'  motor command: {np.rad2deg(self.motor_command):3.0f}',
                            end='')
                        print(f'  motor pos: {motor_pos:3.0f}', end='')
                        print(
                            f'  bar pos: {np.rad2deg(self.bar_position):3.0f}')
                        print(f'  ydim volt: {y_dim_voltage:3.0f}')
                        print(
                            f'  delta heading: {np.rad2deg(self.deltaheading):3.0f}'
                        )

                    if self.time_elapsed > self.experiment_time:
                        self.aout_wind_valve.setVoltage(5.0)
                        self.done = True
                        break

            # go back to 0 deg at the end of the trial
            arduino_str = "H " + str(
                0
            ) + "\n"  # "H is a command used in the Arduino code to indicate heading
            arduino_byte = arduino_str.encode(
            )  # convert unicode string to byte string
            ser.write(arduino_byte)  # send to serial port

            print('Trial finished - quitting!')

    #define function to log data to hdf5 file
    def write_logfile_fictrac(self):
        log_data = {
            'time': self.time_elapsed,
            'frame': self.frame,
            'posx': self.posx,
            'posy': self.posy,
            'intx': self.intx,
            'inty': self.inty,
            'heading': self.heading,
            'deltaheading': self.deltaheading,
            'motor': self.motor_pos_rad,
            'motor_command': self.motor_command,
            'bar_position': self.bar_position,
        }
        self.logger_fictrac.add(log_data)

    def write_logfile_arduino(self):
        log_data = {'time': self.time_arduino, 'motor': self.motor_pos_rad}
        self.logger_arduino.add(log_data)
示例#17
0
right_light.openWaitForAttachment(5000)
right_light.setAcceleration(20)

#Setup pan and tilt motors
tilt = DCMotor()
tilt.setDeviceSerialNumber(465371)
tilt.openWaitForAttachment(1000)
tilt.setAcceleration(ACCEL)

pan = DCMotor()
pan.setDeviceSerialNumber(469502)
pan.openWaitForAttachment(1000)
pan.setAcceleration(ACCEL)

#Setup Pnematics
pressure_ctrl = VoltageOutput()
pressure_ctrl.setDeviceSerialNumber(540047)
pressure_ctrl.setIsHubPortDevice(False)
pressure_ctrl.setHubPort(3)
pressure_ctrl.setChannel(0)
pressure_ctrl.openWaitForAttachment(5000)

pressure_reading = VoltageRatioInput()
pressure_reading.setDeviceSerialNumber(540047)
pressure_reading.setIsHubPortDevice(False)
pressure_reading.setHubPort(0)
pressure_reading.setChannel(0)
pressure_reading.openWaitForAttachment(5000)

solenoid = DigitalOutput()
solenoid.setDeviceSerialNumber(540047)
    def __init__(self, master, colorArray):
        frame1 = Frame(master, borderwidth=2, relief=SUNKEN)
        frame2 = Frame(master, borderwidth=2, relief=SUNKEN)
        frame3 = Frame(master, borderwidth=2, relief=SUNKEN)
        frame4 = Frame(master, borderwidth=2, relief=SUNKEN)
        frame5 = Frame(master, borderwidth=2, relief=SUNKEN)
        frame6 = Frame(master, borderwidth=2, relief=SUNKEN)
        frame7 = Frame(master, borderwidth=2, relief=SUNKEN)
        camera_frame = Frame(master, borderwidth=2, relief=SUNKEN)

        frame1.grid(row=1, column=0)
        frame2.grid(row=1, column=1)
        frame3.grid(row=1, column=2)
        frame4.grid(row=1, column=3)
        frame5.grid(row=1, column=4)
        frame6.grid(row=1, column=5)
        frame7.grid(row=1, column=6)
        camera_frame.grid(row=3, column=0, columnspan=7, sticky=W)

        self.out1 = AxisFrame(frame1, "BASE CIRC", "VESSEL RIGHT",
                              "VESSEL LEFT", HUB1, 5, colorArray[0], 3.3, 0.55)
        self.out2 = AxisFrame(frame2, "BASE AUX", "CW/IN", "CCW/OUT", HUB2, 0,
                              colorArray[1], 2.2, 0.11)
        self.out3 = AxisFrame(frame3, "VARD ROT", "CW", "CCW", HUB1, 3,
                              colorArray[2], 2.2, 0.15)
        self.out4 = AxisFrame(frame4, "VARD VERT", "UP", "DOWN", HUB1, 4,
                              colorArray[3], 7.8, 0.54)
        self.out5 = AxisFrame(frame5, "DA MAST", "UP", "DOWN", HUB1, 0,
                              colorArray[4], 8, 0.86)
        self.out6 = AxisFrame(frame6, "DA PAN", "CW", "CCW", HUB1, 2,
                              colorArray[5], 3.0, 0.30)
        self.out7 = AxisFrame(frame7, "DA TILT", "UP", "DOWN", HUB1, 1,
                              colorArray[6], 3.6, 0.57)

        #RJ Camera Control Code
        self.invert_tilt = BooleanVar()
        self.invert_pan = BooleanVar()
        self.btn_power = Button(camera_frame,
                                text="PWR",
                                font="Courier, 12",
                                command=self.toggle_power)
        self.btn_near = Button(camera_frame,
                               text="NEAR",
                               font="Courier, 12",
                               width=7)
        self.btn_far = Button(camera_frame,
                              text="FAR",
                              font="Courier, 12",
                              width=7)
        self.btn_wide = Button(camera_frame,
                               text="WIDE",
                               font="Courier, 12",
                               width=7)
        self.btn_tele = Button(camera_frame,
                               text="TELE",
                               font="Courier, 12",
                               width=7)
        self.btn_ms = Button(camera_frame,
                             text="MS",
                             font="Courier, 12",
                             width=7)
        self.left_light_scale = Scale(camera_frame,
                                      orient=VERTICAL,
                                      from_=0,
                                      to=0.45,
                                      resolution=0.01,
                                      command=self.update_left_intensity)
        self.right_light_scale = Scale(camera_frame,
                                       orient=VERTICAL,
                                       from_=0,
                                       to=0.45,
                                       resolution=0.01,
                                       command=self.update_right_intensity)
        self.label_lights = Label(camera_frame, text="  Light Intensity")
        self.btn_tilt_up = Button(camera_frame,
                                  text="TILT UP",
                                  font="Courier, 12",
                                  width=10)
        self.btn_tilt_down = Button(camera_frame,
                                    text="TILT DOWN",
                                    font="Courier, 12",
                                    width=10)
        self.btn_pan_right = Button(camera_frame,
                                    text="PAN RIGHT",
                                    font="Courier, 12",
                                    width=10)
        self.btn_pan_left = Button(camera_frame,
                                   text="PAN LEFT",
                                   font="Courier, 12",
                                   width=10)
        self.tilt_speed = Scale(camera_frame,
                                orient=HORIZONTAL,
                                from_=0.01,
                                to=.5,
                                resolution=0.01)
        self.pan_speed = Scale(camera_frame,
                               orient=HORIZONTAL,
                               from_=0.01,
                               to=.5,
                               resolution=0.01)
        self.ckbx_invert_tilt = Checkbutton(camera_frame,
                                            text="Invert Tilt",
                                            variable=self.invert_tilt)
        self.ckbx_invert_pan = Checkbutton(camera_frame,
                                           text="Invert Pan",
                                           variable=self.invert_pan)
        self.activeColor = 'SpringGreen4'

        self.tilt_speed.set(0.15)
        self.pan_speed.set(0.15)

        self.btn_power.grid(row=0, column=0, padx=60)
        self.btn_ms.grid(row=1, column=0, padx=5, pady=5)
        self.btn_near.grid(row=0, column=2, padx=20, pady=10)
        self.btn_far.grid(row=1, column=2, padx=20, pady=10)
        self.btn_tele.grid(row=0, column=3, padx=20, pady=10)
        self.btn_wide.grid(row=1, column=3, padx=20, pady=10)
        self.left_light_scale.grid(row=0, column=4, rowspan=3, padx=20, pady=5)
        self.right_light_scale.grid(row=0,
                                    column=5,
                                    rowspan=3,
                                    padx=45,
                                    pady=5)
        self.label_lights.grid(row=3,
                               column=4,
                               columnspan=2,
                               padx=45,
                               sticky=N)
        self.btn_tilt_up.grid(row=0, column=6, padx=20, pady=5)
        self.btn_tilt_down.grid(row=1, column=6, padx=20, pady=5)
        self.btn_pan_right.grid(row=0, column=8, padx=20, pady=5, rowspan=2)
        self.btn_pan_left.grid(row=0, column=7, padx=20, pady=5, rowspan=2)
        self.tilt_speed.grid(row=2, column=6)
        self.pan_speed.grid(row=2, column=7, columnspan=2)
        self.ckbx_invert_tilt.grid(row=3, column=6)
        self.ckbx_invert_pan.grid(row=3, column=7, columnspan=2)

        #Connect to Phidget Devices
        self.power = DigitalOutput()
        self.power.setDeviceSerialNumber(HUB2)
        self.power.setIsHubPortDevice(False)
        self.power.setHubPort(1)
        self.power.setChannel(0)
        self.power.openWaitForAttachment(5000)

        self.manual_select = DigitalOutput()
        self.manual_select.setDeviceSerialNumber(HUB2)
        self.manual_select.setIsHubPortDevice(False)
        self.manual_select.setHubPort(1)
        self.manual_select.setChannel(1)
        self.manual_select.openWaitForAttachment(5000)

        self.near = DigitalOutput()
        self.near.setDeviceSerialNumber(HUB2)
        self.near.setIsHubPortDevice(False)
        self.near.setHubPort(1)
        self.near.setChannel(2)
        self.near.openWaitForAttachment(5000)

        self.far = DigitalOutput()
        self.far.setDeviceSerialNumber(HUB2)
        self.far.setIsHubPortDevice(False)
        self.far.setHubPort(1)
        self.far.setChannel(3)
        self.far.openWaitForAttachment(5000)

        self.wide = DigitalOutput()
        self.wide.setDeviceSerialNumber(HUB2)
        self.wide.setIsHubPortDevice(False)
        self.wide.setHubPort(1)
        self.wide.setChannel(4)
        self.wide.openWaitForAttachment(5000)

        self.tele = DigitalOutput()
        self.tele.setDeviceSerialNumber(HUB2)
        self.tele.setIsHubPortDevice(False)
        self.tele.setHubPort(1)
        self.tele.setChannel(5)
        self.tele.openWaitForAttachment(5000)

        self.left_light = VoltageOutput()
        self.left_light.setDeviceSerialNumber(HUB2)
        self.left_light.setIsHubPortDevice(False)
        self.left_light.setHubPort(2)
        self.left_light.setChannel(0)
        self.left_light.openWaitForAttachment(5000)

        self.right_light = VoltageOutput()
        self.right_light.setDeviceSerialNumber(HUB2)
        self.right_light.setIsHubPortDevice(False)
        self.right_light.setHubPort(3)
        self.right_light.setChannel(0)
        self.right_light.openWaitForAttachment(5000)

        self.pan = VoltageOutput()
        self.pan.setDeviceSerialNumber(HUB2)
        self.pan.setIsHubPortDevice(False)
        self.pan.setHubPort(5)
        self.pan.setChannel(0)
        self.pan.openWaitForAttachment(5000)

        self.tilt = VoltageOutput()
        self.tilt.setDeviceSerialNumber(HUB2)
        self.tilt.setIsHubPortDevice(False)
        self.tilt.setHubPort(4)
        self.tilt.setChannel(0)
        self.tilt.openWaitForAttachment(5000)

        self.btn_near.bind('<ButtonPress-1>', lambda event: self.focus("+"))
        self.btn_near.bind('<ButtonRelease-1>', lambda event: self.focus("0"))
        self.btn_far.bind('<ButtonPress-1>', lambda event: self.focus("-"))
        self.btn_far.bind('<ButtonRelease-1>', lambda event: self.focus("0"))
        self.btn_wide.bind('<ButtonPress-1>', lambda event: self.zoom("-"))
        self.btn_wide.bind('<ButtonRelease-1>', lambda event: self.zoom("0"))
        self.btn_tele.bind('<ButtonPress-1>', lambda event: self.zoom("+"))
        self.btn_tele.bind('<ButtonRelease-1>', lambda event: self.zoom("0"))
        self.btn_ms.bind('<ButtonPress-1>',
                         lambda event: self.focus_type("ON"))
        self.btn_ms.bind('<ButtonRelease-1>',
                         lambda event: self.focus_type("OFF"))

        self.btn_tilt_up.bind('<ButtonPress-1>',
                              lambda event: self.tilt_move("-"))
        self.btn_tilt_up.bind('<ButtonRelease-1>',
                              lambda event: self.tilt_move("0"))
        self.btn_tilt_down.bind('<ButtonPress-1>',
                                lambda event: self.tilt_move("+"))
        self.btn_tilt_down.bind('<ButtonRelease-1>',
                                lambda event: self.tilt_move("0"))
        self.btn_pan_right.bind('<ButtonPress-1>',
                                lambda event: self.pan_move("R"))
        self.btn_pan_right.bind('<ButtonRelease-1>',
                                lambda event: self.pan_move("0"))
        self.btn_pan_left.bind('<ButtonPress-1>',
                               lambda event: self.pan_move("L"))
        self.btn_pan_left.bind('<ButtonRelease-1>',
                               lambda event: self.pan_move("0"))
示例#19
0
class SocketClient(object):

    DefaultParam = {
        'experiment': 1,
        'stim_speed': 30,
        'turn_type': 'clockwise',
        'experiment_time': 30,
        'logfile_name': 'Z:/Wilson Lab/Mel/FlyOnTheBall/data',
        'logfile_auto_incr': True,
        'logfile_auto_incr_format': '{0:06d}',
        'logfile_dt': 0.01,
    }

    def __init__(self, param=DefaultParam):

        self.param = param
        self.experiment = self.param['experiment']
        self.stim_speed = self.param['stim_speed']
        self.turn_type = self.param['turn_type']
        self.experiment_time = self.param['experiment_time']
        self.time_start = time.time(
        )  # get the current time and use it as a ref for elapsed time
        self.current_wind_dir = 0

        # Set up Phidget serial numbers for using two devices
        self.phidget_vision = 525577  # written on the back of the Phidget
        self.phidget_wind = 589946  # for sending the position of the motor to NI-DAQ

        # Set up Phidget channels in device 1 for vision (0-index)
        self.aout_channel_yaw = 0
        self.aout_channel_x = 1
        self.aout_channel_yaw_gain = 2
        self.aout_channel_y = 3
        self.aout_max_volt = 10.0
        self.aout_min_volt = 0.0

        # Setup analog output YAW
        self.aout_yaw = VoltageOutput()
        self.aout_yaw.setDeviceSerialNumber(self.phidget_vision)
        self.aout_yaw.setChannel(self.aout_channel_yaw)
        self.aout_yaw.openWaitForAttachment(5000)
        self.aout_yaw.setVoltage(0.0)

        # Setup analog output X
        self.aout_x = VoltageOutput()
        self.aout_x.setDeviceSerialNumber(self.phidget_vision)
        self.aout_x.setChannel(self.aout_channel_x)
        self.aout_x.openWaitForAttachment(5000)
        self.aout_x.setVoltage(0.0)

        # Setup analog output YAW gain
        self.aout_yaw_gain = VoltageOutput()
        self.aout_yaw_gain.setDeviceSerialNumber(self.phidget_vision)
        self.aout_yaw_gain.setChannel(self.aout_channel_yaw_gain)
        self.aout_yaw_gain.openWaitForAttachment(5000)
        self.aout_yaw_gain.setVoltage(0.0)

        # Setup analog output Y
        self.aout_y = VoltageOutput()
        self.aout_y.setDeviceSerialNumber(self.phidget_vision)
        self.aout_y.setChannel(self.aout_channel_y)
        self.aout_y.openWaitForAttachment(5000)
        self.aout_y.setVoltage(0.0)

        # Set up Phidget channels in device 2 for wind (0-index)
        self.aout_channel_motor = 0
        self.aout_channel_wind_valve = 2

        # Setup analog output motor
        self.aout_motor = VoltageOutput()
        self.aout_motor.setDeviceSerialNumber(self.phidget_wind)
        self.aout_motor.setChannel(self.aout_channel_motor)
        self.aout_motor.openWaitForAttachment(5000)
        self.aout_motor.setVoltage(0.0)

        # Setup analog output wind valve
        self.aout_wind_valve = VoltageOutput()
        self.aout_wind_valve.setDeviceSerialNumber(self.phidget_wind)
        self.aout_wind_valve.setChannel(self.aout_channel_wind_valve)
        self.aout_wind_valve.openWaitForAttachment(5000)
        self.aout_wind_valve.setVoltage(0.0)

        self.print = True

        # Set up socket info for connecting with the FicTrac
        self.HOST = '127.0.0.1'  # The (receiving) host IP address (sock_host)
        self.PORT = 65432  # The (receiving) host port (sock_port)

        # Set up Arduino connection
        self.COM = 'COM4'  # serial port
        self.baudrate = 115200  # 9600
        self.serialTimeout = 0.001  # blocking timeout for readline()

        # flag for indicating when the trial is done
        self.done = False

        #set up logger to save hd5f file
        self.logger_fictrac = H5Logger(
            filename=self.param['logfile_name'],
            auto_incr=self.param['logfile_auto_incr'],
            auto_incr_format=self.param['logfile_auto_incr_format'],
            param_attr=self.param)

        #set up logger to save hd5f file
        self.logger_arduino = H5Logger(
            filename=(self.param['logfile_name']).replace(
                '.hdf5', '_arduino.hdf5'),
            auto_incr=self.param['logfile_auto_incr'],
            auto_incr_format=self.param['logfile_auto_incr_format'],
            param_attr=self.param)

    def run(self, gain_x=1):
        # connect to socket via UDP, not TCP!
        # connect to Arduino via serial
        with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock,\
         serial.Serial(self.COM, self.baudrate, timeout=self.serialTimeout) as ser:
            sock.bind((self.HOST,
                       self.PORT))  # takes one argument, give it as a tuple
            sock.setblocking(False)  # make it non-blocking

            # Keep receiving data from socket until FicTrac closes
            data = ""
            timeout_in_seconds = 1
            self.time_end = time.time()  #initialize turn time

            while not self.done:  # main loop
                self.aout_wind_valve.setVoltage(
                    5.0)  # keep the wind on for the duration of the trial

                motor_pos = np.nan
                self.motor_pos_rad = np.nan  # default value before receiving the data
                # listening to Arduino
                msg = ser.readline()  # read from serial until there's a \n
                self.time_arduino = time.time() - self.time_start  # (s)
                if msg:  # received a non-empty message
                    try:
                        arduino_line = msg.decode(
                            'utf-8')[:-2]  # decode and remove \r and \n
                        motor_pos = int(
                            arduino_line)  # current motor position (0-360 deg)
                        self.motor_pos_rad = np.deg2rad(motor_pos)

                        # Set analog output voltage of Phidget
                        output_voltage_motor = self.motor_pos_rad * (
                            self.aout_max_volt - self.aout_min_volt) / (2 *
                                                                        np.pi)
                        self.aout_motor.setVoltage(output_voltage_motor)

                        # write to HDF5 file
                        self.write_logfile_arduino()

                    except:
                        print("message from Arduino is not a number:", msg)

                # ask the OS whether the socket is readable
                # give 3 lists of sockets for reading, writing, and checking for errors; we only care about the first one
                # https://docs.python.org/3/howto/sockets.html#socket-programming-howto
                ready = select.select(
                    [sock], [], [], timeout_in_seconds
                )  # returns the subset of sockets that are actually readable

                # Only try to receive data if there is data waiting
                if ready[0]:
                    # Receive one data frame
                    new_data = sock.recv(
                        1024
                    )  # buffer size, should be a relatively small power of 2

                    if not new_data:
                        break

                    # Decode received data
                    data += new_data.decode('UTF-8')
                    self.time_elapsed = time.time() - self.time_start  # (s)

                    # Find the first frame of data
                    endline = data.find("\n")
                    line = data[:endline]  # copy first frame
                    data = data[endline + 1:]  # delete first frame

                    # Tokenise
                    toks = line.split(", ")

                    # Check that we have sensible tokens
                    if ((len(toks) < 24) | (toks[0] != "FT")):
                        print('Bad read')
                        continue

                    # Extract FicTrac variables
                    # (see https://github.com/rjdmoore/fictrac/blob/master/doc/data_header.txt for descriptions)
                    self.frame = int(toks[1])  # frame counter
                    self.posx = float(toks[15])  # integrated x position (rad)
                    self.posy = float(toks[16])  # integrated y position (rad)
                    self.heading = float(
                        toks[17]
                    )  # integrated heading direction of the animal in lab coords (rad)
                    self.intx = float(
                        toks[20]
                    )  # integrated x position (rad) of the sphere in lab coord neglecting heading
                    self.inty = float(
                        toks[21]
                    )  # integrated y position (rad) of the sphere in lab coord neglecting heading
                    self.timestamp = float(
                        toks[22])  # frame capture time (ms) since epoch

                    ## Set Phidget voltages using FicTrac data
                    # Set analog output voltage X
                    wrapped_intx = (self.intx % (2 * np.pi))
                    output_voltage_x = wrapped_intx * (
                        self.aout_max_volt - self.aout_min_volt) / (2 * np.pi)
                    self.aout_x.setVoltage(output_voltage_x)

                    # Set analog output voltage YAW
                    output_voltage_yaw = (self.heading) * (
                        self.aout_max_volt - self.aout_min_volt) / (2 * np.pi)
                    self.aout_yaw.setVoltage(output_voltage_yaw)
                    self.aout_yaw_gain.setVoltage(output_voltage_yaw)

                    # Set analog output voltage Y
                    wrapped_inty = self.inty % (2 * np.pi)
                    output_voltage_y = wrapped_inty * (
                        self.aout_max_volt - self.aout_min_volt) / (2 * np.pi)
                    self.aout_y.setVoltage(output_voltage_y)

                    # Save fictrac data in HDF5 file
                    self.write_logfile_fictrac()

                    # open-loop wind
                    self.time_step = (time.time() - self.time_end)
                    if self.turn_type == 'clockwise':
                        self.current_wind_dir = (
                            self.current_wind_dir +
                            (self.time_step * self.stim_speed)) % 360
                    elif self.turn_type == 'counterclockwise':
                        self.current_wind_dir = (
                            self.current_wind_dir -
                            (self.time_step * self.stim_speed)) % 360

                    self.time_end = time.time()
                    # send the wind direction to Arduino
                    arduino_str = "H " + str(
                        self.current_wind_dir
                    ) + "\n"  # "H is a command used in the Arduino code to indicate heading
                    arduino_byte = arduino_str.encode(
                    )  # convert unicode string to byte string
                    ser.write(arduino_byte)  # send to serial port

                    # Set analog output voltage of Phidget (note different from closed-loop, due to the infrequent nature of communication)
                    output_voltage_motor = (self.current_wind_dir /
                                            360) * 10  # convert from deg to V
                    self.aout_motor.setVoltage(output_voltage_motor)

                    # Display status message
                    if self.print:
                        print(f'time elapsed: {self.time_elapsed: 1.3f} s',
                              end='')
                        print(f'\t wind dir: {self.current_wind_dir:3.0f} deg')
                        #print(f'\t time step: {self.time_step:3.6f} s')

                    if self.time_elapsed > self.experiment_time:
                        self.done = True
                        break

            # go back to 0 deg at the end of the trial
            arduino_str = "H " + str(
                0
            ) + "\n"  # "H is a command used in the Arduino code to indicate heading
            arduino_byte = arduino_str.encode(
            )  # convert unicode string to byte string
            ser.write(arduino_byte)  # send to serial port

            self.aout_wind_valve.setVoltage(
                0.0)  # turn the wind off at the end of the trial

            print('Trial finished - quitting!')

    #define function to log data to hdf5 file
    def write_logfile_fictrac(self):
        log_data = {
            'time': self.time_elapsed,
            'frame': self.frame,
            'posx': self.posx,
            'posy': self.posy,
            'intx': self.intx,
            'inty': self.inty,
            'heading': self.heading,
            'motor': self.motor_pos_rad
        }
        self.logger_fictrac.add(log_data)

    def write_logfile_arduino(self):
        log_data = {'time': self.time_arduino, 'motor': self.motor_pos_rad}
        self.logger_arduino.add(log_data)
示例#20
0
    def __init__(self, master, initial_name, top_name, color, sol, reg_pwr,
                 reg_set, reg_get, PSI):
        self.frame = Frame(master, borderwidth=2, relief=SUNKEN, bg=color)
        self.frame.pack()
        self.master = master
        self.frame_name = StringVar()
        self.frame_name.set(initial_name)
        self.state = 0
        self.fontType = "Comic Sans"
        self.activeColor = 'SpringGreen4'
        self.frameColor = color

        self.pressure = IntVar()
        self.lock_flag = IntVar()
        self.pressure.set("")

        self.power = Button(self.frame,
                            text="PWR",
                            activebackground=self.activeColor,
                            command=lambda: self.toggle_pwr())
        self.set_label = Button(self.frame,
                                text="SET LABEL",
                                font=(self.fontType, 7),
                                command=lambda: self.get_label_input())
        self.observed_pressure = Entry(self.frame,
                                       width=5,
                                       state="readonly",
                                       textvariable=self.pressure)
        if self.frame_name.get() == "Hydro":
            self.set_pressure_scale = Scale(self.frame,
                                            orient=HORIZONTAL,
                                            from_=0,
                                            to=92,
                                            resolution=0.5,
                                            bg=color,
                                            label="Set Pressure (PSI)",
                                            highlightthickness=0,
                                            command=self.set_pressure)
        else:
            self.set_pressure_scale = Scale(self.frame,
                                            orient=HORIZONTAL,
                                            from_=0,
                                            to=50,
                                            resolution=0.5,
                                            bg=color,
                                            label="Set Pressure (PSI)",
                                            highlightthickness=0,
                                            command=self.set_pressure)
        self.custom_label = Label(self.frame,
                                  textvariable=self.frame_name,
                                  font=(self.fontType, 14),
                                  bg=color)
        self.label = Label(self.frame, text=initial_name, bg=color)
        self.lock = Checkbutton(self.frame,
                                text="LOCK",
                                bg=color,
                                variable=self.lock_flag,
                                command=self.lock)
        self.frame_name.set(top_name)

        # Init the pressure scale to the default value.
        self.set_pressure_scale.set(PSI)
        # Lock hydo at startup
        if initial_name == "Hydro":
            self.lock.select()
            self.set_pressure_scale.config(state="disabled")
            self.power.config(state="disable")

        self.frame.rowconfigure(0, minsize=30)
        self.custom_label.grid(row=0, column=0, columnspan=2, sticky=S)
        self.set_label.grid(column=0, row=1, columnspan=2)
        self.frame.rowconfigure(2, minsize=50)
        self.power.grid(column=0, row=2)
        self.observed_pressure.grid(column=1, row=2)
        self.set_pressure_scale.grid(column=0, row=3, columnspan=2, padx=20)
        self.frame.rowconfigure(4, minsize=5)
        self.label.grid(column=0, row=5)
        self.lock.grid(column=1, row=5)

        # Connect to Phidget Solid State Relay for solinoid control
        if self.frame_name.get() == "Hydro":
            self.solenoid_switch = DigitalOutput()
            self.solenoid_switch.setDeviceSerialNumber(sol[0])
            self.solenoid_switch.setIsHubPortDevice(False)
            self.solenoid_switch.setHubPort(sol[1])
            self.solenoid_switch.setChannel(sol[2])
            self.solenoid_switch.openWaitForAttachment(5000)

        #Connect to Phidget Solid State Relay for regulator power control
        self.reg_switch = DigitalOutput()
        self.reg_switch.setDeviceSerialNumber(reg_pwr[0])
        self.reg_switch.setIsHubPortDevice(False)
        self.reg_switch.setHubPort(reg_pwr[1])
        self.reg_switch.setChannel(reg_pwr[2])
        self.reg_switch.openWaitForAttachment(5000)

        #Connect to Phidget Voltage Ouptut for pressure control
        self.pressure_ctrl = VoltageOutput()
        self.pressure_ctrl.setDeviceSerialNumber(reg_set[0])
        self.pressure_ctrl.setIsHubPortDevice(False)
        self.pressure_ctrl.setHubPort(reg_set[1])
        self.pressure_ctrl.setChannel(reg_set[2])
        self.pressure_ctrl.openWaitForAttachment(5000)

        #Connect to Phidget Analog Input for pressure reading
        self.pressure_reading = VoltageRatioInput()
        self.pressure_reading.setDeviceSerialNumber(reg_get[0])

        #One of the VINT Hubs on the SBC is used and needs special configuration
        if reg_get[0] == SBCH:
            self.pressure_reading.setIsHubPortDevice(True)
            self.pressure_reading.setHubPort(0)

        self.pressure_reading.setChannel(reg_get[1])
        self.pressure_reading.openWaitForAttachment(5000)
示例#21
0
    def __init__(self, param=DefaultParam):

        self.param = param
        self.experiment = self.param['experiment']
        self.stim_speed = self.param['stim_speed']
        self.turn_type = self.param['turn_type']
        self.experiment_time = self.param['experiment_time']
        self.time_start = time.time(
        )  # get the current time and use it as a ref for elapsed time
        self.current_wind_dir = 0

        # Set up Phidget serial numbers for using two devices
        self.phidget_vision = 525577  # written on the back of the Phidget
        self.phidget_wind = 589946  # for sending the position of the motor to NI-DAQ

        # Set up Phidget channels in device 1 for vision (0-index)
        self.aout_channel_yaw = 0
        self.aout_channel_x = 1
        self.aout_channel_yaw_gain = 2
        self.aout_channel_y = 3
        self.aout_max_volt = 10.0
        self.aout_min_volt = 0.0

        # Setup analog output YAW
        self.aout_yaw = VoltageOutput()
        self.aout_yaw.setDeviceSerialNumber(self.phidget_vision)
        self.aout_yaw.setChannel(self.aout_channel_yaw)
        self.aout_yaw.openWaitForAttachment(5000)
        self.aout_yaw.setVoltage(0.0)

        # Setup analog output X
        self.aout_x = VoltageOutput()
        self.aout_x.setDeviceSerialNumber(self.phidget_vision)
        self.aout_x.setChannel(self.aout_channel_x)
        self.aout_x.openWaitForAttachment(5000)
        self.aout_x.setVoltage(0.0)

        # Setup analog output YAW gain
        self.aout_yaw_gain = VoltageOutput()
        self.aout_yaw_gain.setDeviceSerialNumber(self.phidget_vision)
        self.aout_yaw_gain.setChannel(self.aout_channel_yaw_gain)
        self.aout_yaw_gain.openWaitForAttachment(5000)
        self.aout_yaw_gain.setVoltage(0.0)

        # Setup analog output Y
        self.aout_y = VoltageOutput()
        self.aout_y.setDeviceSerialNumber(self.phidget_vision)
        self.aout_y.setChannel(self.aout_channel_y)
        self.aout_y.openWaitForAttachment(5000)
        self.aout_y.setVoltage(0.0)

        # Set up Phidget channels in device 2 for wind (0-index)
        self.aout_channel_motor = 0
        self.aout_channel_wind_valve = 2

        # Setup analog output motor
        self.aout_motor = VoltageOutput()
        self.aout_motor.setDeviceSerialNumber(self.phidget_wind)
        self.aout_motor.setChannel(self.aout_channel_motor)
        self.aout_motor.openWaitForAttachment(5000)
        self.aout_motor.setVoltage(0.0)

        # Setup analog output wind valve
        self.aout_wind_valve = VoltageOutput()
        self.aout_wind_valve.setDeviceSerialNumber(self.phidget_wind)
        self.aout_wind_valve.setChannel(self.aout_channel_wind_valve)
        self.aout_wind_valve.openWaitForAttachment(5000)
        self.aout_wind_valve.setVoltage(0.0)

        self.print = True

        # Set up socket info for connecting with the FicTrac
        self.HOST = '127.0.0.1'  # The (receiving) host IP address (sock_host)
        self.PORT = 65432  # The (receiving) host port (sock_port)

        # Set up Arduino connection
        self.COM = 'COM4'  # serial port
        self.baudrate = 115200  # 9600
        self.serialTimeout = 0.001  # blocking timeout for readline()

        # flag for indicating when the trial is done
        self.done = False

        #set up logger to save hd5f file
        self.logger_fictrac = H5Logger(
            filename=self.param['logfile_name'],
            auto_incr=self.param['logfile_auto_incr'],
            auto_incr_format=self.param['logfile_auto_incr_format'],
            param_attr=self.param)

        #set up logger to save hd5f file
        self.logger_arduino = H5Logger(
            filename=(self.param['logfile_name']).replace(
                '.hdf5', '_arduino.hdf5'),
            auto_incr=self.param['logfile_auto_incr'],
            auto_incr_format=self.param['logfile_auto_incr_format'],
            param_attr=self.param)
示例#22
0
    def __init__(self, param=DefaultParam):

        self.param = param
        self.experiment = self.param['experiment']
        self.stim_speed = self.param['stim_speed']
        self.turn_type = self.param['turn_type']
        self.bar_offset = self.param[
            'bar_offset']  # bar relative to wind [deg]
        self.experiment_time = self.param['experiment_time']
        self.time_start = time.time(
        )  # get the current time and use it as a ref for elapsed time
        self.stim_dir = 0
        self.offset_adjust = 15  # use this offset to make bars perfectly aligned to wind, hard coded (deg)
        self.fly_heading = 0  # for calculating heading of the fly (rad)
        self.first_time_in_loop = True

        self.print = True  # for printing the current values on the console

        # specify the time epochs in the experiment
        self.time_baseline = 10  # [s] baseline period
        self.epoch_dur = 200  # [s] duration of an individual epoch
        self.epoch_num = 6  # total number of epochs

        # set voltage range for Phidget
        self.aout_max_volt = 10.0
        self.aout_min_volt = 0.0

        # set up two Phidgets
        self.phidget_vision = 525577  # for writing Fictrac x, y, and panels (yaw_gain)
        self.phidget_wind = 589946  # for sending the position of the motor to NI-DAQ, actual animal yaw

        # Set up Phidget channels in device 1 for vision (0-index)
        self.aout_channel_ydimension = 0
        self.aout_channel_x = 1
        self.aout_channel_y = 3
        self.aout_channel_yaw_gain = 2

        # Setup analog output X
        self.aout_x = VoltageOutput()
        self.aout_x.setDeviceSerialNumber(self.phidget_vision)
        self.aout_x.setChannel(self.aout_channel_x)
        self.aout_x.openWaitForAttachment(5000)
        self.aout_x.setVoltage(0.0)

        # Setup analog output Y
        self.aout_y = VoltageOutput()
        self.aout_y.setDeviceSerialNumber(self.phidget_vision)
        self.aout_y.setChannel(self.aout_channel_y)
        self.aout_y.openWaitForAttachment(5000)
        self.aout_y.setVoltage(0.0)

        # Setup analog output YAW (use this channel to turn panels on and off)
        self.aout_ydim = VoltageOutput()
        self.aout_ydim.setDeviceSerialNumber(self.phidget_vision)
        self.aout_ydim.setChannel(self.aout_channel_ydimension)
        self.aout_ydim.openWaitForAttachment(5000)
        self.aout_ydim.setVoltage(0.0)

        # Setup analog output YAW gain (use this channel to control panel bar position)
        self.aout_yaw_gain = VoltageOutput()
        self.aout_yaw_gain.setDeviceSerialNumber(self.phidget_vision)
        self.aout_yaw_gain.setChannel(self.aout_channel_yaw_gain)
        self.aout_yaw_gain.openWaitForAttachment(5000)
        self.aout_yaw_gain.setVoltage(0.0)

        # Set up Phidget channels in device 2 for wind (0-index)
        self.aout_channel_motor = 0
        self.aout_channel_yaw = 1  # for recording the actual yaw of the fly
        self.aout_channel_wind_valve = 2

        # Setup analog output motor
        self.aout_motor = VoltageOutput()
        self.aout_motor.setDeviceSerialNumber(self.phidget_wind)
        self.aout_motor.setChannel(self.aout_channel_motor)
        self.aout_motor.openWaitForAttachment(5000)
        self.aout_motor.setVoltage(0.0)

        # Setup analog output for yaw
        self.aout_yaw = VoltageOutput()
        self.aout_yaw.setDeviceSerialNumber(self.phidget_wind)
        self.aout_yaw.setChannel(self.aout_channel_yaw)
        self.aout_yaw.openWaitForAttachment(5000)
        self.aout_yaw.setVoltage(0.0)

        # Setup analog output wind valve
        self.aout_wind_valve = VoltageOutput()
        self.aout_wind_valve.setDeviceSerialNumber(self.phidget_wind)
        self.aout_wind_valve.setChannel(self.aout_channel_wind_valve)
        self.aout_wind_valve.openWaitForAttachment(5000)
        self.aout_wind_valve.setVoltage(0.0)

        # Set up socket info for connecting with the FicTrac
        self.HOST = '127.0.0.1'  # The (receiving) host IP address (sock_host)
        self.PORT = 65432  # The (receiving) host port (sock_port)

        # Set up Arduino connection
        self.COM = 'COM4'  # serial port
        self.baudrate = 115200  # 9600
        self.serialTimeout = 0.001  # blocking timeout for readline()

        # flag for indicating when the trial is done
        self.done = False

        #set up logger to save hd5f file
        self.logger_fictrac = H5Logger(
            filename=self.param['logfile_name'],
            auto_incr=self.param['logfile_auto_incr'],
            auto_incr_format=self.param['logfile_auto_incr_format'],
            param_attr=self.param)

        #set up logger to save hd5f file
        self.logger_arduino = H5Logger(
            filename=(self.param['logfile_name']).replace(
                '.hdf5', '_arduino.hdf5'),
            auto_incr=self.param['logfile_auto_incr'],
            auto_incr_format=self.param['logfile_auto_incr_format'],
            param_attr=self.param)
示例#23
0
    ch2.setDeviceSerialNumber(118651)
    ch2.setChannel(0)
    ch2.setOnAttachHandler(onAttachHandler)
    ch2.setOnTemperatureChangeHandler(onTemperatureChangeHandler)
    ch2.openWaitForAttachment(5000)
    temp9 = ch2.getTemperature() * 9 / 5 + 32
    temp8 = temp9
    #time.sleep(10)

    ch2.close()

    print("i got the temperature, its ", temp9)
    return temp8


voltageOutput0 = VoltageOutput()


def setheatersignal(heatersignal):
    global voltageOutput0
    voltageOutput0.openWaitForAttachment(5000)
    voltout = heatersignal / 100 * 5.0
    if voltout >= 0 and voltout <= 5.0:
        voltageOutput0.setVoltage(voltout)
    print("first")
    time.sleep(10)


    #voltageOutput0.close()
def endheatersignal():
    voltageOutput0 = VoltageOutput()