Ignore:
Timestamp:
Nov 17, 2022 10:59:43 AM (7 months ago)
Author:
toby
Message:

add .gpx browser

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/GSASIIctrlGUI.py

    r5371 r5373  
    109109                                   CIF powder histogram imports only
    110110:func:`PhaseSelector`              Select a phase from a list (used for phase importers)
     111:class:`gpxFileSelector`           File browser dialog for opening existing .gpx files
    111112
    112113================================  =================================================================
     
    180181import GSASIImath as G2mth
    181182import GSASIIstrMain as G2stMn
     183import GSASIIIO as G2IO
    182184import config_example
    183185if sys.version_info[0] >= 3:
     
    84928494    dlg.Show()
    84938495
     8496################################################################################
     8497# GPX browser routines
     8498def skimGPX(fl):
     8499    '''pull out fit information from a .gpx file quickly
     8500
     8501    :returns: dict with status info
     8502    '''
     8503    if fl is None: return {}
     8504    result = {}
     8505    if not os.path.exists(fl):
     8506        return {'error':'File does not exist!'}
     8507    cnt = 0
     8508    hist = 0
     8509    fp = open(fl,'rb')
     8510    result['last saved'] = time.ctime(os.stat(fl).st_mtime)
     8511    try:
     8512        while True:
     8513            cnt += 1
     8514            try:
     8515                data = G2IO.cPickleLoad(fp)
     8516            except EOFError:
     8517                #print(cnt,'entries read')       
     8518                break
     8519            if cnt > 50:  # don't spend too long on this file, if big
     8520                result['PWDR'] += 3*['   .']
     8521                break
     8522            datum = data[0]
     8523            if datum[0] == 'Notebook':
     8524                result[datum[0]] = datum[1][-1]
     8525            elif datum[0] == 'Covariance':
     8526                d = datum[1]['Rvals']
     8527                result[datum[0]] = 'Overall: Rwp={:.2f}, GOF={:.1f}'.format(
     8528                    d.get('Rwp','?'),d.get('GOF','?'))
     8529                if d.get('converged',False):
     8530                    result[datum[0]] += '  **Converged**'
     8531            elif datum[0].startswith('PWDR'):
     8532                if 'Residuals' not in datum[1][0]: continue
     8533                if 'PWDR' not in result: result['PWDR'] = []
     8534                result['PWDR'].append(
     8535                    "hist #{}: wR={:.2f} ({:})".format(
     8536                        hist,datum[1][0]['Residuals'].get('wR','?'),datum[0]))
     8537                hist += 1
     8538#            elif datum[0].startswith('HKLF'):
     8539#                pass
     8540#            elif 'Controls' in datum[0]:
     8541#                datum[0]['Seq Data']
     8542            elif datum[0] in ('Constraints','Restraints','Rigid bodies'):
     8543                pass
     8544            else:
     8545                pass
     8546                #GSASIIpath.IPyBreak_base()
     8547    except Exception as msg:
     8548        result['error'] = 'read error: '+str(msg)
     8549    finally:
     8550        fp.close()
     8551    return result
     8552
     8553class gpxFileSelector(wx.Dialog):
     8554    '''Create a file selection widget for locating .gpx files as a modal
     8555    dialog. Displays status information on selected files. After creating
     8556    this use dlg.ShowModal() to wait for selection of a file.
     8557    If dlg.ShowModal() returns wx.ID_OK, use dlg.Selection (multiple=False)
     8558    to obtain the selected file or dlg.Selections (multiple=True) to
     8559    obtain a list of multiple files.
     8560
     8561    :param wx.Frame parent: name of panel or frame that will be
     8562      the parent to the dialog. Can be None.
     8563
     8564    :param path startdir: Specifies the initial directory that is
     8565      opened when the window is initially opened. Default is '.'
     8566
     8567    :param bool multiple: if True, checkboxes are used to allow
     8568      selection of multiple files. Default is False
     8569
     8570    '''
     8571    def __init__(self,parent,startdir='.',multiple=False,*args,**kwargs):
     8572        import wx.lib.filebrowsebutton as wxfilebrowse
     8573        import wx.richtext as wxrt
     8574        self.timer = None
     8575        self.delay = 1500 # time to wait before applying filter (1.5 sec)
     8576        self.Selection = None
     8577        self.Selections = []
     8578        self.startDir = startdir
     8579        if startdir == '.':
     8580            self.startDir = os.getcwd()
     8581        self.multiple = multiple
     8582        wx.Dialog.__init__(self, parent=parent,
     8583                                 style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)
     8584        self.CenterOnParent()
     8585       
     8586        topSizer = wx.BoxSizer(wx.VERTICAL)
     8587        self.dirBtn = wxfilebrowse.DirBrowseButton(self,wx.ID_ANY, size=(650, -1),
     8588                            changeCallback = self.DirSelected,
     8589                            startDirectory = self.startDir
     8590                    )
     8591        topSizer.Add(self.dirBtn,0,wx.EXPAND,1)
     8592       
     8593        subSiz = wx.BoxSizer(wx.HORIZONTAL)
     8594        self.opt = {'useBak':False, 'sort':0, 'filter':'*'}
     8595        chk = G2CheckBoxFrontLbl(self,' Include\n .bakXX?',self.opt,'useBak',
     8596                                     OnChange=self.DirSelected)
     8597        subSiz.Add(chk)
     8598        subSiz.Add((10,-1),1,wx.EXPAND,1)
     8599        subSiz.Add(wx.StaticText(self,wx.ID_ANY,'   Sort by: '),0,wx.ALIGN_CENTER_VERTICAL,1)
     8600        choices = ['age','name (alpha+case)','name (alpha)']
     8601        for w in G2RadioButtons(self,self.opt,'sort',choices,
     8602                                    OnChange=self.DirSelected):
     8603            subSiz.Add(w,0,wx.ALIGN_CENTER_VERTICAL,0)
     8604        subSiz.Add((10,-1),1,wx.EXPAND,1)
     8605        subSiz.Add(wx.StaticText(self,wx.ID_ANY,'Name \nFilter: '),0,wx.ALIGN_CENTER_VERTICAL,1)
     8606        self.filterBox = ValidatedTxtCtrl(self, self.opt, 'filter',
     8607                                size=(80,-1), style=wx.TE_PROCESS_ENTER,
     8608                                OnLeave=self.DirSelected, notBlank=False)
     8609        self.filterBox.Bind(wx.EVT_TEXT,self._startUpdateTimer)
     8610        self.filterBox.Bind(wx.EVT_TEXT_ENTER,self.DirSelected)
     8611        subSiz.Add(self.filterBox)
     8612        subSiz.Add((2,-1))
     8613       
     8614        topSizer.Add(subSiz,0,wx.EXPAND,0)
     8615
     8616        mainPanel = wx.SplitterWindow(self, wx.ID_ANY, style=wx.SP_LIVE_UPDATE|wx.SP_3D)
     8617        mainPanel.SetMinimumPaneSize(100)
     8618
     8619        if self.multiple:
     8620            self.fileBox = wx.CheckListBox(mainPanel,wx.ID_ANY, size=(200, 200),
     8621                                               style=wx.LB_SINGLE)
     8622            self.fileBox.Bind(wx.EVT_CHECKLISTBOX,self.FileSelected)
     8623        else:
     8624            self.fileBox = wx.ListBox(mainPanel,wx.ID_ANY, size=(200, 200),
     8625                                          style=wx.LB_SINGLE)
     8626        self.fileBox.Bind(wx.EVT_LISTBOX,self.FileSelected)
     8627
     8628        self.rtc = wxrt.RichTextCtrl(mainPanel, style=wx.VSCROLL|wx.HSCROLL|
     8629                                       wx.NO_BORDER|wx.richtext.RE_READONLY)
     8630        mainPanel.SplitVertically(self.fileBox, self.rtc, 200)
     8631        topSizer.Add(mainPanel,1,wx.EXPAND)
     8632       
     8633        subSiz = wx.BoxSizer(wx.HORIZONTAL)
     8634        subSiz.Add((-1,-1),1,wx.EXPAND,1)
     8635        self.OKbtn = wx.Button(self, wx.ID_OK, label='Open')
     8636        self.OKbtn.Enable(False)   # A file must be selected 1st
     8637        btn = wx.Button(self, wx.ID_CANCEL)
     8638        subSiz.Add(self.OKbtn)
     8639        subSiz.Add((5,-1))
     8640        subSiz.Add(btn)
     8641        subSiz.Add((-1,-1),1,wx.EXPAND,1)
     8642        topSizer.Add(subSiz,0,wx.EXPAND)
     8643        self.SetSizer(topSizer)
     8644        topSizer.Fit(self)
     8645        self.dirBtn.SetValue(self.startDir)
     8646
     8647    def _startUpdateTimer(self,event):
     8648        if self.timer:
     8649            self.timer.Restart(self.delay)
     8650        else:
     8651            self.timer = wx.CallLater(self.delay,self.DirSelected)
     8652       
     8653    def DirSelected(self,event=None,*args,**kwargs):
     8654        '''Respond to a directory being selected. List files found in fileBox and
     8655        clear any selections. Also clear any reference to a timer.
     8656        '''
     8657        import re
     8658        try:
     8659            if self.timer: self.timer.Stop()
     8660        except:
     8661            pass
     8662        self.timer = None
     8663        self.fileBox.Clear()
     8664        self.rtc.Clear()
     8665        self.Selection = None
     8666        self.Selections = []
     8667        self.OKbtn.Enable(False)
     8668        glb = self.opt['filter'].strip()
     8669        if not glb:
     8670            glb = '*'
     8671        elif not '*' in glb:
     8672            glb = '*' + glb + '*'
     8673        fullglob = os.path.join(self.dirBtn.GetValue(),glb+'.gpx')
     8674        self.fl = glob.glob(fullglob)
     8675        if self.opt['useBak']:
     8676            self.sl = [(os.path.split(i)[1],os.stat(i).st_mtime,i) for i in self.fl]
     8677        else:
     8678            self.sl = [(os.path.split(i)[1],os.stat(i).st_mtime,i) for i in self.fl
     8679                  if not re.match(r'.*\.bak\d+\.gpx.*',i)]
     8680        if self.opt['sort'] == 0:
     8681            self.sl.sort(key=lambda x: x[1],reverse=True)
     8682        elif self.opt['sort'] == 1:
     8683            self.sl.sort(key=lambda x: x[0])
     8684        else:
     8685            self.sl.sort(key=lambda x: x[0].lower())
     8686        items = [i[0]+' ('+self._fmtTimeStampDelta(i[1])+')' for i in self.sl]
     8687        if items:
     8688            self.fileBox.InsertItems(items,0)
     8689       
     8690    def FileSelected(self,event):
     8691        '''Respond to a file being selected (or checked in multiple mode)
     8692        '''
     8693        if self.multiple:  # disable  Open when nothing is selected
     8694            self.Selections = []
     8695            OK = False
     8696            for i in self.fileBox.GetCheckedItems():
     8697                self.Selections.append(self.sl[i][2])
     8698                OK = True
     8699            self.OKbtn.Enable(OK)
     8700        else:
     8701            self.OKbtn.Enable(True)
     8702        self.Selection = self.sl[self.fileBox.GetSelection()][2]
     8703        result = skimGPX(self.Selection)
     8704        self.displayGPXrtc(result,self.Selection)
     8705
     8706    def displayGPXrtc(self,result,fwp):
     8707        '''Show info about selected file in a RichText display'''
     8708        self.rtc.Clear()
     8709        if fwp is None: return
     8710        self.rtc.Freeze()
     8711        self.rtc.BeginSuppressUndo()
     8712        self.rtc.BeginAlignment(wx.TEXT_ALIGNMENT_CENTER)
     8713        self.rtc.BeginFontSize(14)
     8714        self.rtc.BeginBold()
     8715        self.rtc.WriteText(os.path.split(fwp)[1])
     8716        self.rtc.EndBold()
     8717        self.rtc.Newline()
     8718        self.rtc.EndFontSize()
     8719        self.rtc.EndAlignment()
     8720        self.rtc.WriteText('last saved on ')
     8721        self.rtc.WriteText(result['last saved'])
     8722        self.rtc.Newline()
     8723        if 'Covariance' in result:
     8724            self.rtc.BeginLeftIndent(0,40)
     8725            self.rtc.WriteText(result['Covariance'])
     8726            self.rtc.Newline()
     8727            self.rtc.EndLeftIndent()
     8728        if 'Notebook' in result:
     8729            self.rtc.BeginLeftIndent(0,40)
     8730            self.rtc.BeginItalic()
     8731            self.rtc.WriteText('Last notebook entry: ')
     8732            self.rtc.EndItalic()
     8733            self.rtc.WriteText(result['Notebook'])
     8734            self.rtc.Newline()
     8735            self.rtc.EndLeftIndent()
     8736
     8737        if 'PWDR' in result:
     8738            self.rtc.BeginParagraphSpacing(0,0)
     8739            self.rtc.BeginLeftIndent(0)
     8740            self.rtc.BeginBold()
     8741            self.rtc.WriteText('Powder histograms:')
     8742            self.rtc.EndBold()
     8743            self.rtc.EndLeftIndent()
     8744            self.rtc.Newline()
     8745            self.rtc.BeginLeftIndent(40)
     8746            for line in result['PWDR']:
     8747                self.rtc.WriteText(line+'\n')
     8748            self.rtc.EndLeftIndent()
     8749            self.rtc.EndParagraphSpacing()
     8750           
     8751        if 'error' in result:
     8752            self.rtc.Newline()
     8753            self.rtc.BeginBold()
     8754            self.rtc.WriteText('Error encountered: ')
     8755            self.rtc.EndBold()
     8756            self.rtc.WriteText(result['error'])
     8757        self.rtc.EndSuppressUndo()
     8758        self.rtc.Thaw()
     8759
     8760    def _fmtTimeStampDelta(self,tm):
     8761        'Show file age relative to now'
     8762        delta = time.time() - tm
     8763        if delta > 60*60*24*365:
     8764            return "{:.2f} years".format(delta/(60*60*24*365))
     8765        elif delta > 60*60*24*7:
     8766            return "{:.1f} weeks".format(delta/(60*60*24*7))
     8767        elif delta > 60*60*24:
     8768            return "{:.1f} days".format(delta/(60*60*24))
     8769        elif delta > 60*60:
     8770            return "{:.1f} hours".format(delta/(60*60))
     8771        else:
     8772            return "{:.1f} minutes".format(delta/60)
     8773
     8774   
    84948775if __name__ == '__main__':
    84958776    app = wx.App()
Note: See TracChangeset for help on using the changeset viewer.