def __init__(self,
                 parent=None,
                 picks=[],
                 editButtons=False,
                 checkCallback=None):
        """
        Parameters
        ----------

        :param parent: the parent window
        :param picks: the list of pairs to show
        :param editButtons: Indicator whether a configuration button should be displayed
        :param checkCallback: Callback for each pair
        """
        Frame.__init__(self, parent)

        self.parent = parent
        self.vars = []
        self.checks = []
        self.buttons = []

        relY = 0
        relX = 0
        enable_functionality = 'active'

        # Iterate over all pairs of check buttons and buttons
        for pick in picks:
            var = IntVar()

            algorithm_show_function = self.get_algorithm_show_function(
                str(pick))

            # Create a check button dynamically
            check_button = Checkbutton(
                self,
                text=pick,
                variable=var,
                state=enable_functionality,
                command=lambda: self.set_button_state(checkCallback))

            check_button.place(relx=relX, rely=relY, height=30, width=150)
            set_widget_to_left(check_button)

            if editButtons:
                # Create a configuration button dynamically
                edit_button = HoverButton(self,
                                          text=pick + " configuration",
                                          state='disabled',
                                          command=algorithm_show_function)

                edit_button.place(relx=relX + 0.35,
                                  rely=relY,
                                  height=30,
                                  width=220)
                edit_button.configure(cursor="hand2")
                self.buttons.append(edit_button)
            self.vars.append(var)
            self.checks.append(check_button)
            relY = relY + 0.1
Example #2
0
class FeatureSelectionWindow(tk.Frame):
    """
    A Class used to enable the user to select features

    Methods
    -------
    reset_widgets()
            Description | Reset check bar values

    next_window()
            Description | Handle a click on next button

    back_window()
            Description | Handle a click on back button

    reinitialize()
            Description | Reinitialize frame values and view

    get_selected_features()
        Description | Get selected features by the user

    get_features_columns_options()
            Description | Get selected data set columns by the user

    validate_next_step()
        Description | Validation before passing to next step

    set_users_selected_features(features_list)
            Description | Set the selected features from the test data set

    select_all_features
            Description | Select/Clear all input features

    select_all_targets
            Description | Select/Clear all target features

    """
    def __init__(self, parent, controller):
        """
        Parameters
        ----------

        :param parent: window
        :param controller: GUI controller
        """

        tk.Frame.__init__(self, parent)

        # Page init
        self.controller = controller
        self.menubar = Menubar(controller)
        # Disables ability to tear menu bar into own window
        self.controller.option_add('*tearOff', 'FALSE')
        system_logo = CROSS_WINDOWS_SETTINGS.get('LOGO')
        photo_location = os.path.join(system_logo)
        global logo_img
        logo_img = tk.PhotoImage(file=photo_location)

        # Page header
        self.logo_png = tk.Button(self)
        self.logo_png.place(relx=0.28, rely=0.029, height=172, width=300)
        set_logo_configuration(self.logo_png, image=logo_img)

        self.instructions = tk.Label(self)
        self.instructions.place(relx=0.015, rely=0.3, height=32, width=635)
        self.instructions.configure(
            text='''Please choose both input and target features:''')
        set_widget_to_left(self.instructions)

        # Page body

        # initialize features columns options
        self.features_columns_options = {}
        self.features_columns_options = self.get_features_columns_options()

        self.csv_features = tk.StringVar()
        self.csv_features.set(self.features_columns_options)

        self.features_instructions = tk.Label(self)
        self.features_instructions.place(relx=0.05,
                                         rely=0.34,
                                         height=22,
                                         width=100)
        self.features_instructions.configure(text='''Input features:''')
        set_widget_to_left(self.features_instructions)

        self.features_listbox = tk.Listbox(
            self,
            font=tkfont.Font(size=9),
            listvariable=self.csv_features,
            selectmode=tk.MULTIPLE,
            exportselection=
            0,  # Fix : ComboBox clears unrelated ListBox selection
            width=120,
            height=180,
            bd=3,
            bg='antique white',
            selectbackground='sandy brown')
        self.features_listbox.place(relx=0.05,
                                    rely=0.42,
                                    height=230,
                                    width=140)

        self.target_instructions = tk.Label(self)
        self.target_instructions.place(relx=0.35,
                                       rely=0.34,
                                       height=22,
                                       width=100)
        self.target_instructions.configure(text='''Target features:''')
        set_widget_to_left(self.target_instructions)

        self.target_features_listbox = tk.Listbox(
            self,
            font=tkfont.Font(size=9),
            listvariable=self.csv_features,
            selectmode=tk.MULTIPLE,
            exportselection=0,
            # Fix : ComboBox clears unrelated ListBox selection
            width=120,
            height=180,
            bd=3,
            bg='antique white',
            selectbackground='sandy brown')
        self.target_features_listbox.place(relx=0.35,
                                           rely=0.42,
                                           height=230,
                                           width=140)

        # Side logo
        feature_selection_logo = CROSS_WINDOWS_SETTINGS.get(
            'FEATURE_SELECTION')
        feature_selection_photo_location = os.path.join(feature_selection_logo)
        global fs_logo_img
        fs_logo_img = tk.PhotoImage(file=feature_selection_photo_location)

        self.features_logo_png = tk.Button(self)
        self.features_logo_png.place(relx=0.6,
                                     rely=0.28,
                                     height=200,
                                     width=200)
        set_logo_configuration(self.features_logo_png, image=fs_logo_img)

        # Page footer
        self.next_button = HoverButton(self, command=self.next_window)
        self.next_button.place(relx=0.813, rely=0.839, height=25, width=81)
        set_button_configuration(self.next_button, text='''Next''')

        self.back_button = HoverButton(self, command=self.back_window)
        self.back_button.place(relx=0.017, rely=0.839, height=25, width=81)
        set_button_configuration(self.back_button, text='''Back''')

        self.copyright = tk.Label(self)
        self.copyright.place(relx=0, rely=0.958, height=25, width=750)
        set_copyright_configuration(self.copyright)

    def reset_widgets(self):
        """
        Reset check bar values
        :return: empty values in the widgets
        """

        self.features_listbox.selection_clear(0, tk.END)
        self.target_features_listbox.selection_clear(0, tk.END)

    def next_window(self):
        """
        Handle a click on next button
        :return: if validations pass move to next window
        """

        if not self.validate_next_step():
            return
        else:
            current_features, target_features = self.get_selected_features()
            self.set_users_selected_features(current_features, target_features)
            self.controller.reinitialize_frame("SimilarityFunctionsWindow")

    def back_window(self):
        """
        Handle back button click
        :return: previous window
        """

        self.controller.show_frame("AlgorithmsWindow")

    def reinitialize(self):
        """
        Reinitialize frame values and view
        :return: new frame view
        """

        self.features_columns_options = {}
        self.features_columns_options = self.get_features_columns_options()

        self.csv_features = tk.StringVar()
        self.csv_features.set(self.features_columns_options)

        self.input_indicator = False
        self.target_indicator = False

        self.select_all_features_button = tk.Button(
            self, command=self.select_all_features)
        self.select_all_features_button.place(relx=0.17,
                                              rely=0.38,
                                              height=18,
                                              width=55)
        set_button_configuration(self.select_all_features_button,
                                 text='''Select all''')
        self.select_all_features_button.configure(bg='sandy brown')

        self.features_listbox = tk.Listbox(
            self,
            font=tkfont.Font(size=9),
            listvariable=self.csv_features,
            selectmode=tk.MULTIPLE,
            exportselection=
            0,  # Fix : ComboBox clears unrelated ListBox selection
            width=120,
            height=180,
            bd=3,
            bg='antique white',
            selectbackground='sandy brown')
        self.features_listbox.place(relx=0.05,
                                    rely=0.42,
                                    height=230,
                                    width=140)

        self.select_all_target_button = tk.Button(
            self, command=self.select_all_target)
        self.select_all_target_button.place(relx=0.47,
                                            rely=0.38,
                                            height=18,
                                            width=55)
        set_button_configuration(self.select_all_target_button,
                                 text='''Select all''')
        self.select_all_target_button.configure(bg='sandy brown')

        self.target_features_listbox = tk.Listbox(
            self,
            listvariable=self.csv_features,
            font=tkfont.Font(size=9),
            selectmode=tk.MULTIPLE,
            exportselection=0,
            # Fix : ComboBox clears unrelated ListBox selection
            width=120,
            height=180,
            bd=3,
            bg='antique white',
            selectbackground='sandy brown')
        self.target_features_listbox.place(relx=0.35,
                                           rely=0.42,
                                           height=230,
                                           width=140)

        title_styling = Font(size=11, weight=BOLD)

        self.previous_choice_label = tk.Label(self)
        self.previous_choice_label.place(relx=0.58,
                                         rely=0.62,
                                         height=25,
                                         width=300)
        self.previous_choice_label.configure(text="Your previous selections:",
                                             font=title_styling,
                                             fg='blue')
        set_widget_to_left(self.previous_choice_label)

        chosen_algorithms = self.controller.get_algorithms()

        y_coordinate = 0.66
        for algorithm in chosen_algorithms:
            window_size = self.controller.get_window_size(algorithm)

            self.algorithm_label = tk.Label(self)
            self.algorithm_label.place(relx=0.58,
                                       rely=y_coordinate,
                                       height=25,
                                       width=300)
            self.algorithm_label.configure(text="{0} window size: {1}".format(
                algorithm, window_size),
                                           font=Font(size=10),
                                           fg='blue')
            set_widget_to_left(self.algorithm_label)

            y_coordinate += 0.04

    def get_selected_features(self):
        """
        Get selected features by the user
        :return: selected features
        """

        features = []
        target_features = []

        selection = self.features_listbox.curselection()
        target_selection = self.target_features_listbox.curselection()

        for i in selection:
            selected = self.features_listbox.get(i)
            features.append(selected)

        for i in target_selection:
            target_selected = self.target_features_listbox.get(i)
            target_features.append(target_selected)

        return features, target_features

    def get_features_columns_options(self):
        """
        Get selected data set columns by the user
        :return: selected columns
        """

        return self.controller.get_features_columns_options()

    def validate_next_step(self):
        """
        Validation before passing to next step
        :return: True in case validation passed, otherwise False
        """

        current_features, target_features = self.get_selected_features()
        if not current_features or not target_features or len(
                current_features) < 2 or len(target_features) < 2:
            win32api.MessageBox(
                0,
                'Please select at least two features for input and two features for output before the next step.',
                'Invalid Feature', 0x00001000)
            return False

        return True

    def set_users_selected_features(self, features_list, target_features_list):
        """
        Set the selected features from the test data set
        :param features_list: the list of selected features for input
        :param target_features_list: the list of selected features for target
        :return: updates state of features selection
        """

        self.controller.set_users_selected_features(features_list,
                                                    target_features_list)

    def select_all_features(self):
        """
        Select/Clear all input features
        :return: selected/cleared listbox
        """

        if self.input_indicator:
            self.features_listbox.selection_clear(0, tk.END)
            self.select_all_features_button.configure(bg='sandy brown',
                                                      text='''Select all''')
        else:
            self.features_listbox.select_set(0, tk.END)
            self.select_all_features_button.configure(bg='firebrick1',
                                                      text='''Clear all''')

        self.input_indicator = not self.input_indicator

    def select_all_target(self):
        """
        Select/Clear all target features
        :return: selected/cleared listbox
        """

        if self.target_indicator:
            self.target_features_listbox.selection_clear(0, tk.END)
            self.select_all_target_button.configure(bg='sandy brown',
                                                    text='''Select all''')
        else:
            self.target_features_listbox.select_set(0, tk.END)
            self.select_all_target_button.configure(bg='firebrick1',
                                                    text='''Clear all''')

        self.target_indicator = not self.target_indicator
