def __init__(self, parent, controller): tk.Frame.__init__(self, parent) df = self.get_cryptocurrency() tb_m = TableModel(dataframe=df) table = Table(self, model=tb_m) table.show() table.redraw()
def __init__(self, parent, controller): tk.Frame.__init__(self, parent) df = self.get_history() tb_m = TableModel(dataframe=df) table = Table(self, model=tb_m) table.show() #alter the DataFrame in some way, then update table.redraw()
def open_file(): file = filedialog.askopenfilename( initialdir="/home/pi/Desktop/AutomatedCableTester", title="Select file", filetypes=(("csv files", "*.csv"), ("all files", "*.*"))) if len(file) != 0 and ".csv" in file: t = tk.Toplevel() pt = Table(t) pt.importCSV(file) pt.redraw() pt.show()
class Standings(tk.Frame): def __init__(self, df, parent=None): self.parent = parent tk.Frame.__init__(self) self.main = self.master f = tk.Frame(self.main) f.pack(fill=tk.BOTH, expand=1) self.table = Table(f, dataframe=df, read_only=True, showstatusbar=True) self.table.show() def update(self, standings) -> None: self.table.updateModel(TableModel(standings)) self.table.redraw()
class DataPanel(): def __init__(self, root): self.frame3 = Tk.Frame(root) self.frame3.__init__() self.frame3.pack(fill=Tk.BOTH, expand=1) df = pandas.DataFrame() self.table = Table(self.frame3, dataframe=df, showtoolbar=True, showstatusbar=True) self.table.show() def update(self, file_path): self.table.importCSV(file_path) self.table.redraw()
def Table_It(): All_Data = requests.get("https://api.covid19api.com/summary") All_Data = All_Data.json() All_Data = All_Data["Countries"] countries = [] Tot_Case5 = [] Tot_Case7 = [] Tot_Case9 = [] Tot_Case11 = [] for i in All_Data: countries.append(i["Country"]) for i in All_Data: Tot_Case5.append(i["TotalConfirmed"]) for i in All_Data: Tot_Case7.append(i["TotalDeaths"]) for i in All_Data: Tot_Case9.append(i["TotalRecovered"]) for i in All_Data: Tot_Case11.append(i["Date"]) frame = Frame(pencere) frame.place(x=1000, y=0, height=652, width=900) df1 = { "Country": countries, "Confirmed": Tot_Case5, "Deaths": Tot_Case7, "Recovered": Tot_Case9, "Date": Tot_Case11 } df = DataFrame(df1) table = Table(frame, dataframe=df) table.columncolors["Confirmed"] = "#ff6666" table.columncolors["Deaths"] = "#8c8c8c" table.columncolors["Recovered"] = "#94ff9b" table.redraw() table.show()
def show_details(): # declares that showing will refer to the global variable mentioned above instead of to a local variable for this function global showing # toggles on or off by testing whether or not the details are already showing if showing == False: # flips the switch to on. showing = True # declares all of these future variables as global ones so they can be refered to the next time the function runs. global dt # Simply creates a block of text and appends it to the Mainframe(See below for more details) for each variable. # .grid just forces a positon for the newly created label. dt = Table(mainframe, dataframe=StockQuotesCall()) dt.grid(column=10, row=0, sticky=(N, W, E, S)) dt.show() dt.redraw() else: # No matter what I use, dt.close(), dt.grid_forget, dt.pack_forget, dt.pack_remove, dt.grid_remove, dt.destroy, none of them works properly with the table. # Must be mod error showing = False # dt.grid_forget()
class DataFrame(tk.Frame): label = "View Data" def __init__(self, *args, **kwargs): tk.Frame.__init__(self, *args, **kwargs) self.columnconfigure(index=0, weight=1) self.rowconfigure(index=1, weight=1) self.create_widgets() def show(self): self.tkraise() def create_widgets(self): # Create buttons to manage the DB. self.toolbar = tk.Frame(self) self.toolbar.grid(row=0, column=0, padx=12, pady=3, sticky="NSEW") for col in range(12): self.toolbar.columnconfigure(index=col, weight=1) self.save_button = tk.Button( self.toolbar, text="Save Data To DB", command=self.save_to_db) self.export_button = tk.Button( self.toolbar, text="Export Data to File", command=self.export_data) self.import_button = tk.Button( self.toolbar, text="Import Data from CSV", command=self.import_csv) self.refresh_button = tk.Button( self.toolbar, text="Refresh Data from DB", command=self.refresh_table_data) self.save_button.grid(row=0, column=12) self.export_button.grid(row=0, column=11) self.import_button.grid(row=0, column=10) self.refresh_button.grid(row=0, column=9) self.table_container = tk.Frame(self) self.table_container.grid(row=1, column=0, sticky="NSEW") # Create table to display data data_df = DataStore.data self.data_table = Table(self.table_container, dataframe=data_df) self.data_table.autoResizeColumns() self.data_table.show() def refresh_table_data(self): res = tkMessageBox.askyesno(title="Are you sure you want to refresh the DB.", message="Are you sure that you want to refresh the DB.\n" "This will undo any changes that you made before saving your data. This includes CSV file that you have imported") if res == tkMessageBox.NO: return data_df = get_db_data() DataStore.data = data_df self.data_table.updateModel(TableModel(data_df)) self.data_table.redraw() def export_data(self): output_file = tkFileDialog.askopenfilename() if not output_file: tkMessageBox.showerror(title="Export Failed", message="Export failed as no file was selected.") return def save_to_db(self): add_df_to_db(DataStore.data) def import_csv(self): # Get file to import input_file = tkFileDialog.askopenfilename() if not input_file.strip(): tkMessageBox.showerror(title="Import Failed", message="Import failed as no file was selected.") return try: import_df = pd.read_csv(input_file) except ParserError: tkMessageBox.showerror( "The supplied file is not a valid CSV file, could not import.") if len(import_df) > 0: # Data was loaded. DataStore.data.reset_index(level=["id_product"], inplace=True) table_df = DataStore.data.append(import_df, ignore_index=False) table_df.set_index("id_product", inplace=True) DataStore.data = table_df self.data_table.updateModel(TableModel(table_df)) self.data_table.redraw() tkMessageBox.showinfo(title="Import Successful", message="Import Completed Successfully!") else: tkMessageBox.showinfo(title="Import Failed", message="Input file did not have any CSV data so no data was added.")
def run_algo(): print("run") global node_file, edge_file node_file = pd.read_csv(ent_node_loc.get()) edge_file = pd.read_csv(ent_edge_loc.get()) sample_size = int(ent_sample_size.get()) / 100 adjacency_list = fileProcessor(edge_file, node_file) edge_list = adjtoedgelist(adjacency_list) global n n = len(adjacency_list) m = len(edge_list) print("Original Graph") print("len of al = ", n) print("len of el = ", m) rnAdj, rnEdge = randomNode(adjacency_list, sample_size) reAdj, reEdge = randomEdge(edge_list, sample_size) rwAdj, rwEdge = randomWalk(adjacency_list, sample_size) org = dig(adjacency_list) re = dig(reAdj) rn = dig(rnAdj) rw = dig(rwAdj) frm_dist = tk.Frame(frm_preview) frm_dist.pack(expand=tk.TRUE, fill=tk.BOTH) dist.clear() canvas = FigureCanvasTkAgg(fig, frm_dist) dist.plot(list(org.keys()), list(org.values()), label='Original Graph') dist.plot(list(rn.keys()), list(rn.values()), label="Random Node") dist.plot(list(re.keys()), list(re.values()), label="Random Edge") dist.plot(list(rw.keys()), list(rw.values()), label="Random Walk") dist.set_title("Smaple size : " + str(sample_size)) dist.set_xlabel("Degree") dist.set_ylabel("Number of nodes") fig.legend(loc='upper right') canvas.draw() canvas.get_tk_widget().pack(side=tk.TOP, expand=tk.TRUE, fill=tk.BOTH) toolbar = NavigationToolbar2Tk(canvas, frm_dist) toolbar.update() canvas._tkcanvas.pack(side=tk.TOP, expand=tk.TRUE, fill=tk.BOTH) ## Generating reports g = {} # algorithms = ["Original graph","Random Node", "Random Edge", "Random Walk"] g["Original graph"] = (adjacency_list, edge_list) g["Random Node"] = (rnAdj, rnEdge) g["Random Edge"] = (reAdj, reEdge) g["Random Walk"] = (rwAdj, rwEdge) total_node = {} total_edge = {} max_degree = {} min_degree = {} avg_degree = {} for gr in g: adj, edge = g[gr] total_node[gr] = len(adj) total_edge[gr] = len(edge) d = cal_degree(adj) max_degree[gr] = max(d.values()) min_degree[gr] = min(d.values()) avg_degree[gr] = sum(list(d.values())) / len(d.values()) # print("d : ", d) # print("avg_degree ", gr, " : ", avg_degree[gr]) # print(gr, " -- ", len(adj), " -- ", len(edge)) report["Total Nodes"] = report['Algorithm'].map(total_node) report["Total Edges"] = report['Algorithm'].map(total_edge) report["Average_Degree"] = report['Algorithm'].map(avg_degree) report["Maximum_Degree"] = report['Algorithm'].map(max_degree) report["Minimum_Degree"] = report['Algorithm'].map(min_degree) lbl_res = tk.LabelFrame(frm_result, text="Result") lbl_res.pack(expand=tk.TRUE, fill=tk.BOTH) pt = Table(lbl_res, dataframe=report) pt.show() pt.autoResizeColumns() pt.redraw()
class JobSearch: def __init__(self, tk_parent, linkedin_conn): self.parent = tk_parent self.linkedin_conn = linkedin_conn self.search_results_df = pd.DataFrame() self.search_thread = None self.quick_search = True # Paned Window self.search_paned_window = ttk.PanedWindow(tk_parent, orient='horizontal') self.search_paned_window.pack(side='top', fill="both", expand=True, padx=10) ## Search fields Canvas/ScrolledFrame search_fields_canvas = ttk.Canvas(self.search_paned_window) search_fields_frame = ScrolledFrame(search_fields_canvas) search_fields_frame.pack(side='top', fill='both', expand=True, padx=5) search_fields_frame.hide_scrollbars() ### Load/Save search load_save_btn_frame = ttk.Frame(search_fields_frame) load_save_btn_frame.pack(pady=5, side='top', fill="x") load_search_btn = ttk.Button(load_save_btn_frame, text="Load param.") load_search_btn.pack(side='left') load_search_btn['command'] = self.load_search_config save_search_btn = ttk.Button(load_save_btn_frame, text="Save param.") save_search_btn.pack(side='right', padx=10) save_search_btn['command'] = self.save_search_config ### KW-Frame kw_frame = ttk.Frame(search_fields_frame) kw_frame.pack(pady=5, side='top', fill="x") ttk.Label(kw_frame, text="Keywords").pack(side='left') self.entry_keywords = ttk.Entry(kw_frame) self.entry_keywords.pack(side='left', padx=10, fill='x', expand=True) ttk.Separator(search_fields_frame, orient='horizontal').pack(side='top', fill='x', pady=5) ### Radio Frame radio_frame = ttk.Frame(search_fields_frame) radio_frame.pack(side='top', fill="x", pady=5, expand=True) radio_frame.grid_columnconfigure(0,weight=0) radio_frame.grid_columnconfigure(1,weight=0) radio_frame.grid_columnconfigure(2,weight=1) #### Sort by ttk.Label(radio_frame, text="Sort by").grid(row=0, column=0, sticky='nwse') self.sort_by = ttk.StringVar(value="R") ttk.Radiobutton(radio_frame, text='Most recent', variable=self.sort_by, value="DD").grid(row=0, column=1, padx=10, sticky='nwse') ttk.Radiobutton(radio_frame, text='Most relevant', variable=self.sort_by, value="R").grid(row=0, column=2, padx=10, sticky='nwse') ttk.Separator(radio_frame, orient='horizontal').grid(row=1, columnspan=3, pady=5, sticky='nwse') #### Date Posted ttk.Label(radio_frame, text="Date Posted").grid(row=2, column=0, sticky='nwse', pady=5) self.date_posted = ttk.IntVar(value=365) # Days since job was posted ttk.Radiobutton(radio_frame, text='Past 24h', variable=self.date_posted, value=1).grid(row=3, column=1, padx=10, pady=4, sticky='nwse') ttk.Radiobutton(radio_frame, text='Past Week', variable=self.date_posted, value=7).grid(row=3, column=2, padx=10, pady=4, sticky='nwse') ttk.Radiobutton(radio_frame, text='Past Month', variable=self.date_posted, value=30).grid(row=4, column=1, padx=10, pady=4, sticky='nwse') ttk.Radiobutton(radio_frame, text='Any Time', variable=self.date_posted, value=365).grid(row=4, column=2, padx=10, pady=4, sticky='nwse') ttk.Separator(search_fields_frame, orient='horizontal').pack(side='top', fill='x', pady=5) ### Experience exp_frame = ttk.Frame(search_fields_frame) exp_frame.pack(side='top', fill="x") exp_frame.grid_columnconfigure(0,weight=0) exp_frame.grid_columnconfigure(1,weight=0) exp_frame.grid_columnconfigure(2,weight=1) ttk.Label(exp_frame, text="Experience").grid(row=0, column=0, pady=4, sticky='nwse') intern_lvl_bool = ttk.BooleanVar() entry_lvl_bool = ttk.BooleanVar() associate_bool = ttk.BooleanVar() mid_senior_bool = ttk.BooleanVar() director_bool = ttk.BooleanVar() executive_bool = ttk.BooleanVar() self.exp_dict_list = [ {'bool_val': intern_lvl_bool, 'name': '1'}, {'bool_val': entry_lvl_bool, 'name': '2'}, {'bool_val': associate_bool, 'name': '3'}, {'bool_val': mid_senior_bool, 'name': '4'}, {'bool_val': director_bool, 'name': '5'}, {'bool_val': executive_bool, 'name': '6'}, ] ttk.Checkbutton(exp_frame, text="Internship", variable=intern_lvl_bool).grid(row=1, column=0, padx=5, pady=4, sticky='nwse') ttk.Checkbutton(exp_frame, text="Entry level", variable=entry_lvl_bool).grid(row=1, column=1, padx=5, pady=4, sticky='nwse') ttk.Checkbutton(exp_frame, text="Associate", variable=associate_bool).grid(row=1, column=2, padx=5, pady=4, sticky='nwse') ttk.Checkbutton(exp_frame, text="Mid-Senior level", variable=mid_senior_bool).grid(row=2, column=0, padx=5, pady=4, sticky='nwse') ttk.Checkbutton(exp_frame, text="Director", variable=director_bool).grid(row=2, column=1, padx=5, pady=4, sticky='nwse') ttk.Checkbutton(exp_frame, text="Executive", variable=executive_bool).grid(row=2, column=2, padx=5, pady=4, sticky='nwse') ttk.Separator(search_fields_frame, orient='horizontal').pack(side='top', fill='x', pady=5) ### Company frame self.comp_frame = SearchFrame(search_fields_frame, title='Company', fetch_fct=lambda x: utils.extract_urn_dict_from_query_results(linkedin_conn[0].get_company_urn_ids, x)) self.comp_frame.pack(side='top', fill="x") ttk.Separator(search_fields_frame, orient='horizontal').pack(side='top', fill='x', pady=5) ### Job Type job_type_frame = ttk.Frame(search_fields_frame) job_type_frame.pack(side='top', fill="x") job_type_frame.grid_columnconfigure(0,weight=0) job_type_frame.grid_columnconfigure(1,weight=0) job_type_frame.grid_columnconfigure(2,weight=1) ttk.Label(job_type_frame, text="Job Type").grid(row=0, column=0, pady=4, sticky='nwse') full_time_bool = ttk.BooleanVar() part_time_bool = ttk.BooleanVar() temporary_bool = ttk.BooleanVar() contract_bool = ttk.BooleanVar() volunteer_bool = ttk.BooleanVar() intern_type_bool = ttk.BooleanVar() other_type_bool = ttk.BooleanVar() self.job_type_dict_list = [ {'bool_val': full_time_bool, 'name': 'F'}, {'bool_val': part_time_bool, 'name': 'P'}, {'bool_val': temporary_bool, 'name': 'T'}, {'bool_val': contract_bool, 'name': 'C'}, {'bool_val': volunteer_bool, 'name': 'V'}, {'bool_val': intern_type_bool, 'name': 'I'}, {'bool_val': other_type_bool, 'name': 'O'}, ] ttk.Checkbutton(job_type_frame, text="Other", variable=other_type_bool).grid(row=0, column=2, padx=10, pady=4, sticky='nwse') ttk.Checkbutton(job_type_frame, text="Full-time", variable=full_time_bool).grid(row=1, column=0, padx=10, pady=4, sticky='nwse') ttk.Checkbutton(job_type_frame, text="Part-time", variable=part_time_bool).grid(row=1, column=1, padx=10, pady=4, sticky='nwse') ttk.Checkbutton(job_type_frame, text="Temporary", variable=temporary_bool).grid(row=1, column=2, padx=10, pady=4, sticky='nwse') ttk.Checkbutton(job_type_frame, text="Contract", variable=contract_bool).grid(row=2, column=0, padx=10, pady=4, sticky='nwse') ttk.Checkbutton(job_type_frame, text="Volunteer", variable=volunteer_bool).grid(row=2, column=1, padx=10, pady=4, sticky='nwse') ttk.Checkbutton(job_type_frame, text="Internship", variable=intern_type_bool).grid(row=2, column=2, padx=10, pady=4, sticky='nwse') ttk.Separator(search_fields_frame, orient='horizontal').pack(side='top', fill='x', pady=5) ### Location Fallback self.loc_fallback_frame = SearchFrame(search_fields_frame, title='General Location', single_choice=True, fetch_fct=lambda x: utils.extract_urn_dict_from_query_results(linkedin_conn[0].get_geo_urn_ids, x), tooltip="Restrict the geographical area of the results. In the browser, your location will be recognized automatically and shown at the top of the search page close to the keyword field.") self.loc_fallback_frame.pack(side='top', fill="x") ### Location Frame self.loc_frame = SearchFrame(search_fields_frame, title='Location', fetch_fct=lambda x: utils.extract_urn_dict_from_query_results(linkedin_conn[0].get_geo_urn_ids, x)) self.loc_frame.pack(side='top', fill="x") ttk.Separator(search_fields_frame, orient='horizontal').pack(side='top', fill='x', pady=5) ### Industry frame self.industry_frame = SearchFrame(search_fields_frame, title='Industry', fetch_fct=lambda x: utils.extract_urn_dict_from_query_results(linkedin_conn[0].get_industry_urn_ids, x)) self.industry_frame.pack(side='top', fill="x", pady=5) self.search_paned_window.add(search_fields_canvas) ## Table frame self.table_main_frame = ttk.Frame(tk_parent) # pandastable self.table_frame = ttk.Frame(self.table_main_frame, bootstyle="secondary", borderwidth=2) self.table_frame.pack(side="top", fill="both", expand=True) self.table = Table(self.table_frame, dataframe=pd.DataFrame(), showtoolbar=False, showstatusbar=True) utils.fit_table_style_to_theme(self.table, ttk.Style()) self.table.unbind_all("<Tab>") self.table.unbind_all("<Return>") self.table.show() self.search_paned_window.add(self.table_main_frame) # Buttons frame btn_frame = ttk.Frame(tk_parent) btn_frame.pack(padx=10, pady=10, side='top', fill="x") quick_search_btn = ttk.Button(btn_frame, text="Quick search") quick_search_btn.pack(side='left', padx=10) quick_search_btn['command'] = self.start_quick_search ToolTip(quick_search_btn, "This is a single request that will yield the same results as in the linkedin search bar. \ \nIt doesn't contain any personal details (only public IDs) \ \nYou're not likely to reach any search limit using this mode.") btn_sub_frame = ttk.Frame(btn_frame) btn_sub_frame.pack(side="left", fill="none", expand=True) start_search_btn = ttk.Button(btn_sub_frame, text="Deep Search", bootstyle='danger') start_search_btn.pack(side='left', padx=10) start_search_btn['command'] = self.start_deep_search ToolTip(start_search_btn, "Each search result will be fetched for additional information. \ \nDepending on the number of results and search frequency, this can trigger the linkedin limit \ after which you'll only be able to get 3 results per search until the end of the month.") # self.get_contact_info = ttk.BooleanVar() # contact_info_chk_btn = ttk.Checkbutton(btn_sub_frame, text="Fetch contact info", # variable=self.get_contact_info, bootstyle="danger") # contact_info_chk_btn.pack(side='left', padx=10) # ToolTip(contact_info_chk_btn, text=f"Fetch contact info by running one additional request per result.") self.export_to_file_btn = ttk.Button(btn_frame, text="Export to File", state="disabled") self.export_to_file_btn.pack(side='left', padx=10) self.export_to_file_btn['command'] = self.prepare_dataframe_and_save_to_xsl # Status frame self.status_frame = ttk.Frame(tk_parent) self.status_frame.pack(padx=10, pady=2, side='bottom', expand=False, fill="x") self.status_str = ttk.StringVar(value="") ttk.Label(self.status_frame, textvariable=self.status_str).pack(side='left', expand=False) ttk.Separator(tk_parent, orient='horizontal').pack(side='bottom', fill='x') def save_search_config(self): chosen_file = filedialog.asksaveasfile(mode='w', filetypes=[("JSON", ".json")], defaultextension=".json") if chosen_file is None: return config_dict = { 'job_search' : { 'keywords': self.entry_keywords.get(), 'sort_by' : self.sort_by.get(), 'listed_at' : 24 * 3600 * self.date_posted.get(), 'experience' : [x['name'] for x in self.exp_dict_list if x['bool_val'].get()], 'companies' : [[x.lbl_name.get(), x.value] for x in self.comp_frame.get_current_selection()], 'job_type' : [x['name'] for x in self.job_type_dict_list if x['bool_val'].get()], 'location' : [[x.lbl_name.get(), x.value] for x in self.loc_frame.get_current_selection()], 'industries' : [[x.lbl_name.get(), x.value] for x in self.industry_frame.get_current_selection()] } } with open(chosen_file.name, 'w') as f: json.dump(config_dict, f, indent=4) self.status_str.set(f"Search config successfully saved at {chosen_file.name}!") def load_search_config(self): chosen_file = filedialog.askopenfile(mode='r', filetypes=[("JSON", ".json")], defaultextension=".json") if chosen_file is None: return try: with open(chosen_file.name, 'r') as f: config_dict = json.load(f) config = config_dict['job_search'] except: self.status_str.set(f"Please select a valid job search configuration!") self.entry_keywords.delete(0,'end') self.entry_keywords.insert(0, config['keywords']) self.sort_by.set(config['sort_by']) self.date_posted.set(config['listed_at']//(24 * 3600)) utils.set_bools_from_list(self.exp_dict_list, config['experience']) self.comp_frame.load_name_val_from_list(config['companies']) utils.set_bools_from_list(self.job_type_dict_list, config['job_type']) self.loc_frame.load_name_val_from_list(config['location']) self.industry_frame.load_name_val_from_list(config['industries']) self.status_str.set(f"Config loaded succesfully!") def run_search(self): self.search_results_df = pd.DataFrame() self.table.updateModel(TableModel(self.search_results_df)) self.table.redraw() self.status_str.set("Running search...") self.parent.update() loc_fallback = None if self.loc_fallback_frame.get_current_selection(): loc_fallback = self.loc_fallback_frame.get_current_selection()[0].lbl_name.get() try: # see doc under https://linkedin-api.readthedocs.io/en/latest/api.html search_result = self.linkedin_conn[0].search_jobs( keywords=self.entry_keywords.get(), sort_by=self.sort_by.get(), listed_at=24 * 3600 * self.date_posted.get(), companies=[x.value for x in self.comp_frame.get_current_selection()], experience=[x['name'] for x in self.exp_dict_list if x['bool_val'].get()], job_type=[x['name'] for x in self.job_type_dict_list if x['bool_val'].get()], location_name = loc_fallback, geo_urn_ids=[x.value for x in self.loc_frame.get_current_selection()], industries=[x.value for x in self.industry_frame.get_current_selection()], ) if self.quick_search: self.search_results_df = pd.DataFrame(search_result) try: self.search_results_df.drop(['dashEntityUrn', '$recipeTypes', '$type'], axis=1, inplace=True) self.search_results_df['companyDetails'] = self.search_results_df['companyDetails'].apply( lambda x: x.get('company', '').rsplit(':', 1)[-1] ) self.search_results_df.rename(columns={'companyDetails': 'companyUrn'}, inplace=True) self.search_results_df['entityUrn'] = self.search_results_df['entityUrn'].str.rsplit(':', 1, expand=True)[1] self.search_results_df['listedAt'] = self.search_results_df['listedAt'].apply( lambda x : datetime.fromtimestamp(x/1000).date() ) except Exception as e: print(repr(e)) self.table.updateModel(TableModel(self.search_results_df)) self.table.redraw() else: result_size = len(search_result) self.status_str.set("Found " + str(result_size) + " results! Searching jobs details... This can take a while...") self.parent.update() if result_size > 999: answer_is_yes = messagebox.askyesno("Too many results!", "This search yields more than 1000 results (upper limit for this app).\nProceed anyway?", icon="warning") if not answer_is_yes: self.status_str.set("Search cancelled.") self.parent.update() return row = 1 for job in search_result: job_obj = self.linkedin_conn[0].get_job(job['dashEntityUrn'].rsplit(':',1)[1]) if job_obj != {}: job_dict = { 'Title': job_obj['title'], 'Company': job_obj['companyDetails'] .get('com.linkedin.voyager.deco.jobs.web.shared.WebCompactJobPostingCompany', {}, ).get('companyResolutionResult', {} ).get('name', ''), 'Location': job_obj['formattedLocation'], 'Description': job_obj.get('description', {}).get('text', ''), #'Remote': job_obj['workRemoteAllowed'], 'Work Place': job_obj.get('workplaceTypesResolutionResults', {}) .get('urn:li:fs_workplaceType:1', {}) .get('localizedName', ''), 'Posted On': datetime.fromtimestamp(job_obj['listedAt']/1000).date(), 'LinkedIn Link': f"https://www.linkedin.com/jobs/view/{job_obj['jobPostingId']}", 'Direct Link': job_obj.get('applyMethod',{}) .get('com.linkedin.voyager.jobs.OffsiteApply', {} ).get('companyApplyUrl', '').split('?', 1)[0] } # if self.get_contact_info.get(): # contact_info = self.linkedin_conn[0].get_profile_contact_info(urn_id=job['urn_id']) # contact_info = {k: [v] for k,v in contact_info.items()} # job_dict.update(contact_info) self.search_results_df = pd.concat([self.search_results_df, pd.DataFrame([job_dict.values()], columns=job_dict.keys())]) self.table.updateModel(TableModel(self.search_results_df)) self.table.redraw() self.status_str.set("Scanned " + str(row) + " out of " + str(result_size) + " profiles") self.parent.update() row += 1 self.export_to_file_btn.configure(state="normal") self.status_str.set("Done") self.parent.update() except Exception as e: utils.show_exception(e) self.status_str.set("Something went wrong! Check console output for more details.") self.parent.update() def create_search_thread(self): if not self.linkedin_conn[0]: messagebox.showinfo("Error", "First log into Linkedin!", icon="error") return if self.search_thread and self.search_thread.is_alive(): messagebox.showinfo("Search in progress", "Another search is still running.\nWait until it finishes or restart the program.", icon="warning") return self.search_thread = threading.Thread(target=self.run_search) self.search_thread.daemon = True self.search_thread.start() def start_quick_search(self): self.quick_search = True self.create_search_thread() def start_deep_search(self): self.quick_search = False self.create_search_thread() def prepare_dataframe_and_save_to_xsl(self): self.status_str.set("Exporting to File...") export_file = utils.save_dataframe_to_file(self.search_results_df) if export_file is not None: self.status_str.set("Table saved under " + export_file) else: self.status_str.set("Table could not be saved!")
class CallScreenerOptions(tk.ttk.Frame): def __init__(self, root): super().__init__() self.tk_root = root self.close_button = None self.status_label = None self.call_screener_frame = None self.popup_expiration_menu = None self.expiration_var = tk.StringVar(self) self.otm_strike_var = tk.StringVar(self) self.otm_list = ["15%", "5%", "ATM", "10%", "20%"] self.request_queue = Queue() self.response_queue = Queue() self.status_var = tk.StringVar(self) self.init_ui() self.logger = self.create_logger() # self.web = FinanceWeb(self.logger) self.options_db = FinanceDB() self.options_db.initialize() self.companies = OptionsScreenerWatch() self.init_table() self.clear_expiration_menu() self.clear_otm_strike_menu() config = OptionsConfiguration() look_a_heads = ( config.get_configuration())["screener_look_ahead_expirations"] expiration_list = self.get_expirations(look_a_heads) self.update_expiration(expiration_list) self.expiration_var.set(expiration_list[0]) self.update_otm_strike(self.otm_list) self.otm_strike_var.set(self.otm_list[0]) self.temp() self.options_fetch = OptionsFetch(self.request_queue, self.response_queue, self.logger) self.options_fetch.start() self.update_options() self.tk_root.protocol("WM_DELETE_WINDOW", self.quit_app) @staticmethod def get_expirations(count): expiration_date = datetime.datetime.now() result = [] while count > 0: date_str = expiration_date.strftime('%Y-%m-%d') (is_third_friday, date_time) = Utilities.is_third_friday(date_str) if is_third_friday: result.append(date_time.strftime('%Y-%m-%d')) count -= 1 expiration_date += datetime.timedelta(days=1) return result # noinspection PyUnusedLocal def quit_app(self, event=None): print("Exit command") with self.request_queue.mutex: self.request_queue.queue.clear() self.request_queue.put("QUIT") self.options_fetch.join() sys.exit() def clear_call_screener_frame(self): for widget in self.call_screener_frame.winfo_children(): widget.destroy() def create_logger(self): # noinspection SpellCheckingInspection log_format = "%(asctime)s %(levelname)s %(module)s - %(funcName)s: %(message)s" date_fmt = "%m-%d %H:%M" for handler in logging.root.handlers[:]: logging.root.removeHandler(handler) logging.basicConfig(filename="screen_options.log", level=logging.INFO, filemode="w", format=log_format, datefmt=date_fmt) stream_handler = logging.StreamHandler(sys.stderr) stream_handler.setFormatter( logging.Formatter(fmt=log_format, datefmt=date_fmt)) logger = logging.getLogger("screen_options") logger.addHandler(stream_handler) logger.setLevel(logging.DEBUG) return logger def init_ui(self): self.master.title("Option Screener") # frame2 = Frame(self, relief=RAISED, borderwidth=1, style='My.TFrame') tool_bar = tk.ttk.Frame(self, relief=tk.RAISED, borderwidth=1) tool_bar.pack(fill=tk.X, side=tk.TOP, expand=False) self.pack(fill=tk.BOTH, expand=True) start_date_label = tk.ttk.Label(tool_bar, text="Expiration") start_date_label.pack(side=tk.LEFT, padx=5, pady=5) self.popup_expiration_menu = tk.OptionMenu(tool_bar, self.expiration_var, *{''}) self.popup_expiration_menu.config(width=16) self.popup_expiration_menu.pack(side=tk.LEFT, padx=5, pady=5) self.expiration_var.trace('w', self.expiration_var_selection_event) otm_label = tk.ttk.Label(tool_bar, text="OTM Strike delta (%)") otm_label.pack(side=tk.LEFT, padx=10, pady=5) self.otm_strike_menu = tk.OptionMenu(tool_bar, self.otm_strike_var, *{''}) self.otm_strike_menu.config(width=10) self.otm_strike_menu.pack(side=tk.LEFT, padx=5, pady=5) self.otm_strike_var.trace('w', self.otm_strike_var_selection_event) self.close_button = tk.ttk.Button(tool_bar, text="Close") self.close_button.pack(side=tk.RIGHT, padx=5, pady=5) self.close_button.bind('<Button-1>', self.quit_app) tool_bar_style = Style() tool_bar_style.theme_use("default") tool_bar_style.configure('My.TFrame', background='lightsteelblue') self.call_screener_frame = tk.ttk.Frame(self, relief=tk.RAISED, borderwidth=1) self.call_screener_frame.pack(fill=tk.BOTH, side=tk.TOP, expand=True) self.status_var.set("Status") self.status_label = tk.ttk.Label(self, textvariable=self.status_var, background="lightsteelblue") self.status_label.pack(side=tk.BOTTOM, fill=tk.X, expand=False, ipadx=10, ipady=5) # noinspection PyAttributeOutsideInit def init_table(self): table_dict = {} for company in self.companies.get_companies(): table_dict[company["symbol"]] = [ company["symbol"], math.nan, math.nan, math.nan, math.nan, math.nan, math.nan, math.nan, math.nan, math.nan, math.nan ] self.data_frame = pd.DataFrame.from_dict( table_dict, orient='index', columns=[ 'Ticker', 'Stock Price', 'Strike', '%(OTM)', 'Bid', 'Ask', 'ROI(%) (Bid/Stock Price)', 'Annual ROI(%)', 'Implied Volatility', 'Delta', 'Theta' ]) self.table = Table(self.call_screener_frame, dataframe=self.data_frame, showtoolbar=False, showstatusbar=True) self.table.show() self.check_response() def clear_expiration_menu(self): self.expiration_var.set('') self.popup_expiration_menu['menu'].delete(0, 'end') def clear_otm_strike_menu(self): self.otm_strike_var.set('') self.otm_strike_menu['menu'].delete(0, 'end') def update_expiration(self, choices): for choice in choices: self.popup_expiration_menu['menu'].add_command( label=choice, command=lambda value=choice: self.expiration_var.set(value)) def update_otm_strike(self, choices): for choice in choices: self.otm_strike_menu['menu'].add_command( label=choice, command=lambda value=choice: self.otm_strike_var.set(value)) # noinspection PyUnusedLocal def expiration_var_selection_event(self, *args): if self.expiration_var.get(): self.__clear_table() self.table.redraw() def otm_strike_var_selection_event(self, *args): if self.otm_strike_var.get(): numbers = [i for i in self.otm_strike_var.get() if i.isdigit()] strings = [str(integer) for integer in numbers] a_string = "".join(strings) self.otm_percent = 0 if len(a_string) == 0 else int(a_string) self.__clear_table() self.table.redraw() def __clear_table(self): with self.request_queue.mutex: self.request_queue.queue.clear() for index, row in self.data_frame.iterrows(): self.data_frame.loc[row['Ticker'], 'Stock Price'] = math.nan self.data_frame.loc[row['Ticker'], 'Strike'] = math.nan self.data_frame.loc[row['Ticker'], '%(OTM)'] = math.nan self.data_frame.loc[row['Ticker'], 'Bid'] = math.nan self.data_frame.loc[row['Ticker'], 'Ask'] = math.nan self.data_frame.loc[row['Ticker'], 'ROI(%) (Bid/Stock Price)'] = math.nan self.data_frame.loc[row['Ticker'], 'Annual ROI(%)'] = math.nan self.data_frame.loc[row['Ticker'], 'Implied Volatility'] = math.nan self.data_frame.loc[row['Ticker'], 'Delta'] = math.nan self.data_frame.loc[row['Ticker'], 'Theta'] = math.nan def update_options(self): if self.request_queue.empty(): self.status_var.set("Updating...") for company in self.companies.get_companies(): company["expiration"] = self.expiration_var.get() self.request_queue.put(company) self.status_var.set("") else: if self.logger: self.logger.info("Request Queue not empty yet") self.tk_root.after(15000, self.update_options) def check_response(self): if not self.response_queue.empty(): response = self.response_queue.get() if self.logger: if bool(response['options']): self.logger.info("Options received for {0}".format( response['company']['symbol'])) else: self.logger.warning("No Options received for {0}".format( response['company']['symbol'])) self.update_company_in_table(response) self.tk_root.after(500, self.check_response) def update_company_in_table(self, response) -> None: try: display_chain = response['options'] if bool(display_chain): company = display_chain["ticker"] best_index, otm_percent_actual = self.find_best_index( display_chain, self.otm_percent) if best_index != -1: self.data_frame.loc[ company, 'Stock Price'] = display_chain['current_value'] self.data_frame.loc[company, 'Strike'] = display_chain[ 'options_chain']['calls'].iloc[best_index]['strike'] self.data_frame.loc[company, '%(OTM)'] = otm_percent_actual self.data_frame.loc[company, 'Bid'] = display_chain[ 'options_chain']['calls'].iloc[best_index]['bid'] self.data_frame.loc[company, 'Ask'] = display_chain[ 'options_chain']['calls'].iloc[best_index]['ask'] roi_percent = round((display_chain['options_chain'] ['calls'].iloc[best_index]['bid'] / display_chain['current_value'] * 100), 2) self.data_frame.loc[ company, 'ROI(%) (Bid/Stock Price)'] = roi_percent self.data_frame.loc[company, 'Implied Volatility'] = \ round(display_chain['options_chain']['calls'].iloc[best_index]['impliedVolatility'] * 100, 2) now = datetime.datetime.now() expiration = datetime.datetime.strptime( self.expiration_var.get(), '%Y-%m-%d') delta = (expiration - now).days + 1 annual_roi = 365 / delta * roi_percent self.data_frame.loc[company, 'Annual ROI(%)'] = round( annual_roi, 2) if 'delta' in display_chain['options_chain'][ 'calls'].columns: self.data_frame.loc[company, 'Delta'] = \ display_chain['options_chain']['calls'].iloc[best_index]['delta'] if 'theta' in display_chain['options_chain'][ 'calls'].columns: self.data_frame.loc[company, 'Theta'] = \ display_chain['options_chain']['calls'].iloc[best_index]['theta'] else: if self.logger: self.logger.error( "No option available for {0}".format(company)) else: if self.logger: self.logger.error("No option available") except Exception as err: if self.logger: self.logger.error(err) self.table.redraw() def find_best_index(self, chain: {}, otm_percent) -> (int, float): best_index = 0 otm_percent_actual = math.nan index = 0 current_delta = 100 if len(chain['options_chain']['calls']) > 0: while index < len(chain['options_chain']['calls']): diff = chain['options_chain']['calls'].iloc[index][ 'strike'] - chain['current_value'] percent_diff = (diff / chain['current_value'] * 100) delta = otm_percent - percent_diff if abs(delta) < current_delta: current_delta = delta best_index = index otm_percent_actual = round(percent_diff, 2) index += 1 return best_index, otm_percent_actual else: return -1, 0 def temp(self): web = Utilities.get_options_API(self.logger) # response_dict = web.get_quote("MAR") # if response_dict != {}: # print("pass") # else: # print("fail") # # expirations_dict = web.get_expirations("MAR") # if expirations_dict != {}: # print("pass") # else: # print("fail") options_dict = web.get_options_for_symbol_and_expiration( "MAR", "2021-02-19") if options_dict != {}: print("pass") else: print("fail")
class DataViewer(Frame): def __init__(self, parent=None, filename='Diet.xlsx', modelDir="model/"): self.parent = parent self.__filename = filename self.__modelDirectory = modelDir Frame.__init__(self) self.main = self.master self.main.title('Diet Editor') if not os.path.isfile(filename): self.createInitialExcelFile(filename) self.df = pd.read_excel(filename, sheet_name="data") self.uf = pd.read_excel(filename, sheet_name="bounds") self.table = Table(self, dataframe=self.df) self.table.show() buttonsFrame = Frame(self) buttonsFrame.grid(column=0, columnspan=2) self.__progress=Progressbar(buttonsFrame, orient=HORIZONTAL, length=100,\ mode='determinate') self.__saveButton = Button(buttonsFrame, text="Save",\ command=self.saveData) self.__runButton = Button(buttonsFrame, text="Run",\ command=self.runModel) self.__userButton = Button(buttonsFrame, text="User",\ command=self.userData) self.__foodButton = Button(buttonsFrame, text="Food",\ command=self.foodData) self.__closeButton = Button(buttonsFrame, text="Close",\ command=self.destroy) self.__progress.pack(side=BOTTOM, fill=X) self.__saveButton.pack(fill=X, side=LEFT) self.__runButton.pack(fill=X, side=LEFT) self.__userButton.pack(fill=X, side=LEFT) self.__foodButton.pack(fill=X, side=LEFT) self.__closeButton.pack(fill=X, side=LEFT) self.__foodButton['state'] = DISABLED self.__selectedState = Sheets.FOOD return def createInitialExcelFile(self, filename): workbook = xlsxwriter.Workbook(filename) datasheet = workbook.add_worksheet('data') boundssheet = workbook.add_worksheet('bounds') # food entry datasheet.write('A1', 'Name') datasheet.write('B1', 'Price') datasheet.write('C1', 'Energy (kcal)') datasheet.write('D1', 'Protien (g)') datasheet.write('E1', 'Sodium (mg)') datasheet.write('F1', 'Carbohydrates (g)') datasheet.write('G1', 'Saturated Fat (g)') datasheet.write('H1', 'Fibre (g)') datasheet.write('I1', 'Vitamin A (ug)') datasheet.write('J1', 'Vitamin C (mg)') datasheet.write('K1', 'Calcium (mg)') datasheet.write('L1', 'Iron (mg)') datasheet.write('A2', 'Cake') datasheet.write('B2', '25') datasheet.write('C2', '59') datasheet.write('D2', '1') datasheet.write('E2', '110') datasheet.write('F2', '9.4') datasheet.write('G2', '2.2') datasheet.write('H2', '0.3') datasheet.write('I2', '0') datasheet.write('J2', '0') datasheet.write('K2', '20') datasheet.write('L2', '0.2') # user entry boundssheet.write('B1', 'Energy (kcal)') boundssheet.write('C1', 'Protien (g)') boundssheet.write('D1', 'Sodium (mg)') boundssheet.write('E1', 'Carbohydrates (g)') boundssheet.write('F1', 'Saturated Fat (g)') boundssheet.write('G1', 'Fibre (g)') boundssheet.write('H1', 'Vitamin A (ug)') boundssheet.write('I1', 'Vitamin C (mg)') boundssheet.write('J1', 'Calcium (mg)') boundssheet.write('K1', 'Iron (mg)') boundssheet.write('A2', 'LowerBound') boundssheet.write('B2', '1') boundssheet.write('C2', '1') boundssheet.write('D2', '1') boundssheet.write('E2', '1') boundssheet.write('F2', '1') boundssheet.write('G2', '1') boundssheet.write('H2', '1') boundssheet.write('I2', '1') boundssheet.write('J2', '1') boundssheet.write('K2', '1') boundssheet.write('A3', 'UpperBound') boundssheet.write('B3', '1') boundssheet.write('C3', '1') boundssheet.write('D3', '1') boundssheet.write('E3', '1') boundssheet.write('F3', '1') boundssheet.write('G3', '1') boundssheet.write('H3', '1') boundssheet.write('I3', '1') boundssheet.write('J3', '1') boundssheet.write('K3', '1') workbook.close() def foodData(self): self.__foodButton['state'] = DISABLED self.__userButton['state'] = NORMAL self.__selectedState = Sheets.FOOD self.uf = self.table.model.df self.table.updateModel(TableModel(self.df)) self.table.redraw() def userData(self): self.__foodButton['state'] = NORMAL self.__userButton['state'] = DISABLED self.__selectedState = Sheets.USER self.df = self.table.model.df self.table.updateModel(TableModel(self.uf)) self.table.redraw() def charRange(self, c1, c2): for c in range(ord(c1), ord(c2) + 1): yield chr(c) def saveData(self): if self.__selectedState == Sheets.FOOD: self.df = self.table.model.df if self.__selectedState == Sheets.USER: self.uf = self.table.model.df indices = len(self.df.index) setData=[] for v in self.charRange('A', 'L'): setData.append(v + '2:' + v + str(indices + 1)) modelSets=pd.DataFrame(setData) writer = pd.ExcelWriter(self.__filename, engine='xlsxwriter') self.df.to_excel(writer, sheet_name='data', index=False) self.uf.to_excel(writer, sheet_name='bounds', index=False) modelSets.to_excel(writer, sheet_name='metadata', index=False, header=False) saved = writer.save() def runModel(self): firstRun = True config = ConfigParser() config.read('config.ini') dss = edss.Service(config['elytica']['apiKey']) dss.login() self.__progress['value']=20 self.update_idletasks() if len(list(filter(lambda x : x.name == "DIET",\ dss.getProjects()))) > 0: dss.selectProjectByName("DIET") dss.selectJobByName("Basic Job") firstRun=False else: app = dss.selectApplicationByName("MIP Interpreter with Python") dss.createProject("DIET", "The diet problem.", app) dss.createJob("Basic Job", 100) self.__progress['value']=40 self.update_idletasks() md = self.__modelDirectory libDir = self.__modelDirectory + '/libraries/' modelFiles = [f for f in listdir(md) if isfile(join(md, f))] libraries = [f for f in listdir(libDir) if isfile(join(libDir, f))] firstRun = True if firstRun: for f in modelFiles: modelFile = open(md + f, "rb", buffering=0) uf = dss.uploadFileContents(f, modelFile); dss.assignFile(uf, 1) arg = 2 for f in libraries: libraryFile = open(libDir + f, "rb", buffering=0) uf = dss.uploadFileContents(f, libraryFile); dss.assignFile(uf, arg) arg += 1 self.__progress['value']=60 self.update_idletasks() countInputFiles = len(dss.getInputFiles()) excelData = open(self.__filename, "rb", buffering=0) dataFile = dss.uploadFileContents(self.__filename, excelData) dss.assignFile(dataFile, countInputFiles) self.__progress['value']=80 self.update_idletasks() dss.queueJob() self.__progress['value']=100 self.update_idletasks()
class TestApp(Frame): def __init__(self, parent=None): self.root = tk() root = self.root self.parent = parent Frame.__init__(self) top_frame = Frame(root) bottom = Frame(root) box_frame = Frame(top_frame) label_frame = Frame(box_frame) input_frame = Frame(box_frame) bottom.pack(side=BOTTOM, fill=BOTH, expand=True) # Packings top_frame.pack(side=TOP) bottom.pack(side=BOTTOM, fill=BOTH, expand=True) box_frame.pack(side=LEFT) label_frame.pack(side=TOP) input_frame.pack(side=BOTTOM) # create the widgets for the top part of the GUI, # and lay them out self.ticker_field = Text(top_frame, width=5, height=1) self.time_range = Text(top_frame, width=2, height=1) ticker_label = Label(top_frame, text="Ticker:", width=5, height=1) time_label = Label(top_frame, text="Hrs", width=2, height=1) button1 = Button(root, text="Recent Posts", width=10, height=2, command=self.recent_posts) button3 = Button(root, text="Summary", width=10, height=2, command=self.trending_posts) button2 = Button(root, text="All Posts", width=10, height=2, command=self.all_posts) button4 = Button(root, text="Open Url", width=10, height=2, command=self.open_url) button1.pack(in_=top_frame, side=LEFT) button3.pack(in_=top_frame, side=LEFT) button2.pack(in_=top_frame, side=LEFT) button4.pack(in_=top_frame, side=LEFT) ticker_label.pack(in_=label_frame, side=LEFT) time_label.pack(in_=label_frame, side=LEFT) self.ticker_field.pack(in_=input_frame, side=LEFT) self.time_range.pack(in_=input_frame, side=LEFT) self.main = self.master self.main.geometry('1200x800+200+100') self.main.title('Table app') # btn2 = Button(self.root, text="Ticker Post History", command=self.button2) # btn2.pack() # urlbtn = Button(self.root, text="Open url", command=self.open_url) # urlbtn.pack() self.f = Frame(self.main) self.f.pack(fill=BOTH, expand=1) # df = panda_db.get_trending() df = panda_db.get_all_posts("8") # df = panda_db.get_posts_by_ticker("AI") self.table = Table(self.f, dataframe=df, showtoolbar=True, showstatusbar=True) self.table.show() return def all_posts(self): date_range = str(self.time_range.get("1.0", END)) df = panda_db.get_all_posts(date_range) self.table = Table(self.f, dataframe=df, showtoolbar=True, showstatusbar=True) self.table.show() self.table.redraw() def recent_posts(self): ticker = str(self.ticker_field.get("1.0", END)) print(ticker) date_range = str(self.time_range.get("1.0", END)) self.f.pack_forget() df = panda_db.get_posts_by_ticker(ticker.upper(), date_range) self.f.pack(fill=BOTH, expand=1) self.table = Table(self.f, dataframe=df, showtoolbar=True, showstatusbar=True) self.table.show() self.table.redraw() def trending_posts(self): self.f.pack_forget() date_range = str(self.time_range.get("1.0", END)) df = panda_db.get_trending(date_range) self.f.pack(fill=BOTH, expand=1) self.table = Table(self.f, dataframe=df, showtoolbar=True, showstatusbar=True) self.table.show() self.table.redraw() def open_url(self): url = self.table.selection_get() webbrowser.register( 'chrome', None, webbrowser.BackgroundBrowser( "C://Users//awgra//AppData//Local//Google//Chrome//Application//chrome.exe" )) webbrowser.get('chrome').open(url)
class ImporterGUI: """ This class is the main gui and shows the import window, it also contains the main methods which uses other helper classes Attributes: root = the root tk previewFrame = the frame that shows the preview of the dataframe XMLList = the 2D list which holds the xml filepath on the index 0 and the xsl filepath on index 1 """ def __init__(self, root: Tk): self.root = root self.previewFrame = Frame(root) self.pt = Table(self.previewFrame) self.dialect = detector.Dialect() self.XMLList = [] self.DialectList = [] self.hasHeaderVar = BooleanVar() self.currentPath = "" h1 = Label(self.root, text="Imported Files", bg="#eee") h1.pack(padx=5, pady=5, fill="x") # Dialog Frame dialogFrame = Frame(self.root) dialogFrame.grid_columnconfigure(1, weight=1) Button(dialogFrame, text="Import Files", command=self.openFileDialog, width=20).grid(row=0, column=0) Button(dialogFrame, text="Delete selected File", command=self.deleteSelectedFile, width=20).grid(row=1, column=0) Button(dialogFrame, text="Delete all", command=self.deleteAllFiles, width=20).grid(row=2, column=0) # the outside frame for the files listbox (it holds the listbox and the scrollbar) listbox_border = Frame(dialogFrame, bd=2, relief="sunken", background="white") listbox_border.grid(row=0, column=1, rowspan=3, padx=3, sticky="nsew") # the actual listbox self.importedFiles = Listbox(listbox_border, selectmode=SINGLE, height=4, borderwidth=0, highlightthickness=0, relief=SUNKEN, background="white") self.importedFiles.bind("<<ListboxSelect>>", self.selectionChanged) # the scrollbar inside the listbox_border frame vsb = Scrollbar(listbox_border, orient="vertical", command=self.importedFiles.yview) self.importedFiles.configure(yscrollcommand=vsb) vsb.pack(side="right", fill="y") self.importedFiles.pack(padx=2, pady=2, fill="both", expand=True) dialogFrame.pack(fill="x", padx=10) # XSL File Frame (its disabled when a csv file is selected in the listbox, # and set to "normal" when a xml is selected h1 = Label(root, text="XSL File", bg="#eee") h1.pack(padx=5, pady=5, fill="x") xslFrame = Frame(root) self.importXSL_btn = Button(xslFrame, state=DISABLED, text="Import XSL File", command=self.openXSLFileDialog, width=20) self.importXSL_btn.grid(row=0, column=0) self.XSLPath_text = Text(xslFrame, height=1, borderwidth=2, relief=SUNKEN) self.XSLPath_text.grid(row=0, column=1) xslFrame.pack(fill="x", padx=10, pady=5) # Detector Frame h1 = Label(root, text="Detector", bg="#eee") h1.pack(padx=5, pady=5, fill="x") detectorFrame = Frame(root) Label(detectorFrame, text="Encoding:", width=20, anchor="w", justify="left").grid(row=0) self.encodingText = Text(detectorFrame, height=1, borderwidth=2, relief=SUNKEN, width=10) self.encodingText.grid(row=0, column=1) Label(detectorFrame, text="Has Header:", width=20, anchor="w", justify="left").grid(row=1) self.hasHeaderCheckbutton = Checkbutton(detectorFrame, var=self.hasHeaderVar, onvalue=1, offvalue=0) self.hasHeaderCheckbutton.grid(sticky="W", row=1, column=1) Label(detectorFrame, text="Seperator:", width=20, anchor="w", justify="left").grid(row=2) self.seperatorText = Text(detectorFrame, height=1, borderwidth=2, relief=SUNKEN, width=10) self.seperatorText.grid(row=2, column=1) Label(detectorFrame, text="Quote Char:", width=20, anchor="w", justify="left").grid(row=3) self.quoteCharText = Text(detectorFrame, height=1, borderwidth=2, relief=SUNKEN, width=10) self.quoteCharText.grid(row=3, column=1) Button(detectorFrame, text="Save Dialect Changes", command=self.saveDialectChanges, width=20).grid(row=4, column=0) detectorFrame.pack(fill="x", padx=10, pady=5) # dataframe preview frame preview = Label(root, text="Preview", bg="#eee") preview.pack(expand=TRUE, fill="x", padx=5, side=TOP) self.pt.show() self.previewFrame.pack(pady=10, padx=10, fill="both", side=TOP) # the bottom most centered export button which leads to the export window exportBtn = Button(root, text="Export", command=self.export, width=20, padx=0) exportBtn.pack(fill="x", padx=10, pady=10) def saveDialectChanges(self): """ saves the Dialect changes made by the user """ dialect = detector.Dialect() dialect.encoding = self.encodingText.get(1.0, 'end-1c') dialect.hasHeader = self.hasHeaderVar.get() dialect.delimiter = self.seperatorText.get(1.0, 'end-1c') dialect.quoteChar = self.quoteCharText.get(1.0, 'end-1c') if not self.currentPath: files = self.getImportedFiles() self.currentPath = files[0] path = self.currentPath print(path) if not any(path in x for x in self.DialectList): self.DialectList.append([path, dialect]) elif any(path in x for x in self.DialectList): x = [x for x in self.DialectList if path in x][0] self.DialectList[self.DialectList.index(x)][1] = dialect self.updateDf(self.getImportedFiles()) def selectionChanged(self, event): """ this is an event which is triggered by selection changed inside the listbox widget it checks if the selected file is a xml, if so it sets the textbox intractable for the user :param event: the event which called it """ selection = event.widget.curselection() if selection: data = event.widget.get(selection[0]) self.currentPath = data if data.endswith(".xml"): # disable encoding changes self.encodingText.delete(1.0, END) self.hasHeaderVar.set(False) self.seperatorText.delete(1.0, END) self.quoteCharText.delete(1.0, END) self.encodingText["state"] = "disabled" self.hasHeaderCheckbutton["state"] = "disabled" self.seperatorText["state"] = "disabled" self.quoteCharText["state"] = "disabled" self.importXSL_btn["state"] = "normal" if any(data in x for x in self.XMLList): x = [x for x in self.XMLList if data in x][0] self.XSLPath_text.delete(1.0, END) self.XSLPath_text.insert( 1.0, self.XMLList[self.XMLList.index(x)][1]) else: self.XSLPath_text.delete(1.0, END) self.XSLPath_text.insert(1.0, "please import a XSL File!") else: self.encodingText.delete(1.0, END) self.hasHeaderVar.set(False) self.seperatorText.delete(1.0, END) self.quoteCharText.delete(1.0, END) self.encodingText["state"] = "normal" self.hasHeaderCheckbutton["state"] = "normal" self.seperatorText["state"] = "normal" self.quoteCharText["state"] = "normal" self.importXSL_btn["state"] = "disabled" self.XSLPath_text.delete(1.0, END) if any(data in x for x in self.DialectList): x = [x for x in self.DialectList if data in x][0] dialect = self.DialectList[self.DialectList.index(x)][1] self.updateDialect(dialect) def openXSLFileDialog(self): """ this function is called if the user wants to import a xsl file in the xsl file frame it opens the filedialog and appends the xsl to the according xml into the XMLList attribute after that, it try's to update the dataframe and its preview by calling the update function """ file = askopenfilename(parent=self.root, title='Choose a file', filetypes=[("Extensible Stylesheet Language", "*.xsl"), ("All files", "*.*")]) self.XMLList.append( [self.importedFiles.get(self.importedFiles.curselection()), file]) self.XSLPath_text.delete(1.0, END) self.XSLPath_text.insert(1.0, file) self.updateDf(self.getImportedFiles()) def openFileDialog(self): """ this function opens the file dialog and imports the selected filepaths into the listbox and also calls the update function to redraw the new dataframe """ files = list( askopenfilenames(parent=self.root, title='Choose a file', filetypes=[("Excel files", ".xml .csv")])) self.updateSelectedFiles(files) self.updateDf(self.getImportedFiles()) def deleteSelectedFile(self): """ deletes the selected file from the listbox and redraws the dataframe since one of its source is deleted also if a xml file is deleted, it also deletes the corresponding xsl file from the XMLList """ path = self.importedFiles.get(self.importedFiles.curselection()) if path is self.currentPath: self.currentPath = "" # delete from dialect list if any(path in x for x in self.DialectList): x = [x for x in self.DialectList if path in x][0] self.DialectList.pop(self.DialectList.index(x)) index = self.importedFiles.get(0, END).index(path) self.importedFiles.delete(index) # delete from xml list if path.endswith(".xml"): x = [x for x in self.XMLList if path in x][0] self.XMLList.pop(self.XMLList.index(x)) self.updateDf(self.getImportedFiles()) def deleteAllFiles(self): """ deletes all imported filepaths from the listbox and also from the dataframe """ self.importedFiles.delete(0, END) self.currentPath = "" self.XMLList = [] self.DialectList = [] def getImportedFiles(self): """ :return: returns the selected filepath from the listbox """ return self.importedFiles.get(0, END) def updateSelectedFiles(self, files): """ after opening a file dialog, this method is called to pass the new imported filepaths into the listbox :param files: filespaths from the filedialog """ startIndex = self.importedFiles.size() for index, file in enumerate(files): self.importedFiles.insert(index + startIndex, file) def export(self): """ opens the export window and passes the dataframe from the preview frame """ importer.setDataFrame(self.pt.model.df) ExporterGUI(self.root, importer, self.dialect) def updateDf(self, files: list): """ checks if the dataframe can be updated by the newly imported filepaths calls the merge function if there is more than 1 file inside the filelist also udpates the detector frame (displaying dialect data) :param files: the whole filepath list """ if len(files) > 1 or len(self.XMLList) > 0: canMerge = merger.prepareMerge(files, self.XMLList, self.DialectList) self.DialectList = merger.dialectList if canMerge: newDataFrame = merger.mergeFiles() importer.setDataFrame(newDataFrame) self.pt.updateModel(TableModel(newDataFrame)) self.pt.redraw() elif len(files) > 0 and files[0].endswith(".csv"): if not any(files[0] in x for x in self.DialectList): self.dialect.guessDialectCSV(files[0]) self.DialectList.append([files[0], self.dialect]) else: x = [x for x in self.DialectList if files[0] in x][0] self.dialect = self.DialectList[self.DialectList.index(x)][1] importer.importCSV(files[0], self.dialect) updatedDataframe = importer.getDataFrame() self.pt.updateModel(TableModel(updatedDataframe)) self.pt.redraw() self.updateDialect(self.dialect) def updateDialect(self, dialect: detector.Dialect): """ updates the dialect text fields from the gui :param dialect: the new changed dialect """ # updates the dialect data self.encodingText.delete(1.0, END) self.encodingText.insert(1.0, dialect.encoding) self.hasHeaderVar.set(dialect.hasHeader) self.seperatorText.delete(1.0, END) self.seperatorText.insert(1.0, dialect.delimiter) self.quoteCharText.delete(1.0, END) self.quoteCharText.insert(1.0, dialect.quoteChar)
class Program: """Exampleprogram to show possible usage of the module csvxmlImporter""" __importer: CsvXmlImporter __settings: dict def __init__(self): """__init__ creates the tkinter gui""" self.__settings = {} self.__importer = CsvXmlImporter() # ***--*** main window and menu band ***---*** self.__root = ThemedTk(theme=theme) self.__root.title("Csv/Xml Importer") self.__root.minsize(560, 1) menu = Menu(self.__root) self.__root.config(menu=menu) filemenu = Menu(menu, tearoff=0) menu.add_cascade(label="File", menu=filemenu) filemenu.add_command(label="Add Files", command=self.add_files) filemenu.add_command(label="Remove All", command=self.remove_all) filemenu.add_separator() filemenu.add_command(label="Add xsl File", command=self.add_xslfile) filemenu.add_separator() filemenu.add_command(label="Exit", command=self.exit) helpmenu = Menu(menu, tearoff=0) menu.add_cascade(label="Help", menu=helpmenu) helpmenu.add_command(label="?", command=self.ask_help) helpmenu.add_command(label="About", command=self.ask_about) # ***---*** source file frame dialog ***---*** srcfilesframe = LabelFrame(self.__root, text="Sourcefiles") buttonframe = Frame(srcfilesframe) addbutton = Button(buttonframe, text="Add Files", command=self.add_files) addbutton.pack(fill=X) removefilesbutton = Button(buttonframe, text="Remove Selected", command=self.remove_files) removefilesbutton.pack(fill=X) removeallbutton = Button(buttonframe, text="Remove All", command=self.remove_all) removeallbutton.pack(fill=X) buttonframe.grid(column=1, row=1) self.__srcfileslistbox = Listbox(srcfilesframe, selectmode="extended", width=100, height=5) self.__srcfileslistbox.grid(column=2, row=1) Label(srcfilesframe, text="Encoding").grid(column=1, row=2, sticky=E) self.__settings["encoding"] = StringVar() self.__settings["encoding"].trace_add("write", self.update_settings) encCombobox = Combobox(srcfilesframe, textvariable=self.__settings["encoding"], values=encodings, state="readonly") encCombobox.bind("<FocusOut>", self.update_settings) encCombobox.grid(column=2, row=2, pady=10) srcfilesframe.pack(fill=X) # ***---*** xsl file dialog ***---*** xslfileframe = LabelFrame(self.__root, text="XSL-File") Button(xslfileframe, text="Add .xsl", command=self.add_xslfile).grid(column=1, row=1) self.__xsllistbox = Listbox(xslfileframe, width=100, height=1) self.__xsllistbox.grid(column=2, row=1, sticky="w") buttonframe = Frame(xslfileframe) Button(buttonframe, text="Apply Parameter", command=self.apply_xslparameter).pack(fill=X) Button(buttonframe, text="Restore Default", command=self.reset_xslparameter).pack(fill=X) buttonframe.grid(column=1, row=2) box = Frame(xslfileframe) self.__xslparametertext = Text(box, height=3, width=75) self.__xslparametertext.grid(column=0, row=1, sticky="nsew") scrollbar = Scrollbar(box, command=self.__xslparametertext.yview) scrollbar.grid(column=0, row=1, sticky="nse") box.grid(column=2, row=2, sticky="we") self.__xslparametertext["yscrollcommand"] = scrollbar.set xslfileframe.pack(fill=X) # ***---*** file format settings dialog ***---*** # small help function def limit_character(entry_text): """limit_characters cuts down the characters of an entry text to one""" if len(entry_text.get()) > 0: # take only last input character and throw away the rest entry_text.set(entry_text.get()[-1]) fileformatsettingsframe = LabelFrame(self.__root, text="File Format Settings") Label(fileformatsettingsframe, text="Delimiter").grid(column=1, row=1, sticky=E) self.__settings["delimiter"] = StringVar() seperatorentry = Entry(fileformatsettingsframe, textvariable=self.__settings["delimiter"], width=1) self.__settings["delimiter"].trace_add( "write", lambda *_: limit_character(self.__settings["delimiter"])) seperatorentry.bind("<Return>", self.update_settings) seperatorentry.bind("<FocusOut>", self.update_settings) seperatorentry.grid(column=2, row=1, sticky=W, padx=15) Label(fileformatsettingsframe, text="Quotechar").grid(column=1, row=2, sticky=E) self.__settings["quotechar"] = StringVar() quotecharentry = Entry(fileformatsettingsframe, textvariable=self.__settings["quotechar"], width=1) self.__settings["quotechar"].trace_add( "write", lambda *_: limit_character(self.__settings["quotechar"])) quotecharentry.bind("<Return>", self.update_settings) quotecharentry.bind("<FocusOut>", self.update_settings) quotecharentry.grid(column=2, row=2, sticky=W, padx=15) Label(fileformatsettingsframe, text="Doublequote").grid(column=1, row=3, sticky=E) self.__settings["doublequote"] = BooleanVar() Checkbutton(fileformatsettingsframe, variable=self.__settings["doublequote"], command=self.update_settings).grid(column=2, row=3, sticky=W, padx=10) Label(fileformatsettingsframe, text="Quoting").grid(column=1, row=5, sticky=E) quotingopt = {"minimal": 0, "all": 1, "non numeric": 2, "none": 3} self.__settings["quoting"] = IntVar() for i, (key, value) in enumerate(quotingopt.items()): Radiobutton( fileformatsettingsframe, text=key, value=value, variable=self.__settings["quoting"], command=self.update_settings, ).grid( column=2 + i, row=5, padx=10, sticky=W, ) Label(fileformatsettingsframe, text="Ignore spaces at beginning").grid(column=1, row=6, sticky=E) self.__settings["skipinitialspace"] = BooleanVar() self.__settings["skipinitialspace"].set(False) Checkbutton(fileformatsettingsframe, variable=self.__settings["skipinitialspace"], command=self.update_settings).grid(column=2, row=6, sticky=W, padx=10) fileformatsettingsframe.pack(fill=X) # ***---*** preview frame ***---*** previewframe = LabelFrame(self.__root, text="Preview") self.__pdtable = Table(parent=previewframe, dataframe=self.__importer.dfx) self.__pdtable.show() previewframe.pack(fill="both", expand=True) # ***---*** export button ***---*** exportframe = LabelFrame(self.__root, text="Export") Button(exportframe, text="Export", command=self.create_exportdialog).pack() exportframe.pack(fill="both", expand=True) # save settings to check for changes on update self.__prevsettings = self.__unpack_settings(self.__settings) def run(self): """run starts the mainloop of tkinter gui""" self.__root.mainloop() def exit(self): """exit closes tkinter application""" self.__root.destroy() def add_files(self): """add_files called by user to add files via dialog""" names = askopenfilenames(title="Select .csv or .xml files", filetypes=(("any", "*.*"), ("Csv File", "*.csv"), ("Xml File", "*.xml"))) if names: try: self.__srcfileslistbox.insert(END, *names) self.__importer.update_files( *self.__srcfileslistbox.get(0, END)) except AttributeError as e: showerror(title="Error", message="No .xsl file set") except ValueError as _: showerror(title="Error", message="Could not open files") self.__srcfileslistbox.delete(0, END) self.__update_table() self.__update_dialog() def remove_files(self): """remove_files called by user to remove in listbox selected files""" itemstodelete = self.__srcfileslistbox.curselection() if itemstodelete: for i in itemstodelete: self.__srcfileslistbox.delete(i) x = self.__srcfileslistbox.get(0, END) if x: self.__importer.update_files(*x) else: self.__importer.reset() self.__update_table() def remove_all(self): """remove_all called by user to remove all imported files""" self.__srcfileslistbox.delete(0, END) self.__importer.reset() self.__update_table() def add_xslfile(self): """add_xslfile called to open .xsl file via dialog""" filename = askopenfilename(title="Select .xsl file", filetypes=(("Xsl File", "*.xsl"), )) if filename: self.__importer.set_xslfile(filename) self.__xsllistbox.insert(0, filename) self.reset_xslparameter() def apply_xslparameter(self): """apply_xslparameter reads userinput from textbox and parses input in dict""" param = self.__xslparametertext.get("1.0", END) with StringIO(param) as f: lines = [line[:-1] for line in f.readlines()] # escape_decode removes extra escapes added through reading the text d = { x.split("=")[0]: escape_decode(x.split("=")[1])[0] for x in lines if x } self.__importer.set_xslparameter(**d) if not self.__importer.dfx.empty: self.__importer.update_files() self.__update_table() def reset_xslparameter(self): """reset_xslparameter restores default values for xslparameters""" self.__xslparametertext.delete("1.0", END) param = self.__importer.get_xslparameter(default=True) s = "" for key, item in param.items(): s += repr(key + "=" + item)[1:-1] + '\n' self.__xslparametertext.insert("1.0", s) @staticmethod def __unpack_settings(settings): """__unpack_settings takes settings in form of dict with tkinter variables and unpacks them""" return dict((key, settings[key].get()) for key in settings) def __update_table(self): """__update_table updates pandastable to display the actual dataframe""" self.__pdtable.updateModel(TableModel(self.__importer.dfx)) self.__pdtable.redraw() def __update_dialog(self): """__update_dialog updates the input fields with settings from the importer""" importersettings = self.__importer.get_settings() for key in self.__settings: if key in importersettings: self.__settings[key].set(importersettings[key]) def update_settings(self, *_): """update_settings reads input fields and applies the user input to the importer""" newsettings = self.__unpack_settings(self.__settings) if newsettings != self.__prevsettings: # figure out which settings changed changedsettings = dict(newsettings.items() - self.__prevsettings.items()) self.__importer.set_settings(**changedsettings) self.__prevsettings = newsettings if not self.__importer.dfx.empty: self.__update_table() def ask_help(self): showinfo(title="Help", message="""\ To import files select Add Files For .xml import first add a .xsl file. To export select Export and set desired parameters\ """) def ask_about(self): showinfo( title="About", message="Projektarbeit Python\nAuthor: Leo Schurrer\nDate: 19/12/20" ) def create_exportdialog(self): ExportDialog(self.__importer.dfx).run()
class DataFrame(tk.Frame): label = "Data" def __init__(self, *args, **kwargs): tk.Frame.__init__(self, *args, **kwargs) self.columnconfigure(index=0, weight=1) self.rowconfigure(index=1, weight=1) self.create_widgets() def show(self): self.tkraise() def create_widgets(self): self.toolbar = tk.Frame(self) self.toolbar.grid(row=0, column=0, padx=12, pady=3, sticky="NSEW") for col in range(12): self.toolbar.columnconfigure(index=col, weight=1) self.save_button = tk.Button( self.toolbar, text="Store in vault", command=self.save_to_db) self.export_button = tk.Button( self.toolbar, text="Export File", command=self.export_data) self.import_button = tk.Button( self.toolbar, text="Import CSV", command=self.import_csv) self.refresh_button = tk.Button( self.toolbar, text="Refresh DB", command=self.refresh_table_data) self.save_button.grid(row=0, column=12) self.export_button.grid(row=0, column=11) self.import_button.grid(row=0, column=10) self.refresh_button.grid(row=0, column=9) self.table_container = tk.Frame(self) self.table_container = tk.Frame(self) self.table_container.grid(row=1, column=0, sticky="") data_df = Vault.data self.data_table = Table(self.table_container, dataframe=data_df) self.data_table.autoResizeColumns() self.data_table.show() def refresh_table_data(self): res = tkMessageBox.askyesno(title="Ready to reboot DB.", message="Ready to reboot DB.\n" "Undo") if res == tkMessageBox.NO: return data_df = get_db_data() Vault.data = data_df self.data_table.updateModel(TableModel(data_df)) self.data_table.redraw() def export_data(self): output_file = tkFileDialog.askopenfilename() if not output_file: tkMessageBox.showerror(title="Error, Failed!", message="...") return def save_to_db(self): add_df_to_db(Vault.data) def import_csv(self): input_file = tkFileDialog.askopenfilename() if not input_file.strip(): tkMessageBox.showerror(title="Error, Failed!", message="...") return try: import_df = pd.read_csv(input_file) except ParserError: tkMessageBox.showerror("Failed, Try again!.") if len(import_df) > 0: Vault.data.reset_index(level=["id_product"], inplace=True) table_df = Vault.data.append(import_df, ignore_index=False) table_df.set_index("id_product", inplace=True) Vault.data = table_df self.data_table.updateModel(TableModel(table_df)) self.data_table.redraw() tkMessageBox.showinfo(title="Done",message="Pass") else: tkMessageBox.showinfo(title="Error, Failed!", message="...")
class UI(tk.Tk): def __init__(self): super().__init__() __width_label_lc = 16 self.result_type_dict = [('mass', 'mass'), ('mass density', 'mass_density'), ('stiffness', 'stf'), ('shear capacity', 's_c'), ('drift', 'drift')] self.result_type_dict_right = [('displacement ratio', 'dsp_r'), ('drift ratio', 'dft_r'), ('spectrum of time history curve', 'thc'), ('base shear of time history', 'sth'), ('drift of time history', 'dth')] self.result_type_dict_added = [('period', 'period'), ('seismic shear coefficient', 's_s_c'), ('seismic shear adjust factor', 's_a_f') ] # variables of app self.file_path = FilePath() self.yjk_dir = tk.StringVar() self.etabs_name = tk.StringVar() self.result_type = tk.StringVar() self.result_type.set('drift') self.cur_tower_number = tk.StringVar() self.cur_merge_df = None self.tower_number = None self.position = None self.cur_result_type = None self.font = dict(family='KaiTi', color='black', weight='normal', size=10.5) # variables of YJK self.cur_yjk_class = None self.cur_yjk_dic = None self.cur_yjk_df = None self.df_yjk_export = None self.cur_yjk_lc = tk.StringVar() self.cur_yjk_tow_num_name = tk.StringVar() self.cur_yjk_flr_num_name = tk.StringVar() self.cur_yjk_content_name = tk.StringVar() self.lbl_yjk_tree_content = tk.StringVar() # variables of ETABS self.cur_etabs_dic = None self.cur_etabs_df = None self.df_etabs_export = None self.cur_etabs_lc = tk.StringVar() self.cur_etabs_tow_num_name = tk.StringVar() self.cur_etabs_flr_num_name = tk.StringVar() self.cur_etabs_content_name = tk.StringVar() self.lbl_etabs_tree_content = tk.StringVar() self.yjk_disp = None # GUI self.minsize(1280, 800) self.title('ARP_AnalysisResultProcessing') # start widget in frame_yjk_path self.frame_yjk_path = Frame(self) self.entry_yjk_path = Entry(self.frame_yjk_path, textvariable=self.yjk_dir) self.entry_yjk_path.pack(side=tk.LEFT, padx=5, pady=5, expand=tk.YES, fill=tk.X) self.btn_yjk_path = Button(self.frame_yjk_path, text='YJK', width=16, command=self.get_path) self.btn_yjk_path.pack(side=tk.LEFT, padx=5, pady=5) self.frame_yjk_path.pack(side=tk.TOP, fill=tk.X) # end widget in frame_yjk_path # start widget in frame_etabs_name self.frame_etabs_name = Frame(self) self.entry_etabs_name = Entry(self.frame_etabs_name, textvariable=self.etabs_name) self.entry_etabs_name.pack(side=tk.LEFT, padx=5, pady=5, expand=tk.YES, fill=tk.X) self.btn_etabs_path = Button(self.frame_etabs_name, text='ETABS', width=16, command=self.get_file_name) self.btn_etabs_path.pack(side=tk.LEFT, padx=5, pady=5) self.frame_etabs_name.pack(side=tk.TOP, fill=tk.X) # end widget in frame_etabs_name # start widget in frame_result_list self.frame_result_list = Frame(self) # option buttons of results self.lf_result_name = tk.LabelFrame(self.frame_result_list, text='Result to processing') self.frame_result_name_left = Frame(self.lf_result_name) for name, value in self.result_type_dict: _ = tk.Radiobutton(self.frame_result_name_left, text=name, value=value, anchor=tk.W, command=self.get_type, variable=self.result_type) _.pack(side=tk.TOP, fill=tk.X, padx=5) self.frame_result_name_left.pack(side=tk.LEFT, expand=tk.YES, fill=tk.X) self.frame_result_name_right = Frame(self.lf_result_name) for name, value in self.result_type_dict_right: _ = tk.Radiobutton(self.frame_result_name_right, text=name, value=value, anchor=tk.W, command=self.get_type, variable=self.result_type) _.pack(side=tk.TOP, fill=tk.X, padx=5) self.frame_result_name_right.pack(side=tk.LEFT, expand=tk.YES, fill=tk.X) self.frame_result_name_added = Frame(self.lf_result_name) for name, value in self.result_type_dict_added: _ = tk.Radiobutton(self.frame_result_name_added, text=name, value=value, anchor=tk.NW, command=self.get_type, variable=self.result_type) _.pack(side=tk.TOP, fill=tk.X, padx=5) self.frame_result_name_added.pack(side=tk.LEFT, expand=tk.YES, fill=tk.X, anchor=tk.N) self.lf_result_name.pack(side=tk.TOP, fill=tk.X) # labelframe of yjk results self.lf_yjk = tk.LabelFrame(self.frame_result_list, text='YJK') # load combination cmb self.frame_yjk_lc = tk.Frame(self.lf_yjk) self.lbl_yjk_lc = tk.Label(self.frame_yjk_lc, width=__width_label_lc, text='Load Combination', anchor=tk.W) self.lbl_yjk_lc.pack(side=tk.LEFT, fill=tk.X) self.cmb_yjk_lc = ttk.Combobox(self.frame_yjk_lc, state="readonly", height=1, textvariable=self.cur_yjk_lc) self.cmb_yjk_lc.pack(side=tk.LEFT, expand=tk.YES, fill=tk.X, padx=5, pady=5) self.frame_yjk_lc.pack(side=tk.TOP, fill=tk.X) # tower number cmb self.frame_yjk_tower = tk.Frame(self.lf_yjk) self.lbl_yjk_tower = tk.Label(self.frame_yjk_tower, width=__width_label_lc, text='Tower Number', anchor=tk.W) self.lbl_yjk_tower.pack(side=tk.LEFT, fill=tk.X) self.cmb_yjk_tower = ttk.Combobox( self.frame_yjk_tower, state="readonly", height=1, textvariable=self.cur_yjk_tow_num_name) self.cmb_yjk_tower.pack(side=tk.LEFT, expand=tk.YES, fill=tk.X, padx=5, pady=5) self.frame_yjk_tower.pack(side=tk.TOP, fill=tk.X) # floor number cmb self.frame_yjk_floor = tk.Frame(self.lf_yjk) self.lbl_yjk_floor = tk.Label(self.frame_yjk_floor, width=__width_label_lc, text='Floor Number', anchor=tk.W) self.lbl_yjk_floor.pack(side=tk.LEFT, fill=tk.X) self.cmb_yjk_floor = ttk.Combobox( self.frame_yjk_floor, state="readonly", height=1, textvariable=self.cur_yjk_flr_num_name) self.cmb_yjk_floor.pack(side=tk.LEFT, expand=tk.YES, fill=tk.X, padx=5, pady=5) self.frame_yjk_floor.pack(side=tk.TOP, fill=tk.X) # result content cmb self.frame_yjk_content = tk.Frame(self.lf_yjk) self.lbl_yjk_content = tk.Label(self.frame_yjk_content, width=__width_label_lc, text='Content', anchor=tk.W) self.lbl_yjk_content.pack(side=tk.LEFT, fill=tk.X) self.cmb_yjk_content = ttk.Combobox( self.frame_yjk_content, state="readonly", height=1, textvariable=self.cur_yjk_content_name) self.cmb_yjk_content.pack(side=tk.LEFT, expand=tk.YES, fill=tk.X, padx=5, pady=5) self.frame_yjk_content.pack(side=tk.TOP, fill=tk.X) # self.yjk_tree self.yjk_tree = ttk.Treeview(self.lf_yjk, show='headings') self.yjk_tree['column'] = ['a', 'b', 'c'] self.yjk_tree.column('a', width=18) self.yjk_tree.column('b', width=18) self.yjk_tree.column('c', width=18) self.yjk_tree.heading('a', text='Tower No.') self.yjk_tree.heading('b', text='Floor No.') self.yjk_tree.heading('c', text='content') self.yjk_tree.pack(side=tk.TOP, expand=tk.YES, fill=tk.BOTH) self.scr_yjk_tree = tk.Scrollbar(self.yjk_tree) self.scr_yjk_tree.pack(side=tk.RIGHT, fill=tk.Y) self.yjk_tree.config(yscrollcommand=self.scr_yjk_tree.set) self.scr_yjk_tree.config(command=self.yjk_tree.yview) # self.lbl_yjk_tree self.lbl_yjk_tree = tk.Label(self.lf_yjk, anchor=tk.W, textvariable=self.lbl_yjk_tree_content) self.lbl_yjk_tree.pack(side=tk.TOP, fill=tk.X) self.lf_yjk.pack(side=tk.TOP, expand=tk.YES, fill=tk.BOTH) # end of labelframe yjk results # labelframe of etabs results self.lf_etabs = tk.LabelFrame(self.frame_result_list, text='ETABS') # load combination cmb self.frame_etabs_lc = tk.Frame(self.lf_etabs) self.lbl_etabs_lc = tk.Label(self.frame_etabs_lc, width=__width_label_lc, text='Load Combination', anchor=tk.W) self.lbl_etabs_lc.pack(side=tk.LEFT, fill=tk.X) self.cmb_etabs_lc = ttk.Combobox(self.frame_etabs_lc, state="readonly", height=1, textvariable=self.cur_etabs_lc) self.cmb_etabs_lc.pack(side=tk.LEFT, expand=tk.YES, fill=tk.X, padx=5, pady=5) self.frame_etabs_lc.pack(side=tk.TOP, fill=tk.X) # tower number cmb self.frame_etabs_tower = tk.Frame(self.lf_etabs) self.lbl_etabs_tower = tk.Label(self.frame_etabs_tower, width=__width_label_lc, text='Tower Number', anchor=tk.W) self.lbl_etabs_tower.pack(side=tk.LEFT, fill=tk.X) self.cmb_etabs_tower = ttk.Combobox( self.frame_etabs_tower, state="readonly", height=1, textvariable=self.cur_etabs_tow_num_name) self.cmb_etabs_tower.pack(side=tk.LEFT, expand=tk.YES, fill=tk.X, padx=5, pady=5) self.frame_etabs_tower.pack(side=tk.TOP, fill=tk.X) # floor number cmb self.frame_etabs_floor = tk.Frame(self.lf_etabs) self.lbl_etabs_floor = tk.Label(self.frame_etabs_floor, width=__width_label_lc, text='Floor Number', anchor=tk.W) self.lbl_etabs_floor.pack(side=tk.LEFT, fill=tk.X) self.cmb_etabs_floor = ttk.Combobox( self.frame_etabs_floor, state="readonly", height=1, textvariable=self.cur_etabs_flr_num_name) self.cmb_etabs_floor.pack(side=tk.LEFT, expand=tk.YES, fill=tk.X, padx=5, pady=5) self.frame_etabs_floor.pack(side=tk.TOP, fill=tk.X) # result content cmb self.frame_etabs_content = tk.Frame(self.lf_etabs) self.lbl_etabs_content = tk.Label(self.frame_etabs_content, width=__width_label_lc, text='Content', anchor=tk.W) self.lbl_etabs_content.pack(side=tk.LEFT, fill=tk.X) self.cmb_etabs_content = ttk.Combobox( self.frame_etabs_content, state="readonly", height=1, textvariable=self.cur_etabs_content_name) self.cmb_etabs_content.pack(side=tk.LEFT, expand=tk.YES, fill=tk.X, padx=5, pady=5) self.frame_etabs_content.pack(side=tk.TOP, fill=tk.X) # self.etabs_tree self.etabs_tree = ttk.Treeview(self.lf_etabs, show='headings') self.etabs_tree['column'] = ['a', 'b', 'c'] self.etabs_tree.column('a', width=18) self.etabs_tree.column('b', width=18) self.etabs_tree.column('c', width=18) self.etabs_tree.heading('a', text='Tower No.') self.etabs_tree.heading('b', text='Floor No.') self.etabs_tree.heading('c', text='content') self.etabs_tree.pack(side=tk.TOP, expand=tk.YES, fill=tk.BOTH) self.scr_etabs_tree = tk.Scrollbar(self.etabs_tree) self.scr_etabs_tree.pack(side=tk.RIGHT, fill=tk.Y) self.etabs_tree.config(yscrollcommand=self.scr_etabs_tree.set) self.scr_etabs_tree.config(command=self.etabs_tree.yview) # self.lbl_etabs_tree self.lbl_etabs_tree = tk.Label( self.lf_etabs, anchor=tk.W, textvariable=self.lbl_etabs_tree_content) self.lbl_etabs_tree.pack(side=tk.TOP, fill=tk.X) self.lf_etabs.pack(side=tk.TOP, expand=tk.YES, fill=tk.BOTH) # self.lf_data_import self.lf_data_import = tk.LabelFrame(self.frame_result_list, text='action') # button yjk import self.btn_yjk_import = Button(self.lf_data_import, text='add YJK data', width=18, command=self.import_yjk) self.btn_yjk_import.pack(side=tk.LEFT, anchor=tk.W, padx=36) # button etabs import self.btn_etabs_import = Button(self.lf_data_import, text='add ETABS data', width=18, command=self.import_etabs) self.btn_etabs_import.pack(side=tk.LEFT, anchor=tk.CENTER, padx=36) # button merge and import self.btn_merge = Button(self.lf_data_import, text='merge and add', width=18, command=self.merge_import) self.btn_merge.pack(side=tk.LEFT, anchor=tk.E, padx=36) self.lf_data_import.pack(side=tk.TOP, fill=tk.X) self.frame_result_list.pack(side=tk.LEFT, expand=tk.YES, fill=tk.BOTH, padx=5, pady=5) # end widget in frame_result_list # start widget in frame_data_table self.frame_data_table = Frame(self) self.frame_table = Frame(self.frame_data_table) self.data_table = Table(self.frame_table, rows=50, cols=10, showstatusbar=True) self.data_table.show() self.frame_table.pack(side=tk.TOP, expand=tk.YES, fill=tk.BOTH) self.frame_tower = Frame(self.frame_data_table) self.lbl_tower = Label(self.frame_data_table, text='tower No.').pack(side=tk.BOTTOM) self.tower_scale = Scale(self.frame_data_table, orient=tk.HORIZONTAL, length=300, width=16, sliderlength=10, from_=0, to=10, tickinterval=1, variable=self.cur_tower_number, command=self.tower_select) self.tower_scale.pack(side=tk.BOTTOM, fill=tk.BOTH) self.frame_tower.pack(side=tk.TOP, fill=tk.X) self.frame_data_table.pack(side=tk.LEFT, expand=tk.YES, fill=tk.BOTH) # end widget in frame_data_table # start widget in frame_image self.frame_image = Frame(self) self.fig = Figure(figsize=(3.378, 4.331), dpi=150) self.ax = self.fig.add_subplot(111) self.canvas = FigureCanvasTkAgg(self.fig, master=self.frame_image) self.canvas.get_tk_widget().pack(side=tk.TOP) self.canvas.draw() toolbar = NavigationToolbar2Tk(self.canvas, self.frame_image) toolbar.update() self.canvas.get_tk_widget().pack(side=tk.TOP) self.lf_plot_control = tk.LabelFrame(self.frame_image, text='plot') self.lbl = Label(self.lf_plot_control, text='none').pack(side=tk.LEFT, fill=tk.X) self.btn_batch_plot = Button(self.lf_plot_control, text='batch plot', command=self.batch_plot) self.btn_batch_plot.pack(side=tk.RIGHT) self.lf_plot_control.pack(side=tk.BOTTOM, fill=tk.X) self.frame_image.pack(side=tk.LEFT, expand=tk.YES, fill=tk.BOTH) # end widget in frame_image self.data_table.zoomOut() self.data_table.zoomOut() self.action_bind() def action_bind(self): # action when yjk cmb selected self.cmb_yjk_lc.bind("<<ComboboxSelected>>", self.update_yjk_cmb) self.cmb_yjk_tower.bind("<<ComboboxSelected>>", self.update_yjk_tree) self.cmb_yjk_floor.bind("<<ComboboxSelected>>", self.update_yjk_tree) self.cmb_yjk_content.bind("<<ComboboxSelected>>", self.update_yjk_tree) # action when etabs cmb selected self.cmb_etabs_lc.bind("<<ComboboxSelected>>", self.update_etabs_cmb) self.cmb_etabs_tower.bind("<<ComboboxSelected>>", self.update_etabs_tree) self.cmb_etabs_floor.bind("<<ComboboxSelected>>", self.update_etabs_tree) self.cmb_etabs_content.bind("<<ComboboxSelected>>", self.update_etabs_tree) def get_path(self): """ get path of yjk result by FilePath class. update yjk widgets. :return: """ self.file_path.get_path() self.entry_yjk_path.delete(0, tk.END) self.entry_yjk_path.insert(tk.END, self.file_path.yjk_path) self.yjk_update() def get_file_name(self): """ get filename of etabs result in excel format by FilePath class. update etabs widgets. :return: """ self.file_path.get_path(openfile=True) self.entry_etabs_name.delete(0, tk.END) self.entry_etabs_name.insert(tk.END, self.file_path.etabs_name) if self.file_path.etabs_name is not None and self.file_path.etabs_name != '': self.etabs_update() def get_type(self): self.yjk_update() self.etabs_update() def yjk_update(self): if self.file_path.yjk_path is not None and os.path.exists( self.file_path.yjk_path) is True: self.cur_result_type = self.result_type.get() if self.cur_result_type == 'drift': with open(self.file_path.full_name('Wdisp.out'), 'r') as f: self.cur_yjk_class = Wdisp.Wdisp(f.read()) self.cmb_yjk_lc['values'] = self.cur_yjk_class.cqc self.cmb_yjk_lc.current(0) self.cmb_yjk_lc.configure( height=len(self.cur_yjk_class.cqc)) elif self.cur_result_type == 'dsp_r' or self.result_type.get( ) == 'dft_r': with open(self.file_path.full_name('Wdisp.out'), 'r') as f: self.cur_yjk_class = Wdisp.Wdisp(f.read()) self.cmb_yjk_lc['values'] = self.cur_yjk_class.spc_lateral self.cmb_yjk_lc.current(0) self.cmb_yjk_lc.configure( height=len(self.cur_yjk_class.spc_lateral)) elif self.cur_result_type == 'mass': with open(self.file_path.full_name('wmass.out'), 'r') as f: self.cur_yjk_class = Wmass.Wmass(f.read()) self.cmb_yjk_lc['values'] = ['mass_info'] self.cmb_yjk_lc.current(0) elif self.cur_result_type == 'mass_density': with open(self.file_path.full_name('wmass.out'), 'r') as f: self.cur_yjk_class = Wmass.Wmass(f.read()) self.cmb_yjk_lc['values'] = ['mass_density_detail'] self.cmb_yjk_lc.current(0) elif self.cur_result_type == 'stf': with open(self.file_path.full_name('wmass.out'), 'r') as f: self.cur_yjk_class = Wmass.Wmass(f.read()) self.cmb_yjk_lc['values'] = ['stiffness_detail'] self.cmb_yjk_lc.current(0) elif self.cur_result_type == 's_c': with open(self.file_path.full_name('wmass.out'), 'r') as f: self.cur_yjk_class = Wmass.Wmass(f.read()) self.cmb_yjk_lc['values'] = ['storey_shear_capacity_info'] self.cmb_yjk_lc.current(0) elif self.cur_result_type == 'period': with open(self.file_path.full_name('wzq.out'), 'r') as f: self.cur_yjk_class = Wzq.Wzq(f.read()) self.cmb_yjk_lc['values'] = ['period'] self.cmb_yjk_lc.current(0) elif self.cur_result_type == 's_a_f': with open(self.file_path.full_name('wzq.out'), 'r') as f: self.cur_yjk_class = Wzq.Wzq(f.read()) self.cmb_yjk_lc['values'] = ['shear_adjust_factor'] self.cmb_yjk_lc.current(0) elif self.cur_result_type == 's_s_c': with open(self.file_path.full_name('wzq.out'), 'r') as f: self.cur_yjk_class = Wzq.Wzq(f.read()) self.cmb_yjk_lc['values'] = self.cur_yjk_class.s_s_c self.cmb_yjk_lc.current(0) self.read_yjk_df() self.update_yjk_cmb(None) def read_yjk_df(self): if len(self.cmb_yjk_lc['values']) != 0: self.cur_yjk_df = getattr(self.cur_yjk_class, self.cur_yjk_lc.get()) def update_yjk_cmb(self, event): self.read_yjk_df() _columns = self.cur_yjk_df.columns.tolist() if self.result_type.get() == 'drift': self.position = (1, 0, len(_columns) - 3) elif self.result_type.get() == 'dsp_r': self.position = (1, 0, len(_columns) - 1) elif self.result_type.get() == 'dft_r': self.position = (1, 0, 5) elif self.result_type.get() == 'mass': self.position = (1, 0, 5) elif self.result_type.get() == 'mass_density': self.position = (1, 0, 3) elif self.result_type.get() == 'stf': self.position = (1, 0, len(_columns) - 3) elif self.result_type.get() == 's_c': self.position = (1, 0, len(_columns) - 2) elif self.cur_result_type == 'period': self.position = (0, 1, 3) elif self.cur_result_type == 's_a_f': self.position = (1, 0, 2) elif self.cur_result_type == 's_s_c': self.position = (1, 0, 4) self.cmb_yjk_tower['values'] = _columns self.cmb_yjk_tower.configure(height=len(_columns)) self.cmb_yjk_tower.current(self.position[0]) self.cmb_yjk_floor['values'] = _columns self.cmb_yjk_floor.configure(height=len(_columns)) self.cmb_yjk_floor.current(self.position[1]) self.cmb_yjk_content['values'] = _columns self.cmb_yjk_content.configure(height=len(_columns)) self.cmb_yjk_content.current(self.position[2]) self.update_yjk_tree(None) def update_yjk_tree(self, event): if self.cur_yjk_tow_num_name.get() is not None and\ self.cur_yjk_flr_num_name.get() is not None and \ self.cmb_yjk_content.get() is not None: self.df_yjk_export = self.cur_yjk_df[[ self.cur_yjk_tow_num_name.get(), self.cur_yjk_flr_num_name.get(), self.cur_yjk_content_name.get() ]] _content = self.yjk_tree.get_children() for _ in _content: self.yjk_tree.delete(_) for _ in range(len(self.df_yjk_export) - 1, -1, -1): self.yjk_tree.insert( '', 0, values=self.df_yjk_export.iloc[_].tolist()) self.lbl_yjk_tree_content.set( '%d row, %d columns' % (self.df_yjk_export.shape[0], self.df_yjk_export.shape[1])) def etabs_update(self): pass def update_etabs_cmb(self, event): pass def update_etabs_tree(self, event): pass def import_yjk(self): self.data_table.model.df = self.df_yjk_export number_groups = self.df_yjk_export.groupby( self.df_yjk_export.columns.tolist()[0]).ngroups self.tower_scale.config(to=number_groups) self.cur_tower_number.set(0) self.data_table.redraw() self.plot() def import_etabs(self): self.plot() pass def merge_import(self): self.plot() pass def tower_select(self, tower_number): group_by_tower = self.df_yjk_export.groupby( self.df_yjk_export.columns.tolist()[0]) tower_number = int(tower_number) if tower_number == 0: self.data_table.model.df = self.df_yjk_export else: self.data_table.model.df = group_by_tower.get_group(tower_number) self.data_table.redraw() self.plot() def plot(self): self.ax.clear() tower_number = int(self.cur_tower_number.get()) if tower_number == 0 and tower_number > 1: pass elif tower_number > 0: if self.result_type.get() == 'drift': self.ax.plot(1 / self.data_table.model.df.iloc[:, 2] * 1000, self.data_table.model.df.iloc[:, 1], marker='o') self.ax.grid(alpha=0.5, linestyle="-.", linewidth=0.3) self.ax.set_xlabel('位移角(1/1000)', fontdict=self.font) self.ax.set_ylabel('楼层', fontdict=self.font) self.fig.tight_layout(pad=0.3) elif self.result_type.get() == 'dsp_r': self.ax.plot(self.data_table.model.df.iloc[:, 2], self.data_table.model.df.iloc[:, 1], marker='o') self.ax.grid(alpha=0.5, linestyle="-.", linewidth=0.3) self.ax.set_xlabel('位移比', fontdict=self.font) self.ax.set_ylabel('楼层', fontdict=self.font) self.fig.tight_layout(pad=0.3) elif self.result_type.get() == 'dft_r': self.ax.plot(self.data_table.model.df.iloc[:, 2], self.data_table.model.df.iloc[:, 1], marker='o') self.ax.grid(alpha=0.5, linestyle="-.", linewidth=0.3) self.ax.set_xlabel('层间位移比', fontdict=self.font) self.ax.set_ylabel('楼层', fontdict=self.font) self.fig.tight_layout(pad=0.3) elif self.result_type.get() == 'mass': self.ax.plot(self.data_table.model.df.iloc[:, 2], self.data_table.model.df.iloc[:, 1], marker='o') self.ax.grid(alpha=0.5, linestyle="-.", linewidth=0.3) self.ax.set_xlabel('楼层质量', fontdict=self.font) self.ax.set_ylabel('楼层', fontdict=self.font) self.fig.tight_layout(pad=0.3) elif self.result_type.get() == 'mass_density': self.ax.plot(self.data_table.model.df.iloc[:, 2], self.data_table.model.df.iloc[:, 1], marker='o') self.ax.grid(alpha=0.5, linestyle="-.", linewidth=0.3) self.ax.set_xlabel('单位面积楼层质量', fontdict=self.font) self.ax.set_ylabel('楼层', fontdict=self.font) self.fig.tight_layout(pad=0.3) elif self.result_type.get() == 'stf': self.ax.plot(self.data_table.model.df.iloc[:, 2], self.data_table.model.df.iloc[:, 1], marker='o') self.ax.grid(alpha=0.5, linestyle="-.", linewidth=0.3) self.ax.set_xlabel('抗侧刚度(v/d)', fontdict=self.font) self.ax.set_ylabel('楼层', fontdict=self.font) self.fig.tight_layout(pad=0.3) elif self.result_type.get() == 's_c': self.ax.plot(self.data_table.model.df.iloc[:, 2], self.data_table.model.df.iloc[:, 1], marker='o') self.ax.grid(alpha=0.5, linestyle="-.", linewidth=0.3) self.ax.set_xlabel('楼层受剪承载力', fontdict=self.font) self.ax.set_ylabel('楼层', fontdict=self.font) self.fig.tight_layout(pad=0.3) elif self.cur_result_type == 'period': pass elif self.cur_result_type == 's_a_f': self.ax.plot(self.data_table.model.df.iloc[:, 2], self.data_table.model.df.iloc[:, 1], marker='o') self.ax.grid(alpha=0.5, linestyle="-.", linewidth=0.3) self.ax.set_xlabel('地震剪力放大系数', fontdict=self.font) self.ax.set_ylabel('楼层', fontdict=self.font) self.fig.tight_layout(pad=0.3) elif self.cur_result_type == 's_s_c': self.ax.plot(self.data_table.model.df.iloc[:, 2], self.data_table.model.df.iloc[:, 1], marker='o') self.ax.grid(alpha=0.5, linestyle="-.", linewidth=0.3) self.ax.set_xlabel('剪重比(%)', fontdict=self.font) self.ax.set_ylabel('楼层', fontdict=self.font) self.fig.tight_layout(pad=0.3) self.canvas.draw() pass def figure_save(self, fig_name=None): if fig_name is None: fig_name = '%s.png' % self.cur_yjk_lc.get() self.fig.savefig(self.file_path.result_name(fig_name), transparent=True, dpi=300, format='png') def batch_plot(self): result_type_dict = self.result_type_dict + self.result_type_dict_right + self.result_type_dict_added if self.yjk_dir.get() != '' or self.etabs_name.get() != '': for name, result_type in result_type_dict: self.result_type.set(result_type) self.yjk_update() for ct, lc_name in enumerate(self.cmb_yjk_lc['values']): self.cur_yjk_lc.set(lc_name) self.update_yjk_cmb(None) self.import_yjk() self.cur_tower_number.set(1) self.tower_select(1) f_name = '%s-%d-%s.png' % (name, ct, lc_name) self.figure_save(f_name)
class PeopleSearch: def __init__(self, tk_parent, linkedin_conn): self.parent = tk_parent self.linkedin_conn = linkedin_conn self.search_results_df = pd.DataFrame() self.search_thread = None self.quick_search = True # Paned Window self.search_paned_window = ttk.PanedWindow(tk_parent, orient='horizontal') self.search_paned_window.pack(side='top', fill="both", expand=True, padx=10) ## Search fields Canvas/ScrolledFrame search_fields_canvas = ttk.Canvas(self.search_paned_window) search_fields_frame = ScrolledFrame(search_fields_canvas) search_fields_frame.pack(side='top', fill='both', expand=True, padx=5) search_fields_frame.hide_scrollbars() ### Load/Save search load_save_btn_frame = ttk.Frame(search_fields_frame) load_save_btn_frame.pack(pady=5, side='top', fill="x") load_search_btn = ttk.Button(load_save_btn_frame, text="Load param.") load_search_btn.pack(side='left') load_search_btn['command'] = self.load_search_config save_search_btn = ttk.Button(load_save_btn_frame, text="Save param.") save_search_btn.pack(side='right', padx=10) save_search_btn['command'] = self.save_search_config ### Connections conn_frame = ttk.Frame(search_fields_frame) conn_frame.pack(pady=10, side='top', fill='x') conn_lbl = ttk.Label(conn_frame, text="Connections") conn_lbl.pack(side='left', expand=False) ToolTip(conn_lbl, text=f"Degree of Connection with the logged in user.") first_con = ttk.BooleanVar() second_con = ttk.BooleanVar() third_con = ttk.BooleanVar() self.con_dict_list = [{ 'bool_val': first_con, 'name': 'F' }, { 'bool_val': second_con, 'name': 'S' }, { 'bool_val': third_con, 'name': 'O' }] ttk.Checkbutton(conn_frame, text="1st", variable=first_con, bootstyle="primary").pack(side='left', padx=10) ttk.Checkbutton(conn_frame, text="2nd", variable=second_con, bootstyle="primary").pack(side='left', padx=10) ttk.Checkbutton(conn_frame, text="3rd+", variable=third_con, bootstyle="primary").pack(side='left', padx=10) ttk.Separator(search_fields_frame, orient='horizontal').pack(side='top', fill='x', pady=5) ### Connection of self.conn_of_frame = SearchFrame( search_fields_frame, title='Connection of', single_choice=True, fetch_fct=lambda x: utils.extract_urn_dict_from_query_results( linkedin_conn[0].get_contact_urn_ids, x)) self.conn_of_frame.pack(side='top', fill="x") ttk.Separator(search_fields_frame, orient='horizontal').pack(side='top', fill='x', pady=5) ### Location Frame self.loc_frame = SearchFrame( search_fields_frame, title='Location', fetch_fct=lambda x: utils.extract_urn_dict_from_query_results( linkedin_conn[0].get_geo_urn_ids, x)) self.loc_frame.pack(side='top', fill="x") ttk.Separator(search_fields_frame, orient='horizontal').pack(side='top', fill='x', pady=5) ### Current Company frame self.current_comp_frame = SearchFrame( search_fields_frame, title='Current Company', fetch_fct=lambda x: utils.extract_urn_dict_from_query_results( linkedin_conn[0].get_company_urn_ids, x)) self.current_comp_frame.pack(side='top', fill="x") ttk.Separator(search_fields_frame, orient='horizontal').pack(side='top', fill='x', pady=5) ### Past Company frame self.past_comp_frame = SearchFrame( search_fields_frame, title='Past Company', fetch_fct=lambda x: utils.extract_urn_dict_from_query_results( linkedin_conn[0].get_company_urn_ids, x)) self.past_comp_frame.pack(side='top', fill="x", pady=5) ttk.Separator(search_fields_frame, orient='horizontal').pack(side='top', fill='x', pady=5) ### School frame self.school_frame = SearchFrame( search_fields_frame, title='School', fetch_fct=lambda x: utils.extract_urn_dict_from_query_results( linkedin_conn[0].get_school_urn_ids, x)) self.school_frame.pack(side='top', fill="x", pady=5) ttk.Separator(search_fields_frame, orient='horizontal').pack(side='top', fill='x', pady=5) ### Industry frame self.industry_frame = SearchFrame( search_fields_frame, title='Industry', fetch_fct=lambda x: utils.extract_urn_dict_from_query_results( linkedin_conn[0].get_industry_urn_ids, x)) self.industry_frame.pack(side='top', fill="x", pady=5) ### KW-Header kw_header_frame = ttk.Frame(search_fields_frame) kw_header_frame.pack(pady=5, side='top', fill="x") ttk.Label(kw_header_frame, text="Keywords").pack(side='left') ttk.Separator(kw_header_frame, orient='horizontal').pack(side='left', fill='x', expand=True) ### KW-Frame kw_frame = ttk.Frame(search_fields_frame) kw_frame.pack(pady=5, side='top', fill="x") kw_frame.grid_columnconfigure(0, weight=1) kw_frame.grid_columnconfigure(1, weight=1) kw_frame.grid_rowconfigure(0, weight=1) kw_frame.grid_rowconfigure(1, weight=1) kw_frame.grid_rowconfigure(2, weight=1) #### General self.entry_keywords = PlaceholderEntry(kw_frame, 'General') self.entry_keywords.grid(row=0, column=0, sticky='nwse', padx=5, pady=4) #### First Name self.entry_keywords_first_name = PlaceholderEntry( kw_frame, 'First Name') self.entry_keywords_first_name.grid(row=0, column=1, sticky='nwse', padx=5, pady=4) #### Last Name self.entry_keywords_last_name = PlaceholderEntry(kw_frame, 'Last Name') self.entry_keywords_last_name.grid(row=1, column=0, sticky='nwse', padx=5, pady=4) #### Title self.entry_keywords_title = PlaceholderEntry(kw_frame, 'Title') self.entry_keywords_title.grid(row=1, column=1, sticky='nwse', padx=5, pady=4) #### Company self.entry_keywords_company = PlaceholderEntry(kw_frame, 'Company') self.entry_keywords_company.grid(row=2, column=0, sticky='nwse', padx=5, pady=4) #### School self.entry_keywords_school = PlaceholderEntry(kw_frame, 'School') self.entry_keywords_school.grid(row=2, column=1, sticky='nwse', padx=5, pady=4) self.search_paned_window.add(search_fields_canvas) ## Table frame self.table_main_frame = ttk.Frame(tk_parent) # pandastable self.table_frame = ttk.Frame(self.table_main_frame, bootstyle="secondary", borderwidth=2) self.table_frame.pack(side="top", fill="both", expand=True) self.table = Table(self.table_frame, dataframe=pd.DataFrame(), showtoolbar=False, showstatusbar=True) utils.fit_table_style_to_theme(self.table, ttk.Style()) self.table.unbind_all("<Tab>") self.table.unbind_all("<Return>") self.table.show() self.search_paned_window.add(self.table_main_frame) # Buttons frame btn_frame = ttk.Frame(tk_parent) btn_frame.pack(padx=10, pady=10, side='top', fill="x") quick_search_btn = ttk.Button(btn_frame, text="Quick search") quick_search_btn.pack(side='left', padx=10) quick_search_btn['command'] = self.start_quick_search ToolTip( quick_search_btn, "This is a single request that will yield the same results as in the linkedin search bar. \ \nIt doesn't contain any personal details (only public IDs) \ \nYou're not likely to reach any search limit using this mode.") btn_sub_frame = ttk.Frame(btn_frame) btn_sub_frame.pack(side="left", fill="none", expand=True) start_search_btn = ttk.Button(btn_sub_frame, text="Deep Search", bootstyle='danger') start_search_btn.pack(side='left', padx=10) start_search_btn['command'] = self.start_deep_search ToolTip( start_search_btn, "Each search result will be fetched for additional information. \ \nDepending on the number of results and search frequency, this can trigger the linkedin limit \ after which you'll only be able to get 3 results per search until the end of the month." ) self.get_skills = ttk.BooleanVar() skills_chk_btn = ttk.Checkbutton(btn_sub_frame, text="Fetch skills", variable=self.get_skills, bootstyle="danger") skills_chk_btn.pack(side='left', padx=10) ToolTip( skills_chk_btn, text=f"Fetch skills by running one additional request per result.") self.get_contact_info = ttk.BooleanVar() contact_info_chk_btn = ttk.Checkbutton(btn_sub_frame, text="Fetch contact info", variable=self.get_contact_info, bootstyle="danger") contact_info_chk_btn.pack(side='left', padx=10) ToolTip( contact_info_chk_btn, text= f"Fetch contact info by running one additional request per result." ) self.export_to_file_btn = ttk.Button(btn_frame, text="Export to File", state="disabled") self.export_to_file_btn.pack(side='left', padx=10) self.export_to_file_btn[ 'command'] = self.prepare_dataframe_and_save_to_xsl # Status frame self.status_frame = ttk.Frame(tk_parent) self.status_frame.pack(padx=10, pady=2, side='bottom', expand=False, fill="x") self.status_str = ttk.StringVar(value="") ttk.Label(self.status_frame, textvariable=self.status_str).pack(side='left', expand=False) ttk.Separator(tk_parent, orient='horizontal').pack(side='bottom', fill='x') def save_search_config(self): chosen_file = filedialog.asksaveasfile(mode='w', filetypes=[("JSON", ".json")], defaultextension=".json") if chosen_file is None: return config_dict = { 'people_search': { 'connections': [x['name'] for x in self.con_dict_list if x['bool_val'].get()], 'connection_of': [[x.lbl_name.get(), x.value] for x in self.conn_of_frame.get_current_selection()], 'location': [[x.lbl_name.get(), x.value] for x in self.loc_frame.get_current_selection()], 'current_company': [[x.lbl_name.get(), x.value] for x in self.current_comp_frame.get_current_selection()], 'past_company': [[x.lbl_name.get(), x.value] for x in self.past_comp_frame.get_current_selection()], 'school': [[x.lbl_name.get(), x.value] for x in self.school_frame.get_current_selection()], 'industries': [[x.lbl_name.get(), x.value] for x in self.industry_frame.get_current_selection()], 'general_kw': self.entry_keywords.get(), 'first_name_kw': self.entry_keywords_first_name.get(), 'last_name_kw': self.entry_keywords_last_name.get(), 'title_kw': self.entry_keywords_title.get(), 'company_kw': self.entry_keywords_company.get(), 'school_kw': self.entry_keywords_school.get(), } } with open(chosen_file.name, 'w') as f: json.dump(config_dict, f, indent=4) self.status_str.set( f"Search config successfully saved at {chosen_file.name}!") def load_search_config(self): chosen_file = filedialog.askopenfile(mode='r', filetypes=[("JSON", ".json")], defaultextension=".json") if chosen_file is None: return try: with open(chosen_file.name, 'r') as f: config_dict = json.load(f) config = config_dict['people_search'] except: self.status_str.set( f"Please select a valid people search configuration!") utils.set_bools_from_list(self.con_dict_list, config['connections']) self.conn_of_frame.load_name_val_from_list(config['connection_of']) self.loc_frame.load_name_val_from_list(config['location']) self.current_comp_frame.load_name_val_from_list( config['current_company']) self.past_comp_frame.load_name_val_from_list(config['past_company']) self.school_frame.load_name_val_from_list(config['school']) self.industry_frame.load_name_val_from_list(config['industries']) self.entry_keywords.replace_text(config['general_kw']) self.entry_keywords_first_name.replace_text(config['first_name_kw']) self.entry_keywords_last_name.replace_text(config['last_name_kw']) self.entry_keywords_title.replace_text(config['title_kw']) self.entry_keywords_company.replace_text(config['company_kw']) self.entry_keywords_school.replace_text(config['school_kw']) self.status_str.set(f"Config loaded succesfully!") def run_search(self): self.search_results_df = pd.DataFrame() self.table.updateModel(TableModel(self.search_results_df)) self.table.redraw() self.status_str.set("Running search...") self.parent.update() try: # see doc under https://linkedin-api.readthedocs.io/en/latest/api.html search_result = self.linkedin_conn[0].search_people( network_depths=[ x['name'] for x in self.con_dict_list if x['bool_val'].get() ], connection_of=next( (x.value for x in self.conn_of_frame.get_current_selection()), None), regions=[ x.value for x in self.loc_frame.get_current_selection() ], current_company=[ x.value for x in self.current_comp_frame.get_current_selection() ], past_companies=[ x.value for x in self.past_comp_frame.get_current_selection() ], schools=[ x.value for x in self.school_frame.get_current_selection() ], industries=[ x.value for x in self.industry_frame.get_current_selection() ], keywords=self.entry_keywords.get(), keyword_first_name=self.entry_keywords_first_name.get(), keyword_last_name=self.entry_keywords_last_name.get(), keyword_title=self.entry_keywords_title.get(), keyword_company=self.entry_keywords_company.get(), keyword_school=self.entry_keywords_school.get(), ) if self.quick_search: self.search_results_df = pd.DataFrame(search_result) self.table.updateModel(TableModel(self.search_results_df)) self.table.redraw() else: result_size = len(search_result) self.status_str.set( "Found " + str(result_size) + " results! Searching contact details... This can take a while..." ) self.parent.update() if result_size > 999: answer_is_yes = messagebox.askyesno( "Too many results!", "This search yields more than 1000 results (upper limit for this app).\nProceed anyway?", icon="warning") if not answer_is_yes: self.status_str.set("Search cancelled.") self.parent.update() return row = 1 for people in search_result: profile = self.linkedin_conn[0].get_profile( urn_id=people['urn_id']) if profile != {}: if 'geoLocationName' in profile.keys(): geolocation = profile['geoLocationName'] else: geolocation = "" profile_dict = { 'First Name': [profile['firstName']], 'Last Name': [profile['lastName']], 'Title': [profile['experience'][0]['title']], 'Company': [profile['experience'][0]['companyName']], 'Location': [geolocation], 'Headline': [profile['headline']], 'Profile Link': [ 'https://www.linkedin.com/in/' + profile['profile_id'] ] } if self.get_skills.get(): skills_raw = self.linkedin_conn[ 0].get_profile_skills(urn_id=people['urn_id']) skills = [dic['name'] for dic in skills_raw] profile_dict.update({'Skills': [skills]}) if self.get_contact_info.get(): contact_info = self.linkedin_conn[ 0].get_profile_contact_info( urn_id=people['urn_id']) contact_info = { k: [v] for k, v in contact_info.items() } profile_dict.update(contact_info) self.search_results_df = pd.concat([ self.search_results_df, pd.DataFrame(profile_dict) ]) self.table.updateModel( TableModel(self.search_results_df)) self.table.redraw() self.status_str.set("Scanned " + str(row) + " out of " + str(result_size) + " profiles") self.parent.update() row += 1 self.export_to_file_btn.configure(state="normal") self.status_str.set("Done") self.parent.update() except Exception as e: utils.show_exception(e) self.status_str.set( "Something went wrong! Check console output for more details.") self.parent.update() def create_search_thread(self): if not self.linkedin_conn[0]: messagebox.showinfo("Error", "First log into Linkedin!", icon="error") return if self.search_thread and self.search_thread.is_alive(): messagebox.showinfo( "Search in progress", "Another search is still running.\nWait until it finishes or restart the program.", icon="warning") return self.search_thread = threading.Thread(target=self.run_search) self.search_thread.daemon = True self.search_thread.start() def start_quick_search(self): self.quick_search = True self.create_search_thread() def start_deep_search(self): self.quick_search = False self.create_search_thread() def prepare_dataframe_and_save_to_xsl(self): self.status_str.set("Exporting to File...") export_file = utils.save_dataframe_to_file(self.search_results_df) if export_file is not None: self.status_str.set("Table saved under " + export_file) else: self.status_str.set("Table could not be saved!")
class Application(tk.Frame): def __init__(self, master=None): super().__init__(master) self.main = self.master self.main.geometry('600x400+200+100') self.main.title('Budgeting Project') f = tk.Frame(self.main) f.pack() self.df = readInCSV('budget.csv') self.table = Table(f, dataframe=self.df, showtoolbar=False, showstatusbar=False) self.table.show() self.pack() self.createWidgets() def ts(self): timeseries(self.df) def pies(self): pie(self.df) def createWidgets(self): # creates buttons for each function self.modifyButton = tk.Button(self) self.modifyButton["text"] = "Modify Entry" self.modifyButton["command"] = self.modifyRowEntry self.modifyButton.pack(side="top") self.addButton = tk.Button(self) self.addButton["text"] = "Add New Expense" self.addButton["command"] = self.addNewExpense self.addButton.pack(side="top") self.deleteButton = tk.Button(self) self.deleteButton["text"] = "Delete Expense" self.deleteButton["command"] = self.delete self.deleteButton.pack(side="top") self.graphButton = tk.Button(self) self.graphButton["text"] = "Scatter Plot Graph" self.graphButton["command"] = self.ts self.graphButton.pack(side="top") self.graphButton = tk.Button(self) self.graphButton["text"] = "Pie Graph" self.graphButton["command"] = self.pies self.graphButton.pack(side="top") self.quit = tk.Button(self, text="QUIT", fg="red", # calls savefile before ending program command= lambda:[self.savefile(),root.destroy()]) self.quit.pack(side="bottom") def savefile(self): # rewrites CSV file with updated data f = open("budget.csv","w") self.df.to_csv(f, index = False, header = True) print("oo") f.close # Adds a new expense to the dataframe def addNewExpense(self): top = tk.Toplevel() top.title("Add New Expense") dateLabel = tk.Label(top, text='Date', font=('Times', 12)) typeLabel = tk.Label(top, text='Category', font=('Times', 12)) amountLabel = tk.Label(top, text='Amount', font=('Times', 12)) dateLabel.grid(row=0,column=0) typeLabel.grid(row=1,column=0) amountLabel.grid(row=2,column=0) dateEntry = tk.Entry(top) typeEntry = tk.Entry(top) amountEntry = tk.Entry(top) dateEntry.grid(row=0,column=1) typeEntry.grid(row=1,column=1) amountEntry.grid(row=2,column=1) addButton = tk.Button(top,text="Add Expense", command=lambda:[self.addExpenseToDf(dateEntry.get(), typeEntry.get(), amountEntry.get()), top.destroy()]) addButton.grid(row=3,column=0) # Helper method to add expense to dataframe def addExpenseToDf(self, date, category, amount): self.df = newexpense(df=self.df, amount=amount, category=category, date=date) self.table.redraw() self.table.sortTable(0) # Sort by column index 0, which is date # Modify a row entry def modifyRowEntry(self): top = tk.Toplevel() top.title("Modify Row Entry") rowLabel = tk.Label(top, text='Row to Modify', font=('Times', 12)) dateLabel = tk.Label(top, text='Date (Optional)', font=('Times', 12)) typeLabel = tk.Label(top, text='Category (Optional)', font=('Times', 12)) amountLabel = tk.Label(top, text='Amount (Optional)', font=('Times', 12)) rowLabel.grid(row=0,column=0) dateLabel.grid(row=1,column=0) typeLabel.grid(row=2,column=0) amountLabel.grid(row=3,column=0) rowEntry = tk.Entry(top) dateEntry = tk.Entry(top) typeEntry = tk.Entry(top) amountEntry = tk.Entry(top) rowEntry.grid(row=0, column=1) dateEntry.grid(row=1,column=1) typeEntry.grid(row=2,column=1) amountEntry.grid(row=3,column=1) addButton = tk.Button(top,text="Modify Expense", command=lambda:[self.modifyExpenseToDf(rowEntry.get(), dateEntry.get(), typeEntry.get(), amountEntry.get()), top.destroy()]) addButton.grid(row=4,column=0) # Helper method to modify row entry def modifyExpenseToDf(self, row, date, category, amount): try: row = int(row) row = row - 1 # Reduce row value by 1 to match with index value except: print("Please enter an integer for the row value") return if row < 0 or row >= self.df.shape[0]: print("Please enter a valid integer value") return if date == "": date = None if category == "": category = None if amount == "": amount = None self.df = modifyEntry(df=self.df, row=row, date=date, category=category, amount=amount) self.table.redraw() self.table.sortTable(0) # Sort by column index 0, which is date # Delete row entry def delete(self): d = tk.Toplevel() l = tk.Label(d, text = "Row: ") l.pack() row = tk.Entry(d) row.pack() dButton = tk.Button(d, text = "Delete", command = lambda: [self.deleteRow(row.get()), d.destroy()]) dButton.pack() # Helper method to delete a row in the dataframe def deleteRow(self, row): try: x = int(row) - 1 if x < self.df.shape[0] and x >= 0: self.df = deleteRowEntry(df=self.df, row=x) self.table.model.df = self.df self.table.redraw() self.table.sortTable(0) else: print("Please enter a valid row number") return except ValueError: print("Please enter a number")
class Window: # Initialize PanedWindow widget def __init__(self): # Creates the root window self.root = Tk() # Creates size of the window self.root.geometry("1000x600") # Set the title of our master widget self.root.title("Data Science GUI") # Width and height for window self.width = 1280 self.height = 720 # Creates a menu instance menu = Menu(self.root) self.root.config(menu=menu) # Creates a file object for "File" option # Adds several commands to the "File" option fileMenu = Menu(menu, tearoff=0) fileMenu.add_command(label="Open File", command=self.openFile) fileMenu.add_separator() fileMenu.add_command(label="Exit", command=self.client_exit) # Creates a help object for "Help" option # Adds a command to "Help" option helpMenu = Menu(menu, tearoff=0) helpMenu.add_command(label="View parameter descriptions", command=self.displayParameterDesc) # Adds the options to the menu menu.add_cascade(label="File", menu=fileMenu) menu.add_cascade(label="Help", menu=helpMenu) # Paned window for Top (main stuff) and Bottom (mainLog) main = PanedWindow(self.root, orient=VERTICAL, sashpad=1, sashrelief=RAISED) main.pack(fill=BOTH, expand=1) # Paned window for left (choosing features/label and parameters/algorithm) and right (displaying csv log and results log) top = PanedWindow(main, orient=HORIZONTAL, sashpad=1, sashrelief=RAISED) # Log for main stuff bottom = PanedWindow(main, orient=HORIZONTAL, sashpad=1, sashrelief=RAISED) # Adds top and bottom panedwindows main.add(top, height=440) main.add(bottom, height=200) # Paned Window for choosing features/label and parameters/algorithm left = PanedWindow(top, orient=HORIZONTAL, sashpad=1, sashrelief=RAISED) # LabelFrame for Main Frame labelFrameForMainFrame = LabelFrame(left, text="Main Frame") self.mainFrame = Frame(labelFrameForMainFrame) self.mainFrame.pack() # Add the label frame left.add(labelFrameForMainFrame) # Paned window for CSV File and Results right = PanedWindow(top, orient=VERTICAL, sashpad=1, sashrelief=RAISED) # Add left and right panedwindows top.add(left, width=500) top.add(right, width=300) # LabelFrame for CSV log self.labelFrameForCSVFile = LabelFrame(top, text="CSV not specified") # Table for CSV file self.df = None self.csvTable = Table(self.labelFrameForCSVFile, dataframe=self.df, showstatusbar=True) self.csvTable.show() # LabelFrame for Results log self.labelFrameForResult = LabelFrame(top, text="results not specified") # Log for Results self.resultLog = Text2(self.labelFrameForResult, width=self.width, height=self.height - 300) self.resultLog.pack() # Add the two labelframes for displaying CSV file and Result Log right.add(self.labelFrameForCSVFile, height=220) right.add(self.labelFrameForResult, height=220) # Show this at the beginning of the GUI label = Label(self.mainFrame, text="To start, click 'File' and open a CSV file.") label.pack() # Labelframe for Main log labelFrameForMainLog = LabelFrame(bottom, text="Main log") # Log for main frame self.mainLog = Text2(labelFrameForMainLog, width=self.width, height=self.height - 300) self.mainLog.insert("Started the Data Science GUI!\n") self.mainLog.pack() # Add Labelframe for main log bottom.add(labelFrameForMainLog) self.root.mainloop() # Open the link def openHyperlinkCallback(self, event): webbrowser.open_new(event.widget.cget("text")) def displayParameterDesc(self): # Destroy if result window and log exists. try: self.window.destroy() self.parameterDescLog.destroy() except (NameError, AttributeError): pass try: # Create a new frame/window from root window to display parameter descriptions self.window = Toplevel(self.root) self.window.geometry("640x300") self.window.title("Parameters of " + self.algorithm) # Display link to documentation url hyperlinkLabel = Label(self.window, text=self.paramDesc["link"], fg="blue", cursor="hand2") hyperlinkLabel.pack() hyperlinkLabel.bind("<Button-1>", self.openHyperlinkCallback) # Parameter descriptions self.parameterDescLog = Text2(self.window, width=self.width, height=self.height) self.parameterDescLog.pack() # Print out the results for key, value in self.paramDesc.items(): if key == "link": pass else: self.parameterDescLog.insert( str(key) + ": " + str(value) + "\n\n") except (NameError, AttributeError): # Display this if user hasn't open a CSV file and select an algorithm label = Label( self.window, text= "You need to open a CSV file and select an algorithm before displaying this!" ) label.pack() pass # Display the csv file in text def displayFile(self): self.csvTable.model.df = pd.concat([self.X, self.y], axis=1) self.csvTable.redraw() # Display results of selected algorithm and parameters def displayResult(self, dict): # Notify the user that training is done self.mainLog.insert("Done computing.\n") # Clear result log and change label frame self.resultLog.delete() self.labelFrameForResult.config(text="Results for " + self.filename + " using " + self.algorithm) # Print out the results for key, value in dict.items(): self.resultLog.insert(str(key) + ": " + str(value) + "\n") def displayPredictionWindow(self): # Create a new frame/window from root window to display parameter descriptions self.predictionWindow = Toplevel(self.root) self.predictionWindow.geometry("480x240") self.predictionWindow.title("Prediction Window of " + self.algorithm) # Width and height for window width = 480 height = 240 # Paned window for left and right main = PanedWindow(self.predictionWindow, orient=HORIZONTAL, sashpad=1, sashrelief=RAISED) main.pack(fill=BOTH, expand=1) # Paned window for left and right left = PanedWindow(main, orient=VERTICAL, sashpad=1, sashrelief=RAISED) # Log for prediction stuff right = PanedWindow(main, orient=VERTICAL, sashpad=1, sashrelief=RAISED) main.add(left, width=int(width / 2)) main.add(right, width=int(width / 2)) # LabelFrame for Left Frame labelFrameForLeftFrame = LabelFrame(left, text="Prediction Frame") # Object containing feature columns and their datatypes self.datatypes = self.X.dtypes # Validation command # %d = Type of action (1=insert, 0=delete, -1 for others) # %P = value of the entry if the edit is allowed (all, focusin, focusout, forced) vcmdForInt = (self.predictionWindow.register(self.validateInt2), '%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W') vcmdForFloat = (self.predictionWindow.register(self.validateFloat), '%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W') vcmdForFloat2 = (self.predictionWindow.register(self.validateFloat2), '%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W') # Contains entries arrayOfEntries = [] # Counter for row counterForRow = 0 # Go through an object that contains the feature columns and their datatypes for attr, value in self.datatypes.items(): Label(labelFrameForLeftFrame, text=attr).grid(row=counterForRow, sticky=W) entry = None if (value == "int64"): entry = Entry(labelFrameForLeftFrame, width=30, validate="all", validatecommand=vcmdForInt) entry.insert(0, 1) elif (value == "float64"): entry = Entry(labelFrameForLeftFrame, width=30, validate="all", validatecommand=vcmdForFloat2) entry.insert(0, 1.0) entry.grid(row=counterForRow, column=1, sticky=E) arrayOfEntries.append(entry) counterForRow = counterForRow + 1 button = Button(labelFrameForLeftFrame, text="Predict", command=lambda: self.predict(arrayOfEntries)) button.grid(row=counterForRow, columnspan=2, sticky=W + E) left.add(labelFrameForLeftFrame, width=int(width / 2), height=height) # LabelFrame for Right Frame labelFrameForRightFrame = LabelFrame(right, text="Prediction Frame") # Table for Predictions self.prediction_df = pd.DataFrame( columns=self.X.columns.values.tolist()) self.predictionTable = Table(labelFrameForRightFrame, dataframe=self.prediction_df, showstatusbar=True) self.predictionTable.show() right.add(labelFrameForRightFrame, width=int(width / 2), height=height) # For user-input predictions def predict(self, entries): for entry in entries: if not entry.get().strip(): self.predictionWindow.bell() self.mainLog.insert( "Check the parameters! You may have entered nothing or 0 for an input!\n" ) return counter = 0 arrayForUserInput = [] dict = {} for attr, datatype in self.datatypes.items(): if (datatype == "int64"): arrayForUserInput.append(int(entries[counter].get())) elif (datatype == "float64"): arrayForUserInput.append(float(entries[counter].get())) dict[attr] = entries[counter].get() counter = counter + 1 arrayForUserInput = np.array(arrayForUserInput).reshape(1, -1) prediction = self.classifier.predict(arrayForUserInput)[0] dict['Prediction'] = prediction self.prediction_df = self.prediction_df.append(dict, ignore_index=True) self.predictionTable.model.df = self.prediction_df self.predictionTable.redraw() # Remove features from label listbox when user selects the features def removeFeatures(self, event): # Note here that Tkinter passes an event object w = event.widget # Indexes of selected features indexes = w.curselection() # Columns of dataframe cols = list(self.df.columns.values) selected_features = [cols[item] for item in indexes] self.list_of_label.delete(0, END) for col in cols: if col not in selected_features: self.list_of_label.insert(0, col) # Prompts the user to open a CSV File def openFile(self): # The full path of the file file = filedialog.askopenfilename(initialdir=getcwd() + "/csv", title="Select file", filetypes=(("csv files", "*.csv"), )) if file: # Actual filename self.filename = os.path.basename(file) # Notify user that program is reading off the csv self.mainLog.insert("Reading '" + self.filename + "' from '" + file + "'.\n") # Clear the selection_Frame # Clear the widgets in the selection frame after you selected features and labels for widget in self.mainFrame.winfo_children(): widget.destroy() # Change LabelFrame text to filename self.labelFrameForCSVFile.config(text=self.filename) # Clear Results log self.resultLog.delete() # Dataframe created from the file self.df = pd.read_csv(file, sep=',') # Draw the CSV table self.csvTable.model.df = self.df self.csvTable.redraw() # Columns of dataframe cols = list(self.df.columns.values) # Create a listbox self.list_of_features = Listbox(self.mainFrame, selectmode=MULTIPLE, width=30, height=10, exportselection=0) self.list_of_features.bind('<<ListboxSelect>>', self.removeFeatures) self.list_of_label = Listbox(self.mainFrame, selectmode=SINGLE, width=30, height=10, exportselection=0) # Show a list of columns for user to check for column in cols: self.list_of_features.insert(END, column) self.list_of_label.insert(END, column) # Display label, listbox, and button Label(self.mainFrame, text="Select the feature columns", relief=RIDGE).pack() self.list_of_features.pack() Label(self.mainFrame, text="Select the label", relief=RIDGE).pack() self.list_of_label.pack() ok = Button(self.mainFrame, text="Okay", command=self.setUpMatrixes) ok.pack() # Set up the feature matrix and label vector def setUpMatrixes(self): # The selections of feature columns and labels columns = self.list_of_features.get(0, END) indexesForFeatureCols = self.list_of_features.curselection() selected_features = [columns[item] for item in indexesForFeatureCols] selected_label = self.list_of_label.get(ANCHOR) # Clear the widgets in the selection frame after you selected features and labels for widget in self.mainFrame.winfo_children(): widget.destroy() # Notify user of selected features and label self.mainLog.insert("You have selected " + str(selected_features) + " as features.\n") self.mainLog.insert("You have selected " + str(selected_label) + " as the label.\n") # Feature matrix and label vector self.X = self.df[selected_features] self.y = self.df[selected_label] # Labels self.labels = self.df[selected_label].unique() # Number of features and labels self.numberOfFeatures = len(selected_features) self.numberOfLabels = len(self.labels) # Option Menu for choosing machine learning algorithms algorithms = [ "K-Nearest Neighbors", "Decision Tree", "Random Forest", "Linear Regression", "Logistic Regression", "Linear SVC", "Multilayer Perceptron" ] self.default = StringVar() self.default.set("Select an algorithm.") self.options = OptionMenu(self.mainFrame, self.default, *algorithms, command=self.selectedAlgorithm) self.options.pack() # Display the csv file self.displayFile() # Display parameters for the selected algorithm def selectedAlgorithm(self, algorithm): # Clear the widgets in the selection frame when changing algorithm for widget in self.mainFrame.winfo_children(): widget.destroy() # Option Menu for choosing machine learning algorithms algorithms = [ "K-Nearest Neighbors", "Decision Tree", "Random Forest", "Linear Regression", "Logistic Regression", "Linear SVC", "Multilayer Perceptron" ] self.default = StringVar() self.default.set(algorithm) self.options = OptionMenu(self.mainFrame, self.default, *algorithms, command=self.selectedAlgorithm) self.options.pack() # Validation command # %d = Type of action (1=insert, 0=delete, -1 for others) # %P = value of the entry if the edit is allowed (all, focusin, focusout, forced) vcmdForInt = (self.mainFrame.register(self.validateInt), '%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W') vcmdForFloat = (self.mainFrame.register(self.validateFloat), '%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W') vcmdForFloat2 = (self.mainFrame.register(self.validateFloat2), '%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W') vcmdForHiddenLayerSizes = (self.mainFrame.register( self.validateHiddenLayerSizes), '%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W') self.algorithm = algorithm # Load image load = Image.open("img/" + algorithm + ".png") # Load image load = load.resize((100, 100), Image.ANTIALIAS) render = ImageTk.PhotoImage(load) # Labels can be text or images img = Label(self.mainFrame, image=render) img.image = render img.pack() self.paramDesc = {} parameters = [] Label(self.mainFrame, text="test_size", relief=RIDGE).pack() self.test_size = Entry(self.mainFrame, validate="all", validatecommand=vcmdForFloat) self.test_size.insert(0, 0.3) self.test_size.pack() parameters.append(self.test_size) Label(self.mainFrame, text="random_state", relief=RIDGE).pack() self.random_state = Entry(self.mainFrame, validate="all", validatecommand=vcmdForInt) self.random_state.insert(0, 2) self.random_state.pack() parameters.append(self.random_state) Label(self.mainFrame, text="cv", relief=RIDGE).pack() self.cv = Entry(self.mainFrame, validate="all", validatecommand=vcmdForInt) self.cv.insert(0, 10) self.cv.pack() parameters.append(self.cv) self.paramDesc[ "test_size"] = "float, int or None, optional (default=0.25)\nIf float, should be between 0.0 and 1.0 and represent the proportion of the dataset to include in the test split. If int, represents the absolute number of test samples. If None, the value is set to the complement of the train size. By default, the value is set to 0.25. The default will change in version 0.21. It will remain 0.25 only if train_size is unspecified, otherwise it will complement the specified train_size." self.paramDesc[ "random_state"] = "int, RandomState instance or None, optional (default=None)\nIf int, random_state is the seed used by the random number generator; If RandomState instance, random_state is the random number generator; If None, the random number generator is the RandomState instance used by np.random." self.paramDesc[ "cv"] = " int, cross-validation generator or an iterable, optional\nDetermines the cross-validation splitting strategy. Possible inputs for cv are:\nNone, to use the default 3-fold cross validation,\ninteger, to specify the number of folds in a (Stratified)KFold,\nAn object to be used as a cross-validation generator.\nAn iterable yielding train, test splits." if self.algorithm == "K-Nearest Neighbors": Label(self.mainFrame, text="n_neighbors", relief=RIDGE).pack() self.n_neighbors = Entry(self.mainFrame, validate="all", validatecommand=vcmdForInt) self.n_neighbors.insert(0, 5) self.n_neighbors.pack() parameters.append(self.n_neighbors) self.paramDesc[ "link"] = "https:////scikit-learn.org/stable/modules/generated/sklearn.neighbors.KNeighborsClassifier.html" self.paramDesc[ "n_neighbors"] = "int, optional (default = 5)\nNumber of neighbors to use by default for kneighbors queries." elif algorithm == "Decision Tree": self.paramDesc[ "link"] = "https////scikit-learn.org/stable/modules/generated/sklearn.tree.DecisionTreeClassifier.html" elif algorithm == "Random Forest": Label(self.mainFrame, text="n_estimators", relief=RIDGE).pack() self.n_estimators = Entry(self.mainFrame, validate="all", validatecommand=vcmdForInt) self.n_estimators.insert(0, 19) self.n_estimators.pack() parameters.append(self.n_estimators) self.paramDesc[ "link"] = "https:////scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestClassifier.html" self.paramDesc[ "n_estimators"] = "integer, optional (default=10)\nThe number of trees in the forest." elif algorithm == "Linear Regression": self.paramDesc[ "link"] = "https:////scikit-learn.org/stable/modules/generated/sklearn.linear_model.LinearRegression.html" elif algorithm == "Logistic Regression": self.paramDesc[ "link"] = "https:////scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html" elif algorithm == "Linear SVC": Label(self.mainFrame, text="C", relief=RIDGE).pack() self.c = Entry(self.mainFrame, validate="all", validatecommand=vcmdForFloat2) self.c.insert(0, 1.0) self.c.pack() parameters.append(self.c) Label(self.mainFrame, text="max_iter", relief=RIDGE).pack() self.max_iter = Entry(self.mainFrame, validate="all", validatecommand=vcmdForInt) self.max_iter.insert(0, 100) self.max_iter.pack() parameters.append(self.max_iter) self.paramDesc[ "link"] = "https:////scikit-learn.org/stable/modules/generated/sklearn.svm.LinearSVC.html" self.paramDesc[ "C"] = "float, optional (default=1.0)\nPenalty parameter C of the error term." self.paramDesc[ "max_iter"] = "int, (default=1000)\nThe maximum number of iterations to be run." elif algorithm == "Multilayer Perceptron": Label(self.mainFrame, text="max_iter", relief=RIDGE).pack() self.max_iter = Entry(self.mainFrame, validate="all", validatecommand=vcmdForInt) self.max_iter.insert(0, 100) self.max_iter.pack() parameters.append(self.max_iter) Label(self.mainFrame, text="alpha", relief=RIDGE).pack() self.alpha = Entry(self.mainFrame, validate="all", validatecommand=vcmdForFloat2) self.alpha.insert(0, 0.005) self.alpha.pack() parameters.append(self.alpha) Label(self.mainFrame, text="hidden_layer_sizes", relief=RIDGE).pack() self.hidden_layer_sizes = Entry( self.mainFrame, validate="all", validatecommand=vcmdForHiddenLayerSizes) self.hidden_layer_sizes.insert(0, 2) self.hidden_layer_sizes.pack() parameters.append(self.hidden_layer_sizes) self.paramDesc[ "link"] = "https:////scikit-learn.org/stable/modules/generated/sklearn.neural_network.MLPClassifier.html" self.paramDesc[ "max_iter"] = "int, (default=1000)\nThe maximum number of iterations to be run." self.paramDesc[ "alpha"] = "float, optional, default 0.0001\nL2 penalty (regularization term) parameter." self.paramDesc[ "hidden_layer_sizes"] = "tuple, length = n_layers - 2, default (100,)\nThe ith element represents the number of neurons in the ith hidden layer." # Compute using the specified parameters # Lambda means that the method won't be called immediately (only when button is pressed) submit = Button(self.mainFrame, text="Submit", command=lambda: self.validateAllInputs(parameters)) submit.pack() # Notify user that program is reading off the csv self.mainLog.insert(self.algorithm + " has been selected!\n") # Validate integer inputs (don't allow user to enter anything else) def validateInt(self, d, i, P, s, S, v, V, W): # print("end", "OnValidate:\n") # print("end", "d='%s'\n" % d) # print("end", "i='%s'\n" % i) # print("end", "P='%s'\n" % P) # print("end", "s='%s'\n" % s) # print("end", "S='%s'\n" % S) # print("end", "v='%s'\n" % v) # print("end", "V='%s'\n" % V) # print("end", "W='%s'\n" % W) # Accept Integer values and empty string (for erasing the one only number) if (P.isdigit() and int(P) > 0) or P == "": return True else: self.mainLog.insert( "Please enter an integer (if the field is empty, enter an integer greater than 0).\n" ) self.mainFrame.bell() return False # Validate integer inputs (don't allow user to enter anything else) def validateInt2(self, d, i, P, s, S, v, V, W): # Accept Integer values and empty string (for erasing the one only number) if (P.isdigit() and int(P) >= 0) or P == "": return True else: self.mainLog.insert( "Please enter an integer (if the field is empty, enter an integer greater than 0).\n" ) self.mainFrame.bell() return False # Validate float inputs (don't allow user to enter anything else) def validateFloat(self, d, i, P, s, S, v, V, W): # Accept Float values and empty string (for erasing the one only number) if P == "": return True elif S == " ": self.mainLog.insert("No spaces! Enter a digit!\n") self.mainFrame.bell() return False try: number = float(P) if (0.0 <= number and number <= 1.0): return True else: self.mainLog.insert( "Float numbers must be between 0.0 and 1.0 (inclusive)!\n") self.mainFrame.bell() return False except ValueError: self.mainLog.insert( "Float numbers are only allowed (ex: 0.3 or .3)!\n") self.mainFrame.bell() return False # Vaidate float inputs (don't allow user to enter anything else) def validateFloat2(self, d, i, P, s, S, v, V, W): # Accept Float values and empty string (for erasing the one only number) if P == "": return True elif S == " ": self.mainLog.insert("No spaces! Enter a digit!\n") self.mainFrame.bell() return False try: number = float(P) if (0.0 <= number and number <= 1000.0): return True else: self.mainLog.insert( "Float numbers must be between 0.00001 and 1000.0 (inclusive)!\n" ) self.mainFrame.bell() return False except ValueError: self.mainLog.insert( "Float numbers are only allowed (ex: 0.00001 or .00001)!\n") self.mainFrame.bell() return False # Vaidate hidden layer sizes inputs (don't allow user to enter anything else) def validateHiddenLayerSizes(self, d, i, P, s, S, v, V, W): # Accept Float values and empty string (for erasing the one only number) if P == "": return True try: if S.isdigit() or S == "," or S == "": return True else: self.mainLog.insert( "Hidden layer sizes should be separated by commas (ex: 2,3,4). This means there are 2 nodes in first hidden layer, 3 nodes in second hidden layer, and 4 nodes in the third hidden layer.!\n" ) self.mainFrame.bell() return False except ValueError: self.mainLog.insert( "Hidden layer sizes should be separated by commas (ex: 2,3,4). This means there are 2 nodes in first hidden layer, 3 nodes in second hidden layer, and 4 nodes in the third hidden layer.!\n" ) self.mainFrame.bell() return False # Final validation of inputs (doesn't compute anything if a parameter is field or is 0 def validateAllInputs(self, parameters): for parameter in parameters: if not parameter.get().strip() or parameter.get() == "0": self.mainFrame.bell() self.mainLog.insert( "Check the parameters! You may have entered nothing or 0 for an input!\n" ) return self.compute() # Compute the results of def compute(self): self.mainLog.insert("Computing...\n") self.classifier = None # Split the dataframe dataset. X_train, X_test, y_train, y_test = train_test_split( self.X, self.y, test_size=float(self.test_size.get()), random_state=int(self.random_state.get())) if self.algorithm == "K-Nearest Neighbors": # Instantiating KNN object self.classifier = KNeighborsClassifier( n_neighbors=int(self.n_neighbors.get())) elif self.algorithm == "Decision Tree": # Instantiating DecisionTreeClassifier object self.classifier = DecisionTreeClassifier() elif self.algorithm == "Random Forest": # Instantiating RandomForestClassifier object self.classifier = RandomForestClassifier(n_estimators=int( self.n_estimators.get()), bootstrap=True) elif self.algorithm == "Linear Regression": # Instantiating Linear Regression object self.classifier = LinearRegression() elif self.algorithm == "Logistic Regression": # Instantiating Logistic Regression object self.classifier = LogisticRegression() elif self.algorithm == "Linear SVC": # LinearSVC classifier self.classifier = LinearSVC() elif self.algorithm == "Multilayer Perceptron": # Turn the string (containing commas) into a list modified_hidden_layer_sizes = self.hidden_layer_sizes.get().split( ",") # Remove any empty string in the list modified_hidden_layer_sizes = [ item.strip() for item in modified_hidden_layer_sizes if item.strip() ] # Turn the list of strings into a tuple of int modified_hidden_layer_sizes = tuple( [int(i) for i in modified_hidden_layer_sizes]) # Instantiate MLP classifier self.classifier = MLPClassifier( activation='logistic', solver='adam', max_iter=int(self.max_iter.get()), learning_rate_init=0.002, alpha=float(self.alpha.get()), hidden_layer_sizes=modified_hidden_layer_sizes) # fit the model with the training set self.classifier.fit(X_train, y_train) # Predict method is used for creating a prediction on testing data y_predict = self.classifier.predict(X_test) # Accuracy of testing data on predictive model accuracy = accuracy_score(y_test, y_predict) # Add #-fold Cross Validation with Supervised Learning accuracy_list = cross_val_score(self.classifier, self.X, self.y, cv=int(self.cv.get()), scoring='accuracy') # # Report # report = classification_report(y_test, y_predict, target_names=self.labels) # Dictionary containing information dict = { "Training Set Size": 1.00 - float(self.test_size.get()), "Testing Set Size": float(self.test_size.get()), "Training Set Shape": X_train.shape, "Testing Set Shape": X_test.shape, "Classifier": self.classifier, "Accuracy for " + self.algorithm: str(accuracy), "Cross Validation for " + self.algorithm: accuracy_list.mean() } self.displayResult(dict) self.displayPredictionWindow() # Exit the client def client_exit(self): exit()
class CAPE_UI: def __init__(self, parent, conn, config, frame_color='light yellow'): self.conn = conn self.config = config self.cur = self.conn.cursor() self.frame_color = frame_color # self.assigned_local_table = assigned_local_table # self.assigned_global_table = assigned_global_table style = ttk.Style() style.map('TCombobox', fieldbackground=[('readonly', 'white')]) style.theme_use("clam") style.configure("Treeview", background=self.frame_color, fieldbackground=self.frame_color) #----------------------------main frame----------------------------------------# self.parent = parent self.main_frame = Frame(self.parent, bg=self.frame_color) self.main_frame.columnconfigure(0, weight=1) self.main_frame.columnconfigure(1, weight=8, uniform=1) self.main_frame.columnconfigure(2, weight=7, uniform=1) self.main_frame.rowconfigure(0, weight=3) self.main_frame.rowconfigure(1, weight=2) self.main_frame.rowconfigure(2, weight=2) self.main_frame.rowconfigure(3, weight=2) self.main_frame.rowconfigure(4, weight=2) self.main_frame.rowconfigure(5, weight=2) self.main_frame.rowconfigure(6, weight=2) self.main_frame.rowconfigure(7, weight=2) self.main_frame.rowconfigure(8, weight=2) self.main_frame.rowconfigure(9, weight=2) #----------------------------------place frames----------------------------------# self.main_frame.grid(column=0, row=0, columnspan=3, rowspan=10, sticky='nsew') self.table_frame = Frame(self.main_frame, borderwidth=5, relief="sunken", bg=self.frame_color) self.table_frame.grid(column=0, row=0, columnspan=1, rowspan=10, sticky='nsew') self.table_frame.rowconfigure(0, weight=1) self.table_frame.rowconfigure(1, weight=14) self.query_frame = Frame(self.main_frame, borderwidth=5, relief="ridge", bg=self.frame_color) self.query_frame.grid(column=1, row=0, columnspan=1, rowspan=2, sticky='nsew') self.query_frame.rowconfigure(0, weight=5) self.query_frame.rowconfigure(1, weight=1) self.query_template_frame = Frame(self.query_frame, bg=self.frame_color) self.query_template_frame.grid(row=0, sticky='nsew') self.query_button_frame = Frame(self.query_frame, bg=self.frame_color) self.query_button_frame.grid(row=1, sticky='nsew') self.query_result = Frame(self.main_frame, borderwidth=5, relief="sunken", bg=self.frame_color) self.query_result.grid(column=1, row=2, columnspan=1, rowspan=8, sticky='nsew') self.local_pattern = Frame(self.main_frame, borderwidth=5, relief="sunken", bg=self.frame_color) self.local_pattern.grid(column=2, row=0, columnspan=2, rowspan=5, sticky='nsew') self.explanation_frame = Frame(self.main_frame, borderwidth=5, relief="sunken", bg=self.frame_color) self.explanation_frame.grid(column=2, row=5, columnspan=2, rowspan=5, sticky='nsew') #---------------------------table frame----------------------------------------- self.table_info = Label(self.table_frame, text="Database Information", font=('Times New Roman bold', 15), bg=self.frame_color, borderwidth=5, relief=RIDGE) self.table_info.grid(column=0, row=0, sticky='nsew') self.tree_view_frame = Frame(self.table_frame) self.tree_view_frame.grid(column=0, row=1, sticky='nsew') self.table_view = ttk.Treeview(self.tree_view_frame) self.table_view.pack(side='left', fill=BOTH) self.tree_view_scroll = ttk.Scrollbar(self.tree_view_frame, orient="vertical", command=self.table_view.yview) self.tree_view_scroll.pack(side='right', fill='y') self.table_view.configure(yscrollcommand=self.tree_view_scroll.set) self.db_info = DBinfo(conn=self.conn) self.db_info_dict = self.db_info.get_db_info() table_index = 0 for key, value in self.db_info_dict.items(): self.table_view.insert('', 'end', 'item' + str(table_index), text=key) for n in value: self.table_view.insert('item' + str(table_index), 'end', text=n) table_index += 1 # self.pub_dict = {"dict_name":"pub", # "global_name":"dev.pub_global", # "local_name":"dev.pub_local" # } # self.crime_dict = {"dict_name":"crime", # "global_name": "dev.crime_global", # "local_name":"dev.crime_local" # } #----------------------------Query frame----------------------------------------# self.query_temp = User_Query_Frame(conn=self.conn, table_dict=self.db_info_dict, parent=self.query_frame) self.query_button = Button(self.query_button_frame, text="Run Query", font=('Times New Roman bold', 12), command=self.run_query) self.query_button.pack(side=RIGHT) self.show_global_pattern_button = Button( self.query_button_frame, text="Show Global Pattern", font=('Times New Roman bold', 12), command=self.show_global_pattern) self.show_global_pattern_button.pack(side=RIGHT) self.show_local_pattern_button = Button( self.query_button_frame, text="Show Local Pattern", font=('Times New Roman bold', 12), command=self.show_local_pattern) self.show_local_pattern_button.pack(side=RIGHT) #----------------------------Query result frame --------------------------------# self.query_result.columnconfigure(0, weight=6) self.query_result.columnconfigure(1, weight=1) self.query_result.rowconfigure(0, weight=1) self.query_result.rowconfigure(1, weight=10) self.query_result.rowconfigure(2, weight=10) self.result_label = Label(self.query_result, text='Query Result', font=('Times New Roman bold', 20), borderwidth=5, relief=RIDGE, bg=self.frame_color) self.result_label.grid(row=0, column=0, sticky='nsew') self.high_low_frame = Frame(self.query_result, bg=self.frame_color) self.high_low_frame.grid(column=1, row=1, rowspan=2, sticky='nsew') self.high_low_frame.columnconfigure(0, weight=1) self.high_low_frame.rowconfigure(0, weight=1) self.high_low_frame.rowconfigure(1, weight=1) self.high_low_frame.rowconfigure(2, weight=1) self.high_low_frame.rowconfigure(3, weight=1) self.high_low_frame.rowconfigure(4, weight=1) self.high_low_frame.rowconfigure(5, weight=1) self.high_low_frame.rowconfigure(6, weight=1) self.high_low_frame.rowconfigure(7, weight=1) self.high_button = Button(self.high_low_frame, text='High', font=('Times New Roman bold', 12), command=self.handle_high) self.high_button.grid(column=0, row=1) self.low_button = Button(self.high_low_frame, text='Low', font=('Times New Roman bold', 12), command=self.handle_low) self.low_button.grid(column=0, row=2) self.show_results = Frame(self.query_result) self.show_results.grid(column=0, row=1, sticky='nsew') self.show_global = Frame(self.query_result) self.show_global.grid(column=0, row=2, sticky='nsew') self.query_result_table = Table(self.show_results) self.query_result_table.show() self.parent.columnconfigure(0, weight=1) self.parent.rowconfigure(0, weight=1) #---------------------------Global Pattern Frame -----------------------------------# self.show_global.rowconfigure(0, weight=1) self.show_global.rowconfigure(1, weight=10) self.show_global.columnconfigure(0, weight=1) self.global_pattern_label = Label(self.show_global, text="Global Patterns", font=('Times New Roman bold', 20), borderwidth=5, bg=self.frame_color, relief=RIDGE) self.global_pattern_label.grid(column=0, row=0, sticky='nsew') self.show_global_patterns = Frame(self.show_global) self.show_global_patterns.grid(column=0, row=1, sticky='nsew') self.global_description_button = Button( self.high_low_frame, text='Describe\nGlobal', font=('Times New Roman bold', 12), command=self.global_description) self.global_description_button.grid(column=0, row=5) self.global_pattern_filter_button = Button( self.high_low_frame, text='Filter \nLocal\n Pattern', font=('Times New Roman bold', 12), command=self.use_global_filter_local) self.global_pattern_filter_button.grid(column=0, row=6) self.global_pattern_table = Table(self.show_global_patterns) self.global_pattern_table.show() # create a sql function for sorting the array in order to be used for filtering sort_array_function = "CREATE OR REPLACE FUNCTION array_sort(anyarray) RETURNS anyarray AS $$"+\ "SELECT array_agg(x order by x) FROM unnest($1) x;"+\ "$$ LANGUAGE sql;" # logger.debug(sort_array_function) self.cur.execute(sort_array_function) #------------------------------- local pattern frame---------------------------------------# self.local_pattern.rowconfigure(0, weight=1) self.local_pattern.rowconfigure(1, weight=20) self.local_pattern.rowconfigure(2, weight=1) self.local_pattern.columnconfigure(0, weight=1) self.local_pattern.columnconfigure(1, weight=1) self.local_pattern.columnconfigure(2, weight=1) self.local_pattern.columnconfigure(3, weight=1) self.local_pattern.columnconfigure(4, weight=1) self.local_show_patterns = Frame(self.local_pattern) self.local_show_patterns.grid(column=0, row=1, sticky='nsew') self.local_pattern_label = Label(self.local_pattern, text="Local Patterns", font=('Times New Roman bold', 20), borderwidth=5, bg=self.frame_color, relief=RIDGE) self.local_pattern_label.grid(column=0, row=0, columnspan=5, sticky='nsew') self.local_pattern_filter_button = Button(self.local_pattern, text='Reset Query Output', font=('Times New Roman bold', 12), command=self.reset_output) self.local_pattern_filter_button.grid(column=0, row=2) self.local_pattern_filter_button = Button( self.local_pattern, text='Filter Output', font=('Times New Roman bold', 12), command=self.show_updated_output) self.local_pattern_filter_button.grid(column=2, row=2) self.draw_pattern_button = Button(self.local_pattern, text='Draw Pattern', font=('Times New Roman bold', 12), command=self.pop_up_pattern) self.draw_pattern_button.grid(column=4, row=2) self.local_pattern_table_frame = Frame(self.local_pattern) self.local_pattern_table_frame.grid(row=1, column=0, columnspan=5, sticky='nsew') self.local_pattern_table = Table(self.local_pattern_table_frame) self.local_pattern_table.show() #---------------------------------explanation frame-----------------------------# self.explanation_frame.rowconfigure(0, weight=1) self.explanation_frame.rowconfigure(1, weight=10) self.explanation_frame.rowconfigure(2, weight=1) self.explanation_frame.columnconfigure(0, weight=10) self.exp_label = Label(self.explanation_frame, text="Top Explanations", font=('Times New Roman bold', 20), borderwidth=5, bg=self.frame_color, relief=RIDGE) self.exp_label.grid(column=0, row=0, sticky='nsew') self.exp_table_frame = Frame(self.explanation_frame) self.exp_table_frame.grid(row=1, column=0, sticky='nsew') self.exp_table = Table(self.exp_table_frame) self.exp_table.show() self.describe_exp_button = Button(self.explanation_frame, text="Describe Explanation", font=('Times New Roman bold', 12), command=self.pop_up_explanation) self.describe_exp_button.grid(row=2, column=0) #----------------------------------Functions----------------------------------------# def run_query(self): self.user_query, self.query_group_str, self.agg_function, self.user_agg, self.agg_name, self.cur_table_name = self.query_temp.get_query( ) # logger.debug(self.user_query) self.handle_view ="\nDROP VIEW IF EXISTS user_query;"+\ "\nCREATE VIEW user_query as "+ self.user_query # logger.debug(self.handle_view) try: self.cur.execute(self.handle_view) except: tkinter.messagebox.showinfo("Info", "Invalid Query, Please Doublecheck!") self.original_query_result_df = pd.read_sql(self.user_query, self.conn) self.query_result_df = self.original_query_result_df self.plot_data_convert_dict, self.query_data_convert_dict = self.db_info.get_db_data_type( self.cur_table_name) self.plot_data_convert_dict[self.agg_name] = 'numeric' self.query_data_convert_dict[self.agg_name] = 'float' self.assigned_global_table = 'dev.{}_global'.format( self.cur_table_name) self.assigned_local_table = 'dev.{}_local'.format(self.cur_table_name) model = TableModel(dataframe=self.original_query_result_df) self.query_result_table.updateModel(model) self.query_result_table.redraw() # if(self.cur_table_name.lower()==self.pub_dict['dict_name']): # self.table_dict = self.pub_dict # elif(self.cur_table_name.lower()==self.crime_dict['dict_name']): # self.table_dict = self.crime_dict def show_global_pattern(self): global_query = "select array_to_string(fixed,',') as Partition,array_to_string(variable,',') as Predictor,agg,"+\ "round((lambda)::numeric(4,2),2) as Support,model from "+self.assigned_global_table+\ " where array_to_string(array_sort(fixed||variable),',')='"+self.query_group_str+"';" # logger.debug(global_query) self.global_pattern_df = pd.read_sql(global_query, self.conn) # logger.debug(self.global_pattern_df.head()) # logger.debug(list(self.global_pattern_df)) pattern_model = TableModel(dataframe=self.global_pattern_df) self.global_pattern_table.updateModel(pattern_model) self.global_pattern_table.redraw() def show_local_pattern(self): local_query = "select array_to_string(fixed,',') as Partition,array_to_string(variable,',') as Predictor,"+\ "array_to_string(fixed_value,',') as partition_values,agg,model,fixed,fixed_value,variable,"+\ "theta,param,stats,dev_pos,dev_neg from "+self.assigned_local_table+\ " where array_to_string(array_sort(fixed||variable),',')='"+self.query_group_str+"';" for n in self.local_pattern_table.multiplerowlist: self.chosen_local_pattern = self.global_pattern_table.model.df.iloc[ int(n)] self.local_output_pattern_df = pd.read_sql(local_query, self.conn) local_shown = self.local_output_pattern_df[[ 'partition', 'partition_values', 'predictor', 'agg' ]] pattern_model = TableModel(local_shown) self.local_pattern_table.updateModel(pattern_model) self.local_pattern_table.redraw() def use_global_filter_local(self): pattern_df_lists = [] for n in self.global_pattern_table.multiplerowlist: model_name = self.global_pattern_table.model.df.iloc[int( n)]['model'] # logger.debug("model_name"+model_name) global_partition = self.global_pattern_table.model.df.iloc[int( n)]['partition'] global_predictor = self.global_pattern_table.model.df.iloc[int( n)]['predictor'] g_filter_l_query = " select array_to_string(fixed,',') as Partition,array_to_string(variable,',') as Predictor,"+\ "array_to_string(fixed_value,',') as partition_values,agg,model,fixed,fixed_value,variable,"+\ "theta,param,stats,dev_pos,dev_neg from "+self.assigned_local_table+\ " where array_to_string(fixed,',')='"+global_partition+\ "' and array_to_string(variable,',')='"+global_predictor+\ "' and model = '"+model_name+"';" self.local_output_pattern_df = pd.read_sql(g_filter_l_query, self.conn) # logger.debug(g_filter_l_query) local_shown = self.local_output_pattern_df[[ 'partition', 'partition_values', 'predictor', 'agg' ]] model = TableModel(dataframe=local_shown) self.local_pattern_table.updateModel(model) self.local_pattern_table.redraw() def global_description(self): for n in self.global_pattern_table.multiplerowlist: fixed_attribute = self.global_pattern_table.model.df.iloc[int( n)]['partition'] aggregation_function = self.global_pattern_table.model.df.iloc[int( n)]['agg'] modeltype = self.global_pattern_table.model.df.iloc[int( n)]['model'] variable_attribute = self.global_pattern_table.model.df.iloc[int( n)]['predictor'] Lambda = self.global_pattern_table.model.df.iloc[int(n)]['support'] fixed_attribute = fixed_attribute.replace(",", ", ") global_desc = "For each ("+fixed_attribute+'), the '+aggregation_function +' is '+modeltype+'\n in '+variable_attribute+'.'+\ 'This pattern holds for '+str(Lambda*100)+ ' % of the '+fixed_attribute desc_win = Toplevel() x = self.parent.winfo_x() y = self.parent.winfo_y() w = 540 h = 120 desc_win.geometry("%dx%d+%d+%d" % (w, h, x + 450, y + 500)) desc_win.wm_title("Global Pattern Description") desc_frame = Frame(desc_win) desc_frame.pack(fill=BOTH, expand=True) desc_label = Label(desc_frame, text=global_desc, font=('Times New Roman bold', 12), borderwidth=5, relief=SOLID, justify=LEFT) desc_label.pack(fill=BOTH, expand=True) def use_local_filter_output( self ): # given partition attributes and partition values, get explanation(query on user query) l_filter_o_query = None for n in self.local_pattern_table.multiplerowlist: chosen_row = self.local_pattern_table.model.df.iloc[int(n)] logger.debug(chosen_row) partition_attr_list = self.local_pattern_table.model.df.iloc[int( n)]['partition'].split(',') partition_value_list = self.local_pattern_table.model.df.iloc[int( n)]['partition_values'].split(',') where_clause_list = [] where_clause = None for n in range(len(partition_attr_list)): if (self.query_data_convert_dict[partition_attr_list[n]] == 'str'): condition = "{} =\'{}\'".format(partition_attr_list[n], partition_value_list[n]) elif (self.query_data_convert_dict[partition_attr_list[n]] == 'float'): condition = "{} = {}::float".format(partition_attr_list[n], partition_value_list[n]) else: condition = "{} = {}::int".format(partition_attr_list[n], partition_value_list[n]) where_clause_list.append(condition) if (len(where_clause_list) == 1): where_clause = where_clause_list[0] else: where_clause = " and ".join(where_clause_list) l_filter_o_query = "select user_query.* from user_query where " + where_clause + ";" # logger.debug("filter_output_query:") # logger.debug(l_filter_o_query) filtered_result_df = pd.read_sql(l_filter_o_query, self.conn) return chosen_row, filtered_result_df def show_updated_output(self): filtered_result_df = self.use_local_filter_output()[1] self.query_result_df = filtered_result_df model = TableModel(dataframe=filtered_result_df) self.query_result_table.updateModel(model) self.query_result_table.redraw() def handle_question(self, direction): self.question_tuple = '' config = ExplConfig() config.conn = self.config.conn config.cur = self.config.cur config.query_table_name = self.cur_table_name eg = ExplanationGenerator( config, { 'pattern_table': 'dev.{}'.format(self.cur_table_name), 'query_result_table': self.cur_table_name }) eg.initialize() col_name = [ 'Explanation_Tuple', "Score", 'From_Pattern', "Drill_Down_To", "Distance", "Outlierness", "Denominator", "relevent_model", "relevent_param", "refinement_model", "drill_param" ] exp_df = pd.DataFrame(columns=[ "From_Pattern", "Drill_Down_To", "Score", "Distance", "Outlierness", "Denominator", "relevent_model", "relevent_param", "refinement_model", "drill_param" ]) for n in self.query_result_table.multiplerowlist: self.question = self.query_result_table.model.df.iloc[[int(n)]] self.original_question = self.question.copy(deep=True) self.question.rename(columns={self.agg_name: self.user_agg}, inplace=True) self.question_tuple = self.query_result_df.iloc[[int(n)]] # logger.debug(self.question) self.question['direction'] = direction self.question['lambda'] = 0.2 question = self.question.iloc[0].to_dict() # logger.debug(question) elist = eg.do_explain_online(question) exp_list = [] for e in elist: tuple_list = [] # print(str(e.tuple_value)) # print(str(e.tuple_value.keys())) # e_tuple_str = ','.join(map(str, e.tuple_value.values())) e_tuple_str = e.ordered_tuple_string() tuple_list.append(e_tuple_str) score = round(e.score, 2) tuple_list.append(score) if e.expl_type == 1: local_pattern=( '[' + ','.join(e.relevent_pattern[0]) +\ '=' + ','.join(list(map(str, e.relevent_pattern[1]))) +']:'+ \ ','.join(list(map(str, e.relevent_pattern[2])))+' \u2933 '+self.agg_name ) relevent_model = e.relevent_pattern[4] if e.relevent_pattern[4] == 'const': relevent_param = str( round( float(e.relevent_pattern[6].split(',')[0][1:]), 2)) else: # relevent_param = 'Intercept=' + str(e.relevent_pattern[7]['Intercept'])+', '+str(list(e.relevent_pattern[7])[1])+'='+str(round(e.relevent_pattern[7][list(e.relevent_pattern[7])[1]],2)) relevent_param = e.relevent_pattern[7] drill_down_to = ','.join([ x for x in e.refinement_pattern[0] if x not in e.relevent_pattern[0] ]) refinement_model = e.refinement_pattern[4] if e.refinement_pattern[4] == 'const': drill_param = str( round( float( e.refinement_pattern[6].split(',')[0][1:]), 2)) else: drill_param = e.refinement_pattern[7] else: relevent_model = e.relevent_pattern[4] local_pattern=( '[' + ','.join(e.relevent_pattern[0]) +\ '=' + ','.join(list(map(str, e.relevent_pattern[1]))) +']:'+ \ ','.join(list(map(str, e.relevent_pattern[2])))+' \u2933 '+self.agg_name ) if e.relevent_pattern[4] == 'const': relevent_param = str( round( float(e.relevent_pattern[6].split(',')[0][1:]), 2)) else: # relevent_param = 'Intercept=' + str(e.relevent_pattern[7]['Intercept'])+', '+str(list(e.relevent_pattern[7])[1])+'='+str(e.relevent_pattern[7][list(e.relevent_pattern[7])[1]]) relevent_param = e.relevent_pattern[7] refinement_model = '' drill_down_to = '' drill_param = '' tuple_list.append(local_pattern) tuple_list.append(drill_down_to) distance = round(e.distance, 2) tuple_list.append(distance) outlierness = round(e.deviation, 2) tuple_list.append(outlierness) denominator = round(e.denominator, 2) tuple_list.append(denominator) tuple_list.append(relevent_model) tuple_list.append(relevent_param) tuple_list.append(refinement_model) tuple_list.append(drill_param) exp_list.append(tuple_list) df_exp = pd.DataFrame(exp_list, columns=col_name) exp_df = exp_df.append(df_exp, ignore_index=True) self.exp_df = exp_df[col_name] model = TableModel(dataframe=self.exp_df) self.exp_table.updateModel(model) self.exp_table.redraw() def handle_low(self): self.user_direction = 'low' self.handle_question(self.user_direction) def handle_high(self): self.user_direction = 'high' self.handle_question(self.user_direction) def reset_output(self): model = TableModel(dataframe=self.original_query_result_df) self.query_result_table.updateModel(model) self.query_result_table.redraw() self.query_result_df = self.original_query_result_df def pop_up_pattern(self): chosen_row, pattern_data_df = self.use_local_filter_output() fetch_full_chosen_row_info = "select array_to_string(fixed,',') as Partition,array_to_string(variable,',') as Predictor,"+\ "array_to_string(fixed_value,',') as partition_values,agg,model,fixed,fixed_value,variable,"+\ "theta,param,stats,dev_pos,dev_neg from "+self.assigned_local_table+\ " where array_to_string(fixed_value,',')='"+chosen_row['partition_values']+"'"+\ " and array_to_string(variable,',')='"+chosen_row['predictor']+"';" full_chosen_row = pd.read_sql(fetch_full_chosen_row_info, self.conn) full_chosen_row['stats'] = full_chosen_row['stats'].str.split( ',', expand=True)[0] full_chosen_row['stats'] = full_chosen_row['stats'].str.strip('[') full_chosen_row['stats'] = pd.to_numeric(full_chosen_row['stats']) full_chosen_row['stats'] = full_chosen_row['stats'].round(2) logger.debug(full_chosen_row) self.local_pattern_detail = Local_Pattern_Frame( chosen_row=full_chosen_row.iloc[0], pattern_data_df=pattern_data_df, agg_alias=self.agg_name, data_convert_dict=self.plot_data_convert_dict) self.local_pattern_detail.load_pattern_description() self.local_pattern_detail.load_pattern_graph() def get_pattern_result( self, partition_attr_list=None, partition_value_list=None, pred_attr_list=None ): # given partition attributes and partition values, get explanation(query on table) where_clause_list = [] where_clause = None # logger.debug("partition_attr_list is ") # logger.debug(partition_attr_list) # logger.debug("partition_value_list is ") # logger.debug(partition_value_list) for n in range(len(partition_attr_list)): if (self.query_data_convert_dict[partition_attr_list[n]] == 'str'): condition = "{} =\'{}\'".format(partition_attr_list[n], partition_value_list[n]) elif (self.query_data_convert_dict[partition_attr_list[n]] == 'float'): condition = "{} = {}::float".format(partition_attr_list[n], partition_value_list[n]) else: condition = "{} = {}::int".format(partition_attr_list[n], partition_value_list[n]) where_clause_list.append(condition) if (len(where_clause_list) == 1): where_clause = where_clause_list[0] else: where_clause = " and ".join(where_clause_list) if (pred_attr_list is not None): Pattern_Q = "SELECT "+self.agg_function+" as "+self.agg_name+","+','.join(partition_attr_list)+","+','.join(pred_attr_list)+\ " FROM " +self.cur_table_name+" WHERE " + where_clause+\ " GROUP BY "+','.join(partition_attr_list)+","+','.join(pred_attr_list) else: Pattern_Q = "SELECT "+self.agg_function+" as "+self.agg_name+","+','.join(partition_attr_list)+\ " FROM " +self.cur_table_name + " WHERE " + where_clause+\ " GROUP BY "+','.join(partition_attr_list) # logger.debug("Pattern_Q") # logger.debug(Pattern_Q) exp_pattern_df = pd.read_sql(Pattern_Q, self.conn) # logger.debug('exp_pattern_df is :') # logger.debug(exp_pattern_df) return exp_pattern_df def pop_up_explanation(self): for n in self.exp_table.multiplerowlist: exp_chosen_row = self.exp_table.model.df.iloc[int(n)] relevent_pattern = self.exp_table.model.df.iloc[int( n)]['From_Pattern'] rel_pattern_part = relevent_pattern.split(':')[0].split( '=')[0].strip('[') rel_pattern_part_value = relevent_pattern.split(':')[0].split( '=')[1].split(']') rel_pattern_pred = relevent_pattern.split(':')[1].split( ' \u2933 ')[0] agg_name = relevent_pattern.split(':')[1].split(' \u2933 ')[1] rel_pattern_model = self.exp_df.iloc[int(n)]['relevent_model'] rel_param = self.exp_df.iloc[int(n)]['relevent_param'] rel_pattern_part_list = rel_pattern_part.split(',') rel_pattern_pred_list = rel_pattern_pred.split(',') rel_pattern_part_value_list = rel_pattern_part_value[0].split(',') exp_tuple = self.exp_df.iloc[int(n)]['Explanation_Tuple'] exp_tuple_list = exp_tuple.split(',')[:-1] exp_tuple_score = float(self.exp_df.iloc[int(n)]['Score']) drill_attr_list = self.exp_df.iloc[int(n)]['Drill_Down_To'].split( ',') if (drill_attr_list != ['']): exp_tuple_col = rel_pattern_part_list + rel_pattern_pred_list + drill_attr_list exp_tuple_col.sort() else: exp_tuple_col = rel_pattern_part_list + rel_pattern_pred_list exp_tuple_col.sort() # logger.debug('exp_tuple_col is:') # logger.debug(exp_tuple_col) # logger.debug('exp_tuple_list is:') # logger.debug(exp_tuple_list) exp_tuple_df_list = [exp_tuple_list] exp_tuple_df = pd.DataFrame(exp_tuple_df_list) logger.debug("exp_tuple_df:") exp_tuple_df.columns = exp_tuple_col logger.debug(exp_tuple_df) if (drill_attr_list != ['']): drill_values = [] for n in drill_attr_list: drill_value = exp_tuple_df[n].to_string(index=False) drill_values.append(drill_value) # logger.debug('rel_pattern_part_list') # logger.debug(rel_pattern_part_list) # logger.debug('rel_pattern_part_value_list') # logger.debug(rel_pattern_part_value_list) drill_pattern_df = self.get_pattern_result( partition_attr_list=rel_pattern_part_list + drill_attr_list, partition_value_list=rel_pattern_part_value_list + drill_values, pred_attr_list=rel_pattern_pred_list) # logger.debug("drill_pattern_df is") # logger.debug(drill_pattern_df) rel_pattern_df = self.get_pattern_result( partition_attr_list=rel_pattern_part_list, partition_value_list=rel_pattern_part_value_list, pred_attr_list=rel_pattern_pred_list) question_df = self.original_question explanation_df = self.get_pattern_result( partition_attr_list=exp_tuple_col, partition_value_list=exp_tuple_list, pred_attr_list=None) logger.debug(explanation_df) exp_selected = exp_chosen_row data_convert_dict = self.plot_data_convert_dict self.Explainer = Exp_Frame( input_question_df=question_df, input_explanation_df=explanation_df, input_exp_chosen_row=exp_selected, input_none_drill_down_df=rel_pattern_df, input_drill_down_df=drill_pattern_df, input_data_convert_dict=data_convert_dict) self.Explainer.load_exp_graph() self.Explainer.load_exp_description( user_direction=self.user_direction) else: rel_pattern_df = self.get_pattern_result( partition_attr_list=rel_pattern_part_list, partition_value_list=rel_pattern_part_value_list, pred_attr_list=rel_pattern_pred_list) question_df = self.original_question explanation_df = self.get_pattern_result( partition_attr_list=exp_tuple_col, partition_value_list=exp_tuple_list, pred_attr_list=None) exp_selected = exp_chosen_row data_convert_dict = self.plot_data_convert_dict self.Explainer = Exp_Frame( input_question_df=question_df, input_explanation_df=explanation_df, input_exp_chosen_row=exp_selected, input_none_drill_down_df=rel_pattern_df, input_drill_down_df=None, input_data_convert_dict=data_convert_dict) self.Explainer.load_exp_graph() self.Explainer.load_exp_description( user_direction=self.user_direction)
class ImageLabelingForm(object): def __init__(self): self.img_col_title = 'image' self.lbl_col_title = 'label' self.df = self.empty_df() # All folders self.folder_name_list = [] self.folder_list = [] # Current folder self.dirname = '' self.folder_idx = 0 self.folder_name = None self.img_list = [] self.data_file = '' # Current Image self.current_idx = 0 self.max_idx = 0 self.image_name = None self.image_path = None self.window = tk.Tk() self.window.title("Image Labeling Program") # Folder Selection self.frm_folder = tk.Frame(master=self.window, relief=tk.FLAT) self.btn_browse = tk.Button( master=self.frm_folder, text="Browse", command=self.browseFiles, ) self.btn_prev = tk.Button( master=self.frm_folder, text="Previous", command=self.prev_folder, ) self.btn_next = tk.Button( master=self.frm_folder, text="Next", command=self.next_folder, ) self.btn_browse.pack(side=tk.TOP, padx=2, pady=2) self.btn_next.pack(side=tk.RIGHT, padx=2, pady=2) self.btn_prev.pack(side=tk.LEFT, padx=2, pady=2) # Label Submission self.frm_input = tk.Frame(master=self.window, relief=tk.FLAT) self.btn_submit = tk.Button( master=self.frm_input, text="Submit & Next", command=self.submit, ) self.btn_back = tk.Button( master=self.frm_input, text="Back", command=self.back, ) self.btn_save = tk.Button( master=self.frm_input, text="Save", command=self.save, ) self.btn_reset = tk.Button( master=self.frm_input, text="RESET", fg="red", command=self.reset, ) self.lbl_cow = tk.Label(master=self.frm_input, text="Image label: ") self.ent_label = tk.Entry(master=self.frm_input, width=6) self.lbl_cow.grid(row=0, column=0, padx=2, pady=2) self.ent_label.grid(row=0, column=1, padx=2, pady=2) self.btn_back.grid(row=1, column=1, padx=2, pady=2) self.btn_submit.grid(row=1, column=0, padx=2, pady=2) self.btn_save.grid(row=2, column=0, padx=2, pady=2) self.btn_reset.grid(row=2, column=1, padx=2, pady=2) # Dialogue self.frm_dialogue = tk.Frame(master=self.window, relief=tk.RIDGE, borderwidth=5) self.lbl_dialogue = tk.Label(master=self.frm_dialogue, text="Please browse for a folder") self.lbl_dialogue.pack(side=tk.BOTTOM, padx=2, pady=2) #Image self.frm_image = tk.Frame(master=self.window, relief=tk.SUNKEN) self.lbl_folder = tk.Label(master=self.frm_image, text="No folder selected") self.lbl_folder.pack() img = ImageTk.PhotoImage(Image.open(".\\src\\noimage_placeholder.png")) self.img_image = tk.Label(master=self.frm_image, image=img) self.img_image.pack() self.lbl_file = tk.Label(master=self.frm_image, text="No file...") self.lbl_file.pack() #Tables self.frm_data = tk.Frame(master=self.window, relief=tk.FLAT) self.pt = Table(self.frm_data, dataframe=self.df) self.pt.show() # Frames self.frm_image.pack(side=tk.LEFT) self.frm_dialogue.pack(side=tk.BOTTOM, pady=60) self.frm_folder.pack(pady=30) self.frm_input.pack(pady=30) self.frm_data.pack(pady=30) # Handlers self.pt.rowheader.bind("<Button-1>", self.select_row_handler) self.pt.bind("<Button-1>", self.select_row_handler) self.window.bind("<Return>", self.return_row_handler) self.window.bind("<Tab>", self.return_row_handler) self.window.bind("<Left>", self.return_row_handler) self.window.bind("<Right>", self.return_row_handler) self.window.bind("<Up>", self.return_row_handler) self.window.bind("<Down>", self.return_row_handler) self.window.mainloop() def browseFiles(self): self.dirname = filedialog.askdirectory(initialdir = "./images", title = "Select the directory containing the data") if not self.dirname: return -1 self.folder_name_list = [ name for name in os.listdir(os.path.dirname(self.dirname)) if os.path.isdir(os.path.join(os.path.dirname(self.dirname), name)) ] self.folder_list = [ os.path.join(os.path.dirname(self.dirname), name) for name in os.listdir(os.path.dirname(self.dirname)) if os.path.isdir(os.path.join(os.path.dirname(self.dirname), name)) ] self.folder_idx = self.folder_name_list.index(os.path.basename(self.dirname)) self.load_set() def next_folder(self): if self.folder_idx < len(self.folder_list)-1: self.folder_idx += 1 self.dirname = self.folder_list[self.folder_idx] self.load_set() else: pass # self.reinitiate() def prev_folder(self): if self.folder_idx > 0: self.folder_idx -= 1 self.dirname = self.folder_list[self.folder_idx] self.load_set() else: pass def submit(self): # Reads the input label input_label = self.ent_label.get() self.df.at[self.current_idx, self.lbl_col_title] = input_label self.pt.redraw() if self.current_idx == self.max_idx: self.df.to_csv(self.data_file, index=False) self.ent_label.delete(0, tk.END) self.lbl_dialogue.configure(text="(AUTO SAVE) No more images remaining") self.next_folder() else: self.current_idx += 1 self.load_image() def back(self): if self.current_idx > 0: self.current_idx -= 1 # Place the highlight on the current row in the table self.pt.setSelectedRow(self.current_idx) self.pt.redraw() self.load_image() def save(self): self.df.to_csv(self.data_file, index=False) self.lbl_dialogue.configure(text="Progress saved") def reset(self): self.df.drop(columns=self.lbl_col_title, inplace=True) self.df[self.lbl_col_title] = np.nan self.df = self.df.astype(dtype={self.lbl_col_title: object}) self.pt.redraw() self.ent_label.delete(0, tk.END) self.lbl_dialogue.configure(text="Progress reset") def reinitiate(self): self.df = self.empty_df() self.current_idx = 0 self.max_idx = 0 self.image_name = None self.image_path = None self.pt.model.df = self.df self.pt.setSelectedRow(self.current_idx) self.pt.redraw() self.lbl_folder.configure(text="No folder selected") self.lbl_file.configure(text='No file...') img = ImageTk.PhotoImage(Image.open(".\\src\\noimage_placeholder.png")) self.img_image.configure(image=img) self.img_image.image = img def empty_df(self): return pd.DataFrame({self.img_col_title:[np.nan], self.lbl_col_title:[np.nan]}) def select_row_handler(self, e): rowclicked_single = self.pt.get_row_clicked(e) if rowclicked_single <= self.max_idx: self.current_idx = rowclicked_single self.load_image() # TODO: This method is not functioning properly (Possibly a bug with pandas table) def return_row_handler(self, e): rowclicked_single = self.pt.getSelectedRow() if rowclicked_single <= self.max_idx: self.current_idx = rowclicked_single self.load_image() def load_set(self): self.data_file = '{}/labels.csv'.format(self.dirname) self.folder_name = os.path.basename(self.dirname) if os.path.isfile(self.data_file): # Load the dataframe self.df = pd.read_csv(self.data_file, dtype={self.lbl_col_title: object}) # Read image list from dataframe self.img_list = list(self.df['image']) else: # Create dataframe self.df = self.empty_df() # Create image list self.img_list = glob.glob(self.dirname + "//*.jpg") self.fill_image_column() self.df.to_csv(self.data_file, index=False) # Update current folder label self.lbl_folder.configure(text=self.folder_name) # Set image properties self.max_idx = len(self.df) - 1 self.current_idx = self.find_first_unlabeled() self.load_image() self.update_button_status() self.lbl_dialogue.configure(text="Woking on folder '{}'".format(self.folder_name)) def load_image(self): self.image_name = self.img_list[self.current_idx] self.image_path = os.path.join(self.dirname, self.image_name) # Update image label self.lbl_file.configure(text=self.image_name) # Update the table and place the highlight on the current row self.pt.model.df = self.df self.pt.setSelectedRow(self.current_idx) self.pt.redraw() # Set the default value for the text box tb_value = self.determine_text_box_value() self.ent_label.delete(0, tk.END) self.ent_label.insert(0, tb_value) # Load the image img = ImageTk.PhotoImage(Image.open(self.image_path).resize((960, 540))) self.img_image.configure(image=img) self.img_image.image = img self.update_button_status() def callback(self, event): self.ent_label.selection_range(0, tk.END) def fill_image_column(self): col1 = [os.path.basename(x) for x in self.img_list] col2 = np.nan temp_dict = {self.img_col_title:col1, self.lbl_col_title:col2} self.df = pd.DataFrame(temp_dict) self.df = self.df.astype(dtype={self.lbl_col_title: object}) def find_first_unlabeled(self): first_null = 0 nulls = self.df.index[self.df[self.lbl_col_title].isnull()] if nulls.any(): first_null = nulls[0] return first_null def determine_text_box_value(self): current_value = self.ent_label.get() df_value = self.df[self.lbl_col_title][self.current_idx] if pd.isnull(df_value): return current_value else: return df_value def update_button_status(self): if self.folder_idx == 0: self.btn_prev["state"] = "disabled" else: self.btn_prev["state"] = "active" if self.folder_idx == len(self.folder_list)-1: self.btn_next["state"] = "disabled" else: self.btn_next["state"] = "active" if self.current_idx == 0: self.btn_back["state"] = "disabled" else: self.btn_back["state"] = "active" # if (self.current_idx == self.max_idx) and (self.folder_idx == len(self.folder_list)-1): # self.btn_submit["state"] = "disabled" # else: # self.btn_submit["state"] = "active"
class MainFrame(Tk): def __init__(self): super().__init__() # Create DataFrame self.df = pd.DataFrame({'': ['']}) self.frame = Frame(self, relief=RAISED, borderwidth=1) self.table = Table(self.frame, dataframe=self.df, showtoolbar=True, showstatusbar=True) #self.parent = parent self.mycompany = company.Company() self.initUI() self.style = Style() print(self.style.theme_names()) self.style.theme_use('winnative') self.closeButton = Button(self, text="Закрыть", command=self.quit) self.closeButton.pack(side=RIGHT, padx=5, pady=5) self.loadButton = Button(self, text="Загрузить", command=self.loadCompany) self.loadButton.pack(side=RIGHT) self.modelButton = Button(self, text="Модель", command=self.createModel) self.modelButton.pack(side=RIGHT) self.prognosisButton = Button(self, text="Прогноз", command=self.prognosis) self.prognosisButton.pack(side=RIGHT) self.l1 = Label(self, text='От') self.l2 = Label(self, text='До') self.entry_from = Entry(self, width=4, textvariable=StringVar(self, '2021')) self.entry_to = Entry(self, width=4, textvariable=StringVar(self, '2026')) self.entry_to.pack(side=RIGHT, padx=5) self.l2.pack(side=RIGHT) self.entry_from.pack(side=RIGHT, padx=5) self.l1.pack(side=RIGHT) def initUI(self): self.title("Fluger Investor 1.00 2021") #self.pack(fill=BOTH, expand=1) self.centerWindow() self.frame.pack(fill=BOTH, expand=True) # Специальная таблица для DataFrame self.table.show() #self.pack(fill=BOTH, expand=True) def centerWindow(self): w = 1200 h = 800 sw = self.winfo_screenwidth() sh = self.winfo_screenheight() x = (sw - w) / 2 y = (sh - h) / 2 self.geometry('%dx%d+%d+%d' % (w, h, x, y)) def loadCompany(self): Tk().withdraw( ) # we don't want a full GUI, so keep the root window from appearing # show an "Open" dialog box and return the path to the selected file filename = askopenfilename(initialdir=os.getcwd(), title="Открыть компанию", filetypes=(("json", "*.json"), ("all files", "*.*"))) self.mycompany = company.Company() self.mycompany.load_company_from_file(filename) self.mycompany.load_financials_from_file() self.df = self.mycompany.get_financials() print(self.df) self.table.model.df = self.df self.table.redraw() self.title("Fluger Investor 1.00 2021 - " + self.mycompany.ticker) def createModel(self): modelgen = model_generator.ModelGenerator() modelgen.set_financials(self.mycompany.get_financials()) model, score = modelgen.build_linear_regression_model('Price') self.mycompany.set_price_model(model) messagebox.showinfo("Модель", "Модель создана, score = " + str(score)) def prognosis(self): f = self.entry_from.get() t = self.entry_to.get() years = [i for i in range(int(f), int(t))] fin = self.mycompany.get_financials() fin = fin.drop(["Price"], axis=1) modelgen = model_generator.ModelGenerator() features, predictions = modelgen.predict( self.mycompany.get_price_model(), fin, years) print(features) prognosis_frame.PrognosisFrame(self, predictions, years)
class processingFrame(Frame): def __init__(self, master): # 1 is csv, 2 is file with correct fields # txt,xls,append file names self.filename1="" self.filename2="" self.filename3="" self.trouble=[] self.maxwordlen=[] self.checklabel= StringVar() self.countlabel= StringVar() self.neglabel=StringVar() # make frames for each step self.processing = Frame(master, bg="#DAF7A6" ) Frame.__init__(self,self.processing) self.processing.grid(column=0,row=1) # Make Frames for tables, buttons and output self.stuffframe = Frame(self.processing,bg="#DAF7A6") self.stuffframe.grid(column = 0,row = 0, sticky=W+N) # Frames for tables tableframe1 = Frame(self.processing,bg="#DAF7A6") tableframe1.grid(column=2,row = 0, sticky = N) self.stuffframe2 = Frame(tableframe1) self.stuffframe2.grid(row=0,column=0, sticky=E) # This is the Table Frame for showing data self.f1 = Frame(tableframe1) self.f1.grid(row = 0, column = 3, columnspan=25, rowspan=15, sticky = N) #tableframe2 = Frame(self.processing,bg="#DAF7A6") #tableframe2.grid(column=2,row = 1, sticky = N) self.stuffframe3 = Frame(tableframe1) self.stuffframe3.grid(row=1,column=0, sticky=E) # This is the table frame for negatives self.f2 = Frame(tableframe1, bg="#DAF7A6") self.f2.grid(row = 1, column = 3, columnspan=25, rowspan=15,pady=(320,0), sticky = S) #self.toplevel = Toplevel() #Buttons/Text self.title2 = Label(self.stuffframe,text="Cleaning & Processing Data", font = "-weight bold") self.title2.grid(row=0,column=0,sticky=W+N) self.title3 = Label(self.stuffframe,text="Visit Github.com/ljstrnadiii") self.title3.grid(row=1,column=0,sticky=W+N) self.text1 = Label(self.stuffframe, text="Choose files:") self.text1.grid(row=2,column=0, pady =(10,0),sticky=W) self.button1= Button(self.stuffframe, text="Scanned txt", command = self.browsecsv) self.button1.grid(row=3, column=0, sticky=W) self.button7= Button(self.stuffframe, text="amend data", command = self.ammend) self.button7.grid(row=4, column=0, sticky=W) self.button2= Button(self.stuffframe, text="Valid xls", command = self.browsevalid) self.button2.grid(row=5, column=0, sticky = W) self.text2 = Label(self.stuffframe, text="Process:") self.text2.grid(row=7,column=0, pady =(10,0), sticky = W) self.button3= Button(self.stuffframe, text="Correct", command = self.check ) self.button3.grid(row=8, column=0,sticky=W+N ) self.button4= Button(self.stuffframe, text="Get Count", command = self.count) self.button4.grid(row=9, column=0, sticky = W+N) label1 = Label(self.processing,text ="") self.title_instr = Label(self.stuffframe,text="Procedure: show negative, edit, update, repeat") self.title_instr.grid(row=15,column=0,sticky=W+N) self.button5 = Button(self.stuffframe, text="show negatives", command = self.fixnegs) self.button5.grid(row=16, column = 0, sticky = W) self.button6 = Button(self.stuffframe, text="update", command = self.update) self.button6.grid(row=17, column = 0, sticky = W) # setting tables up self.pt1 = Table(self.f1, rows=14,column=24, showtoolbar=False, showstatusbar=False) self.pt2 = Table(self.f2, rows=17, column=24, showtoolbar=False, showstatusbar=False) self.pt1.show() self.pt2.show() self.processing.config(bd=5) # functions made for Window def browsecsv(self): Tk().withdraw() self.filename1 = askopenfilename() filename = ntpath.basename(self.filename1) Label(self.stuffframe,text=filename, wraplength = 200 , justify = LEFT).grid(row=10, column=0, sticky=W) def ammend(self): Tk().withdraw() self.filename3 = askopenfilename() filename = ntpath.basename(self.filename3) Label(self.stuffframe,text=filename, wraplength = 200 , justify = LEFT).grid(row=11, column=0, sticky=W) def browsevalid(self): Tk().withdraw() self.filename2 = askopenfilename() filename = ntpath.basename(self.filename2) Label(self.stuffframe,text=filename ).grid(row=12, column=0, sticky = W) def check(self): text1 = proc.correctfields(self.filename1, self.filename2) proc.ammend(self.filename1,self.filename3) self.checklabel.set(text1) #label1 = Label(self.stuffframe,textvariable = self.checklabel, \ # wraplength=250, justify=LEFT) #label1.grid(row=13,column=0, sticky = W) def count(self): self.corrected, self.trouble, self.text2 = \ proc.getcount(self.filename1) # self.pt1, \ self.countlabel.set(self.text2) Label2 = Label(self.stuffframe, text = self.countlabel.get(), \ wraplength = 250,justify=LEFT) Label2.grid(row = 14, column = 0, sticky =W) self.corrected = self.corrected.fillna(0) self.pt1.model.df = self.corrected self.pt1.redraw() def fixnegs(self): if len(self.trouble)>0: dq = self.corrected.ix[self.corrected[ \ "Account_Number"]==self.trouble[-1][-1],:] print(list(dq)) dq = dq[["Store","Inv_Type","Date",self.trouble[-1][-2]]] # where is the neg value and what it is. append it in a column where = self.trouble[-1][-3] negcol=np.zeros(len(dq)) negcol[where-1]=self.trouble[-1][-6] dq["value"]=negcol # uncomment for label of neg value # self.n = (self.trouble[-1][-5].isoformat()[0:10],self.trouble[-1][-6]) #self.neglabel.set(str(self.n)) #Label3 = Label(self.stuffframe, text = self.neglabel.get(), \ # wraplength = 250,justify=LEFT) #Label3.grid(row=15,column=0,sticky=W) dq = pd.DataFrame(dq) dq = dq.fillna(0) dq[list(dq)[-2]]= dq[list(dq)[-2]].astype(int) dq[list(dq)[-1]]= dq[list(dq)[-1]].astype(int) dq[list(dq)[-4]]= dq[list(dq)[-4]].astype(int) self.pt2.model.df = dq#.loc[:last+1,:] self.pt2.redraw() # pop last element from list assuming user will update before fixnegs again self.trouble.pop() else: self.pt2.clearTable() self.pt2.redraw() def update(self): #note: i dont think i need a child table: # try to just create a table in fixnegs and below in update call on the # df o update accordingly. consider the indexes though self.pt1.model.df.update(self.pt2.model.df) self.pt1.redraw() #uncomment to save self.pt1.model.df.to_csv(self.filename1, index=False)