def no_acc(): global win2, habusrenr win2 = Toplevel(root) win2.geometry('250x50') win2.iconbitmap('Logo.ico') win2.resizable(width=FALSE, height=FALSE) win2.title("Support") habusrlab = Label(win2, text="Full Name") habusrenr = Entry(win2) habusrbtt = Button(win2, text="Send", command=send_acc_req) habusrlab.grid(column=0, row=0) habusrenr.grid(column=1, row=0) habusrbtt.place(relx=0.6, x=1, y=22.5, anchor=NE)
class SkyglowEstimationToolbox: """Main class that establishes GUI.""" def __init__(self, root): self.root = root # Radio action buttons self.action = None self.sgmap_single_btn, self.krn_lib_btn, self.multi_map_btn = None, None, None self.file_log_var = StringVar() self.csv_file_var = StringVar() self.krn_folder_var = StringVar() self.output_folder_var = StringVar() self.sgmap_folder_var = StringVar() self.krn_ent_var = StringVar() self.krn_var, self.hem_var = IntVar(), IntVar() self.img, self.cdiag = None, None self.lat_lbl, self.lat_entry = None, None self.k_lbl, self.k_entry = None, None self.zen_lbl, self.zen_entry = None, None self.azi_lbl, self.azi_entry = None, None self.krn_lvl, self.krn_entry, self.krn_btn = None, None, None self.txt_redir, self.prg_log = None, None self.map_btn, self.gen_krn_btn = None, None # Sets window title, size, and icon on screen. self.root.title("Skyglow Estimation Toolbox (SET)") self.root.geometry('%dx%d+%d+%d' % (constants.SW * 0.75, constants.SH * 0.75, 25, 25)) self.root.iconbitmap(os.path.join(os.getcwd(), constants.ICO)) self.root.resizable(False, False) self.root.update_idletasks() # Creates three paned windows for the main screen. base = PanedWindow() base.pack(fill=BOTH, expand=1) sub1 = PanedWindow(base, orient=VERTICAL, height=self.root.winfo_height() * 3 / 4) base.add(sub1) sub2 = PanedWindow(sub1, orient=HORIZONTAL, height=self.root.winfo_height() / 5) sub1.add(sub2) # Creates frame for holding inputs. self.input_frame = Frame(sub2) sub2.add(self.input_frame) # Creates frame for bottom half of main screen. self.img_frame = Frame(sub1, bd=2, bg='white', relief="sunken") sub1.add(self.img_frame) # Creates canvas for displaying images. self.img_canvas = Canvas(self.img_frame, bd=2, relief="groove", width=constants.SW * 0.6, height=self.root.winfo_height() * 3 / 4 * 0.9) self.img_canvas.place(relx=.5, rely=.5, anchor=CENTER) # Creates help button for link to documentation, instructions, and about. self.help_btn = Menubutton(self.input_frame, text="Help", relief="raised", bd=2, width=8, pady=1) #self.help_btn.place(relx=1, rely=0, anchor=NE) self.help_btn.grid(column=4, columnspan=1, row=0) self.help_btn_menu = Menu(self.help_btn, tearoff=0) doc = 'https://github.com/NASA-DEVELOP' self.help_btn_menu.add_command(label="Documentation", command=lambda: self.open_url(doc)) self.help_btn_menu.add_command(label="Instructions", command=self.instructions) self.help_btn_menu.add_separator() self.help_btn_menu.add_command(label="About", command=self.about) self.help_btn["menu"] = self.help_btn_menu def main_screen(self): """Set up input GUI and image display screen.""" self.action = IntVar() btn_width = int(constants.SW / 60) file_width = int(constants.SW / 18) lbl_width = int(constants.SW / 60) gen_width = int(constants.SW / 42) radio_font = Font(family='TkDefaultFont', size=12) self.sgmap_single_btn = Radiobutton( self.input_frame, text="Generate Artificial Skyglow Map", font=radio_font, width=btn_width, variable=self.action, value='sng', command=self.sng_popup) self.krn_lib_btn = Radiobutton(self.input_frame, text="Generate Kernel Library", font=radio_font, width=btn_width, variable=self.action, value='krn', command=self.krn_popup) self.multi_map_btn = Radiobutton( self.input_frame, text="Generate Maps from Multiple Kernels", font=radio_font, width=btn_width, variable=self.action, value='mul', command=self.mul_popup) self.hem_map_btn = Radiobutton( self.input_frame, text="Generate Hemispherical Visualization", font=radio_font, width=btn_width, variable=self.action, value='hem', command=self.hem_popup) #Place widget self.sgmap_single_btn.grid(column=0, columnspan=1, row=0) self.krn_lib_btn.grid(column=1, columnspan=1, row=0) self.multi_map_btn.grid(column=2, columnspan=1, row=0) self.hem_map_btn.grid(column=3, columnspan=1, row=0) # VIIRS Image Reference File self.file_lbl = Label(self.input_frame, text="Image File:", width=lbl_width, anchor=E) self.file_log = Entry(self.input_frame, width=file_width, bd=2, relief="sunken", textvariable=self.file_log_var) self.browse_btn = Button(self.input_frame, text="Browse", command=self.import_viirs) # Angles CSV File self.csv_file_lbl = Label(self.input_frame, text="Angles CSV File:", width=lbl_width, anchor=E) self.csv_file_log = Entry(self.input_frame, width=file_width, bd=2, relief="sunken", textvariable=self.csv_file_var) self.csv_browse_btn = Button(self.input_frame, text="Browse", command=self.import_csv) # Multiple Maps form Kernel library self.mul_file_lbl = Label(self.input_frame, text="Kernel Folder:", width=lbl_width, anchor=E) self.mul_file_log = Entry(self.input_frame, width=file_width, bd=2, relief="sunken", textvariable=self.krn_folder_var) self.mul_browse_btn = Button(self.input_frame, text="Browse", command=self.import_krn_folder) # MultiKrn Map Output Location self.output_lbl = Label(self.input_frame, text="Output Location:", width=lbl_width, anchor=E) self.output_log = Entry(self.input_frame, width=file_width, bd=2, relief="sunken", textvariable=self.output_folder_var) self.output_btn = Button(self.input_frame, text="Browse", command=self.import_out_folder) # Hemisphere Output Location self.sgmap_folder_lbl = Label(self.input_frame, text="Skyglow Map Location:", width=lbl_width, anchor=E) self.sgmap_folder_log = Entry(self.input_frame, width=file_width, bd=2, relief="sunken", textvariable=self.sgmap_folder_var) self.sgmap_folder_btn = Button(self.input_frame, text="Browse", command=self.import_sgmap_folder) # Import Kernel Checkbutton self.check_lbl = Label(self.input_frame, text="Import Kernel:", width=lbl_width, anchor=E) self.krn_chk = Checkbutton(self.input_frame, anchor=W, variable=self.krn_var, command=self.checkbtn_val) self.hem_chk_lbl = Label(self.input_frame, text="Generate kernels for hemisphere:", width=lbl_width, anchor=E) self.hem_chk = Checkbutton(self.input_frame, anchor=W, variable=self.hem_var) # Region Latitude (deg), Grand Teton National park = 43.7904 degrees N self.lat_lbl = Label(self.input_frame, text="Latitude (deg):", width=lbl_width, anchor=E) self.lat_entry = Entry(self.input_frame, width=btn_width, bd=2, relief="sunken") self.lon_lbl = Label(self.input_frame, text="Longitude (deg):", width=lbl_width, anchor=E) self.lon_entry = Entry(self.input_frame, width=btn_width, bd=2, relief="sunken") # Atmospheric Clarity Parameter, REF 2, Eq. 12, p. 645 self.k_lbl = Label(self.input_frame, text="Atmospheric Clarity Parameter:", width=btn_width, anchor=E) self.k_entry = Entry(self.input_frame, width=btn_width, bd=2, relief="sunken") # Zenith angle (deg), z, REF 2, Fig. 6, p.648 self.zen_lbl = Label(self.input_frame, text="Zenith Angle (deg):", width=lbl_width, anchor=E) self.zen_entry = Entry(self.input_frame, width=btn_width, bd=2, relief="sunken") # Azimuth angle (deg) self.azi_lbl = Label(self.input_frame, text="Azimuth Angle (deg):", width=lbl_width, anchor=E) self.azi_entry = Entry(self.input_frame, width=btn_width, bd=2, relief="sunken") self.krn_lbl = Label(self.input_frame, text="Kernel File:", width=lbl_width, anchor=E) self.krn_ent = Entry(self.input_frame, width=file_width, bd=2, relief="sunken", textvariable=self.krn_ent_var) self.krn_btn = Button(self.input_frame, text="Browse", command=self.import_krn) # Generate Artificial Skyglow Map Button self.map_btn = Button(self.input_frame, text="Generate Artificial Skyglow Map", width=gen_width, command=self.generate_map) # Generate Kernal library button for SET self.gen_krn_btn = Button(self.input_frame, text="Generate Kernel Library", width=gen_width, command=self.generate_krn) # Generate Map of Multiple Kernals(word better later on) self.mul_map_btn = Button(self.input_frame, text="Generate Maps from Multiple Kernels", width=gen_width, command=self.generate_mmap) # Generate Hemispherical Visualization Display of Skyglow self.hem_gen_btn = Button(self.input_frame, text="Generate Hemisphere", width=gen_width, command=self.generate_hem) def import_viirs(self): """Import a VIIRS DNB file.""" # Allows user to search through his directory for VIIRS Image file. file_types = [('TIFF Files', '*.tif'), ('All files', '*')] file_name = filedialog.askopenfilename(initialdir='/', title="Select file", filetypes=file_types) self.file_log_var.set(file_name) # Checks to see if file is empty. If not, displays image on canvas. if file_name != '': pilimg = Image.open(file_name) pilimg_width, pilimg_height = pilimg.size pilimg.tile = [ t for t in pilimg.tile if t[1][2] < pilimg_width and t[1][3] < pilimg_height ] canvas_size = (self.img_canvas.winfo_width(), self.img_canvas.winfo_height()) pilimg_r = pilimg.resize(canvas_size, Image.ANTIALIAS) pilimg_col = ImageOps.colorize(ImageOps.grayscale(pilimg_r), (0, 0, 0), (255, 255, 255)) pilimg_cont = ImageOps.autocontrast(pilimg_col, cutoff=.4, ignore=None) self.img = ImageTk.PhotoImage(pilimg_cont) self.img_canvas.create_image(canvas_size[0] / 2, canvas_size[1] / 2, image=self.img) else: print('File is empty.') def import_csv(self): """Import CSV file.""" file_types = [('CSV Files', '*.csv'), ('All files', '*')] file_name = filedialog.askopenfilename(initialdir='/', title="Select file", filetypes=file_types) self.csv_file_var.set(file_name) if file_name is '': print('File is empty.') def import_krn_folder(self): """Import kernel folder.""" krn_dir = filedialog.askdirectory(initialdir='/', title="Select kernel folder") self.krn_folder_var.set(krn_dir) if krn_dir is '': print('Directory is empty.') def import_out_folder(self): """Import skyglow output folder.""" output_dir = filedialog.askdirectory(initialdir='/', title="Select output folder") self.output_folder_var.set(output_dir) if output_dir is '': print('Directory is empty.') def import_krn(self): """Import existing kernel tif.""" file_types = [('TIFF Files', '*.tif'), ('All files', '*')] file_name = filedialog.askopenfilename(initialdir='/', title="Select file", filetypes=file_types) self.krn_ent_var.set(file_name) def import_sgmap_folder(self): """Import skyglow map folder for hemisphere building.""" sgmap_dir = filedialog.askdirectory(initialdir='/', title="Select skyglow map folder") self.sgmap_folder_var.set(sgmap_dir) if sgmap_dir is '': print('Directory is empty.') def sng_popup(self): """Single map tab.""" self.remove_all() self.check_lbl.grid(column=0, row=2) self.krn_chk.place(relx=.22, rely=.41, anchor=CENTER) self.file_lbl.grid(column=0, row=1) self.file_log.grid(column=1, columnspan=3, row=1) self.browse_btn.grid(column=4, row=1, sticky=W, padx=3) self.lat_lbl.grid(column=0, row=3) self.lat_entry.grid(column=1, row=3) self.k_lbl.grid(column=2, row=3) self.k_entry.grid(column=3, row=3) self.zen_lbl.grid(column=0, row=4) self.zen_entry.grid(column=1, row=4) self.azi_lbl.grid(column=2, row=4) self.azi_entry.grid(column=3, row=4) self.map_btn.grid(column=1, columnspan=3, row=5, sticky=N + S + E + W) def krn_popup(self): """Kernel lib tab.""" self.remove_all() # latitude self.lat_lbl.grid(column=0, row=3) self.lat_entry.grid(column=1, row=3) # atmospheric clarity self.k_lbl.grid(column=2, row=3) self.k_entry.grid(column=3, row=3) # angles file self.csv_file_lbl.grid(column=0, row=1) self.csv_file_log.grid(column=1, columnspan=3, row=1) self.csv_browse_btn.grid(column=4, row=1, sticky=W, padx=3) # input VIIRS image self.file_lbl.grid(column=0, row=2) self.file_log.grid(column=1, columnspan=3, row=2) self.browse_btn.grid(column=4, row=2, sticky=W, padx=3) self.hem_chk_lbl.grid(column=0, row=4) self.hem_chk.place(relx=.21, rely=.69) self.gen_krn_btn.grid(column=1, columnspan=3, row=5, sticky=N + S + E + W) def mul_popup(self): """Multiple maps tab.""" self.remove_all() # Kernel folder location self.mul_file_lbl.grid(column=0, row=1) self.mul_file_log.grid(column=1, columnspan=3, row=1) self.mul_browse_btn.grid(column=4, row=1, sticky=W, padx=3) # input VIIRS image self.file_lbl.grid(column=0, row=2) self.file_log.grid(column=1, columnspan=3, row=2) self.browse_btn.grid(column=4, row=2, sticky=W, padx=3) # Choose output location self.output_lbl.grid(column=0, row=3) self.output_log.grid(column=1, columnspan=3, row=3) self.output_btn.grid(column=4, row=3, sticky=W, padx=3) # Generate map from kernel folder self.mul_map_btn.grid(column=1, columnspan=3, row=4, sticky=N + S + E + W) def hem_popup(self): """Hemisphere tab.""" self.remove_all() # Skyglow Map Folder self.sgmap_folder_lbl.grid(column=0, row=1) self.sgmap_folder_log.grid(column=1, columnspan=3, row=1) self.sgmap_folder_btn.grid(column=4, row=1, sticky=W, padx=3) # Latitude entry self.lat_lbl.grid(column=0, row=3) self.lat_entry.grid(column=1, row=3) # Longitude entry self.lon_lbl.grid(column=2, row=3) self.lon_entry.grid(column=3, row=3) # Generate Hemispherical Visualization button self.hem_gen_btn.grid(column=1, columnspan=3, row=4, sticky=N + S + E + W) def remove_all(self): """Remove all existing GUI elements before opening new tab.""" self.check_lbl.grid_remove() self.krn_chk.place_forget() self.hem_chk.place_forget() self.hem_chk_lbl.grid_remove() self.file_lbl.grid_remove() self.file_log.grid_remove() self.browse_btn.grid_remove() self.krn_lbl.grid_remove() self.krn_ent.grid_remove() self.krn_btn.grid_remove() self.lat_lbl.grid_remove() self.lat_entry.grid_remove() self.k_lbl.grid_remove() self.k_entry.grid_remove() self.zen_lbl.grid_remove() self.zen_entry.grid_remove() self.azi_lbl.grid_remove() self.azi_entry.grid_remove() self.map_btn.grid_remove() self.gen_krn_btn.grid_remove() self.mul_map_btn.grid_remove() self.csv_file_lbl.grid_remove() self.csv_file_log.grid_remove() self.csv_browse_btn.grid_remove() self.mul_file_lbl.grid_remove() self.mul_file_log.grid_remove() self.mul_browse_btn.grid_remove() self.output_lbl.grid_remove() self.output_log.grid_remove() self.output_btn.grid_remove() self.hem_gen_btn.grid_remove() self.lat_lbl.grid_remove() self.lat_entry.grid_remove() self.lon_lbl.grid_remove() self.lon_entry.grid_remove() self.sgmap_folder_lbl.grid_remove() self.sgmap_folder_log.grid_remove() self.sgmap_folder_btn.grid_remove() def checkbtn_val(self): """Change interface based on if Import Kernel button is checked.""" # Import Kernel File widgets when Kernel Checkbutton is marked. if self.krn_var.get(): self.lat_lbl.grid_remove() self.lat_entry.grid_remove() self.k_lbl.grid_remove() self.k_entry.grid_remove() self.zen_lbl.grid_remove() self.zen_entry.grid_remove() self.azi_lbl.grid_remove() self.azi_entry.grid_remove() self.krn_lbl.grid(column=0, row=2) self.krn_ent.grid(column=1, columnspan=3, row=2) self.krn_btn.grid(column=4, row=2, sticky=W, padx=3) self.krn_chk.place_forget() self.krn_chk.place(relx=0.19, rely=.5) # Input parameter widgets when Kernel Checkbuttton is unmarked else: self.krn_lbl.grid_remove() self.krn_ent.grid_remove() self.krn_btn.grid_remove() self.lat_lbl.grid(column=0, row=3) self.lat_entry.grid(column=1, row=3) self.k_lbl.grid(column=2, row=3) self.k_entry.grid(column=3, row=3) self.zen_lbl.grid(column=0, row=4) self.zen_entry.grid(column=1, row=4) self.azi_lbl.grid(column=2, row=4) self.azi_entry.grid(column=3, row=4) self.krn_chk.place_forget() self.krn_chk.place(relx=0.22, rely=.41, anchor=CENTER) @staticmethod def open_url(url): """"Open a url""" webbrowser.open_new(url) def instructions(self): """Open instructions window.""" # Instantiates separate Toplevel instruction window. instr_window = Toplevel(self.root) instr_window.geometry('550x575+25+25') instr_window.title('Instructions') instr_window.wm_iconbitmap(constants.ICO) instr_window.resizable(False, False) # Creatse Scrollbar and Frame for containing other widgets. instr_scroll = Scrollbar(instr_window) instr_scroll.pack(fill=Y, side="right") instr_frame = Frame(instr_window, bg='white') instr_frame.pack(fill=BOTH, side="left") # Adds instruction text from constants and adds image of Cinzano's diagram. instr = Text(instr_frame, width=65, height=40, padx=10, pady=5, bd=0, wrap="word") instr.insert("end", constants.INSTR) cdiagram_file = Image.open("./static/cinzano_diagram.PNG") cdiagram_file = cdiagram_file.resize((500, 450), Image.ANTIALIAS) self.cdiag = ImageTk.PhotoImage(cdiagram_file) instr.image_create("end", image=self.cdiag) instr.tag_add("top", "1.0", "4.10") instr.tag_config("top", font='Times 12 bold') instr.tag_add("body", "5.0", "19.20") instr.tag_config("body", font='Times 12') instr.insert("end", constants.CDIAG) instr.pack() instr_scroll.config(command=instr.yview) def about(self): """Open an about window. Window gives authors, SET version number, and icon credit. """ # Instantiates a new Toplevel about window. about_window = Toplevel(self.root) about_window.geometry('350x335+25+25') about_window.title('About') about_window.wm_iconbitmap(constants.ICO) about_window.resizable(False, False) # Adds text to about window. about = Text(about_window, width=50, height=30, padx=10, pady=3) about.insert("end", constants.ABOUT) about.tag_add("abt", "1.0", "21.30") about.tag_config("abt", font='Times 10 bold', justify=CENTER) about.pack() def progress(self): """Construct a progress window to monitor darksky.""" # Instantiates a new Toplevel window and frame for progress bar and loading log. self.prg_window = Toplevel(self.root) self.prg_window.geometry('650x325+250+250') self.prg_window.title('Generating Artificial Skyglow Map...') self.prg_window.iconbitmap(constants.ICO) self.prg_window.resizable(False, False) prg_frame = Frame(self.prg_window) prg_frame.pack(fill=BOTH) # Creates Scrollbar, Progressbar, and Label for checking progress.. prg_scroll = Scrollbar(prg_frame) prg_scroll.pack(fill=Y, side="right") self.prg_bar = ttk.Progressbar(prg_frame, orient=HORIZONTAL, length=750, mode='indeterminate') self.prg_bar.pack() self.prg_bar.start() prg_lbl_txt = StringVar() prg_lbl = Label(prg_frame, textvariable=prg_lbl_txt) prg_lbl.pack() # Displays message log that prints from log file and starts darkskypy. self.prg_log = Text(prg_frame, width=90, padx=5, pady=5, relief="sunken") self.prg_log.pack() self.prg_log.insert( "end", "*****Progress Log*****\n=======================\n") self.prg_log.tag_add("abt", "1.0", "3.0") self.prg_log.tag_config("abt", font='Courier 12 bold', justify=CENTER) self.txt_redir = LogRedirector(self.prg_log) logger.addHandler(self.txt_redir) sys.stderr = StderrRedirector(self.prg_log) prg_lbl_txt.set("Start time: " + str(time.asctime())) self.no_progress = 0 def update_progress(self): """Update progress window to prevent it from freezing.""" self.prg_log.update() # if only one thread exists, stop progress bar and close window if len(threading.enumerate()) == 1: self.prg_bar.stop() self.no_progress += 1 if self.no_progress == 3: self.prg_window.withdraw() else: self.prg_bar.start() self.root.after(1000, self.update_progress) def generate_map(self): """Call darksky.sgmapper in background thread.""" # Acquires input arguments. lat_in, k_in, zen_in, azi_in, file_in, krn_file_in = 0, 0, 0, 0, '', '' if self.krn_var.get(): krn_file_in = self.krn_ent_var.get() else: lat_in = float(self.lat_entry.get()) k_in = float(self.k_entry.get()) zen_in = float(self.zen_entry.get()) azi_in = float(self.azi_entry.get()) file_in = self.file_log_var.get() self.progress() # Create new threads to run light propagation model simultaneously. p_thread = threading.Thread(target=self.update_progress()) t_thread = threading.Thread(target=darksky.sgmapper, args=(lat_in, k_in, zen_in, azi_in, file_in, krn_file_in)) t_thread.setDaemon(True) p_thread.start() t_thread.start() def generate_krn(self): """Start kernel generation in background threads.""" # Acquires input arguments csv_in, file_in, lat_in, k_in, hem = '', '', 0, 0, False csv_in = self.csv_file_var.get() file_in = self.file_log_var.get() lat_in = float(self.lat_entry.get()) k_in = float(self.k_entry.get()) hem = self.hem_var.get() self.progress() # Create new threads to run light propagation model simultaneously. p_thread = threading.Thread(target=self.update_progress()) with open(csv_in, "rb") as f: angle_list = loadtxt(f, delimiter=",", skiprows=1) p_thread.start() for angle_set in angle_list: t_thread = threading.Thread(target=darksky.generate_krn, args=(lat_in, k_in, angle_set[0], angle_set[1], file_in, hem)) t_thread.setDaemon(True) t_thread.start() def generate_mmap(self): """Start brightness map creation from kernels.""" # Acquires input arguments krn_folder_in, file_in, output_in, = '', '', '' krn_folder_in = self.krn_folder_var.get() file_in = self.file_log_var.get() output_in = self.output_folder_var.get() self.progress() # Create new threads to run light propagation model simultaneously. p_thread = threading.Thread(target=self.update_progress()) t_thread = threading.Thread(target=darksky.multisgmapper, args=(file_in, krn_folder_in, output_in)) t_thread.setDaemon(True) p_thread.start() t_thread.start() def generate_hem(self): """Generate hemisphere.""" sgmap_folder_in, lat_in, lon_in, = '', 0, 0 sgmap_folder_in = self.sgmap_folder_var.get() lat_in = float(self.lat_entry.get()) lon_in = float(self.lon_entry.get()) darksky.generate_hem(lat_in, lon_in, sgmap_folder_in)