Example #3
0
class SimilarityFunctionsWindow(tk.Frame):
    """
    A Class used to enable the user to choose a similarity functions

    Methods
    -------
    reset_widgets()
            Description | Reset check bar values

    set_similarity_score()
            Description | Set selected similarity functions in global input settings

    next_window()
            Description | Handle a click on next button

    back_window()
            Description | Handle a click on back button

    reinitialize()
            Description | Reinitialize frame values and view

    set_saving_model()
            Description | Set indicator whether the user want to save the model or not

    similarity_functions_validation()
            Description | Validations that at least one similarity function was checked

    """
    def __init__(self, parent, controller):
        """
        Parameters
        ----------

        :param parent: window
        :param controller: GUI controller
        """

        tk.Frame.__init__(self, parent)

        # Page init
        self.controller = controller
        self.menubar = Menubar(controller)
        # Disables ability to tear menu bar into own window
        self.controller.option_add('*tearOff', 'FALSE')
        system_logo = CROSS_WINDOWS_SETTINGS.get('LOGO')
        photo_location = os.path.join(system_logo)
        global logo_img
        logo_img = tk.PhotoImage(file=photo_location)

        # Page header
        self.logo_png = tk.Button(self)
        self.logo_png.place(relx=0.28, rely=0.029, height=172, width=300)
        set_logo_configuration(self.logo_png, image=logo_img)

        self.instructions = tk.Label(self)
        self.instructions.place(relx=0.015, rely=0.3, height=32, width=635)
        self.instructions.configure(
            text=
            '''Please choose similarity functions from the following options.'''
        )
        set_widget_to_left(self.instructions)

        # Page body
        self.similarity_functions = Checkbar(
            self,
            load_similarity_list(),
            checkCallback=self.set_similarity_score)
        self.similarity_functions.place(relx=0.1,
                                        rely=0.36,
                                        height=400,
                                        width=700)

        self.save_model_var = tk.IntVar()
        self.save_model_check_button = tk.Checkbutton(
            self,
            text="Save model",
            variable=self.save_model_var,
            command=self.set_saving_model)

        self.note = tk.Label(self)
        self.note.place(relx=0.015, rely=0.7, height=32, width=635)
        self.note.configure(
            text=
            '''Note: Similarity function is used for calculating a score for each record''',
            font=Font(size=9, weight=BOLD))
        set_widget_to_left(self.note)

        # Page footer
        self.next_button = HoverButton(self, command=self.next_window)
        self.next_button.place(relx=0.813, rely=0.839, height=25, width=81)
        set_button_configuration(self.next_button, text='''Run''')

        self.back_button = HoverButton(self, command=self.back_window)
        self.back_button.place(relx=0.017, rely=0.839, height=25, width=81)
        set_button_configuration(self.back_button, text='''Back''')

        self.copyright = tk.Label(self)
        self.copyright.place(relx=0, rely=0.958, height=25, width=750)
        set_copyright_configuration(self.copyright)

    def reset_widgets(self):
        """
        Reset check bar values
        :return: empty values in the widgets
        """

        for check, var in zip(self.similarity_functions.get_checks(),
                              self.similarity_functions.get_vars()):
            var.set(0)
            check['variable'] = var
            check['state'] = 'active'

        # In case the check button was not destroyed - should be in new model flow
        is_new_model_flow = self.controller.get_new_model_running()

        if is_new_model_flow:
            self.save_model_var.set(0)
            self.save_model_check_button['variable'] = self.save_model_var

    def set_similarity_score(self):
        """
        Set selected similarity functions in global input settings
        :return: updated global settings
        """

        similarity_list = set()

        for check, var in zip(self.similarity_functions.get_checks(),
                              self.similarity_functions.get_vars()):
            if var.get():
                similarity_list.add(check.cget("text"))
        self.controller.set_similarity_score(similarity_list)

    def next_window(self):
        """
        Handle a click on next button
        :return: if validations pass move to next window
        """

        if self.similarity_functions_validation():
            self.controller.reinitialize_frame("LoadingWindow")
        else:
            win32api.MessageBox(
                0, 'Please select at least one similarity function',
                'Invalid input', 0x00001000)

    def back_window(self):
        """
        Handle back button click
        :return: previous window
        """

        is_new_model_flow = self.controller.get_new_model_running()

        if is_new_model_flow:
            self.controller.show_frame("FeatureSelectionWindow")
        else:
            self.controller.show_frame("ExistingAlgorithmsWindow")

    def reinitialize(self):
        """
        Reinitialize frame values and view
        :return: new frame view
        """

        if self.controller.get_new_model_running():
            if not self.save_model_var:
                self.save_model_var = tk.IntVar()
            if not self.save_model_check_button:
                self.save_model_check_button = tk.Checkbutton(
                    self,
                    text="Save model",
                    variable=self.save_model_var,
                    command=self.set_saving_model)
            self.save_model_check_button.place(relx=0.65,
                                               rely=0.75,
                                               height=25,
                                               width=100)
        else:
            self.save_model_check_button.place_forget()

    def set_saving_model(self):
        """
        Set indicator whether the user want to save the model or not
        :return: updated indicator
        """

        self.controller.set_saving_model(self.save_model_var.get() == 1)

    def similarity_functions_validation(self):
        """
        Validations that at least one similarity function was checked
        :return: True if at least one was checked, otherwise false
        """

        for var in self.similarity_functions.get_vars():
            if var.get() != 0:
                return True

        return False
class PreTuneModel(tk.Frame):
    """
    A Class used to get the data in order to tune model parameters by user selection

    Methods
    -------
    reset_widgets()
            Description | Reset check bar values

    back_window()
            Description | Handle a click on back button

    next_window()
            Description | Handle a click on next button

    reinitialize()
            Description | Reinitialize frame values and view

    input_file_browse_command()
            Description | Set the input file path to entry widget

    results_browse_command()
            Description | Set the results path to entry widget

    """
    def __init__(self, parent, controller):
        """
        Parameters
        ----------

        :param parent: window
        :param controller: GUI controller
        """

        tk.Frame.__init__(self, parent)

        # Page init
        self.controller = controller
        self.menubar = Menubar(controller)
        # Disables ability to tear menu bar into own window
        self.controller.option_add('*tearOff', 'FALSE')
        system_logo = CROSS_WINDOWS_SETTINGS.get('LOGO')
        photo_location = os.path.join(system_logo)
        global logo_img
        logo_img = tk.PhotoImage(file=photo_location)

        # Page header
        self.logo_png = tk.Button(self)
        self.logo_png.place(relx=0.28, rely=0.029, height=172, width=300)
        set_logo_configuration(self.logo_png, image=logo_img)

        self.instructions = tk.Label(self)
        self.instructions.place(relx=0.015, rely=0.3, height=32, width=635)
        self.instructions.configure(
            text='''Please select your choice for parameters tuning:''')
        set_widget_to_left(self.instructions)

        # Page body
        self.reinitialize()

        # Page footer
        self.next_button = HoverButton(self, command=self.next_window)
        self.next_button.place(relx=0.813, rely=0.839, height=25, width=81)
        set_button_configuration(self.next_button, text='''Next''')

        self.back_button = HoverButton(self, command=self.back_window)
        self.back_button.place(relx=0.017, rely=0.839, height=25, width=81)
        set_button_configuration(self.back_button, text='''Back''')

        self.copyright = tk.Label(self)
        self.copyright.place(relx=0, rely=0.958, height=25, width=750)
        set_copyright_configuration(self.copyright)

    def reset_widgets(self):
        """
        Reset check bar values
        :return: empty values in the widgets
        """

        clear_text(self.path_input)

    def back_window(self):
        """
        Handle back button click
        :return: previous window
        """

        self.controller.set_new_model_running(False)
        self.controller.show_frame("MainWindow")

    def next_window(self):
        """
        Handle a click on next button
        :return: if validations pass move to next window
        """

        if pre_tune_model_path_validation(self.path_input.get(),
                                          self.results_path_input.get()):
            self.controller.set_tune_model_input_path(self.path_input.get())
            self.controller.set_tune_model_results_path(
                self.results_path_input.get())
            self.controller.set_tune_model_features()
            self.controller.reinitialize_frame("TuneModel")
        else:
            win32api.MessageBox(0, 'Input path file is invalid!',
                                'Invalid input', 0x00001000)

    def reinitialize(self):
        """
        Reinitialize frame values and view
        :return: new frame view
        """

        self.path_label = tk.Label(self)
        self.path_label.place(relx=0.015, rely=0.4, height=32, width=146)
        self.path_label.configure(text='''Input file:''')
        set_widget_to_left(self.path_label)

        self.path_input = tk.Entry(self)
        self.path_input.place(relx=0.195, rely=0.4, height=25, relwidth=0.624)

        self.browse_btn = HoverButton(self,
                                      command=self.input_file_browse_command)
        self.browse_btn.place(relx=0.833, rely=0.4, height=25, width=60)
        set_button_configuration(self.browse_btn, text='''Browse''')

        # Results output directory
        self.results_path_label = tk.Label(self)
        self.results_path_label.place(relx=0.015,
                                      rely=0.5,
                                      height=32,
                                      width=146)
        self.results_path_label.configure(text='''Results directory:''')
        set_widget_to_left(self.results_path_label)

        self.results_path_input = tk.Entry(self)
        self.results_path_input.place(relx=0.195,
                                      rely=0.5,
                                      height=25,
                                      relwidth=0.624)

        self.results_browse_btn = HoverButton(
            self, command=self.results_browse_command)
        self.results_browse_btn.place(relx=0.833,
                                      rely=0.5,
                                      height=25,
                                      width=60)
        set_button_configuration(self.results_browse_btn, text='''Browse''')

    def input_file_browse_command(self):
        """
        Set the path to entry widget
        :return: updated path
        """

        self.path_input.delete(0, tk.END)
        path = set_file_path()
        self.path_input.insert(0, path)

    def results_browse_command(self):
        """
        Set the results path to entry widget
        :return: updated path
        """

        self.results_path_input.delete(0, tk.END)
        path = set_path()
        self.results_path_input.insert(0, path)
