def check_for_uncombined_files(self): """ Go through working directory and check for uncombined files. (I.e., location1_specimens.txt and location2_specimens.txt but no specimens.txt.) Show a warning if uncombined files are found. Return True if no uncombined files are found OR user elects to continue anyway. """ wd_files = os.listdir(self.WD) ftypes = ['specimens.txt', 'samples.txt', 'sites.txt', 'locations.txt'] uncombined = set() for ftype in ftypes: if ftype not in wd_files: for f in wd_files: if f.endswith('_' + ftype): uncombined.add(ftype) if uncombined: msg = 'It looks like you may have uncombined files of type(s) {} in your working directory.\nYou may want to go back to Step 1 and finish combining all files.\nIf you continue, the program will try to extract as much information as possible from your measurement file.'.format( ", ".join(list(uncombined))) dlg = pw.ChooseOne(self, 'Continue anyway', 'Go back', msg, title="Warning!") res = dlg.ShowModal() if res == wx.ID_NO: return return True
def on_add_cols(self, event): """ Show simple dialog that allows user to add a new column name """ col_labels = self.grid.col_labels dia = pw.ChooseOne(self, yes="Add single columns", no="Add groups") result1 = dia.ShowModal() if result1 == wx.ID_CANCEL: return elif result1 == wx.ID_YES: items = [col_name for col_name in self.dm.index if col_name not in col_labels] dia = pw.HeaderDialog(self, 'columns to add', items1=list(items), groups=[]) dia.Centre() result2 = dia.ShowModal() else: groups = self.dm['group'].unique() dia = pw.HeaderDialog(self, 'groups to add', items1=list(groups), groups=True) dia.Centre() result2 = dia.ShowModal() new_headers = [] if result2 == 5100: new_headers = dia.text_list # if there is nothing to add, quit if not new_headers: return if result1 == wx.ID_YES: # add individual headers errors = self.add_new_grid_headers(new_headers) else: # add header groups errors = self.add_new_header_groups(new_headers) if errors: errors_str = ', '.join(errors) pw.simple_warning('You are already using the following headers: {}\nSo they will not be added'.format(errors_str)) # problem: if widgets above the grid are too wide, # the grid does not re-size when adding columns # awkward solution (causes flashing): if self.grid.GetWindowStyle() != wx.DOUBLE_BORDER: self.grid.SetWindowStyle(wx.DOUBLE_BORDER) self.main_sizer.Fit(self) self.grid.SetWindowStyle(wx.NO_BORDER) self.Centre() self.main_sizer.Fit(self) # self.grid.changes = set(range(self.grid.GetNumberRows())) dia.Destroy()
def on_remove_row(self, event, row_num=-1): """ Remove specified grid row. If no row number is given, remove the last row. """ text = "Are you sure? If you select delete you won't be able to retrieve these rows..." dia = pw.ChooseOne(self, "Yes, delete rows", "Leave rows for now", text) dia.Centre() result = dia.ShowModal() if result == wx.ID_NO: return default = (255, 255, 255, 255) if row_num == -1: # unhighlight any selected rows: for row in self.selected_rows: attr = wx.grid.GridCellAttr() attr.SetBackgroundColour(default) self.grid.SetRowAttr(row, attr) row_num = self.grid.GetNumberRows() - 1 self.deleteRowButton.Disable() self.selected_rows = {row_num} # remove row(s) from the contribution df = self.contribution.tables[self.grid_type].df row_nums = list(range(len(df))) df = df.iloc[[i for i in row_nums if i not in self.selected_rows]] self.contribution.tables[self.grid_type].df = df # now remove row(s) from grid # delete rows, adjusting the row # appropriately as you delete for num, row in enumerate(self.selected_rows): row -= num if row < 0: row = 0 self.grid.remove_row(row) attr = wx.grid.GridCellAttr() attr.SetBackgroundColour(default) self.grid.SetRowAttr(row, attr) # reset the grid self.selected_rows = set() self.deleteRowButton.Disable() self.grid.Refresh() self.main_sizer.Fit(self)
def on_btn_upload(self, event): """ Try to run upload_magic. Open validation mode if the upload file has problems. """ if not self.check_for_uncombined_files(): return outstring = "upload_magic.py" print("-I- running python script:\n %s" % (outstring)) wait = wx.BusyInfo("Please wait, working...") wx.SafeYield() self.contribution.tables['measurements'].add_measurement_names() if self.data_model_num == 3: res, error_message, has_problems, all_failing_items = ipmag.upload_magic3( dir_path=self.WD, vocab=self.contribution.vocab, contribution=self.contribution) if self.data_model_num == 2: res, error_message, errors = ipmag.upload_magic( dir_path=self.WD, data_model=self.er_magic.data_model) del wait if res: text = "You are ready to upload!\n{} was generated in {}".format( os.path.split(res)[1], os.path.split(res)[0]) dlg = pw.ChooseOne(self, "Go to MagIC for uploading", "Not ready yet", text, "Saved") del wait #dlg = wx.MessageDialog(self, caption="Saved", message=text, style=wx.OK) else: text = "There were some problems with the creation of your upload file.\nError message: {}\nSee Terminal/message window for details".format( error_message) dlg = wx.MessageDialog(self, caption="Error", message=text, style=wx.OK) dlg.Centre() result = dlg.ShowModal() if result == wx.ID_OK: dlg.Destroy() if result == wx.ID_YES: pw.on_database_upload(None) if self.data_model_num == 3: if not res: from programs import magic_gui self.Disable() self.Hide() self.magic_gui_frame = magic_gui.MainFrame( self.WD, dmodel=self.data_model, title="Validations", contribution=self.contribution) self.magic_gui_frame.validation_mode = ['specimens'] self.magic_gui_frame.failing_items = all_failing_items self.magic_gui_frame.change_dir_button.Disable() self.magic_gui_frame.Centre() self.magic_gui_frame.Show() self.magic_gui_frame.highlight_problems(has_problems) # # change name of upload button to 'exit validation mode' self.magic_gui_frame.bSizer2.GetStaticBox().SetLabel( 'return to main GUI') self.magic_gui_frame.btn_upload.SetLabel( "exit validation mode") # bind that button to quitting magic gui and re-enabling Pmag GUI self.magic_gui_frame.Bind(wx.EVT_BUTTON, self.on_end_validation, self.magic_gui_frame.btn_upload)
def on_btn_unpack(self, event): """ Create dialog to choose a file to unpack with download magic. Then run download_magic and create self.contribution. """ def magic_download_dia(warn=""): dia = pw.TextDialog( self, "Download from MagIC\nusing contribution id or DOI", "MagIC id/DOI", warn) res = dia.ShowModal() magic_id = dia.text_ctrl.return_value() if res == wx.ID_CANCEL: return wx.ID_CANCEL if res == wx.ID_OK: return magic_id else: return False dlg = pw.ChooseOne( self, "Download from MagIC", "Unpack previous downloaded file", text= "You can unpack a downloaded file from MagIC, or download a file from MagIC directly using the contribution id or DOI.", title="") dlg.Centre() res = dlg.ShowModal() # try to download directly from MagIC if res == wx.ID_YES: magic_id = True warning = "" while magic_id: magic_id = magic_download_dia(warning) # if magic id was blank if magic_id == "": warning = "You must provide a MagIC contribution id or DOI" magic_id = True continue # if user canceled the download if magic_id == wx.ID_CANCEL: return # if everything looks good, try to download if len(str(magic_id)) < 8: # use contribution id status, stuff = ipmag.download_magic_from_id(magic_id) f = "magic_contribution_{}.txt".format(magic_id) else: # use DOI status, stuff = ipmag.download_magic_from_doi(magic_id) f = "magic_contribution.txt" if not status: warning = stuff if status: break if not os.path.exists(os.path.join(self.WD, f)): os.rename(os.path.join(os.getcwd(), f), os.path.join(self.WD, f)) input_dir = self.WD # try to unpack a previously downloaded file if res == wx.ID_NO: dlg = wx.FileDialog( None, message="choose txt file to unpack", defaultDir=self.WD, defaultFile="", style=wx.FD_OPEN #| wx.FD_CHANGE_DIR ) if dlg.ShowModal() == wx.ID_OK: FILE = dlg.GetPath() input_dir, f = os.path.split(FILE) else: return False outstring = "download_magic.py -f {} -WD {} -ID {}".format( f, self.WD, input_dir) # run as module: print("-I- running python script:\n %s" % (outstring)) wait = wx.BusyInfo("Please wait, working...") wx.SafeYield() ex = None try: if ipmag.download_magic(f, self.WD, input_dir, overwrite=True, data_model=self.data_model): text = "Successfully ran download_magic.py program.\nMagIC files were saved in your working directory.\nSee Terminal/message window for details." else: text = "Something went wrong. Make sure you chose a valid file downloaded from the MagIC database and try again." return except Exception as ex: text = "Something went wrong. Make sure you chose a valid file downloaded from the MagIC database and try again." del wait dlg = wx.MessageDialog(self, caption="Saved", message=text, style=wx.OK) result = dlg.ShowModal() if result == wx.ID_OK: dlg.Destroy() if ex: raise (ex) return self.contribution = cb.Contribution(self.WD) # make a success pop-up dlg = wx.MessageDialog( self, caption="Success", message= "You can now add orientation information or metadata, or open one of the analysis tools", style=wx.OK) dlg.ShowModal()
def on_btn_upload(self, event): """ Try to run upload_magic. Open validation mode if the upload file has problems. """ if not self.check_for_uncombined_files(): return outstring = "upload_magic.py" print("-I- running python script:\n %s" % (outstring)) wait = wx.BusyInfo("Please wait, working...") wx.SafeYield() success_responses = ['200', 200, '201', 201, True] if 'measurements' in self.contribution.tables: self.contribution.tables['measurements'].add_measurement_names() upload_file, val_response, dummy1, dummy2 = ipmag.upload_magic( concat=False, input_dir_path=self.WD, dir_path=self.WD) del wait if val_response == "no 3.0 files found, upload file not created": pw.simple_warning( "No 3.0 files were found in your directory, so no upload could be created!" ) return status = val_response['status'] if not status: pw.simple_warning( "Oops, something went wrong with validating on the server.\n{}\nTry again later or submit a bug report." .format(val_response['warnings'])) return validation_errors = val_response['validation'] if (not validation_errors['warnings']) and ( not validation_errors['errors']): text = "You are ready to upload!\n{} was generated in {}".format( os.path.split(upload_file)[1], self.WD) dlg = pw.ChooseOne(self, "Go to MagIC for uploading", "Not ready yet", text, "Saved") dlg.Centre() result = dlg.ShowModal() if result == wx.ID_OK: dlg.Destroy() if result == wx.ID_YES: pw.on_database_upload(None) return # there were problems, so display validation text = "There were some problems with the creation of your upload file.\nSee Terminal/message window for details" dlg = wx.MessageDialog(self, caption="Error", message=text, style=wx.OK) dlg.Centre() result = dlg.ShowModal() # TODO: get the error-y business formatted into a dict of lists of dicts from programs import magic_gui self.Disable() self.Hide() self.magic_gui_frame = magic_gui.MainFrame( self.WD, dmodel=self.data_model, title="Validations", contribution=self.contribution, errors=validation_errors['errors']) self.magic_gui_frame.Centre() self.magic_gui_frame.Show() self.magic_gui_frame.highlight_problems() # bind that button to quitting magic gui and re-enabling Pmag GUI self.magic_gui_frame.Bind(wx.EVT_BUTTON, self.on_end_validation, self.magic_gui_frame.return_btn) # do binding so that closing/quitting re-opens the main frame self.magic_gui_frame.Bind(wx.EVT_CLOSE, self.on_end_validation) # this makes it work with only the validation window open self.magic_gui_frame.Bind( wx.EVT_MENU, lambda event: self.menubar.on_quit(event, self.magic_gui_frame), self.magic_gui_frame.menubar.file_quit) # this makes it work if an additional grid is open self.Bind( wx.EVT_MENU, lambda event: self.menubar.on_quit(event, self.magic_gui_frame), self.magic_gui_frame.menubar.file_quit)
def onImport(self, event): """ Import a MagIC-format file """ if self.grid.changes: print("-W- Your changes will be overwritten...") wind = pw.ChooseOne(self, "Import file anyway", "Save grid first", "-W- Your grid has unsaved changes which will be overwritten if you import a file now...") wind.Centre() res = wind.ShowModal() # save grid first: if res == wx.ID_NO: self.onSave(None, alert=True, destroy=False) # reset self.changes self.grid.changes = set() openFileDialog = wx.FileDialog(self, "Open MagIC-format file", self.WD, "", "MagIC file|*.*", wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) result = openFileDialog.ShowModal() if result == wx.ID_OK: # get filename filename = openFileDialog.GetPath() # make sure the dtype is correct f = open(filename) line = f.readline() if line.startswith("tab"): delim, dtype = line.split("\t") else: delim, dtype = line.split("") f.close() dtype = dtype.strip() if (dtype != self.grid_type) and (dtype + "s" != self.grid_type): text = "You are currently editing the {} grid, but you are trying to import a {} file.\nPlease open the {} grid and then re-try this import.".format(self.grid_type, dtype, dtype) pw.simple_warning(text) return # grab old data for concatenation if self.grid_type in self.contribution.tables: old_df_container = self.contribution.tables[self.grid_type] else: old_df_container = None old_col_names = self.grid.col_labels # read in new file and update contribution df_container = nb.MagicDataFrame(filename, dmodel=self.dm, columns=old_col_names) # concatenate if possible if not isinstance(old_df_container, type(None)): df_container.df = pd.concat([old_df_container.df, df_container.df], axis=0) self.contribution.tables[df_container.dtype] = df_container self.grid_builder = GridBuilder(self.contribution, self.grid_type, self.panel, parent_type=self.parent_type, reqd_headers=self.reqd_headers) # delete old grid self.grid_box.Hide(0) self.grid_box.Remove(0) # create new, updated grid self.grid = self.grid_builder.make_grid() self.grid.InitUI() # add data to new grid self.grid_builder.add_data_to_grid(self.grid, self.grid_type) # add new grid to sizer and fit everything self.grid_box.Add(self.grid, flag=wx.ALL, border=5) self.main_sizer.Fit(self) self.Centre() # add any needed drop-down-menus self.drop_down_menu = drop_down_menus.Menus(self.grid_type, self.contribution, self.grid) # done! return