Beispiel #1
0
class IniGenGui(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent)
        self.parent = parent
        self.initUIGlobals()

    def initUIGlobals(self):

        self.parent.title("Ini Generator")

        Style().configure("TButton", padding=(0, 0, 0, 0), font='serif 10')

        f1 = Frame(self)
        f1.grid(row=0, column=0, padx=10, sticky=N + S + E + W)

        f11 = LabelFrame(f1, text="Algorithms to Run")
        f11.grid(row=0, column=0)
        row = 0

        self.check_algs_value_list = []
        self.check_algs_map = {}
        for alg in algorithms:
            if alg == 'clean':
                continue
            check_alg_value = IntVar()
            check_alg = Checkbutton(f11,
                                    text=alg,
                                    variable=check_alg_value,
                                    justify=LEFT,
                                    width=25)
            check_alg.grid(row=row, column=0, sticky=W + E)
            self.check_algs_value_list.append(check_alg_value)
            self.check_algs_map[alg] = check_alg_value
            row += 1

        f111 = Frame(f11)
        f111.grid(row=row, column=0)

        button_checkall = Button(f111, text="All", command=self.checkall)
        button_checkall.grid(row=0, column=0, sticky=W + E)
        button_uncheckall = Button(f111, text="None", command=self.uncheckall)
        button_uncheckall.grid(row=0, column=1, sticky=W + E)

        row = 0

        f12 = Frame(f1)
        f12.grid(row=1, column=0, pady=20, sticky=S + W + E)

        f121 = LabelFrame(f12, text='Location of uPMU')
        f121.grid(row=0, column=0)

        self.radio_loc_string = StringVar()
        locations.append('Other Location')
        for loc in locations:
            radio_loc = Radiobutton(f121,
                                    text=loc,
                                    variable=self.radio_loc_string,
                                    value=loc,
                                    command=self.set_loc,
                                    justify=LEFT,
                                    width=25)
            radio_loc.grid(row=row, column=0, sticky=W + E)
            row += 1

        self.entry_otherloc = Entry(f121)

        f2 = Frame(self)
        f2.grid(row=0, column=1, padx=10, sticky=N + S + E + W)

        f21 = LabelFrame(f2, text='Name of uPMU (raw)')
        f21.grid(row=0)
        row = 0

        f211 = Frame(f21)
        f211.grid(row=row)
        row += 1

        self.entry_namesearch = Entry(f211)
        self.entry_namesearch.grid(row=0, column=0, sticky=E + W)

        button_namesearch = Button(f211,
                                   text="Search",
                                   command=self.namesearch)
        button_namesearch.grid(row=0, column=1, sticky=W + E)

        self.lstbx_namelist = Listbox(f21)
        self.lstbx_namelist.bind("<Double-Button-1>", self.namelist_select)
        self.lstbx_namelist.grid(row=row, sticky=W + E)
        row += 1

        f212 = Frame(f21)
        f212.grid(row=row)
        row += 1

        label_nameselected = Label(f212, text="Selected:")
        label_nameselected.grid(row=0, column=0)

        self.entry_nameselected = Entry(f212, state=DISABLED)
        self.entry_nameselected.grid(row=0, column=1, sticky=W + E)

        f22 = LabelFrame(f2, text="Name of uPMU (abbr)")
        f22.grid(row=1, sticky=W + E, pady=10)
        self.entry_name = Entry(f22, width=30)
        self.entry_name.grid(row=0, column=0, sticky=E + W)

        f23 = LabelFrame(f2, text="Name of Reference uPMU (clean)")
        f23.grid(row=2, pady=10)
        row = 0

        f231 = Frame(f23)
        f231.grid(row=row)
        row += 1

        self.entry_refnamesearch = Entry(f231)
        self.entry_refnamesearch.grid(row=0, column=0, sticky=E + W)

        button_refnamesearch = Button(f231,
                                      text="Search",
                                      command=self.refnamesearch)
        button_refnamesearch.grid(row=0, column=1, sticky=W + E)

        self.lstbx_refnamelist = Listbox(f23)
        self.lstbx_refnamelist.bind("<Double-Button-1>",
                                    self.refnamelist_select)
        self.lstbx_refnamelist.grid(row=row, sticky=W + E)
        row += 1

        f232 = Frame(f23)
        f232.grid(row=row)
        row += 1

        label_refnameselected = Label(f232, text="Selected:")
        label_refnameselected.grid(row=0, column=0)

        self.entry_refnameselected = Entry(f232, state=DISABLED)
        self.entry_refnameselected.grid(row=0, column=1, sticky=W + E)

        button_gen = Button(self,
                            text="Generate Files",
                            command=self.generate_files)
        button_gen.grid(row=1, column=0, columnspan=2, sticky=W + E)

        self.pack()

    def generate_files(self):
        algs = []
        for alg in self.check_algs_map:
            if self.check_algs_map[alg].get() == 1:
                algs.append(alg)

        if self.radio_loc_string.get() == "Other Location":
            location = self.entry_otherloc.get()
        else:
            location = self.radio_loc_string.get()

        name_raw = self.entry_nameselected.get()
        name = self.entry_name.get()
        ref_name = self.entry_refnameselected.get()

        uuid_map = self.get_uuid_map(name_raw)
        reference_uuid_map = self.get_ref_uuid_map(ref_name)

        IniGenAutomation(location, name_raw, name, uuid_map, ref_name,
                         reference_uuid_map, algs)

    def namesearch(self):
        searchterm = self.entry_namesearch.get()
        if searchterm.contains("/"):
            loc = searchterm.split('/')
            searchphrase = '/upmu/%{0}%/%{1}%/%'.format(loc[0], loc[1])
        else:
            searchphrase = '/upmu/%{0}%/%'.format(searchterm)
        search_results = self.search(searchterm, searchphrase)
        self.lstbx_namelist.delete(0, END)
        if len(search_results) == 0:
            tkMessageBox.showwarning(
                'Search Error',
                'No matches from search for \'{0}\''.format(searchterm))
        else:
            for result in search_results:
                self.lstbx_namelist.insert(END, result)

    def refnamesearch(self):
        searchterm = self.entry_refnamesearch.get()
        searchphrase = '/Clean/%{0}%/%'.format(searchterm)
        search_results = self.search(searchterm, searchphrase)
        self.lstbx_refnamelist.delete(0, END)
        if len(search_results) == 0:
            tkMessageBox.showwarning(
                'Search Error',
                'No matches from search for \'{0}\''.format(searchterm))
        else:
            for result in search_results:
                self.lstbx_refnamelist.insert(END, result)

    def search(self, searchterm, searchphrase):
        connection = _mysql.connect(host="128.32.37.231",
                                    port=3306,
                                    user="******",
                                    passwd="moresecuredataftw",
                                    db='upmu')
        connection.query(
            "SELECT * FROM uuidpathmap WHERE path LIKE '{0}'".format(
                searchphrase))
        results = connection.store_result()
        queried_data = {}
        result = results.fetch_row()
        while result != tuple():
            queried_data[result[0][0]] = result[0][1]
            result = results.fetch_row()
        search_results = set()
        for path in queried_data:
            dirs = path.split('/')
            if searchterm in dirs[2]:
                search_results.add(dirs[2])
        return search_results

    def set_loc(self):
        if self.radio_loc_string.get() == "Other Location":
            self.entry_otherloc.grid(sticky=W + E)
        else:
            self.entry_otherloc.grid_forget()

    def checkall(self):
        for check in self.check_algs_value_list:
            check.set(1)

    def uncheckall(self):
        for check in self.check_algs_value_list:
            check.set(0)

    def namelist_select(self, event):
        selected_index = self.lstbx_namelist.curselection()
        selected = self.lstbx_namelist.get(selected_index)
        self.entry_nameselected.configure(state=NORMAL)
        self.entry_nameselected.delete(0, END)
        self.entry_nameselected.insert(0, selected)
        self.entry_nameselected.configure(state=DISABLED)

    def refnamelist_select(self, event):
        selected_index = self.lstbx_refnamelist.curselection()
        selected = self.lstbx_refnamelist.get(selected_index)
        self.entry_refnameselected.configure(state=NORMAL)
        self.entry_refnameselected.delete(0, END)
        self.entry_refnameselected.insert(0, selected)
        self.entry_refnameselected.configure(state=DISABLED)

    def get_uuid_map(self, name):
        uuid_map = {}
        connection = _mysql.connect(host="128.32.37.231",
                                    port=3306,
                                    user="******",
                                    passwd="moresecuredataftw",
                                    db='upmu')
        connection.query(
            "SELECT * FROM uuidpathmap WHERE path LIKE '/upmu/{0}/%'".format(
                name))
        results = connection.store_result()
        result = results.fetch_row()
        while result != tuple():
            path = result[0][0].split('/')
            uuid_map[path[-1]] = result[0][1]
            result = results.fetch_row()
        return uuid_map

    def get_ref_uuid_map(self, name):
        uuid_map = {}
        connection = _mysql.connect(host="128.32.37.231",
                                    port=3306,
                                    user="******",
                                    passwd="moresecuredataftw",
                                    db='upmu')
        connection.query(
            "SELECT * FROM uuidpathmap WHERE path LIKE '/Clean/{0}/%'".format(
                name))
        results = connection.store_result()
        result = results.fetch_row()
        while result != tuple():
            path = result[0][0].split('/')
            uuid_map[path[-2]] = result[0][1]
            result = results.fetch_row()
        return uuid_map