class LoadModel(tk.Frame):
    """
    A Class used to get all the paths from the user in order to load existing models

    Methods
    -------
    reset_widgets()
            Description | Reset check bar values

    back_window()
            Description | Handle a click on back button

    next_window()
            Description | Handle a click on next button

    set_test_path()
            Description | Set the test data set path to entry widget

    set_results_path()
            Description | Set the results path to entry widget

    set_load_model_parameters()
            Description | Set parameters to load model flow

    """

    def __init__(self, parent, controller):

        """
        Parameters
        ----------

        :param parent: window
        :param controller: GUI controller
        """

        tk.Frame.__init__(self, parent)

        # Page init
        self.controller = controller
        self.menubar = Menubar(controller)
        # Disables ability to tear menu bar into own window
        self.controller.option_add('*tearOff', 'FALSE')
        system_logo = CROSS_WINDOWS_SETTINGS.get('LOGO')
        photo_location = os.path.join(system_logo)
        global logo_img
        logo_img = tk.PhotoImage(file=photo_location)

        # Page header
        self.logo_png = tk.Button(self)
        self.logo_png.place(relx=0.28, rely=0.029, height=172, width=300)
        set_logo_configuration(self.logo_png, image=logo_img)

        self.instructions = tk.Label(self)
        self.instructions.place(relx=0.015, rely=0.3, height=32, width=635)
        self.instructions.configure(
            text='''Please insert input files for existing model.''')
        set_widget_to_left(self.instructions)

        # Page body

        # Testing input directory
        self.test_label = tk.Label(self)
        self.test_label.place(relx=0.015, rely=0.4, height=32, width=146)
        self.test_label.configure(text='''Test directory''')
        set_widget_to_left(self.test_label)

        self.test_input = tk.Entry(self)
        self.test_input.place(relx=0.195, rely=0.4, height=25, relwidth=0.624)

        self.test_btn = HoverButton(self, command=self.set_test_path)
        self.test_btn.place(relx=0.833, rely=0.4, height=25, width=60)
        set_button_configuration(self.test_btn, text='''Browse''')

        # Results output directory
        self.results_label = tk.Label(self)
        self.results_label.place(relx=0.015, rely=0.5, height=32, width=146)
        self.results_label.configure(text='''Results directory''')
        set_widget_to_left(self.results_label)

        self.results_input = tk.Entry(self)
        self.results_input.place(relx=0.195, rely=0.5, height=25, relwidth=0.624)

        self.results_btn = HoverButton(self, command=self.set_results_path)
        self.results_btn.place(relx=0.833, rely=0.5, height=25, width=60)
        set_button_configuration(self.results_btn, text='''Browse''')

        # Page footer
        self.next_button = HoverButton(self, command=self.next_window)
        self.next_button.place(relx=0.813, rely=0.839, height=25, width=81)
        set_button_configuration(self.next_button, text='''Next''')

        self.back_button = HoverButton(self, command=self.back_window)
        self.back_button.place(relx=0.017, rely=0.839, height=25, width=81)
        set_button_configuration(self.back_button, text='''Back''')

        self.copyright = tk.Label(self)
        self.copyright.place(relx=0, rely=0.958, height=25, width=750)
        set_copyright_configuration(self.copyright)

    def reset_widgets(self):
        """
        Reset check bar values
        :return: empty values in the widgets
        """

        widgets = [
            self.test_input,
            self.results_input
        ]

        for widget in widgets:
            clear_text(widget)

    def back_window(self):
        """
        Handle back button click
        :return: previous window
        """

        self.controller.set_new_model_running(False)
        self.controller.show_frame("MainWindow")

    def next_window(self):
        """
        Handle a click on next button
        :return: if validations pass move to next window
        """

        if load_model_paths_validation(self.test_input.get(), self.results_input.get()):
            self.set_load_model_parameters()
            self.controller.show_frame("ExistingAlgorithmsWindow")

    def set_test_path(self):
        """
        Set the test data set path to entry widget
        :return: updated test path
        """

        self.test_input.delete(0, END)
        path = set_path()
        self.test_input.insert(0, path)

    def set_results_path(self):
        """
        Set the results path to entry widget
        :return: updated results path
        """

        self.results_input.delete(0, END)
        path = set_path()
        self.results_input.insert(0, path)

    def set_load_model_parameters(self):
        """
        Set parameters to load model flow
        :return: updated parameters in load model flow in the system
        """

        self.controller.set_new_model_test_input_path(self.test_input.get())
        self.controller.set_new_model_results_input_path(self.results_input.get())
        self.controller.set_new_model_running(False)
Example #6
0
class MainWindow(tk.Frame):
    """
    A Class used to configure and populate the main window

    Methods
    -------
    reset_widgets()
            Description | Reset check bar values

    load_flow()
            Description | Move to load model flow

    new_flow()
            Description | Move to new model flow

    tune_flow():
            Description | Move to tune model flow

    """
    def __init__(self, parent, controller):
        """
        Parameters
        ----------

        :param parent: window
        :param controller: GUI controller
        """

        ttk.Frame.__init__(self, parent)

        # Page init
        self.controller = controller
        self.menubar = Menubar(controller)
        # Disables ability to tear menu bar into own window
        self.controller.option_add('*tearOff', 'FALSE')

        system_logo = CROSS_WINDOWS_SETTINGS.get('LOGO')
        bgu_logo = CROSS_WINDOWS_SETTINGS.get('BGU')
        israel_innovation_authority_logo = CROSS_WINDOWS_SETTINGS.get(
            'ISRAEL_INNOVATION_AUTHORITY')
        ministry_of_defense_logo = CROSS_WINDOWS_SETTINGS.get(
            'MINISTRY_OF_DEFENSE')
        mobilicom_logo = CROSS_WINDOWS_SETTINGS.get('MOBILICOM')

        photo_location = os.path.join(system_logo)
        bgu_location = os.path.join(bgu_logo)
        israel_innovation_authority_location = os.path.join(
            israel_innovation_authority_logo)
        ministry_of_defense_location = os.path.join(ministry_of_defense_logo)
        mobilicom_location = os.path.join(mobilicom_logo)

        global logo_img, bgu_img, israel_innovation_authority_img, ministry_of_defense_img, mobilicom_img

        logo_img = tk.PhotoImage(file=photo_location)
        bgu_img = tk.PhotoImage(file=bgu_location)
        israel_innovation_authority_img = tk.PhotoImage(
            file=israel_innovation_authority_location)
        ministry_of_defense_img = tk.PhotoImage(
            file=ministry_of_defense_location)
        mobilicom_img = tk.PhotoImage(file=mobilicom_location)

        self.controller.geometry("700x550")
        self.controller.minsize(700, 550)
        self.controller.maxsize(700, 550)
        self.controller.resizable(1, 1)
        self.controller.title("Anomaly Detection System")
        self.controller.configure(background="#eeeeee")

        # Page header
        self.logo_png = tk.Button(self)
        self.logo_png.place(relx=0.28, rely=0.029, height=172, width=300)
        set_logo_configuration(self.logo_png, image=logo_img)

        # Page body
        self.create_model_btn = HoverButton(self, command=self.new_flow)
        self.create_model_btn.place(relx=0.41, rely=0.35, height=42, width=120)
        set_button_configuration(self.create_model_btn,
                                 text='''Create model''')

        self.load_model_btn = HoverButton(self, command=self.load_flow)
        self.load_model_btn.place(relx=0.41, rely=0.52, height=42, width=120)
        set_button_configuration(self.load_model_btn, text='''Load model''')

        # self.tune_model_btn = HoverButton(self, command=self.tune_flow)
        # self.tune_model_btn.place(relx=0.395, rely=0.65, height=42, width=140)
        # set_button_configuration(self.tune_model_btn, text='''Tune model parameters''')

        self.bgu_png = tk.Button(self)
        self.bgu_png.place(relx=0, rely=0, height=35, width=186)
        set_logo_configuration(self.bgu_png, image=bgu_img)

        self.israel_innovation_authority_png = tk.Button(self)
        self.israel_innovation_authority_png.place(relx=0.04,
                                                   rely=0.78,
                                                   height=61,
                                                   width=200)
        set_logo_configuration(self.israel_innovation_authority_png,
                               image=israel_innovation_authority_img)

        self.ministry_of_defense_png = tk.Button(self)
        self.ministry_of_defense_png.place(relx=0.7,
                                           rely=0.67,
                                           height=119,
                                           width=136)
        set_logo_configuration(self.ministry_of_defense_png,
                               image=ministry_of_defense_img)

        self.mobilicom_png = tk.Button(self)
        self.mobilicom_png.place(relx=0.41, rely=0.75, height=116, width=116)
        set_logo_configuration(self.mobilicom_png, image=mobilicom_img)

        # Page footer
        self.copyright = tk.Label(self)
        self.copyright.place(relx=0, rely=0.958, height=25, width=750)
        set_copyright_configuration(self.copyright)

    def reset_widgets(self):
        """
        Reset check bar values
        :return: empty values in the widgets
        """

        pass

    def load_flow(self):
        """
        Move to load model flow
        :return: load model window
        """

        self.controller.set_new_model_running(False)
        self.controller.show_frame("LoadModel")

    def new_flow(self):
        """
        Move to new model flow
        :return: new model window
        """

        self.controller.set_new_model_running(True)
        self.controller.show_frame("NewModel")

    def tune_flow(self):
        """
        Move to tune model flow
        :return: tune model window
        """

        self.controller.set_new_model_running(False)
        self.controller.show_frame("PreTuneModel")
