def __init__(self, master=None): super(ULAO01, self).__init__(master) self.board_num = 0 self.ao_props = AnalogOutputProps(self.board_num) self.create_widgets()
def __init__(self, master=None): super(ULAIO01, self).__init__(master) self.period = 1 self.period_switch = [] self.tempo = None # for arena output self.board_num = 0 self.ai_props = AnalogInputProps(self.board_num) self.ao_props = AnalogOutputProps(self.board_num) # Initialize tkinter self.create_widgets()
def run_example(): board_num = 0 if use_device_detection: ul.ignore_instacal() if not util.config_first_detected_device(board_num): print("Could not find device.") return channel = 0 ao_props = AnalogOutputProps(board_num) if ao_props.num_chans < 1: util.print_unsupported_example(board_num) return ao_range = ao_props.available_ranges[0] data_value = ao_range.range_max / 2 try: print("Outputting " + str(data_value) + " Volts to channel " + str(channel) + ".") # Send the value to the device (optional parameter omitted) ul.v_out(board_num, channel, ao_range, data_value) except ULError as e: util.print_ul_error(e) finally: if use_device_detection: ul.release_daq_device(board_num)
def __init__(self, master=None): super(ULAIO01, self).__init__(master) self.board_num = 0 self.ai_props = AnalogInputProps(self.board_num) self.ao_props = AnalogOutputProps(self.board_num) # Initialize tkinter self.create_widgets()
def __init__(self, master=None): super(DaqOutScan01, self).__init__(master) self.board_num = 0 self.daqo_props = DaqOutputProps(self.board_num) if self.daqo_props.is_supported: self.ao_props = AnalogOutputProps(self.board_num) self.digital_props = DigitalProps(self.board_num) self.init_scan_channel_info() self.create_widgets()
class ULAIO01(UIExample): def __init__(self, master=None): super(ULAIO01, self).__init__(master) self.period = 1 self.period_switch = [] self.tempo = None # for arena output self.board_num = 0 self.ai_props = AnalogInputProps(self.board_num) self.ao_props = AnalogOutputProps(self.board_num) # Initialize tkinter self.create_widgets() def start_input_scan(self): self.input_low_chan = self.get_input_low_channel_num() self.input_high_chan = self.get_input_high_channel_num() self.num_input_chans = (self.input_high_chan - self.input_low_chan + 1) self.periodtime = int( self.periodbox.get()) # variable of the duration in sec self.periodtimevar = self.periodtime # a placeholder of periodtime which can be changed if self.input_low_chan > self.input_high_chan: messagebox.showerror( "Error", "Low Channel Number must be greater than or equal to High " "Channel Number") self.set_input_ui_idle_state() return rate = int( self.input_Samplingrate.get()) # data sampling rate per second # self.samplingrate = rate points_per_channel = self.test_time() total_count = points_per_channel * self.num_input_chans range_ = self.ai_props.available_ranges[0] scan_options = ScanOptions.BACKGROUND | ScanOptions.CONTINUOUS # Allocate a buffer for the scan if self.ai_props.resolution <= 16: # Use the win_buf_alloc method for devices with a resolution <= # 16 self.input_memhandle = ul.win_buf_alloc(total_count) else: # Use the win_buf_alloc_32 method for devices with a resolution # > 16 self.input_memhandle = ul.win_buf_alloc_32(total_count) if not self.input_memhandle: messagebox.showerror("Error", "Failed to allocate memory") self.set_input_ui_idle_state() return # Create the frames that will hold the data self.recreate_input_data_frame() try: # Run the scan ul.a_in_scan(self.board_num, self.input_low_chan, self.input_high_chan, total_count, rate, range_, self.input_memhandle, scan_options) except ULError as e: self.show_ul_error(e) self.set_input_ui_idle_state() return # Convert the input_memhandle to a ctypes array # Note: the ctypes array will no longer be valid after win_buf_free is called. # A copy of the buffer can be created using win_buf_to_array # or win_buf_to_array_32 before the memory is freed. The copy can # be used at any time. if self.ai_props.resolution <= 16: # self.copied_array = ul.win_buf_to_array(self.iput_memhandle) # Use the memhandle_as_ctypes_array method for devices with a # resolution <= 16 self.ctypes_array = self.memhandle_as_ctypes_array( self.input_memhandle) else: # Use the memhandle_as_ctypes_array_32 method for devices with a # resolution > 16 self.ctypes_array = self.memhandle_as_ctypes_array_32( self.input_memhandle) # Start updating the displayed values self.update_input_displayed_values(range_) # Start the arena output self.tempo = 2.2 self.update_arena_output() def update_input_displayed_values(self, range_): # Get the status from the device status, curr_count, curr_index = ul.get_status(self.board_num, FunctionType.AIFUNCTION) # Display the status info self.update_input_status_labels(status, curr_count, curr_index) # Update period if necessary self.update_input_period(curr_count) # Display the values self.display_input_values(range_, curr_index, curr_count) # Open the directory text file self.textfile = open("Rawtext.txt", "a+") # textfile that the data will be written to # Function for the writing of the complete buffer to a text file and stopping the process if curr_count >= self.test_time() - 100: self.full_file() # Call this method again until the stop_input button is pressed if status == Status.RUNNING: self.after(10, self.update_input_displayed_values, range_) else: # Free the allocated memory ul.win_buf_free(self.input_memhandle) self.set_input_ui_idle_state() def update_input_status_labels(self, status, curr_count, curr_index): if status == Status.IDLE: self.input_status_label["text"] = "Idle" else: self.input_status_label["text"] = "Running" self.input_period_label["text"] = self.period self.input_index_label["text"] = str(curr_index) self.input_count_label["text"] = str(curr_count) def update_input_period(self, curr_count): if t.clock() > self.periodtimevar: # Beep(2000, 500) self.period += 1 # switch to next period self.periodtimevar = self.periodtimevar + self.periodtime self.period_switch.append( curr_count) # documentation of period switch if self.tempo == 1.8: print("twmpo", self.tempo) self.tempo = 2.2 # make it relative to input!!!! else: self.tempo = 1.8 self.update_arena_output() def display_input_values(self, range_, curr_index, curr_count): per_channel_display_count = 1 array = self.ctypes_array low_chan = self.input_low_chan high_chan = self.input_high_chan ULAIO01.channel_text = [] # Add the headers for chan_num in range(low_chan, high_chan + 1): ULAIO01.channel_text.append("Channel " + str(chan_num) + "\n") # If no data has been gathered, don't add data to the labels if curr_count > 1: chan_count = high_chan - low_chan + 1 chan_num = low_chan # curr_index points to the start_input of the last completed channel scan that # was transferred between the board and the data buffer. Based on this, # calculate the first index we want to display using subtraction. first_index = max( curr_index - ((per_channel_display_count - 1) * chan_count), 0) # Add (up to) the latest 10 values for each channel to the text for data_index in range( first_index, first_index + min(chan_count * per_channel_display_count, curr_count)): raw_value = array[data_index] if self.ai_props.resolution <= 16: ULAIO01.eng_value = ul.to_eng_units( self.board_num, range_, raw_value) else: ULAIO01.eng_value = ul.to_eng_units_32( self.board_num, range_, raw_value) ULAIO01.channel_text[chan_num - low_chan] += ( '{:.3f}'.format(ULAIO01.eng_value) + "\n") self.datasheet() # custom datahandling if chan_num == high_chan: chan_num = low_chan else: chan_num += 1 # Update the labels for each channel for chan_num in range(low_chan, high_chan + 1): ULAIO01.chan_index = chan_num - low_chan self.chan_labels[ULAIO01.chan_index][ "text"] = ULAIO01.channel_text[ULAIO01.chan_index] def recreate_input_data_frame(self): low_chan = self.input_low_chan high_chan = self.input_high_chan new_data_frame = tk.Frame(self.input_inner_data_frame) self.chan_labels = [] # Add the labels for each channel for chan_num in range(low_chan, high_chan + 1): chan_label = tk.Label(new_data_frame, justify=tk.LEFT, padx=3) chan_label.grid(row=0, column=chan_num - low_chan) self.chan_labels.append(chan_label) self.data_frame.destroy() self.data_frame = new_data_frame self.data_frame.grid() def exit(self): status, curr_count, curr_index = ul.get_status(self.board_num, FunctionType.AIFUNCTION) if status == status.RUNNING: self.full_file() else: # else just stop the arena (whether turning or not) self.tempo = 2 self.update_arena_output() self.save_inputs() self.master.destroy() def save_inputs(self): self.save_firstname.text = str(self.input_firstname.get()) self.save_lastname.text = str(self.input_lastname.get()) self.save_orcid.text = str(self.input_orcid.get()) self.save_flytype.text = str(self.input_flytype.get()) self.save_flyname.text = str(self.input_flyname.get()) self.save_flydescription.text = str(self.input_flydescription.get()) self.save_experimenttype.text = str(self.input_experimenttype.get()) self.save_experimentdescription.text = str( self.input_ExperimentDescription.get()) self.save_filename.text = str(self.input_filename.get()) self.save_samplingrate.text = str(self.input_Samplingrate.get()) self.save_outcome.text = str(self.input_outcome.get()) self.save_pattern.text = str(self.input_Pattern.get()) self.save_lowchan.text = str(self.input_low_channel_entry.get()) self.save_highchan.text = str(self.input_high_channel_entry.get()) self.save_periodtime.text = str(self.periodbox.get()) self.save_testtime.text = str(self.testtimebox.get()) self.save_tree.write("Input_save.xml") def update_arena_output(self): channel = self.get_channel_num() ao_range = self.ao_props.available_ranges[0] data_value = self.get_speed() if self.tempo is not None: ULAIO01.output_value = ul.from_eng_units(self.board_num, ao_range, self.tempo) else: ULAIO01.output_value = ul.from_eng_units(self.board_num, ao_range, data_value) print(ULAIO01.output_value) try: ul.a_out(self.board_num, channel, ao_range, ULAIO01.output_value) except ULError as e: self.show_ul_error(e) def get_speed(self): try: return float(self.arena_speed_out.get()) except ValueError: return 2 # 2 will put the arena to rest def get_channel_num(self): if self.ao_props.num_chans == 1: return 0 try: return int(self.channel_entry.get()) except ValueError: return 0 def validate_channel_entry(self, p): if p == '': return True try: value = int(p) if (value < 0 or value > self.ao_props.num_chans - 1): return False except ValueError: return False return True def stop_input(self): self.tempo = 2 # stop turning arena self.update_arena_output() status, curr_count, curr_index = ul.get_status(self.board_num, FunctionType.AIFUNCTION) my_array = self.ctypes_array # save all the collected data ul.stop_background(self.board_num, FunctionType.AIFUNCTION) open("KHZtext.txt", "w") # clear existing file endfile = open( "KHZtext.txt", "a+") # textfile that the data will be written to (kiloherztext) millisec = 0 # the time column parameter in milliseconds ULAIO01.txt_count = 0 # for the order of the KHZtext file self.period = 1 print("count", curr_count) for i in list( range(0, curr_count) ): # curr_count should represent the length of the ctypes_array eng_value = ul.to_eng_units(self.board_num, self.ai_props.available_ranges[0], my_array[i]) eng_value_proper = ( "%f " % (eng_value) ) # thats how it is supposed to be written into the txt file, but right now it isn't unicode endfile.write( eng_value_proper.decode("unicode-escape") ) # eng_value returns float, but after (4) floats all channels are printed (also: encode to utf8 format) ULAIO01.txt_count = ULAIO01.txt_count + 1 # thats why we need the count (know when to newline) if self.period < len( self.period_switch ) and i == self.period_switch[ self.period - 1]: # when we iterated to the point where a new period was started, we need to switch the period parameter self.period = self.period + 1 print("hat funktioniert", self.period) if ULAIO01.txt_count == ( (self.input_high_chan - self.input_low_chan) + 1): endfile.write(u"%d %d\n" % (millisec, self.period)) ULAIO01.txt_count = 0 millisec = millisec + 10 # for each loop the next millisecond is measured Beep(3000, 500) def set_input_ui_idle_state(self): self.input_high_channel_entry["state"] = tk.NORMAL self.input_low_channel_entry["state"] = tk.NORMAL self.periodbox["state"] = tk.NORMAL self.testtimebox["state"] = tk.NORMAL self.input_start_button["command"] = self.start_input self.input_start_button["text"] = "Start Analog Input" def start_input(self): self.input_high_channel_entry["state"] = tk.DISABLED self.input_low_channel_entry["state"] = tk.DISABLED self.periodbox["state"] = tk.DISABLED self.testtimebox["state"] = tk.DISABLED #self.input_start_button["command"] = self.stop_input() if self.input_start_button["text"] == "Stop Analog Input": self.full_file() self.input_start_button["text"] = "Start Analog Input" else: self.input_start_button["text"] = "Stop Analog Input" self.start_input_scan() def get_input_low_channel_num(self): if self.ai_props.num_ai_chans == 1: return 0 try: return int(self.input_low_channel_entry.get()) except ValueError: return 0 def get_input_high_channel_num(self): if self.ai_props.num_ai_chans == 1: return 0 try: return int(self.input_high_channel_entry.get()) except ValueError: return 0 def get_output_low_channel_num(self): if self.ao_props.num_chans == 1: return 0 try: return int(self.output_low_channel_entry.get()) except ValueError: return 0 def get_output_high_channel_num(self): if self.ao_props.num_chans == 1: return 0 try: return int(self.output_high_channel_entry.get()) except ValueError: return 0 def validate_channel_entry(self, p): if p == '': return True try: value = int(p) if (value < 0 or value > self.ai_props.num_ai_chans - 1): return False except ValueError: return False return True # Function for preparing the textfile, which will be read by the live plotter def makecheck(self): ULAIO01.txt_count = 0 # for the txt file order open("Rawtext.txt", "w").close() # delete any existing contents of the rawtext file os.startfile("live_graph.pyc") global check # to recognise if the "write to xml" checkbox was clicked check = "on" return check # Function for writing some data to the text file, which will be read by the live plotter def datasheet(self): try: # the try because there is no "check" if the checkbox hasn't been clicked if check == "on": eng_value_proper = ( "%f " % (ULAIO01.eng_value) ) # thats how it is supposed to be written into the txt file, but right now it isn't unicode self.textfile.write( eng_value_proper.decode("unicode-escape") ) # eng_value returns float, but after (4) floats all channels are printed (also: encode to utf8 format) ULAIO01.txt_count = ULAIO01.txt_count + 1 # thats why we need the count (know when to newline) time = t.clock() # for the time column if ULAIO01.txt_count == ( (self.input_high_chan - self.input_low_chan) + 1): self.textfile.write(u"%f %d\n" % (time, self.period)) ULAIO01.txt_count = 0 else: print("xml off") except NameError: return None # Function for writing all data to the text file, which will be used for the xml file def full_file(self): self.stop_input() # The process of writing the finished text file to the xml file def txt_to_xml(self): # del last line in KHZtext: (source: https://stackoverflow.com/questions/1877999/delete-final-line-in-file-with-python) file = open("KHZtext.txt", "r+") # Move the pointer (similar to a cursor in a text editor) to the end of the file. file.seek(0, os.SEEK_END) # This code means the following code skips the very last character in the file - # i.e. in the case the last line is null we delete the last line # and the penultimate one pos = file.tell() - 1 # Read each character in the file one at a time from the penultimate # character going backwards, searching for a newline character # If we find a new line, exit the search while pos > 0 and file.read(1) != "\n": pos -= 1 file.seek(pos, os.SEEK_SET) # So long as we're not at the start of the file, delete all the characters ahead of this position if pos > 0: file.seek(pos, os.SEEK_SET) file.truncate() status, curr_count, curr_index = ul.get_status(self.board_num, FunctionType.AOFUNCTION) if status == Status.IDLE: datafile = open("KHZtext.txt", "r") # text with periods for xml data = datafile.read() xml_name = self.input_filename.get() + ".xml" print(xml_name) target_folder = os.path.join(os.curdir, "AndersSoft") target_file = os.path.join(target_folder, "Optomotorics_blueprint.xml") xml_location = os.path.join(target_folder, xml_name) copy("Optomotorics_blueprint.xml", "AndersSoft") if os.path.exists(xml_location): print("warning") showwarning( "Warning", "The specified file already exists, rename the existing one NOW if overwriting should be avoided" ) move(target_file, xml_location) tree = et.parse(xml_location) #C:\Bachelor\FinishedSoft\ self.firstname = tree.find("./metadata/experimenter/firstname") self.firstname.text = str(self.input_firstname.get()) self.lastname = tree.find("./metadata/experimenter/lastname") self.lastname.text = str(self.input_lastname.get()) self.orcid = tree.find("./metadata/experimenter/orcid") self.orcid.text = str(self.input_orcid.get()) self.fly = tree.find("./metadata/fly") self.fly.attribute = str(self.input_flytype.get()) self.fly_name = tree.find("./metadata/fly/name") self.fly_name.text = str(self.input_flyname.get()) self.fly_description = tree.find("./metadata/fly/description") self.fly_description.text = str(self.input_flydescription.get()) # x = tree.find("./metadata/experiment") # x.attribute = str(self.input_experimenttype self.experiment_dateTime = tree.find( "./metadata/experiment/dateTime") self.experiment_dateTime.text = str(self.input_dateTime.get()) self.experiment_duration = tree.find( "./metadata/experiment/duration") self.experiment_duration.text = str(self.testtimebox.get()) self.experiment_description = tree.find( "./metadata/experiment/description") self.experiment_description.text = str( self.input_ExperimentDescription.get()) self.sample_rate = tree.find("./metadata/experiment/sample_rate") self.sample_rate.text = str(self.input_Samplingrate.get()) self.sequences = int( int(self.testtimebox.get()) * 60 / int(self.periodbox.get())) + 1 sequence = tree.find("./sequence") sequence.attribute = self.sequences # perioddescription for i in list(range(1, self.sequences)): period = et.SubElement(sequence, "period") period.set("number", "%d" % i) print(et.tostring(period)) if i % 2 == 0: type = et.SubElement(period, "type") type.text = "OptomotoR" else: type = et.SubElement(period, "type") type.text = "OptomotoL" duration = et.SubElement(period, "duration") duration.text = str(self.periodbox.get()) outcome = et.SubElement(period, "outcome") outcome.text = str(self.input_outcome.get()) pattern = et.SubElement(period, "pattern") pattern.text = str(self.input_Pattern.get()) csv = tree.find( "./timeseries/csv_data") # adress the right spot for the data csv.text = data # implement the data in the xml tree.write(xml_location) file.close() def restart_program( self ): # source: https://www.daniweb.com/programming/software-development/code/260268/restart-your-python-program """Restarts the current program. Note: this function does not return. Any cleanup action (like saving data) must be done before calling this function.""" python = sys.executable os.execl(python, python, *sys.argv) # small function for test time calculus def test_time(self): self.testtime = self.num_input_chans * 60 * 100 * int( self.testtimebox.get()) # variable of the duration in sec # (number of channels) * 60 (minute to sec)* 1000 (sec to millisec) while self.testtime % 31 != 0: # the variable has to be divisible by 31 (COUNTINOUS mode restriction) self.testtime += 1 return self.testtime def give_curr_count(self): status, curr_count, curr_index = ul.get_status(self.board_num, FunctionType.AOFUNCTION) return curr_count def create_widgets(self): '''Create the tkinter UI''' example_supported = (self.ao_props.num_chans > 0 and self.ao_props.supports_scan and self.ai_props.num_ai_chans > 0 and self.ai_props.supports_scan) if example_supported: self.save_tree = et.parse( "Input_save.xml") # load the latest input print(self.save_tree.find("./input/firstname"), "save") channel_vcmd = self.register(self.validate_channel_entry) main_frame = tk.Frame(self) main_frame.pack(fill=tk.X, anchor=tk.NW) input_groupbox = tk.LabelFrame(main_frame, text="Analog Input") input_groupbox.pack(side=tk.LEFT, anchor=tk.NW) if self.ai_props.num_ai_chans > 1: curr_row = 0 input_channels_frame = tk.Frame(input_groupbox) input_channels_frame.pack(fill=tk.X, anchor=tk.NW) input_low_channel_entry_label = tk.Label(input_channels_frame) input_low_channel_entry_label["text"] = ("Low Channel Number:") input_low_channel_entry_label.grid(row=curr_row, column=0, sticky=tk.W) self.input_low_channel_entry = tk.Spinbox( input_channels_frame, from_=0, to=max(self.ai_props.num_ai_chans - 1, 0), validate='key', validatecommand=(channel_vcmd, '%P')) self.save_lowchan = self.save_tree.find( "./input/lowchan") # load latest input self.input_low_channel_entry.delete(0, tk.END) # clear the entry self.input_low_channel_entry.insert( int(self.save_lowchan.text), self.save_lowchan.text) self.input_low_channel_entry.grid(row=curr_row, column=1, sticky=tk.W) curr_row += 1 input_high_channel_entry_label = tk.Label(input_channels_frame) input_high_channel_entry_label["text"] = ( "High Channel Number:") input_high_channel_entry_label.grid(row=curr_row, column=0, sticky=tk.W) self.input_high_channel_entry = tk.Spinbox( input_channels_frame, from_=0, to=max(self.ai_props.num_ai_chans - 1, 0), validate='key', validatecommand=(channel_vcmd, '%P')) self.save_highchan = self.save_tree.find( "./input/highchan") # load latest input self.input_high_channel_entry.delete(0, tk.END) # clear the entry self.input_high_channel_entry.insert( int(self.save_highchan.text), self.save_highchan.text) self.input_high_channel_entry.grid(row=curr_row, column=1, sticky=tk.W) curr_row += 1 # selfmade, for length of period choice periodbox_label = tk.Label(input_channels_frame) periodbox_label["text"] = ("Time per period (sec):") periodbox_label.grid(row=curr_row, column=0, sticky=tk.W) self.periodbox = tk.Spinbox(input_channels_frame, from_=10, to=500, increment=5, validate='key', validatecommand=(channel_vcmd, '%P')) self.save_periodtime = self.save_tree.find( "./input/periodtime") # load latest input self.periodbox.delete(0, tk.END) # clear the entry self.periodbox.insert(int(self.save_periodtime.text), self.save_periodtime.text) self.periodbox.grid(row=curr_row, column=1, sticky=tk.W) curr_row += 1 # selfmade, for length of test time choice testtime_label = tk.Label(input_channels_frame) testtime_label["text"] = ("Test time overall (min):") testtime_label.grid(row=curr_row, column=0, sticky=tk.W) self.testtimebox = tk.Spinbox(input_channels_frame, from_=0, to=100, increment=1, validate='key') self.save_testtime = self.save_tree.find( "./input/testtime") # load latest input self.testtimebox.delete(0, tk.END) # clear the entry self.testtimebox.insert(int(self.save_testtime.text), self.save_testtime.text) self.testtimebox.grid(row=curr_row, column=1, sticky=tk.W) # selfmade, for datasheet option (source: effbot tkinter checkbutton) self.checkmarker = tk.Checkbutton( input_groupbox, text="Write to TXT and plot live graph", command=self.makecheck) self.checkmarker.pack(anchor=tk.NW, side=tk.TOP) self.txt_to_xml_button = tk.Button(input_groupbox) self.txt_to_xml_button[ "text"] = "Transfer data to XML (only when IDLE)" self.txt_to_xml_button["command"] = self.txt_to_xml self.txt_to_xml_button.pack(anchor=tk.NW, side=tk.TOP) self.input_start_button = tk.Button(input_groupbox) self.input_start_button["text"] = "Start Analog Input" self.input_start_button["command"] = self.start_input self.input_start_button.pack(fill=tk.X, anchor=tk.NW, padx=3, pady=3) self.input_results_group = tk.LabelFrame(input_groupbox, text="Results", padx=3, pady=3) self.input_results_group.pack(fill=tk.X, anchor=tk.NW, padx=3, pady=3) self.input_results_group.grid_columnconfigure(1, weight=1) curr_row = 0 input_status_left_label = tk.Label(self.input_results_group) input_status_left_label["text"] = "Status:" input_status_left_label.grid(row=curr_row, column=0, sticky=tk.W) self.input_status_label = tk.Label(self.input_results_group) self.input_status_label["text"] = "Idle" self.input_status_label.grid(row=curr_row, column=1, sticky=tk.W) curr_row += 1 input_period_left_label = tk.Label(self.input_results_group) input_period_left_label["text"] = "Period:" input_period_left_label.grid(row=curr_row, column=0, sticky=tk.W) self.input_period_label = tk.Label(self.input_results_group) self.input_period_label["text"] = "-1" self.input_period_label.grid(row=curr_row, column=1, sticky=tk.W) curr_row += 1 input_index_left_label = tk.Label(self.input_results_group) input_index_left_label["text"] = "Index:" input_index_left_label.grid(row=curr_row, column=0, sticky=tk.W) self.input_index_label = tk.Label(self.input_results_group) self.input_index_label["text"] = "-1" self.input_index_label.grid(row=curr_row, column=1, sticky=tk.W) curr_row += 1 input_count_left_label = tk.Label(self.input_results_group) input_count_left_label["text"] = "Count:" input_count_left_label.grid(row=curr_row, column=0, sticky=tk.W) self.input_count_label = tk.Label(self.input_results_group) self.input_count_label["text"] = "0" self.input_count_label.grid(row=curr_row, column=1, sticky=tk.W) curr_row += 1 self.input_inner_data_frame = tk.Frame(self.input_results_group) self.input_inner_data_frame.grid(row=curr_row, column=0, columnspan=2, sticky=tk.W) self.data_frame = tk.Frame(self.input_inner_data_frame) self.data_frame.grid() ########## METADATA ########################### xml_groupbox = tk.LabelFrame(main_frame, text="Metadata") xml_groupbox.pack(side=tk.LEFT, anchor=tk.NW) curr_row = 0 label = tk.Label(xml_groupbox, text="Firstname") label.grid(row=curr_row, column=1, sticky=tk.W) self.input_firstname = tk.Entry(xml_groupbox) self.input_firstname.grid(row=curr_row, column=2, sticky=tk.W) self.save_firstname = self.save_tree.find( "./input/firstname") # load the latest input self.input_firstname.insert(0, self.save_firstname.text) curr_row += 1 label = tk.Label(xml_groupbox, text="Lastname") label.grid(row=curr_row, column=1, sticky=tk.W) self.input_lastname = tk.Entry(xml_groupbox) self.input_lastname.grid(row=curr_row, column=2, sticky=tk.W) self.save_lastname = self.save_tree.find( "./input/lastname") # load the latest input self.input_lastname.insert(0, self.save_lastname.text) curr_row += 1 label = tk.Label(xml_groupbox, text="orcid ID") label.grid(row=curr_row, column=1, sticky=tk.W) self.input_orcid = tk.Entry(xml_groupbox) self.input_orcid.grid(row=curr_row, column=2, sticky=tk.W) self.save_orcid = self.save_tree.find( "./input/orcid") # load the latest input self.input_orcid.insert(0, self.save_orcid.text) curr_row += 1 label = tk.Label(xml_groupbox, text="Flytype") label.grid(row=curr_row, column=1, sticky=tk.W) self.input_flytype = tk.Entry(xml_groupbox) self.input_flytype.grid(row=curr_row, column=2, sticky=tk.W) self.save_flytype = self.save_tree.find( "./input/flytype") # load the latest input self.input_flytype.insert(0, self.save_flytype.text) curr_row += 1 label = tk.Label(xml_groupbox, text="Flyname") label.grid(row=curr_row, column=1, sticky=tk.W) self.input_flyname = tk.Entry(xml_groupbox) self.input_flyname.grid(row=curr_row, column=2, sticky=tk.W) self.save_flyname = self.save_tree.find( "./input/flyname") # load the latest input self.input_flyname.insert(0, self.save_flyname.text) curr_row += 1 label = tk.Label(xml_groupbox, text="Flydescription") label.grid(row=curr_row, column=1, sticky=tk.W) self.input_flydescription = tk.Entry(xml_groupbox) self.input_flydescription.grid(row=curr_row, column=2, sticky=tk.W) self.save_flydescription = self.save_tree.find( "./input/flydescription") # load the latest input self.input_flydescription.insert(0, self.save_flydescription.text) curr_row += 1 label = tk.Label(xml_groupbox, text="Experimenttype") label.grid(row=curr_row, column=1, sticky=tk.W) self.input_experimenttype = tk.Entry(xml_groupbox) self.input_experimenttype.grid(row=curr_row, column=2, sticky=tk.W) self.save_experimenttype = self.save_tree.find( "./input/experimenttype") # load the latest input self.input_experimenttype.insert(0, self.save_experimenttype.text) curr_row += 1 label = tk.Label(xml_groupbox, text="Date and Time") label.grid(row=curr_row, column=1, sticky=tk.W) self.input_dateTime = tk.Entry(xml_groupbox) self.input_dateTime.grid(row=curr_row, column=2, sticky=tk.W) self.input_dateTime.insert( 0, datetime.now().isoformat()) # display current datetime # curr_row += 1 # label = tk.Label(xml_groupbox, text="Period Duration") # label.grid(row=curr_row, column=1, sticky=tk.W) # self.input_duration = tk.Entry(xml_groupbox) # self.input_duration.grid(row=curr_row, column=2, sticky=tk.W) # self.input_duration.insert(20, "20") curr_row += 1 label = tk.Label(xml_groupbox, text="Experiment Description") label.grid(row=curr_row, column=1, sticky=tk.W) self.input_ExperimentDescription = tk.Entry(xml_groupbox) self.input_ExperimentDescription.grid(row=curr_row, column=2, sticky=tk.W) self.save_experimentdescription = self.save_tree.find( "./input/experimentdescription") # load the latest input self.input_ExperimentDescription.insert( 0, self.save_experimentdescription.text) curr_row += 1 label = tk.Label(xml_groupbox, text="File Name") label.grid(row=curr_row, column=1, sticky=tk.W) self.input_filename = tk.Entry(xml_groupbox) self.input_filename.grid(row=curr_row, column=2, sticky=tk.W) self.save_filename = self.save_tree.find( "./input/filename") # load the latest input self.input_filename.insert(0, self.save_filename.text) curr_row += 1 label = tk.Label(xml_groupbox, text="Samplingrate(Hz)") label.grid(row=curr_row, column=1, sticky=tk.W) self.input_Samplingrate = tk.Entry(xml_groupbox) self.input_Samplingrate.grid(row=curr_row, column=2, sticky=tk.W) self.save_samplingrate = self.save_tree.find( "./input/samplingrate") # load the latest input self.input_Samplingrate.insert(int(self.save_samplingrate.text), self.save_samplingrate.text) curr_row += 1 label = tk.Label(xml_groupbox, text="Outcome (number)") label.grid(row=curr_row, column=1, sticky=tk.W) self.input_outcome = tk.Entry(xml_groupbox) self.input_outcome.grid(row=curr_row, column=2, sticky=tk.W) self.save_outcome = self.save_tree.find( "./input/outcome") # load the latest input self.input_outcome.insert(int(self.save_outcome.text), self.save_outcome.text) curr_row += 1 label = tk.Label(xml_groupbox, text="Pattern(number)") label.grid(row=curr_row, column=1, sticky=tk.W) self.input_Pattern = tk.Entry(xml_groupbox) self.input_Pattern.grid(row=curr_row, column=2, sticky=tk.W) self.save_pattern = self.save_tree.find( "./input/pattern") # load the latest input self.input_Pattern.insert(int(self.save_pattern.text), self.save_pattern.text) ####################### OUTPUT ############################# output_groupbox = tk.LabelFrame(main_frame, text="Analog Output") output_groupbox.pack(side=tk.RIGHT, anchor=tk.NW) channel_vcmd = self.register(self.validate_channel_entry) float_vcmd = self.register(self.validate_float_entry) curr_row = 0 if self.ao_props.num_chans > 1: channel_vcmd = self.register(self.validate_channel_entry) channel_entry_label = tk.Label(output_groupbox) channel_entry_label["text"] = "Channel Number:" channel_entry_label.grid(row=curr_row, column=0, sticky=tk.W) self.channel_entry = tk.Spinbox( output_groupbox, from_=0, to=max(self.ao_props.num_chans - 1, 0), validate='key', validatecommand=(channel_vcmd, '%P')) self.channel_entry.grid(row=curr_row, column=1, sticky=tk.W) self.channel_entry.insert(1, "1") self.channel_entry["state"] = tk.DISABLED curr_row += 1 units_text = self.ao_props.get_units_string( self.ao_props.available_ranges[0]) # value_label_text = "Value (" + units_text + "):" value_label_text = "Arena Speed:" data_value_label = tk.Label(output_groupbox) data_value_label["text"] = value_label_text data_value_label.grid(row=curr_row, column=0, sticky=tk.W) # # self.data_value_entry = tk.Entry( # output_groupbox, validate='key', validatecommand=(float_vcmd, '%P')) # self.data_value_entry.grid(row=curr_row, column=1, sticky=tk.W) # self.data_value_entry.insert(2, "2") self.arena_speed_out = tk.StringVar(output_groupbox) self.arena_speed_out.set("slow") self.arena_speed_out_options = tk.OptionMenu( output_groupbox, self.arena_speed_out, "very slow", "slow", "medium") self.arena_speed_out_options.grid(row=curr_row, column=1, sticky=tk.W) update_button = tk.Button(output_groupbox) update_button["text"] = "Update" update_button["command"] = self.update_arena_output update_button.grid(row=curr_row, column=2, padx=3, pady=3) button_frame = tk.Frame(self) button_frame.pack(fill=tk.X, side=tk.RIGHT, anchor=tk.SE) self.quit_button = tk.Button(button_frame) self.quit_button["text"] = "Quit" self.quit_button["command"] = self.exit self.quit_button.grid(row=0, column=2, padx=3, pady=3) self.restart_button = tk.Button(button_frame) self.restart_button["text"] = "Restart" self.restart_button["command"] = self.restart_program self.restart_button.grid(row=0, column=1, padx=3, pady=3) else: self.create_unsupported_widgets(self.board_num)
def run_example(): board_num = 0 if use_device_detection: ul.ignore_instacal() if not util.config_first_detected_device(board_num): print("Could not find device.") return ao_props = AnalogOutputProps(board_num) if ao_props.num_chans < 1: util.print_unsupported_example(board_num) return low_chan = 0 high_chan = min(3, ao_props.num_chans - 1) num_chans = high_chan - low_chan + 1 rate = 100 points_per_channel = 1000 total_count = points_per_channel * num_chans ao_range = ao_props.available_ranges[0] # Allocate a buffer for the scan memhandle = ul.win_buf_alloc(total_count) # Convert the memhandle to a ctypes array # Note: the ctypes array will no longer be valid after win_buf_free # is called. # A copy of the buffer can be created using win_buf_to_array # before the memory is freed. The copy can be used at any time. ctypes_array = util.memhandle_as_ctypes_array(memhandle) # Check if the buffer was successfully allocated if not memhandle: print("Failed to allocate memory.") return frequencies = add_example_data(board_num, ctypes_array, ao_range, num_chans, rate, points_per_channel) for ch_num in range(low_chan, high_chan + 1): print("Channel " + str(ch_num) + " Output Signal Frequency: " + str(frequencies[ch_num - low_chan])) try: # Start the scan ul.a_out_scan(board_num, low_chan, high_chan, total_count, rate, ao_range, memhandle, ScanOptions.BACKGROUND) # Wait for the scan to complete print("Waiting for output scan to complete...", end="") status = Status.RUNNING while status != Status.IDLE: print(".", end="") # Slow down the status check so as not to flood the CPU time.sleep(0.5) status, _, _ = ul.get_status(board_num, FunctionType.AOFUNCTION) print("") print("Scan completed successfully.") except ULError as e: util.print_ul_error(e) finally: # Free the buffer in a finally block to prevent errors from causing # a memory leak. ul.win_buf_free(memhandle) if use_device_detection: ul.release_daq_device(board_num)
class ULAO01(UIExample): def __init__(self, master=None): super(ULAO01, self).__init__(master) self.board_num = 0 self.ao_props = AnalogOutputProps(self.board_num) self.create_widgets() def update_value(self): channel = self.get_channel_num() ao_range = self.ao_props.available_ranges[0] data_value = self.get_data_value() raw_value = ul.from_eng_units(self.board_num, ao_range, data_value) try: ul.a_out(self.board_num, channel, ao_range, raw_value) except ULError as e: self.show_ul_error(e) def get_data_value(self): try: return float(self.data_value_entry.get()) except ValueError: return 0 def get_channel_num(self): if self.ao_props.num_chans == 1: return 0 try: return int(self.channel_entry.get()) except ValueError: return 0 def validate_channel_entry(self, p): if p == '': return True try: value = int(p) if (value < 0 or value > self.ao_props.num_chans - 1): return False except ValueError: return False return True def create_widgets(self): '''Create the tkinter UI''' if self.ao_props.num_chans > 0: main_frame = tk.Frame(self) main_frame.pack(fill=tk.X, anchor=tk.NW) channel_vcmd = self.register(self.validate_channel_entry) float_vcmd = self.register(self.validate_float_entry) curr_row = 0 if self.ao_props.num_chans > 1: channel_vcmd = self.register(self.validate_channel_entry) channel_entry_label = tk.Label(main_frame) channel_entry_label["text"] = "Channel Number:" channel_entry_label.grid(row=curr_row, column=0, sticky=tk.W) self.channel_entry = tk.Spinbox( main_frame, from_=0, to=max(self.ao_props.num_chans - 1, 0), validate='key', validatecommand=(channel_vcmd, '%P')) self.channel_entry.grid(row=curr_row, column=1, sticky=tk.W) curr_row += 1 units_text = self.ao_props.get_units_string( self.ao_props.available_ranges[0]) value_label_text = "Value (" + units_text + "):" data_value_label = tk.Label(main_frame) data_value_label["text"] = value_label_text data_value_label.grid(row=curr_row, column=0, sticky=tk.W) self.data_value_entry = tk.Entry(main_frame, validate='key', validatecommand=(float_vcmd, '%P')) self.data_value_entry.grid(row=curr_row, column=1, sticky=tk.W) self.data_value_entry.insert(0, "0") update_button = tk.Button(main_frame) update_button["text"] = "Update" update_button["command"] = self.update_value update_button.grid(row=curr_row, column=2, padx=3, pady=3) button_frame = tk.Frame(self) button_frame.pack(fill=tk.X, side=tk.RIGHT, anchor=tk.SE) quit_button = tk.Button(button_frame) quit_button["text"] = "Quit" quit_button["command"] = self.master.destroy quit_button.grid(row=0, column=0, padx=3, pady=3) else: self.create_unsupported_widgets(self.board_num)