Beispiel #2
0
class IniGenGui(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent)
        self.parent = parent
        self.inigen = IniGen()
        self.initUIGlobals()

    def initUIGlobals(self):
        """
      This is the first part of the window to be rendered. After these have been
       set by the user and 'Emit Globals' has been clicked, the given algorithm
       can then specify how to generate the second part of the window. All fields
       are disabled for user input after globals have been emitted.

      Information in Global Parameters:
        Algorithm
          - name of the algorithm to use
        File Name
          - name of the output file to be generated
        Min Time
          - Minimum Time for distillers to run
        Max Time
          - Maximum Time for distillers to run
        Set Enabled:
          - checkbox to specify if the distiller should be enabled True or False
    """
        self.parent.title("Ini Generator")

        Style().configure("TButton", padding=(0, 5, 0, 5), font='serif 10')

        # initialize row counter. This is incremented after each element added to grid
        row = 0
        # initialize column counter. This is incremented after a column has been filled
        self.column = 0

        # Globals: entries for info common to all runs
        label_globals = Label(self, text="Globals")
        label_globals.grid(row=row, column=self.column)
        row += 1

        label_alg = Label(self, text="Algorithm")
        label_alg.grid(row=row, column=self.column, sticky=E + W)
        row += 1
        self.cbox_alg = Combobox(self,
                                 values=algorithms.keys(),
                                 state='readonly')
        self.cbox_alg.current(0)
        self.cbox_alg.grid(row=row, column=self.column, sticky=E + W + S + N)
        row += 1

        label_filename = Label(self, text="Output File Name")
        label_filename.grid(row=row, column=self.column, sticky=E + W)
        row += 1
        self.entry_filename = Entry(self)
        self.entry_filename.grid(row=row, column=self.column, sticky=W + E)
        row += 1

        label_mintime = Label(self, text="Min Time")
        label_mintime.grid(row=row, column=self.column, sticky=E + W)
        row += 1
        self.entry_mintime = Entry(self)
        self.entry_mintime.grid(row=row, column=self.column, sticky=W + E)
        row += 1

        label_maxtime = Label(self, text="Max Time")
        label_maxtime.grid(row=row, column=self.column, sticky=W + E)
        row += 1
        self.entry_maxtime = Entry(self)
        self.entry_maxtime.grid(row=row, column=self.column, sticky=W + E)
        row += 1

        self.enabled = IntVar()
        self.check_enabled = Checkbutton(self,
                                         text="set enabled",
                                         variable=self.enabled)
        self.check_enabled.grid(row=row, column=self.column, sticky=W + E)
        row += 1

        # Control: buttons used to emmiting text and generating file
        self.button_emit_globals = Button(self,
                                          text="Emit Globals",
                                          command=self.emit_globals)
        self.button_emit_globals.grid(row=row,
                                      column=self.column,
                                      sticky=W + E)
        row += 1

        button_addrun = Button(self, text="Add Run", command=self.emit_run)
        button_addrun.grid(row=row, column=self.column, sticky=W + E)
        row += 1

        button_generate = Button(self,
                                 text="Generate File",
                                 command=self.generate_file)
        button_generate.grid(row=row, column=self.column, sticky=W + E)
        row += 1

        self.column += 1

        self.pack()

    def initUIRuns(self):
        """
      Second part of gui to be rendered. This contains all the fields needed to emit
       a single run within a distiller file. Multiple runs can be added by clicking
       'Add Run' multiple times.

      Information in Run Parameters:
        Run Name
          - header name for run
        Dependencies
          - description and uuid fields for each dependency in the algorithm
        Params
          - parameter fields for each parameter in the algorithm
    """

        self.entry_run_name = None
        self.entries_dep_description = []
        self.entries_dep_uuid = []
        self.entries_param = []

        row = 0

        label_runs = Label(self, text="Runs")
        label_runs.grid(row=row, column=self.column)
        row += 1

        label_run_name = Label(self, text="Run Name")
        label_run_name.grid(row=row, column=self.column, sticky=W + E)
        row += 1

        self.entry_run_name = Entry(self)
        self.entry_run_name.grid(row=row, column=self.column, sticky=W + E)
        row += 1

        algorithm = self.cbox_alg.get()
        settings = algorithms[algorithm]

        for dep in settings['deps']:

            if row >= 21:
                self.column += 1
                row = 1

            label_dep_description = Label(self,
                                          text="{0} (description)".format(dep))
            label_dep_description.grid(row=row,
                                       column=self.column,
                                       sticky=W + E)
            row += 1

            entry_dep_description = Entry(self)
            entry_dep_description.grid(row=row,
                                       column=self.column,
                                       sticky=W + E)
            row += 1

            label_dep_uuid = Label(self, text="{0} (uuid)".format(dep))
            label_dep_uuid.grid(row=row, column=self.column, sticky=W + E)
            row += 1

            entry_dep_uuid = Entry(self)
            entry_dep_uuid.grid(row=row, column=self.column, sticky=W + E)
            row += 1

            self.entries_dep_description.append(entry_dep_description)
            self.entries_dep_uuid.append(entry_dep_uuid)

        for param in settings['params']:

            if row >= 21:
                self.column += 1
                row = 1

            label_param = Label(self, text=param)
            label_param.grid(row=row, column=self.column, sticky=W + E)
            row += 1

            entry_param = Entry(self)
            entry_param.grid(row=row, column=self.column, sticky=W + E)
            row += 1

            self.entries_param.append(entry_param)

        row = 0
        self.column += 1

        self.text_file = Text(self)
        self.text_file.grid(row=row,
                            column=self.column,
                            rowspan=31,
                            sticky=W + E + N + S,
                            padx=5,
                            pady=5)
        self.column += 1
        scrollbar = Scrollbar(self, command=self.text_file.yview)
        self.text_file.config(yscrollcommand=scrollbar.set)
        scrollbar.grid(row=row, column=self.column, rowspan=31, sticky=N + S)

        self.pack()

    def emit_globals(self):
        self.algorithm = algorithms[self.cbox_alg.get()]
        path = self.algorithm['path']
        if self.enabled.get():
            enabled = 'True'
        else:
            enabled = 'False'

        lines = self.inigen.emit_global(path, enabled)

        self.mintime = self.entry_mintime.get()
        self.maxtime = self.entry_maxtime.get()

        self.cbox_alg.configure(state='disabled')
        self.entry_filename.configure(state='disabled')
        self.entry_mintime.configure(state='disabled')
        self.entry_maxtime.configure(state='disabled')
        self.check_enabled.configure(state='disabled')
        self.button_emit_globals.configure(state='disabled')

        self.initUIRuns()
        self.update_text(lines)

    def emit_run(self):
        label = self.entry_run_name.get()
        chunking = 'parallel'  #hardcoded for now
        mintime = self.mintime
        maxtime = self.maxtime
        lines = self.inigen.emit_run_header(label, chunking, mintime, maxtime)
        self.update_text(lines)

        deps = []
        for i in range(len(self.entries_dep_description)):
            deps.append([
                self.entries_dep_description[i].get(),
                self.algorithm['deps'][i], self.entries_dep_uuid[i].get()
            ])
        params = []
        for i in range(len(self.entries_param)):
            params.append(
                [self.algorithm['params'][i], self.entries_param[i].get()])
        outputs = self.algorithm['outputs']
        lines = self.inigen.emit_run_body(deps, params, outputs)
        self.update_text(lines)

    def generate_file(self):
        self.inigen.generate_file(self.entry_filename.get())
        self.quit()

    def update_text(self, lines):
        self.text_file.configure(state='normal')
        string = "\n".join(lines)
        self.text_file.insert(END, string)
        self.text_file.configure(state='disabled')