Example #7
0
class LoadingWindow(tk.Frame):
    """
    A Class used to be presented while the models are running in the background of the application

    Methods
    -------
    reset_widgets()
            Description | Reset check bar values

    stop_model_process()
            Description | Handle a click on stop button

    reinitialize()
            Description | Reinitialize frame values and view

    update_clock()
            Description | Updates the time on the clock

    loading_process()
            Description | Run chosen models and move to results window

    show_model_process_label(y_coordinate, algorithm):
            Description | Show model process label on the screen
    """
    def __init__(self, parent, controller):
        """
        Parameters
        ----------

        :param parent: window
        :param controller: GUI controller
        """

        tk.Frame.__init__(self, parent)

        # Page init
        self.controller = controller
        self.menubar = Menubar(controller)
        # Disables ability to tear menu bar into own window
        self.controller.option_add('*tearOff', 'FALSE')
        system_logo = CROSS_WINDOWS_SETTINGS.get('LOGO')
        stop_logo = LOADING_WINDOW_SETTINGS.get('STOP')
        photo_location = os.path.join(system_logo)
        stop_photo_location = os.path.join(stop_logo)
        global logo_img, stop_img
        logo_img = tk.PhotoImage(file=photo_location)
        stop_img = tk.PhotoImage(file=stop_photo_location)

        # Page header
        self.logo_png = tk.Button(self)
        self.logo_png.place(relx=0.28, rely=0.029, height=172, width=300)
        set_logo_configuration(self.logo_png, image=logo_img)

        self.instructions = tk.Label(self)
        self.instructions.place(relx=0.015, rely=0.3, height=32, width=635)
        self.instructions.configure(
            text='''Creating models and runs them, please wait...''',
            font=Font(size=9, weight=BOLD))
        set_widget_to_left(self.instructions)

        # Page body
        self.stop_png = tk.Button(self)
        self.loading_gif_animation = LOADING_WINDOW_SETTINGS.get('LOADING_GIF')
        self.delay_between_frames = LOADING_WINDOW_SETTINGS.get(
            'DELAY_BETWEEN_FRAMES')

        self.title_font = Font(family='Helvetica', size=12, weight="bold")

        self.loading_gif = AnimatedGif(self, self.loading_gif_animation,
                                       self.delay_between_frames)
        self.loading_gif.place(relx=0.1, rely=0.38, height=330, width=600)

        self.clock_label = tk.Label(self, text="", font=self.title_font)
        self.clock_label.place(relx=0.38, rely=0.73, height=32, width=150)

        # Page footer
        self.stop_button = HoverButton(self, command=self.stop_model_process)
        self.stop_button.place(relx=0.813, rely=0.839, height=25, width=81)
        set_button_configuration(self.stop_button, text='''Stop''')

        self.copyright = tk.Label(self)
        self.copyright.place(relx=0, rely=0.958, height=25, width=750)
        set_copyright_configuration(self.copyright)

        # Page logic
        self.loading_gif.start()

    def reset_widgets(self):
        """
        Reset check bar values
        :return: empty values in the widgets
        """

        pass

    def stop_model_process(self):
        """
        Handle stop button click
        :return: freeze state
        """

        if self.event.isSet():  # check if the event flag is True or False
            self.event.clear()
            self.stop_button.configure(text='Resume')
            self.loading_gif.place_forget()
            self.stop_png.place(relx=0.385, rely=0.5, height=132, width=132)
            set_logo_configuration(self.stop_png, image=stop_img)
        else:
            self.event.set()
            self.stop_button.configure(text='Stop')
            self.stop_png.place_forget()
            self.loading_gif.place(relx=0.1, rely=0.35, height=330, width=600)

        self.start_time = timer() - self.prev_saved_time
        self.update_clock()

    def reinitialize(self):
        """
        Reinitialize frame values and view
        :return: new frame view
        """

        self.stop_button.configure(text='Stop')
        self.event = threading.Event()
        self.model_process_thread = threading.Thread(
            name='model_process', target=self.loading_process)
        self.model_process_thread.start()
        self.start_time = timer()
        self.event.set()
        self.update_clock()

    def update_clock(self):
        """
        Updates the time on the clock
        :return: updated time
        """

        if not self.event.isSet():
            return
        now = timer()
        duration = timedelta(seconds=now - self.start_time)
        self.prev_saved_time = now - self.start_time
        self.clock_label.configure(text=strfdelta(duration, '%H:%M:%S'))
        self.controller.after(200, self.update_clock)

    def loading_process(self):
        """
        Run chosen models and move to results window
        :return: results window
        """

        similarity_score, test_data_path, results_path, new_model_running = self.controller.init_models(
        )

        if new_model_running:
            chosen_algorithms = self.controller.get_algorithms()
        else:
            chosen_algorithms = set(
                self.controller.get_existing_algorithms().keys())

        y_coordinate = 0.34
        enumerate_details = 0

        for algorithm in chosen_algorithms:
            if new_model_running:
                print_text = '''{0} : Creates a new model and runs the test data on it...'''.format(
                    algorithm)
            else:
                print_text = '''{0} : Runs the test data...'''.format(
                    algorithm)

            if enumerate_details < 4:
                self.algorithm_process_finished = tk.Label(self)
                self.algorithm_process_finished.place(relx=0.015,
                                                      rely=y_coordinate,
                                                      height=22,
                                                      width=400)
                self.algorithm_process_finished.configure(text=print_text)
                set_widget_to_left(self.algorithm_process_finished)

                y_coordinate += 0.04

            self.controller.run_models(algorithm, similarity_score,
                                       test_data_path, results_path,
                                       new_model_running, self.event)

            enumerate_details += 1

        self.controller.reinitialize_frame("ResultsWindow")

    def show_model_process_label(self, y_coordinate, algorithm):
        """
        Show model process label on the screen
        :param y_coordinate: y place coordinate
        :param algorithm: which algorithm to display
        :return: new label
        """

        self.model_process_finished = tk.Label(self)
        self.model_process_finished.place(relx=0.015,
                                          rely=y_coordinate,
                                          height=22,
                                          width=215)
        self.model_process_finished.configure(
            text='''{0} model runs on the test...'''.format(algorithm))
        set_widget_to_left(self.model_process_finished)
Example #8
0
class TuneResultsWindow(tk.Frame):
    """
    A Class used to present tune parameters results

    Methods
    -------
    reset_widgets()
            Description | Reset check bar values

    back_window()
            Description | Handle a click on back button

    reinitialize()
            Description | Reinitialize frame values and view

    """
    def __init__(self, parent, controller):
        """
        Parameters
        ----------

        :param parent: window
        :param controller: GUI controller
        """

        tk.Frame.__init__(self, parent)

        # Page init
        self.controller = controller
        self.menubar = Menubar(controller)
        # Disables ability to tear menu bar into own window
        self.controller.option_add('*tearOff', 'FALSE')
        system_logo = CROSS_WINDOWS_SETTINGS.get('LOGO')
        photo_location = os.path.join(system_logo)
        global logo_img
        logo_img = tk.PhotoImage(file=photo_location)

        # Page header
        self.logo_png = tk.Button(self)
        self.logo_png.place(relx=0.28, rely=0.029, height=172, width=300)
        set_logo_configuration(self.logo_png, image=logo_img)

        # Page body

        # Page footer
        self.back_button = HoverButton(self, command=self.back_window)
        self.back_button.place(relx=0.017, rely=0.839, height=25, width=81)
        set_button_configuration(self.back_button, text='''Home page''')

        self.copyright = tk.Label(self)
        self.copyright.place(relx=0, rely=0.958, height=25, width=750)
        set_copyright_configuration(self.copyright)

    def reset_widgets(self):
        """
        Reset check bar values
        :return: empty values in the widgets
        """

        pass

    def back_window(self):
        """
        Handle back button click
        :return: previous window
        """

        self.controller.reset_frame()
        self.controller.reset_input_settings_params()
        self.controller.show_frame("MainWindow")

    def reinitialize(self):
        """
         Reinitialize frame values and view
         :return: new frame view
         """

        pass
