Example #1
0
 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
Example #2
0
    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()
Example #3
0
 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)
Example #4
0
    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)
Example #5
0
    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()
Example #6
0
    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)
Example #7
0
    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