Beispiel #3
0
class MainForm(Frame):
    """
    If method is handling some GUI shit, its written in camelCase style
    """
    def __init__(self, parent, caller_instance):
        Frame.__init__(self, parent)
        self.caller_instance = caller_instance
        self.running_on = "%s:%s" % (get_local_addr(),
                                     getattr(self.caller_instance, 'port',
                                             None) or "8888")
        self.parent = parent
        caller_instance.messangers.append(self)
        self.initUI()

    def initUI(self):
        self.__centerWindow()
        self.parent.title("epyks %s" % self.running_on)
        #
        # Addr textbox
        #
        addr_validate = (self.parent.register(self.addrValidation), '%S', '%d')
        self.EntryAddress = Entry(self,
                                  validate='key',
                                  validatecommand=addr_validate,
                                  width=17)
        self.EntryAddress.grid(row=0,
                               column=0,
                               padx=10,
                               pady=5,
                               columnspan=2,
                               sticky=W)
        self.EntryAddress.delete(0, END)
        self.EntryAddress.insert(0, "192.168.0.102:8889")
        #
        # Call button
        #
        self.ButtonCall = Button(self,
                                 text="Call",
                                 command=self.onButtonCallClick)
        self.ButtonCall.grid(row=0, column=1, pady=5)
        #
        #   Callmode status canvas
        #
        self.CanvasCallmode = Canvas(self,
                                     width=20,
                                     height=20,
                                     bg="light grey")
        self.CanvasCallmode.create_oval(1,
                                        1,
                                        20,
                                        20,
                                        fill="red",
                                        outline="light grey")
        self.CanvasCallmode.grid(row=1,
                                 column=0,
                                 pady=0,
                                 padx=10,
                                 sticky=W,
                                 columnspan=2)
        #
        #   Callmode status label
        #
        self.LabelCallmode = Label(self, text="Not connected")
        self.LabelCallmode.grid(row=1, column=0, padx=35)
        #
        #   End call button
        #
        self.ButtonEndCall = Button(self,
                                    text="End call",
                                    command=self.onButtonEndCallClick)
        self.ButtonEndCall.grid(row=1, column=1)

        #
        #   Message listbox
        #
        self.MessagesListBox = Listbox(self)
        self.MessagesListBox.grid(row=2,
                                  column=0,
                                  columnspan=2,
                                  padx=2,
                                  pady=2,
                                  sticky="EW")
        #
        # Message entry
        #
        self.EntryMessage = Entry(self)
        self.EntryMessage.grid(row=3, column=0, padx=2)
        #
        # Send message
        #
        self.ButtonSendMessage = Button(self,
                                        text="Send",
                                        command=self.onButtonSendMessageClick)
        self.ButtonSendMessage.grid(row=3, column=1)

        # Testing

        # Pack all
        self.pack(fill=BOTH, expand=1)

    def onGetAnswerMessageBox(self, interlocutor):
        return tkMessageBox.askyesno(
            title="Incoming call",
            message="A call from {}, wanna answer?".format(interlocutor))

    def addrValidation(self, string, action):
        print string
        if action != 1:
            # 0 - delete, 1 - insert, -1 - focus in/out
            return True
        print "addrValidation: %s" % string
        if len(string) > 1:
            return full_ipv4_check(fulladdr=string)
        return string in ACCEPTABLE_CHARS

    def onTextBoxChange(self, *args, **kwargs):
        print 'lol ' + str(args) + str(kwargs)

    def onButtonCallClick(self):
        address = (self.EntryAddress.get())
        if not full_ipv4_check(fulladdr=address):
            tkMessageBox.showerror(message="Incorrect address")
        ip, port = address.split(':')
        self.caller_instance.call((ip, int(port)))

    def onButtonSendMessageClick(self):
        message = self.EntryMessage.get()
        self.MessagesListBox.insert(
            END, "{author}> {message}".format(author="self", message=message))
        ip, port = self.EntryAddress.get().split(':')
        self.caller_instance.send(message=message, address=(ip, int(port)))

    def onButtonEndCallClick(self):
        self.caller_instance.hang_up()

    def onMessageRecieved(self, author, message):
        """
        :param author: Address of author, tuple (ip, port)
        :param message: Content
        """
        author = ''.join([author[0], ':', str(author[1])])
        self.MessagesListBox.insert(
            END, "{author}> {message}".format(author=author, message=message))

    def checkStatus(self):
        status = self.caller_instance.status
        if status.startswith('On'):
            self.CanvasCallmode.create_oval(1,
                                            1,
                                            20,
                                            20,
                                            fill="green",
                                            outline="light grey")
            self.EntryAddress.delete(0, END)
            self.EntryAddress.insert(
                0, "{}:{}".format(self.caller_instance.interlocutor[0],
                                  self.caller_instance.interlocutor[1]))
            self.EntryAddress.configure(state='readonly')

        elif status.startswith('Not'):
            self.CanvasCallmode.create_oval(1,
                                            1,
                                            20,
                                            20,
                                            fill="red",
                                            outline="light grey")
            self.EntryAddress.configure(state='')
        else:
            self.CanvasCallmode.create_oval(1,
                                            1,
                                            20,
                                            20,
                                            fill="yellow",
                                            outline="light grey")
            self.EntryAddress.configure(state='readonly')
        self.LabelCallmode['text'] = status
        self.parent.after(ms=100, func=self.checkStatus)

    def __centerWindow(self):
        w = 260
        h = 270
        sw = self.parent.winfo_screenwidth()
        sh = self.parent.winfo_screenheight()
        x = (sw - w) / 2
        y = (sh - h) / 2
        self.parent.geometry('%dx%d+%d+%d' % (w, h, x, y))