class ExistingAlgorithmsWindow(tk.Frame):
    """
    A Class used to enable the user load existing machine learning model

    Methods
    -------
    reset_widgets()
            Description | Reset check bar values

    back_window()
            Description | Handle back button click

    set_input_entry()
            Description | Set input entry and update the state

    set_algorithm_path()
            Description | Set the algorithm path in the UI

    next_window()
            Description |  Handle next button click

    validate_next_step()
            Description | Validation before approving the move to the next window

    update_selected_algorithms()
            Description | Updates local variables which algorithms were selected by the user

    set_load_model_parameters()
            Description | Updates input settings and move to next window

    """

    def __init__(self, parent, controller):

        """
        Parameters
        ----------

        :param parent: window
        :param controller: GUI controller
        """

        tk.Frame.__init__(self, parent)

        # Page init
        self.controller = controller
        self.menubar = Menubar(controller)
        # Disables ability to tear menu bar into own window
        self.controller.option_add('*tearOff', 'FALSE')
        system_logo = CROSS_WINDOWS_SETTINGS.get('LOGO')
        photo_location = os.path.join(system_logo)
        global logo_img
        logo_img = tk.PhotoImage(file=photo_location)

        # Page header
        self.logo_png = tk.Button(self)
        self.logo_png.place(relx=0.28, rely=0.029, height=172, width=300)
        set_logo_configuration(self.logo_png, image=logo_img)

        self.instructions = tk.Label(self)
        self.instructions.place(relx=0.015, rely=0.3, height=32, width=635)
        self.instructions.configure(
            text='''Please insert paths for existing models.''')
        set_widget_to_left(self.instructions)

        # Page body
        self.algorithms = dict()
        self.browse_buttons = dict()
        self.input_entries = dict()

        # LSTM existing algorithm
        self.lstm_var = tk.IntVar()
        self.lstm_check_button = tk.Checkbutton(self)
        self.lstm_check_button.place(relx=0.015, rely=0.38, height=32, width=146)
        self.lstm_check_button.configure(text="LSTM",
                                         variable=self.lstm_var,
                                         command=lambda: self.set_input_entry("LSTM", self.lstm_var.get()))
        set_widget_to_left(self.lstm_check_button)

        self.lstm_input = tk.Entry(self)
        self.lstm_input.place(relx=0.195, rely=0.38, height=25, relwidth=0.624)
        self.lstm_input.configure(state='disabled')

        self.lstm_btn = HoverButton(self, command=lambda: self.set_algorithm_path("LSTM"))
        self.lstm_btn.place(relx=0.833, rely=0.38, height=25, width=60)
        self.lstm_btn.configure(state='disabled')
        set_button_configuration(self.lstm_btn, text='''Browse''')

        self.browse_buttons["LSTM"] = self.lstm_btn
        self.input_entries["LSTM"] = self.lstm_input

        # SVR existing algorithm
        self.svr_var = tk.IntVar()
        self.svr_check_button = tk.Checkbutton(self)
        self.svr_check_button.place(relx=0.015, rely=0.47, height=32, width=146)
        self.svr_check_button.configure(text="SVR",
                                        variable=self.svr_var,
                                        command=lambda: self.set_input_entry("SVR", self.svr_var.get()))
        set_widget_to_left(self.svr_check_button)

        self.svr_input = tk.Entry(self)
        self.svr_input.place(relx=0.195, rely=0.47, height=25, relwidth=0.624)
        self.svr_input.configure(state='disabled')

        self.svr_btn = HoverButton(self, command=lambda: self.set_algorithm_path("SVR"))
        self.svr_btn.place(relx=0.833, rely=0.47, height=25, width=60)
        self.svr_btn.configure(state='disabled')
        set_button_configuration(self.svr_btn, text='''Browse''')

        self.browse_buttons["SVR"] = self.svr_btn
        self.input_entries["SVR"] = self.svr_input

        # MLP existing algorithm
        self.mlp_var = tk.IntVar()
        self.mlp_check_button = tk.Checkbutton(self)
        self.mlp_check_button.place(relx=0.015, rely=0.56, height=32, width=146)
        self.mlp_check_button.configure(text="MLP",
                                        variable=self.mlp_var,
                                        command=lambda: self.set_input_entry("MLP",
                                                                             self.mlp_var.get()))
        set_widget_to_left(self.mlp_check_button)

        self.mlp_input = tk.Entry(self)
        self.mlp_input.place(relx=0.195, rely=0.56, height=25, relwidth=0.624)
        self.mlp_input.configure(state='disabled')

        self.mlp_btn = HoverButton(self, command=lambda: self.set_algorithm_path("MLP"))
        self.mlp_btn.place(relx=0.833, rely=0.56, height=25, width=60)
        self.mlp_btn.configure(state='disabled')
        set_button_configuration(self.mlp_btn, text='''Browse''')

        self.browse_buttons["MLP"] = self.mlp_btn
        self.input_entries["MLP"] = self.mlp_input

        # Random Forest existing algorithm
        self.random_forest_var = tk.IntVar()
        self.random_forest_check_button = tk.Checkbutton(self)
        self.random_forest_check_button.place(relx=0.015, rely=0.65, height=32, width=146)
        self.random_forest_check_button.configure(text="Random Forest",
                                                  variable=self.random_forest_var,
                                                  command=lambda: self.set_input_entry("Random Forest",
                                                                                       self.random_forest_var.get()))
        set_widget_to_left(self.random_forest_check_button)

        self.random_forest_input = tk.Entry(self)
        self.random_forest_input.place(relx=0.195, rely=0.65, height=25, relwidth=0.624)
        self.random_forest_input.configure(state='disabled')

        self.random_forest_btn = HoverButton(self, command=lambda: self.set_algorithm_path("Random Forest"))
        self.random_forest_btn.place(relx=0.833, rely=0.65, height=25, width=60)
        self.random_forest_btn.configure(state='disabled')
        set_button_configuration(self.random_forest_btn, text='''Browse''')

        self.browse_buttons["Random Forest"] = self.random_forest_btn
        self.input_entries["Random Forest"] = self.random_forest_input

        # Page footer
        self.next_button = HoverButton(self, command=self.next_window)
        self.next_button.place(relx=0.813, rely=0.839, height=25, width=81)
        set_button_configuration(self.next_button, text='''Next''')

        self.back_button = HoverButton(self, command=self.back_window)
        self.back_button.place(relx=0.017, rely=0.839, height=25, width=81)
        set_button_configuration(self.back_button, text='''Back''')

        self.copyright = tk.Label(self)
        self.copyright.place(relx=0, rely=0.958, height=25, width=750)
        set_copyright_configuration(self.copyright)

    def reset_widgets(self):
        """
        Reset check bar values
        :return: empty values in the widgets
        """

        widgets = [
            self.lstm_input,
            self.svr_input,
            self.mlp_input,
            self.random_forest_input
        ]

        variables = [
            self.lstm_var,
            self.svr_var,
            self.mlp_var,
            self.random_forest_var
        ]

        check_buttons = [
            self.lstm_check_button,
            self.svr_check_button,
            self.mlp_check_button,
            self.random_forest_check_button
        ]

        for widget in widgets:
            clear_text(widget)
            widget['state'] = 'disabled'

        for var, check_button in zip(variables, check_buttons):
            var.set(0)
            check_button['variable'] = var

    def back_window(self):
        """
        Handle back button click
        :return: previous window
        """

        self.controller.set_new_model_running(False)
        self.controller.show_frame("MainWindow")

    def set_input_entry(self, entry_name, state):
        """
        Set input entry and update the state
        :param entry_name: input's algorithm name
        :param state: input's state
        :return: updated input
        """

        if state:
            self.browse_buttons[entry_name]['state'] = 'active'
            self.input_entries[entry_name]['state'] = 'normal'
            self.algorithms[entry_name] = ""
        else:
            self.input_entries[entry_name].delete(0, END)
            self.browse_buttons[entry_name]['state'] = 'disabled'
            self.input_entries[entry_name]['state'] = 'disabled'
            self.algorithms.pop(entry_name, None)

    def set_algorithm_path(self, algorithm):
        """
        Set the algorithm path in the UI
        :param algorithm: input algorithm
        :return: updated state
        """

        self.input_entries[algorithm].delete(0, END)
        path = set_path()
        self.input_entries[algorithm].insert(0, path)

    def next_window(self):
        """
        Handle next button click
        :return: if validations pass move to next window
        """

        self.update_selected_algorithms()
        if self.validate_next_step():
            self.set_load_model_parameters()

    def validate_next_step(self):
        """
        Validation before approving the move to the next window
        :return:
        """

        if not self.algorithms:
            win32api.MessageBox(0, 'Please select algorithm & path for the model before the next step.',
                                'Invalid algorithm', 0x00001000)
            return False

        if not is_valid_model_paths(self.algorithms.values()):
            win32api.MessageBox(0,
                                'At least one of your algorithms paths invalid or not include the required files! '
                                'Please check that there are no duplicate files in the same directory.',
                                'Invalid inputs', 0x00001000)
            return False

        if not is_valid_model_data_file(self.algorithms.values()):
            win32api.MessageBox(0,
                                'At least one of the required data is missing in model_data json file!',
                                'Missing data', 0x00001000)
            return False

        return True

    def update_selected_algorithms(self):
        """
        Updates local variables which algorithms were selected by the user
        :return: updated selection
        """

        tmp_algorithms = dict()

        for algorithm in self.algorithms:
            tmp_algorithms[algorithm] = self.input_entries[algorithm].get()

        self.algorithms = tmp_algorithms

    def set_load_model_parameters(self):
        """
        Updates input settings and move to next window
        :return: next window
        """

        self.controller.set_existing_algorithms(self.algorithms)
        self.controller.reinitialize_frame("SimilarityFunctionsWindow")
Example #10
0
class TuningLoadingWindow(tk.Frame):
    """
    A Class used to be presented tuning model process is running in the background of the application

    Methods
    -------
    reset_widgets()
            Description | Reset check bar values

    back_window()
            Description | Handle a click on back button

    stop_model_process()
            Description | Handle a click on stop button

    reinitialize()
            Description | Reinitialize frame values and view

    update_clock()
            Description | Updates the time on the clock

    loading_process()
            Description | Run chosen models and move to results window

    """

    def __init__(self, parent, controller):

        """
        Parameters
        ----------

        :param parent: window
        :param controller: GUI controller
        """

        tk.Frame.__init__(self, parent)

        # Page init
        self.controller = controller
        self.menubar = Menubar(controller)
        # Disables ability to tear menu bar into own window
        self.controller.option_add('*tearOff', 'FALSE')
        system_logo = CROSS_WINDOWS_SETTINGS.get('LOGO')
        photo_location = os.path.join(system_logo)
        global logo_img
        logo_img = tk.PhotoImage(file=photo_location)

        # Page header
        self.logo_png = tk.Button(self)
        self.logo_png.place(relx=0.28, rely=0.029, height=172, width=300)
        set_logo_configuration(self.logo_png, image=logo_img)

        self.instructions = tk.Label(self)
        self.instructions.place(relx=0.015, rely=0.3, height=32, width=635)
        self.instructions.configure(text='''Tuning parameters, please wait...''')
        set_widget_to_left(self.instructions)

        # Page body
        loading_gif = LOADING_WINDOW_SETTINGS.get('LOADING_GIF')
        delay_between_frames = LOADING_WINDOW_SETTINGS.get('DELAY_BETWEEN_FRAMES')

        self.title_font = Font(family='Helvetica', size=12, weight="bold")

        self.loading_gif = AnimatedGif(self, loading_gif, delay_between_frames)
        self.loading_gif.place(relx=0.1, rely=0.35, height=330, width=600)

        self.clock_label = tk.Label(self, text="", font=self.title_font)
        self.clock_label.place(relx=0.38, rely=0.7, height=32, width=150)

        # Page footer
        self.stop_button = HoverButton(self, command=self.stop_model_process)
        self.stop_button.place(relx=0.813, rely=0.839, height=25, width=81)
        set_button_configuration(self.stop_button, text='''Stop''')

        self.back_button = HoverButton(self, command=self.back_window)
        self.back_button.place(relx=0.017, rely=0.839, height=25, width=81)
        set_button_configuration(self.back_button, text='''Back''')
        self.back_button.configure(state='disabled')

        self.copyright = tk.Label(self)
        self.copyright.place(relx=0, rely=0.958, height=25, width=750)
        set_copyright_configuration(self.copyright)

        # Page logic
        self.loading_gif.start()

    def reset_widgets(self):
        """
        Reset check bar values
        :return: empty values in the widgets
        """

        pass

    def back_window(self):
        """
        Handle back button click
        :return: previous window
        """

        self.controller.reinitialize_frame("TuneModel")

    def stop_model_process(self):
        """
        Handle stop button click
        :return: freeze state
        """

        self.back_button.configure(state='active')
        self.stop_button.configure(state='disabled')
        try:
            self.model_process_thread.join()
        except Exception:
            pass

    def reinitialize(self):
        """
        Reinitialize frame values and view
        :return: new frame view
        """

        self.model_process_thread = threading.Thread(name='model_process', target=self.loading_process)
        self.model_process_thread.start()
        self.start_time = timer()
        self.update_clock()

    def update_clock(self):
        """
        Updates the time on the clock
        :return: updated time
        """

        now = timer()
        duration = timedelta(seconds=now - self.start_time)
        self.clock_label.configure(text=strfdelta(duration, '%H:%M:%S'))
        self.controller.after(200, self.update_clock)

    def loading_process(self):
        """
        Run tuning parameters process and move to results window
        :return: results window
        """

        self.controller.run_tuning()
        self.controller.reinitialize_frame("TuneResultsWindow")
