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
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
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)
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")
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)
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")
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")
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)
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
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"))