Beispiel #4
0
class AvionicsLogger(KRCCModule):
    def __init__(self, root):
        super().__init__()
        self.root = root
        self.exception = None

        self.list_string = StringVar()
        self.listbox = Listbox(root,
                               listvariable=self.list_string,
                               font='TkFixedFont',
                               width=30)

        self.write_cache = ''
        self.logfile = None
        self.enable_logging = BooleanVar()
        self.enable_logging_checkbox = Checkbutton(
            root,
            var=self.enable_logging,
            text='Enable logging',
            command=self.enable_logging_changed)

        self.logfile_label = Label(root, text='Logfile name:')
        self.logfile_name = StringVar()
        self.logfile_name_entry = Entry(root, textvar=self.logfile_name)

        self.load()

    def write(self, string):
        if self.enable_logging.get() and self.logfile is None:
            if self.logfile_name.get() == '':
                self.logfile_name.set('logs/{}.log'.format(time.time()))
            self.logfile = io.open(self.logfile_name.get(), 'a')
            self.logfile.write(self.write_cache)
            self.write_cache = ''
        self.logfile.write(string)

    def cache(self, string):
        self.write_cache += string

    def enable_logging_changed(self):
        if not self.enable_logging.get():
            self.logfile_name_entry.configure(state=NORMAL)
            if self.logfile is not None:
                self.logfile.close()
                self.logfile = None
                self.logfile_name.set('')
        else:
            self.logfile_name_entry.configure(state=DISABLED)

    def establish_connection_and_run(self):
        error = None
        dots = 0
        connection = None
        while not self.terminate:
            try:
                if connection is None:
                    connection = krpc.connect(name=self.name)
                self.run_with_connection(connection)
                error = None
                dots = 0
            except Exception as e:
                if error != e.args[0]:
                    error = e.args[0]
                    print('\n')
                    print(traceback.format_exc())
                    sys.stdout.write('Retrying')
                if dots > 80:
                    dots = 0
                    sys.stdout.write('\n')
                sys.stdout.write('.')
                dots += 1
                sys.stdout.flush()
                time.sleep(1)
        if connection is not None:
            connection.close()

    def run_with_connection(self, connection):
        logging.debug('KRPC connection established')
        vessel = connection.space_center.active_vessel
        ref = vessel.orbit.body.reference_frame
        flight = connection.add_stream(vessel.flight, ref)
        floats = [
            'mean_altitude',
            'atmosphere_density',
            'ballistic_coefficient',
            'drag_coefficient',
        ]
        vectors = [
            'velocity',
        ]
        colon_pos_float = max([len(v) for v in floats])
        colon_pos_vec = max([len(v) + 3 for v in vectors])
        self.listbox.configure(width=max(colon_pos_float, colon_pos_vec) + 11)

        # Write the log file header.
        self.cache('time\t' + '\t'.join(floats) + '\t')
        s = '{}\t' + '\t'.join('{{}}[{}]'.format(x) for x in [0, 1, 2])
        self.cache('\t'.join(
            s.format(*(v for _ in [0, 1, 2, 3])) for v in vectors))
        self.cache('\n')
        log_sample_interval = 0.01
        next_log_sample = time.time()
        while not self.terminate:
            values = [time.time()]
            strings = []
            for name in floats:
                value = flight().__getattribute__(name)
                values.append(value)
                padding = colon_pos_float - len(name) + 9
                format_string = '{{}}: {{:>{}.3f}}'.format(padding)
                strings.append(format_string.format(name, value))
            for name in vectors:
                value = flight().__getattribute__(name)
                magnitude = value[0]
                padding = colon_pos_float - len(name) + 9
                format_string = '{{}}: {{:>{}.3f}}'.format(padding)
                strings.append(format_string.format(name, magnitude))
                values.append(magnitude)
                padding = colon_pos_vec - len(name) + 2
                format_string = '{{}}[{{}}]: {{:>{}.3f}}'.format(padding)
                for i in [0, 1, 2]:
                    values.append(value[i])
                    strings.append(format_string.format(name, i, value[i]))
            if self.enable_logging.get() and time.time() > next_log_sample:
                self.write('\t'.join(['{}'.format(v) for v in values]) + '\n')
                next_log_sample = time.time() + log_sample_interval
            self.list_string.set(tuple(strings))

    def run(self):
        try:
            self.establish_connection_and_run()
            self.logfile_name_entry.destroy()
            self.logfile_label.destroy()
            self.enable_logging_checkbox.destroy()
            self.listbox.destroy()
        except RuntimeError:
            # Should only happen when KeyboardInterrupt is thrown in the MainThread.
            pass
        if self.logfile is not None:
            self.logfile.close()

    @property
    def name(self):
        return 'Avionics Logger'

    def load(self):
        self.listbox.pack(side=LEFT, fill=BOTH)
        self.logfile_label.pack(side=LEFT, anchor=NW)
        self.logfile_name_entry.pack(side=LEFT, anchor=NE, fill=X, expand=True)
        self.enable_logging_checkbox.pack(side=LEFT, anchor=NW)