Example #11
0
class ParametersOptionsWindow(tk.Frame):
    """
    A Class used to show all the parameters for each algorithm in the application

    Methods
    -------
    reset_widgets()
            Description | Reset check bar values

    handle_next_button()
            Description | Handle a click on next button

    set_algorithm_parameters(algorithm_name, algorithm_parameters)
            Description | Set parameters for each algorithm

    save_algorithm_parameters(algorithm_parameters)
            Description | Save the parameters for each algorithm which was chosen

    set_suitable_yaml_file(algorithm_name)
            Description | Set the yaml file according to algorithm name

    reinitialize()
            Description | Reinitialize frame values and view

    reinitialize_current_algorithm_options()
            Description |  Reinitialize algorithm value and view

    """
    def __init__(self, parent, controller):
        """
        Parameters
        ----------

        :param parent: window
        :param controller: GUI controller
        """

        tk.Frame.__init__(self, parent)

        # Page init
        self.controller = controller
        self.menubar = Menubar(controller)
        # Disables ability to tear menu bar into own window
        self.controller.option_add('*tearOff', 'FALSE')
        system_logo = CROSS_WINDOWS_SETTINGS.get('LOGO')
        photo_location = os.path.join(system_logo)
        global logo_img
        logo_img = tk.PhotoImage(file=photo_location)

        # Page header
        self.logo_png = tk.Button(self)
        self.logo_png.place(relx=0.28, rely=0.029, height=172, width=300)
        set_logo_configuration(self.logo_png, image=logo_img)

        self.instructions = tk.Label(self)
        self.instructions.place(relx=0.015, rely=0.3, height=32, width=635)
        self.instructions.configure(
            text=
            '''Please select the values for each of the following parameters:'''
        )
        set_widget_to_left(self.instructions)

        # Page body

        # Dynamic algorithm options
        self.algorithms_files = load_anomaly_detection_list()
        self.current_algorithm = self.controller.get_current_algorithm_to_edit(
        )
        self.current_yaml = self.set_suitable_yaml_file(self.current_algorithm)

        self.height_options_frame = 268
        self.width_options_frame = 620

        self.options_to_show = AlgorithmFrameOptions(
            self, yaml_filename=self.current_yaml)
        self.options_to_show.place(relx=0.05,
                                   rely=0.35,
                                   height=self.height_options_frame,
                                   width=self.width_options_frame)

        # Page footer
        self.next_button = HoverButton(self, command=self.handle_next_button)
        self.next_button.place(relx=0.813, rely=0.839, height=25, width=81)
        set_button_configuration(self.next_button, text='''Save''')

        self.back_button = HoverButton(
            self,
            command=lambda: self.controller.show_frame("AlgorithmsWindow"))
        self.back_button.place(relx=0.017, rely=0.839, height=25, width=81)
        set_button_configuration(self.back_button, text='''Cancel''')

        self.copyright = tk.Label(self)
        self.copyright.place(relx=0, rely=0.958, height=25, width=750)
        set_copyright_configuration(self.copyright)

    def reset_widgets(self):
        """
        Reset check bar values
        :return: empty values in the widgets
        """

        pass

    def handle_next_button(self):
        """
        Handle a click on next button
        :return: if validations pass move to next window
        """

        algorithm_parameters = self.options_to_show.get_algorithm_parameters()
        self.save_algorithm_parameters(algorithm_parameters)

    def set_algorithm_parameters(self, algorithm_name, algorithm_parameters):
        """
        Set parameters for each algorithm
        :param algorithm_name: the name of the algorithm
        :param algorithm_parameters: the values of the parameteres
        :return: updates state
        """

        self.controller.set_algorithm_parameters(algorithm_name,
                                                 algorithm_parameters)

    def save_algorithm_parameters(self, algorithm_parameters):
        """
        Save the parameters for each algorithm which was chosen
        :param algorithm_parameters: new values
        :return: updated state of user choice
        """

        algorithm_name = self.controller.get_current_algorithm_to_edit()
        self.set_algorithm_parameters(algorithm_name, algorithm_parameters)
        self.controller.show_frame("AlgorithmsWindow")

    def set_suitable_yaml_file(self, algorithm_name):
        """
        Set the yaml file according to algorithm name
        :param algorithm_name: the name of the algorithm
        :return: yaml file
        """

        switcher = {
            self.algorithms_files[0]: "lstm_params.yaml",
            self.algorithms_files[1]: "svr_params.yaml",
            self.algorithms_files[2]: "mlp_params.yaml",
            self.algorithms_files[3]: "random_forest_params.yaml",
        }

        return switcher.get(algorithm_name, None)

    def reinitialize(self):
        """
        Reinitialize frame values and view
        :return: new frame view
        """

        self.reinitialize_current_algorithm_options()

    def reinitialize_current_algorithm_options(self):
        """
        Reinitialize algorithm value and view
        :return: new frame view
        """

        self.current_algorithm = self.controller.get_current_algorithm_to_edit(
        )
        self.current_yaml = self.set_suitable_yaml_file(self.current_algorithm)
        self.controller.remove_algorithm(self.current_algorithm)

        self.options_to_show.destroy()
        self.options_to_show = AlgorithmFrameOptions(
            self, yaml_filename=self.current_yaml)
        self.options_to_show.place(relx=0.05, rely=0.35, height=268, width=620)
class ResultsWindow(tk.Frame):
    """
    A Class used to enable the user to choose a permutation of a results table

    Methods
    -------
    reset_widgets()
            Description | Reset check bar values

    back_window()
            Description | Handle a click on back button

    toggle_results()
            Description | Toggle permutation of results

    reinitialize()
            Description | Reinitialize frame values and view

    """
    def __init__(self, parent, controller):
        """
        Parameters
        ----------

        :param parent: window
        :param controller: GUI controller
        """

        tk.Frame.__init__(self, parent)

        # Page init
        self.controller = controller
        self.menubar = Menubar(controller)
        # Disables ability to tear menu bar into own window
        self.controller.option_add('*tearOff', 'FALSE')
        system_logo = CROSS_WINDOWS_SETTINGS.get('LOGO')
        photo_location = os.path.join(system_logo)
        global logo_img
        logo_img = tk.PhotoImage(file=photo_location)

        # Page header
        self.logo_png = HoverButton(self)
        self.logo_png.place(relx=0.28, rely=0.029, height=172, width=300)
        set_logo_configuration(self.logo_png, image=logo_img)

        # Page body
        self.toggle_results_button = HoverButton(self,
                                                 command=self.toggle_results)
        self.toggle_results_button.place(relx=0.68,
                                         rely=0.5,
                                         height=25,
                                         width=81)
        set_button_configuration(self.toggle_results_button,
                                 text='''Show results''')

        # Page footer
        self.back_button = HoverButton(self, command=self.back_window)
        self.back_button.place(relx=0.017, rely=0.839, height=25, width=81)
        set_button_configuration(self.back_button, text='''Home page''')

        self.copyright = tk.Label(self)
        self.copyright.place(relx=0, rely=0.958, height=25, width=750)
        set_copyright_configuration(self.copyright)

    def reset_widgets(self):
        """
        Reset check bar values
        :return: empty values in the widgets
        """

        pass

    def back_window(self):
        """
        Handle back button click
        :return: Home page window
        """

        self.controller.reset_frame()
        self.controller.reset_input_settings_params()
        self.controller.show_frame("MainWindow")

    def toggle_results(self):
        """
        Toggle permutation of results
        :return: updated permutation which was selected by the user
        """
        selected_algorithm = self.parameters['algorithm'].get()
        selected_flight_route = self.parameters['flight_route'].get()
        selected_similarity_function = self.parameters[
            'similarity_function'].get()

        self.controller.set_results_selected_algorithm(selected_algorithm)
        self.controller.set_results_selected_flight_route(
            selected_flight_route)
        self.controller.set_results_selected_similarity_function(
            selected_similarity_function)

        self.controller.reinitialize_frame("ResultsTableWindow")

    def reinitialize(self):
        """
        Reinitialize frame values and view
        :return: new frame view
        """

        new_model_running = self.controller.get_new_model_running()
        if new_model_running:
            chosen_algorithms = list(self.controller.get_algorithms())
        else:
            chosen_algorithms = list(
                self.controller.get_existing_algorithms().keys())

        flight_routes = list(self.controller.get_flight_routes())
        similarity_functions = list(self.controller.get_similarity_functions())

        transformed_chosen_algorithms = transform_list(chosen_algorithms)
        transformed_flight_routes = transform_list(flight_routes)
        transformed_similarity_functions = transform_list(similarity_functions)

        self.instructions = tk.Label(self)
        self.instructions.place(relx=0.015, rely=0.3, height=32, width=635)
        self.instructions.configure(
            text=
            "Choose an algorithm and a flight route in order to get the results."
        )
        set_widget_to_left(self.instructions)

        # Algorithm and Flight route permutation choice
        self.parameters = {}

        # set dynamic pair of label and combo box to select an algorithm
        set_widget_for_param(frame=self,
                             text="Algorithm:",
                             combobox_values=transformed_chosen_algorithms,
                             param_key="algorithm",
                             relative_x=0.05,
                             y_coordinate=0.4)

        # set dynamic pair of label and combo box to select a flight route
        set_widget_for_param(frame=self,
                             text="Flight route:",
                             combobox_values=transformed_flight_routes,
                             param_key="flight_route",
                             relative_x=0.45,
                             y_coordinate=0.4)

        # set dynamic pair of label and combo box to select a similarity function
        set_widget_for_param(frame=self,
                             text="Similarity:",
                             combobox_values=transformed_similarity_functions,
                             param_key="similarity_function",
                             relative_x=0.05,
                             y_coordinate=0.45)