class IniGenGui(Frame):

  def __init__(self, parent):
    Frame.__init__(self, parent)
    self.parent = parent
    self.initUIGlobals()

  def initUIGlobals(self):
   
    self.parent.title("Ini Generator")

    Style().configure("TButton", padding=(0, 0, 0, 0), font='serif 10')

    f1 = Frame(self)
    f1.grid(row=0, column=0, padx=10, sticky=N+S+E+W)

    f11 = LabelFrame(f1, text="Algorithms to Run")
    f11.grid(row=0, column=0)
    row = 0

    self.check_algs_value_list = []
    self.check_algs_map = {}
    for alg in algorithms:
      if alg == 'clean':
        continue
      check_alg_value = IntVar()
      check_alg = Checkbutton(f11, text=alg, variable=check_alg_value, justify=LEFT, width=25)
      check_alg.grid(row=row, column=0, sticky=W+E)
      self.check_algs_value_list.append(check_alg_value)
      self.check_algs_map[alg] = check_alg_value
      row += 1

    f111 = Frame(f11)
    f111.grid(row=row, column=0)

    button_checkall = Button(f111, text="All", command=self.checkall)
    button_checkall.grid(row=0, column=0, sticky=W+E)
    button_uncheckall = Button(f111, text="None", command=self.uncheckall)
    button_uncheckall.grid(row=0, column=1, sticky=W+E)

    row = 0

    f12 = Frame(f1)
    f12.grid(row=1, column=0, pady=20, sticky=S+W+E)

    f121 = LabelFrame(f12, text='Location of uPMU')
    f121.grid(row=0, column=0)

    self.radio_loc_string = StringVar()
    locations.append('Other Location')
    for loc in locations:
      radio_loc = Radiobutton(f121, text=loc, variable=self.radio_loc_string, value=loc, command=self.set_loc, justify=LEFT, width=25)
      radio_loc.grid(row=row, column=0, sticky=W+E)
      row += 1

    self.entry_otherloc = Entry(f121)

    f2 = Frame(self)
    f2.grid(row=0, column=1, padx=10, sticky=N+S+E+W)

    f21 = LabelFrame(f2, text='Name of uPMU (raw)')
    f21.grid(row=0)
    row = 0

    f211 = Frame(f21)
    f211.grid(row=row)
    row += 1

    self.entry_namesearch = Entry(f211)
    self.entry_namesearch.grid(row=0, column=0, sticky=E+W)

    button_namesearch = Button(f211, text="Search", command=self.namesearch)
    button_namesearch.grid(row=0, column=1, sticky=W+E)

    self.lstbx_namelist = Listbox(f21)
    self.lstbx_namelist.bind("<Double-Button-1>", self.namelist_select)
    self.lstbx_namelist.grid(row=row, sticky=W+E)
    row += 1

    f212 = Frame(f21)
    f212.grid(row=row)
    row += 1

    label_nameselected = Label(f212, text="Selected:")
    label_nameselected.grid(row=0, column=0)

    self.entry_nameselected = Entry(f212, state=DISABLED)
    self.entry_nameselected.grid(row=0, column=1, sticky=W+E)

    f22 = LabelFrame(f2, text="Name of uPMU (abbr)")
    f22.grid(row=1, sticky=W+E, pady=10)
    self.entry_name = Entry(f22, width=30)
    self.entry_name.grid(row=0, column=0, sticky=E+W)

    f23 = LabelFrame(f2, text="Name of Reference uPMU (clean)")
    f23.grid(row=2, pady=10)
    row = 0

    f231 = Frame(f23)
    f231.grid(row=row)
    row += 1

    self.entry_refnamesearch = Entry(f231)
    self.entry_refnamesearch.grid(row=0, column=0, sticky=E+W)

    button_refnamesearch = Button(f231, text="Search", command=self.refnamesearch)
    button_refnamesearch.grid(row=0, column=1, sticky=W+E)

    self.lstbx_refnamelist = Listbox(f23)
    self.lstbx_refnamelist.bind("<Double-Button-1>", self.refnamelist_select)
    self.lstbx_refnamelist.grid(row=row, sticky=W+E)
    row += 1

    f232 = Frame(f23)
    f232.grid(row=row)
    row += 1

    label_refnameselected = Label(f232, text="Selected:")
    label_refnameselected.grid(row=0, column=0)

    self.entry_refnameselected = Entry(f232, state=DISABLED)
    self.entry_refnameselected.grid(row=0, column=1, sticky=W+E)

    button_gen = Button(self, text="Generate Files", command=self.generate_files)
    button_gen.grid(row=1, column=0, columnspan=2, sticky=W+E)

    self.pack()

  def generate_files(self):
    algs = []
    for alg in self.check_algs_map:
      if self.check_algs_map[alg].get() == 1:
        algs.append(alg)

    if self.radio_loc_string.get() == "Other Location":
      location = self.entry_otherloc.get()
    else:
      location = self.radio_loc_string.get()

    name_raw = self.entry_nameselected.get()
    name = self.entry_name.get()
    ref_name = self.entry_refnameselected.get()

    uuid_map = self.get_uuid_map(name_raw)
    reference_uuid_map = self.get_ref_uuid_map(ref_name)

    IniGenAutomation(location, name_raw, name, uuid_map, ref_name, reference_uuid_map, algs)

  def namesearch(self):
    searchterm = self.entry_namesearch.get()
    searchphrase = '/upmu/%{0}%/%'.format(searchterm)
    search_results = self.search(searchterm, searchphrase)
    self.lstbx_namelist.delete(0, END)
    if len(search_results) == 0:
      tkMessageBox.showwarning('Search Error', 'No matches from search for \'{0}\''.format(searchterm))
    else:
      for result in search_results:
        self.lstbx_namelist.insert(END, result)
        
  def refnamesearch(self):
    searchterm = self.entry_refnamesearch.get()
    searchphrase = '/Clean/%{0}%/%'.format(searchterm)
    search_results = self.search(searchterm, searchphrase, ref=True)
    self.lstbx_refnamelist.delete(0, END)
    if len(search_results) == 0:
      tkMessageBox.showwarning('Search Error', 'No matches from search for \'{0}\''.format(searchterm))
    else:
      for result in search_results:
        self.lstbx_refnamelist.insert(END, result)
  
  def search(self, searchterm, searchphrase, ref=False):
    connection = _mysql.connect(host="128.32.37.231", port=3306, user="******",
                                passwd="moresecuredataftw", db='upmu')
    connection.query("SELECT * FROM uuidpathmap WHERE path LIKE '{0}'".format(searchphrase))
    results = connection.store_result()
    queried_data = {}
    result = results.fetch_row()
    while result != tuple():
      queried_data[result[0][0]] = result[0][1]
      result = results.fetch_row()
    search_results = set()
    for path in queried_data:
      dirs = path.split('/')
      if ref:
        if searchterm in '/'.join(dirs[2:-2]):
          search_results.add('/'.join(dirs[2:-2]))
      else:
        if searchterm in '/'.join(dirs[2:-1]):
          search_results.add('/'.join(dirs[2:-1]))
    return search_results

  def set_loc(self):
    if self.radio_loc_string.get() == "Other Location":
      self.entry_otherloc.grid(sticky=W+E)
    else:
      self.entry_otherloc.grid_forget()

  def checkall(self):
    for check in self.check_algs_value_list:
      check.set(1)
  
  def uncheckall(self):
    for check in self.check_algs_value_list:
      check.set(0)

  def namelist_select(self, event):
    selected_index = self.lstbx_namelist.curselection()
    selected = self.lstbx_namelist.get(selected_index)
    self.entry_nameselected.configure(state=NORMAL)
    self.entry_nameselected.delete(0, END)
    self.entry_nameselected.insert(0, selected)
    self.entry_nameselected.configure(state=DISABLED)

  def refnamelist_select(self, event):
    selected_index = self.lstbx_refnamelist.curselection()
    selected = self.lstbx_refnamelist.get(selected_index)
    self.entry_refnameselected.configure(state=NORMAL)
    self.entry_refnameselected.delete(0, END)
    self.entry_refnameselected.insert(0, selected)
    self.entry_refnameselected.configure(state=DISABLED)

  def get_uuid_map(self, name):
    uuid_map = {}
    connection = _mysql.connect(host="128.32.37.231", port=3306, user="******",
                                passwd="moresecuredataftw", db='upmu')
    connection.query("SELECT * FROM uuidpathmap WHERE path LIKE '/upmu/{0}/%'".format(name))
    results = connection.store_result()
    result = results.fetch_row()
    while result != tuple():
      path = result[0][0].split('/')
      uuid_map[path[-1]] = result[0][1]
      result = results.fetch_row()
    return uuid_map
    
  def get_ref_uuid_map(self, name):
    uuid_map = {}
    connection = _mysql.connect(host="128.32.37.231", port=3306, user="******",
                                passwd="moresecuredataftw", db='upmu')
    connection.query("SELECT * FROM uuidpathmap WHERE path LIKE '/Clean/{0}/%'".format(name))
    results = connection.store_result()
    result = results.fetch_row()
    while result != tuple():
      path = result[0][0].split('/')
      uuid_map[path[-2]] = result[0][1]
      result = results.fetch_row()
    return uuid_map