Example #13
0
class ResultsTableWindow(tk.Frame):
    """
    A Class used to present a results table permutation by an algorithm and a flight route

    Methods
    -------
    reset_widgets()
            Description | Reset check bar values

    back_window()
            Description | Handle a click on back button

    reinitialize()
            Description | Reinitialize frame values and view

    reinitialize_results_table()
            Description | Reinitialize results table and view

    generate_table_columns_list()
            Description | Generates a list of columns for table init by given attacks

    """
    def __init__(self, parent, controller):
        """
        Parameters
        ----------

        :param parent: window
        :param controller: GUI controller
        """

        tk.Frame.__init__(self, parent)

        # Page init
        self.controller = controller
        self.menubar = Menubar(controller)
        # Disables ability to tear menu bar into own window
        self.controller.option_add('*tearOff', 'FALSE')
        system_logo = CROSS_WINDOWS_SETTINGS.get('LOGO')
        comparison_logo = CROSS_WINDOWS_SETTINGS.get('RESULTS')
        photo_location = os.path.join(system_logo)
        comparison_location = os.path.join(comparison_logo)
        global logo_img, comparison_img
        logo_img = tk.PhotoImage(file=photo_location)
        comparison_img = tk.PhotoImage(file=comparison_location)

        # Page header
        self.logo_png = tk.Button(self)
        self.logo_png.place(relx=0.28, rely=0.029, height=172, width=300)
        set_logo_configuration(self.logo_png, image=logo_img)

        # Page body
        self.results_table = Table(self,
                                   columns=[
                                       "Metric", "Down attack", "Up attack",
                                       "Fore attack", "Random attack"
                                   ],
                                   header_anchor=CENTER,
                                   column_minwidths=[1, 1, 1],
                                   pady=2)
        self.results_table.pack(fill=X, padx=18, pady=182)

        self.comparison_png = tk.Button(self)
        self.comparison_png.place(relx=0.65, rely=0.7, height=150, width=145)
        set_logo_configuration(self.comparison_png, image=comparison_img)

        # Page footer
        self.back_button = HoverButton(self, command=self.back_window)
        self.back_button.place(relx=0.017, rely=0.839, height=25, width=81)
        set_button_configuration(self.back_button, text='''Back''')

        self.copyright = tk.Label(self)
        self.copyright.place(relx=0, rely=0.958, height=25, width=750)
        set_copyright_configuration(self.copyright)

    def reset_widgets(self):
        """
        Reset check bar values
        :return: empty values in the widgets
        """

        pass

    def back_window(self):
        """
        Handle back button click
        :return: previous window
        """

        self.controller.reinitialize_frame("ResultsWindow")

    def reinitialize(self):
        """
         Reinitialize frame values and view
         :return: new frame view
         """

        self.reinitialize_results_table()

    def reinitialize_results_table(self):
        """
         Reinitialize results table and view
         :return: new frame view
         """

        try:
            # Handle suitable flow
            new_model_running = self.controller.get_new_model_running()

            if new_model_running:
                chosen_algorithms = list(self.controller.get_algorithms())
            else:
                chosen_algorithms = list(
                    self.controller.get_existing_algorithms().keys())

            flight_routes = list(self.controller.get_flight_routes())
            similarity_functions = list(
                self.controller.get_similarity_functions())

            # selected values with transformation to UI components
            selected_algorithm = self.controller.get_results_selected_algorithm(
            )
            selected_flight_route = self.controller.get_results_selected_flight_route(
            )
            selected_similarity_function = self.controller.get_results_selected_similarity_function(
            )

            original_algorithm = ""

            for algorithm in chosen_algorithms:
                if trim_unnecessary_chars(
                        algorithm).lower() == selected_algorithm.lower():
                    original_algorithm = algorithm

            original_flight_route = ""

            for route in flight_routes:
                if trim_unnecessary_chars(
                        route).lower() == selected_flight_route.lower():
                    original_flight_route = route

            original_similarity_function = ""

            for similarity_function in similarity_functions:
                if trim_unnecessary_chars(similarity_function).lower(
                ) == selected_similarity_function.lower():
                    original_similarity_function = similarity_function

            current_title = 'Test set attacks comparison table'

            self.instructions = tk.Label(self)
            self.instructions.place(relx=0.015,
                                    rely=0.29,
                                    height=35,
                                    width=635)
            self.instructions.configure(text=current_title)
            set_widget_to_left(self.instructions)

            results_data = self.controller.get_results_metrics_data()

            data = results_data[original_algorithm][original_flight_route][
                original_similarity_function]

            attacks_columns = list(data.values())[0]

            transform_attacks_list = transform_list(
                list(attacks_columns.keys()))
            table_columns = self.generate_table_columns_list(
                transform_attacks_list)

            self.results_table.pack_forget()
            # self.results_table.destroy()
            self.results_table = Table(self,
                                       columns=table_columns,
                                       header_anchor=CENTER,
                                       column_minwidths=[1, 1, 1],
                                       pady=2)
            self.results_table.pack(fill=X, padx=18, pady=182)

            # Creates a 2D array, all set to 0
            rows = len(data.keys()) + 2
            columns = len(attacks_columns)
            zero_matrix = [[0 for i in xrange(columns)] for i in xrange(rows)]
            self.results_table.set_data(zero_matrix)

            # Set the updated values to the table
            for i, metric in enumerate(data.keys()):
                attacks_data = data[metric]
                if metric.upper() == 'DELAY':
                    self.results_table.cell(i, 0, metric.upper() + " [sec]")
                else:
                    self.results_table.cell(i, 0, metric.upper())
                for j, attack in enumerate(attacks_data.keys()):
                    self.results_table.cell(i, j + 1, attacks_data[attack])

            self.results_table.cell(rows - 2, 0, "Attack duration [sec]")
            for i in range(1, columns + 1):
                self.results_table.cell(
                    rows - 2, i,
                    str(
                        float(results_data[original_algorithm]
                              [original_flight_route][
                                  list(attacks_columns.keys())[i - 1] +
                                  "_attack_duration"])))

            self.results_table.cell(rows - 1, 0, "Flight duration [sec]")
            for i in range(1, columns + 1):
                self.results_table.cell(
                    rows - 1, i,
                    str(
                        float(results_data[original_algorithm]
                              [original_flight_route][
                                  list(attacks_columns.keys())[i - 1] +
                                  "_duration"])))

            permutation_styling = Font(family="Times New Roman",
                                       size=11,
                                       weight=BOLD)

            self.algorithm_label = tk.Label(self)
            self.algorithm_label.place(relx=0.015,
                                       rely=0.68,
                                       height=25,
                                       width=300)
            self.algorithm_label.configure(
                text="Algorithm: {0}".format(selected_algorithm),
                font=permutation_styling,
                fg='blue')
            set_widget_to_left(self.algorithm_label)

            self.similarity_function_label = tk.Label(self)
            self.similarity_function_label.place(relx=0.015,
                                                 rely=0.72,
                                                 height=25,
                                                 width=300)
            self.similarity_function_label.configure(
                text="Similarity function: {0}".format(
                    selected_similarity_function),
                font=permutation_styling,
                fg='blue')
            set_widget_to_left(self.similarity_function_label)

            self.route_label = tk.Label(self)
            self.route_label.place(relx=0.015, rely=0.76, height=25, width=300)
            self.route_label.configure(
                text="Flight route: {0}".format(selected_flight_route),
                font=permutation_styling,
                fg='blue')
            set_widget_to_left(self.route_label)

        except Exception as e:
            # Handle error in setting new data in the table
            print("Source: gui/windows/results_table_window.py")
            print("Function: reinitialize_results_table")
            print("error: " + str(e))

    def generate_table_columns_list(self, attacks_list):
        """
        Generates a list of columns for table init by given attacks
        :param attacks_list: all existing attacks in the test data set
        :return: full columns list for creating a new results table
        """

        table_columns = ["Metric"]

        for attack in attacks_list:
            table_columns.append(attack)

        return table_columns
class TuneModel(tk.Frame):
    """
    A Class used to tune model parameters by user selection

    Methods
    -------
    reset_widgets()
            Description | Reset check bar values

    back_window()
            Description | Handle a click on back button

    next_window()
            Description | Handle a click on next button

    get_features_columns_options()
            Description | Get selected data set columns by the user

    reinitialize()
            Description | Reinitialize frame values and view

    get_selected_features()
            Description | Get selected features by the user

    browse_command()
            Description | Set the path to entry widget

    validate_next_step()
            Description | Validation before passing to next step

    select_all_features
            Description | Select/Clear all input features

    select_all_targets
            Description | Select/Clear all target features

    select_all_windows
            Description | Select/Clear all window sizes

    """
    def __init__(self, parent, controller):
        """
        Parameters
        ----------

        :param parent: window
        :param controller: GUI controller
        """

        tk.Frame.__init__(self, parent)

        # Page init
        self.controller = controller
        self.menubar = Menubar(controller)
        # Disables ability to tear menu bar into own window
        self.controller.option_add('*tearOff', 'FALSE')
        system_logo = CROSS_WINDOWS_SETTINGS.get('LOGO')
        photo_location = os.path.join(system_logo)
        global logo_img
        logo_img = tk.PhotoImage(file=photo_location)

        # Page header
        self.logo_png = tk.Button(self)
        self.logo_png.place(relx=0.28, rely=0.029, height=172, width=300)
        set_logo_configuration(self.logo_png, image=logo_img)

        self.instructions = tk.Label(self)
        self.instructions.place(relx=0.015, rely=0.3, height=32, width=635)
        self.instructions.configure(
            text='''Please select your choice for parameters tuning:''')
        set_widget_to_left(self.instructions)

        # Page body
        self.input_instructions = tk.Label(self)
        self.input_instructions.place(relx=0.05,
                                      rely=0.34,
                                      height=22,
                                      width=100)
        self.input_instructions.configure(text='''Input features:''')
        set_widget_to_left(self.input_instructions)

        self.target_instructions = tk.Label(self)
        self.target_instructions.place(relx=0.3,
                                       rely=0.34,
                                       height=22,
                                       width=100)
        self.target_instructions.configure(text='''Target features:''')
        set_widget_to_left(self.target_instructions)

        self.window_instructions = tk.Label(self)
        self.window_instructions.place(relx=0.55,
                                       rely=0.34,
                                       height=22,
                                       width=100)
        self.window_instructions.configure(text='''Window sizes:''')
        set_widget_to_left(self.window_instructions)

        self.algorithm_instructions = tk.Label(self)
        self.algorithm_instructions.place(relx=0.78,
                                          rely=0.42,
                                          height=25,
                                          width=130)
        self.algorithm_instructions.configure(text='''Algorithm:''')
        set_widget_to_left(self.algorithm_instructions)

        self.reinitialize()

        # Page footer
        self.next_button = HoverButton(self, command=self.next_window)
        self.next_button.place(relx=0.813, rely=0.839, height=25, width=81)
        set_button_configuration(self.next_button, text='''Next''')

        self.back_button = HoverButton(self, command=self.back_window)
        self.back_button.place(relx=0.017, rely=0.839, height=25, width=81)
        set_button_configuration(self.back_button, text='''Back''')

        self.copyright = tk.Label(self)
        self.copyright.place(relx=0, rely=0.958, height=25, width=750)
        set_copyright_configuration(self.copyright)

    def reset_widgets(self):
        """
        Reset check bar values
        :return: empty values in the widgets
        """

        self.features_listbox.selection_clear(0, tk.END)
        self.target_features_listbox.selection_clear(0, tk.END)
        self.window_size_listbox.selection_clear(0, tk.END)

    def back_window(self):
        """
        Handle back button click
        :return: previous window
        """

        self.controller.set_new_model_running(False)
        self.controller.show_frame("MainWindow")

    def next_window(self):
        """
        Handle a click on next button
        :return: if validations pass move to next window
        """

        if not self.validate_next_step():
            return
        else:
            current_features, target_features, chosen_window_sizes = self.get_selected_features(
            )
            self.controller.set_tune_model_configuration(
                current_features, target_features, chosen_window_sizes,
                self.algorithm_combo.get())
            self.controller.reinitialize_frame("TuningLoadingWindow")

    def get_features_columns_options(self):
        """
        Get selected data set columns by the user
        :return: selected columns
        """

        return self.controller.get_tune_model_features()

    def reinitialize(self):
        """
        Reinitialize frame values and view
        :return: new frame view
        """

        self.features_columns_options = {}
        self.features_columns_options = self.get_features_columns_options()

        self.csv_features = tk.StringVar()
        self.csv_features.set(self.features_columns_options)

        self.input_indicator = False
        self.target_indicator = False
        self.windows_indicator = False

        self.select_all_features_button = tk.Button(
            self, command=self.select_all_features)
        self.select_all_features_button.place(relx=0.17,
                                              rely=0.38,
                                              height=18,
                                              width=55)
        set_button_configuration(self.select_all_features_button,
                                 text='''Select all''')
        self.select_all_features_button.configure(bg='sandy brown')

        self.features_listbox = tk.Listbox(
            self,
            font=tkfont.Font(size=9),
            listvariable=self.csv_features,
            selectmode=tk.MULTIPLE,
            exportselection=
            0,  # Fix : ComboBox clears unrelated ListBox selection
            width=120,
            height=180,
            bd=3,
            bg='antique white',
            selectbackground='sandy brown')
        self.features_listbox.place(relx=0.05,
                                    rely=0.42,
                                    height=230,
                                    width=140)

        self.select_all_target_button = tk.Button(
            self, bg='sky blue', command=self.select_all_target)
        self.select_all_target_button.place(relx=0.42,
                                            rely=0.38,
                                            height=18,
                                            width=55)
        set_button_configuration(self.select_all_target_button,
                                 text='''Select all''')
        self.select_all_target_button.configure(bg='sandy brown')

        self.target_features_listbox = tk.Listbox(
            self,
            font=tkfont.Font(size=9),
            listvariable=self.csv_features,
            selectmode=tk.MULTIPLE,
            exportselection=0,
            # Fix : ComboBox clears unrelated ListBox selection
            width=120,
            height=180,
            bd=3,
            bg='antique white',
            selectbackground='sandy brown')
        self.target_features_listbox.place(relx=0.3,
                                           rely=0.42,
                                           height=230,
                                           width=140)

        window_options = tk.StringVar()
        numbers = list(range(1, 16))
        window_options.set([str(i) for i in numbers])

        self.select_all_windows_button = tk.Button(
            self, bg='sky blue', command=self.select_all_windows)
        self.select_all_windows_button.place(relx=0.67,
                                             rely=0.38,
                                             height=18,
                                             width=55)
        set_button_configuration(self.select_all_windows_button,
                                 text='''Select all''')
        self.select_all_windows_button.configure(bg='sandy brown')

        self.window_size_listbox = tk.Listbox(
            self,
            font=tkfont.Font(size=9),
            listvariable=window_options,
            selectmode=tk.MULTIPLE,
            exportselection=0,
            # Fix : ComboBox clears unrelated ListBox selection
            width=120,
            height=180,
            bd=3,
            bg='antique white',
            selectbackground='sandy brown')
        self.window_size_listbox.place(relx=0.55,
                                       rely=0.42,
                                       height=230,
                                       width=140)

        algorithms_list = load_anomaly_detection_list()

        self.algorithm_combo = ttk.Combobox(self,
                                            state="readonly",
                                            values=algorithms_list)
        self.algorithm_combo.place(relx=0.78, rely=0.47, height=25, width=130)
        self.algorithm_combo.current(0)

    def get_selected_features(self):
        """
        Get selected features by the user
        :return: selected features
        """

        features = []
        target_features = []
        window_sizes = []

        selection = self.features_listbox.curselection()
        target_selection = self.target_features_listbox.curselection()
        window_selection = self.window_size_listbox.curselection()

        for i in selection:
            selected = self.features_listbox.get(i)
            features.append(selected)

        for i in target_selection:
            target_selected = self.target_features_listbox.get(i)
            target_features.append(target_selected)

        for i in window_selection:
            window_selected = self.window_size_listbox.get(i)
            window_sizes.append(window_selected)

        return features, target_features, window_sizes

    def validate_next_step(self):
        """
        Validation before passing to next step
        :return: True in case validation passed, otherwise False
        """

        current_features, target_features, chosen_window_sizes = self.get_selected_features(
        )
        if not current_features \
                or not target_features \
                or not chosen_window_sizes \
                or len(chosen_window_sizes) < 1 \
                or len(current_features) < 2 \
                or len(target_features) < 2:
            win32api.MessageBox(
                0,
                'Please select at least two features for input, two features for output and window size before the next step.',
                'Invalid Feature', 0x00001000)
            return False

        return True

    def select_all_features(self):
        """
        Select/Clear all input features
        :return: selected/cleared listbox
        """

        if self.input_indicator:
            self.features_listbox.selection_clear(0, tk.END)
            self.select_all_features_button.configure(bg='sandy brown',
                                                      text='''Select all''')
        else:
            self.features_listbox.select_set(0, tk.END)
            self.select_all_features_button.configure(bg='firebrick1',
                                                      text='''Clear all''')

        self.input_indicator = not self.input_indicator

    def select_all_target(self):
        """
        Select/Clear all target features
        :return: selected/cleared listbox
        """

        if self.target_indicator:
            self.target_features_listbox.selection_clear(0, tk.END)
            self.select_all_target_button.configure(bg='sandy brown',
                                                    text='''Select all''')
        else:
            self.target_features_listbox.select_set(0, tk.END)
            self.select_all_target_button.configure(bg='firebrick1',
                                                    text='''Clear all''')

        self.target_indicator = not self.target_indicator

    def select_all_windows(self):
        """
        Select/Clear all windows sizes
        :return: selected/cleared listbox
        """

        if self.windows_indicator:
            self.window_size_listbox.selection_clear(0, tk.END)
            self.select_all_windows_button.configure(bg='sandy brown',
                                                     text='''Select all''')
        else:
            self.window_size_listbox.select_set(0, tk.END)
            self.select_all_windows_button.configure(bg='firebrick1',
                                                     text='''Clear all''')

        self.windows_indicator = not self.windows_indicator
Example #15
0
class AlgorithmsWindow(tk.Frame):
    """
    A Class used to enable the user the option to choose algorithms

    Methods
    -------
    reset_widgets()
            Description | Reset check bar values

    show_algorithms_options(algorithm_name)
            Description | Show the parameters options window

    set_algorithm_parameters(algorithm_name, algorithm_parameters)
            Description | Set updated parameters' values

    remove_algorithm_parameters(algorithm_name, algorithm_parameters)
            Description | Remove parameters' values

    check_algorithm_selected()
            Description | Validates that any algorithm was selected before continue to next window

    check_algorithm_parameters_edited()
            Description | Validates that algorithm's parameters was changed before approve save functionality

    validate_next_step()
            Description | Validates that algorithm was selected and the parameters were updated before
                          moving to next window

    next_window()
            Description | Handle a click on next button

    set_algorithm_checked()
            Description | Set each algorithm that was checked by the check button

    """
    def __init__(self, parent, controller):
        """
        Parameters
        ----------

        :param parent: window
        :param controller: GUI controller
        """

        tk.Frame.__init__(self, parent)

        # Page init
        self.controller = controller
        self.menubar = Menubar(controller)
        # Disables ability to tear menu bar into own window
        self.controller.option_add('*tearOff', 'FALSE')
        system_logo = CROSS_WINDOWS_SETTINGS.get('LOGO')
        photo_location = os.path.join(system_logo)
        global logo_img
        logo_img = tk.PhotoImage(file=photo_location)

        # Page header
        self.logo_png = tk.Button(self)
        self.logo_png.place(relx=0.28, rely=0.029, height=172, width=300)
        set_logo_configuration(self.logo_png, image=logo_img)

        self.instructions = tk.Label(self)
        self.instructions.place(relx=0.015, rely=0.3, height=32, width=635)
        self.instructions.configure(
            text=
            '''Please select the algorithms for which you want to build anomaly detection models.'''
        )
        set_widget_to_left(self.instructions)

        # Page body
        self.anomaly_detection_methods = Checkbar(
            self,
            picks=load_anomaly_detection_list(),
            editButtons=True,
            checkCallback=self.set_algorithm_checked)
        self.anomaly_detection_methods.place(relx=0.1,
                                             rely=0.35,
                                             height=400,
                                             width=700)

        # Page footer
        self.next_button = HoverButton(self, command=self.next_window)
        self.next_button.place(relx=0.813, rely=0.839, height=25, width=81)
        set_button_configuration(self.next_button, text='''Next''')

        self.back_button = HoverButton(
            self, command=lambda: controller.show_frame("NewModel"))
        self.back_button.place(relx=0.017, rely=0.839, height=25, width=81)
        set_button_configuration(self.back_button, text='''Back''')

        self.copyright = tk.Label(self)
        self.copyright.place(relx=0, rely=0.958, height=25, width=750)
        set_copyright_configuration(self.copyright)

    def reset_widgets(self):
        """
        Reset check bar values
        :return: empty values in the widgets
        """

        for check, button, var in zip(
                self.anomaly_detection_methods.get_checks(),
                self.anomaly_detection_methods.get_buttons(),
                self.anomaly_detection_methods.get_vars()):
            button['state'] = 'disabled'
            var.set(0)
            check['variable'] = var
            check['state'] = 'active'

    def show_algorithms_options(self, algorithm_name):
        """
        Show the parameters options window
        :param algorithm_name: input algorithm
        :return: new window opened
        """

        self.controller.set_current_algorithm_to_edit(algorithm_name)
        self.controller.reinitialize_frame("ParametersOptionsWindow")

    def set_algorithm_parameters(self, algorithm_name, algorithm_parameters):
        """
        Set updated parameters' values
        :param algorithm_name: input algorithm
        :param algorithm_parameters:  parameters to update
        :return: updated parameters' values for a given algorithm
        """

        self.controller.set_algorithm_parameters(algorithm_name,
                                                 algorithm_parameters)

    def remove_algorithm_parameters(self, algorithm_name,
                                    algorithm_parameters):
        """
        Remove parameters' values
        :param algorithm_name: input algorithm
        :param algorithm_parameters: parameters to remove
        :return: empty values for give parameters
        """

        self.controller.remove_algorithm_parameters(algorithm_name,
                                                    algorithm_parameters)

    def check_algorithm_selected(self):
        """
        Validates that any algorithm was selected before continue to next window
        :return: True if valid, otherwise False
        """

        for check, var in zip(self.anomaly_detection_methods.get_checks(),
                              self.anomaly_detection_methods.get_vars()):
            if var.get():
                return True
        win32api.MessageBox(0, 'Please select algorithm before the next step.',
                            'Invalid Algorithm', 0x00001000)

        return False

    def check_algorithm_parameters_edited(self):
        """
        Validates that algorithm's parameters was changed before approve save functionality
        :return: True if valid, otherwise False
        """

        selected_algorithms = self.controller.get_algorithms()

        for check, var in zip(self.anomaly_detection_methods.get_checks(),
                              self.anomaly_detection_methods.get_vars()):
            current_algorithm = check.cget("text")
            algoritm_selected = var.get()
            if algoritm_selected and current_algorithm not in selected_algorithms:
                win32api.MessageBox(
                    0,
                    'Please edit algorithm parameters before the next step.',
                    'Invalid Parameters', 0x00001000)
                return False

        return True

    def validate_next_step(self):
        """
        Validates that algorithm was selected and the parameters were updated before moving to next window
        :return: True if valid, otherwise False
        """

        if self.check_algorithm_selected(
        ) and self.check_algorithm_parameters_edited():
            return True

        return False

    def next_window(self):
        """
        Handle a click on next button
        :return: if validations pass move to next window
        """

        if self.validate_next_step():
            self.controller.reinitialize_frame("FeatureSelectionWindow")

    def set_algorithm_checked(self):
        """
        Set each algorithm that was checked by the check button
        :return: updated input settings
        """

        for check, var in zip(self.anomaly_detection_methods.get_checks(),
                              self.anomaly_detection_methods.get_vars()):
            if not var.get():
                self.controller.remove_algorithm(check.cget("text"))