class IniGenGui(Frame):

  def __init__(self, parent):
    Frame.__init__(self, parent)
    self.parent = parent
    self.inigen = IniGen()
    self.initUIGlobals()


  def initUIGlobals(self):
    """
      This is the first part of the window to be rendered. After these have been
       set by the user and 'Emit Globals' has been clicked, the given algorithm
       can then specify how to generate the second part of the window. All fields
       are disabled for user input after globals have been emitted.

      Information in Global Parameters:
        Algorithm
          - name of the algorithm to use
        File Name
          - name of the output file to be generated
        Min Time
          - Minimum Time for distillers to run
        Max Time
          - Maximum Time for distillers to run
        Set Enabled:
          - checkbox to specify if the distiller should be enabled True or False
    """
    self.parent.title("Ini Generator")

    Style().configure("TButton", padding=(0, 5, 0, 5), font='serif 10')

    # initialize row counter. This is incremented after each element added to grid
    row = 0
    # initialize column counter. This is incremented after a column has been filled
    self.column = 0

    # Globals: entries for info common to all runs
    label_globals = Label(self, text="Globals")
    label_globals.grid(row=row, column=self.column)
    row += 1

    label_alg = Label(self, text="Algorithm")
    label_alg.grid(row=row, column=self.column, sticky=E+W)
    row += 1
    self.cbox_alg = Combobox(self, values=algorithms.keys(), state='readonly')
    self.cbox_alg.current(0)
    self.cbox_alg.grid(row=row, column=self.column, sticky=E+W+S+N)
    row += 1

    label_filename = Label(self, text="Output File Name")
    label_filename.grid(row=row, column=self.column, sticky=E+W)
    row += 1
    self.entry_filename = Entry(self)
    self.entry_filename.grid(row=row, column=self.column, sticky=W+E)
    row += 1

    label_mintime = Label(self, text="Min Time")
    label_mintime.grid(row=row, column=self.column, sticky=E+W)
    row += 1
    self.entry_mintime = Entry(self)
    self.entry_mintime.grid(row=row, column=self.column, sticky=W+E)
    row += 1

    label_maxtime = Label(self, text="Max Time")
    label_maxtime.grid(row=row, column=self.column, sticky=W+E)
    row += 1
    self.entry_maxtime = Entry(self)
    self.entry_maxtime.grid(row=row, column=self.column, sticky=W+E)
    row += 1

    self.enabled = IntVar()
    self.check_enabled = Checkbutton(self, text="set enabled", variable=self.enabled)
    self.check_enabled.grid(row=row, column=self.column, sticky=W+E)
    row += 1

    # Control: buttons used to emmiting text and generating file
    self.button_emit_globals = Button(self, text="Emit Globals", command=self.emit_globals)
    self.button_emit_globals.grid(row=row, column=self.column, sticky=W+E)
    row += 1

    button_addrun = Button(self, text="Add Run", command=self.emit_run)
    button_addrun.grid(row=row, column=self.column, sticky=W+E)
    row += 1

    button_generate = Button(self, text="Generate File", command=self.generate_file)
    button_generate.grid(row=row, column=self.column, sticky=W+E)
    row += 1

    self.column += 1

    self.pack()

  def initUIRuns(self):
    """
      Second part of gui to be rendered. This contains all the fields needed to emit
       a single run within a distiller file. Multiple runs can be added by clicking
       'Add Run' multiple times.

      Information in Run Parameters:
        Run Name
          - header name for run
        Dependencies
          - description and uuid fields for each dependency in the algorithm
        Params
          - parameter fields for each parameter in the algorithm
    """

    self.entry_run_name = None
    self.entries_dep_description = []
    self.entries_dep_uuid = []
    self.entries_param = []

    row = 0

    label_runs = Label(self, text="Runs")
    label_runs.grid(row=row, column=self.column)
    row += 1

    label_run_name = Label(self, text="Run Name")
    label_run_name.grid(row=row, column=self.column, sticky=W+E)
    row += 1

    self.entry_run_name = Entry(self)
    self.entry_run_name.grid(row=row, column=self.column, sticky=W+E)
    row += 1

    algorithm = self.cbox_alg.get()
    settings = algorithms[algorithm]

    for dep in settings['deps']:

      if row >= 21:
        self.column += 1
        row = 1

      label_dep_description = Label(self, text="{0} (description)".format(dep))
      label_dep_description.grid(row=row, column=self.column, sticky=W+E)
      row += 1

      entry_dep_description = Entry(self)
      entry_dep_description.grid(row=row, column=self.column, sticky=W+E)
      row += 1

      label_dep_uuid = Label(self, text="{0} (uuid)".format(dep))
      label_dep_uuid.grid(row=row, column=self.column, sticky=W+E)
      row += 1

      entry_dep_uuid = Entry(self)
      entry_dep_uuid.grid(row=row, column=self.column, sticky=W+E)
      row += 1

      self.entries_dep_description.append(entry_dep_description)
      self.entries_dep_uuid.append(entry_dep_uuid)

    for param in settings['params']:

      if row >= 21:
        self.column += 1
        row = 1

      label_param = Label(self, text=param)
      label_param.grid(row=row, column=self.column, sticky=W+E)
      row += 1

      entry_param = Entry(self)
      entry_param.grid(row=row, column=self.column, sticky=W+E)
      row += 1

      self.entries_param.append(entry_param)

    row = 0
    self.column += 1

    self.text_file = Text(self)
    self.text_file.grid(row=row, column=self.column, rowspan=31, sticky=W+E+N+S, padx=5, pady=5)
    self.column += 1
    scrollbar = Scrollbar(self, command=self.text_file.yview)
    self.text_file.config(yscrollcommand=scrollbar.set)
    scrollbar.grid(row=row, column=self.column, rowspan=31, sticky=N+S)

    self.pack()

  def emit_globals(self):
    self.algorithm = algorithms[self.cbox_alg.get()]
    path = self.algorithm['path']
    if self.enabled.get():
      enabled = 'True'
    else:
      enabled = 'False'

    lines = self.inigen.emit_global(path, enabled)

    self.mintime = self.entry_mintime.get()
    self.maxtime = self.entry_maxtime.get()

    self.cbox_alg.configure(state='disabled')
    self.entry_filename.configure(state='disabled')
    self.entry_mintime.configure(state='disabled')
    self.entry_maxtime.configure(state='disabled')
    self.check_enabled.configure(state='disabled')
    self.button_emit_globals.configure(state='disabled')

    self.initUIRuns()
    self.update_text(lines)

  def emit_run(self):
    label = self.entry_run_name.get()
    chunking = 'parallel' #hardcoded for now
    mintime = self.mintime
    maxtime = self.maxtime
    lines = self.inigen.emit_run_header(label, chunking, mintime, maxtime)
    self.update_text(lines)

    deps = []
    for i in range(len(self.entries_dep_description)):
      deps.append([self.entries_dep_description[i].get(),
                   self.algorithm['deps'][i],
                   self.entries_dep_uuid[i].get()])
    params = []
    for i in range(len(self.entries_param)):
      params.append([self.algorithm['params'][i],
                     self.entries_param[i].get()])
    outputs = self.algorithm['outputs']
    lines = self.inigen.emit_run_body(deps, params, outputs)
    self.update_text(lines)

  def generate_file(self):
    self.inigen.generate_file(self.entry_filename.get())
    self.quit()

  def update_text(self, lines):
    self.text_file.configure(state='normal')
    string = "\n".join(lines)
    self.text_file.insert(END, string)
    self.text_file.configure(state='disabled')