Ignore:
Timestamp:
Apr 22, 2017 6:50:33 PM (6 years ago)
Author:
toby
Message:

at long last, tracked down Mac bug in Expression Editor

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/GSASIIexprGUI.py

    r2569 r2801  
    307307            if val:
    308308                self.varValue[v] = val
    309         wx.CallAfter(self.ShowVars)
     309        wx.CallAfter(self.Repaint)
    310310
    311311    def Show(self,mode=True):
     
    407407        return
    408408
    409     def ShowVars(self):
     409    def OnDepChoice(self,event):
     410        '''Respond to a selection of a variable type for a label in
     411        an expression
     412        '''
     413        if event: event.Skip()
     414        sel = self.depChoices[event.GetEventObject().GetSelection()]
     415        var = self.SelectG2var(sel,'Dependent variable',self.depParmLists[sel])
     416        if var is None:
     417            self.dependentVar = None
     418            self.OnValidate(None)
     419            event.GetEventObject().SetSelection(wx.NOT_FOUND)
     420            return
     421        self.dependentVar = var
     422        self.depLabel.SetLabel(var)
     423        self.OnValidate(None)
     424        self.Layout()
     425
     426    def GetDepVar(self):
     427        '''Returns the name of the dependent variable, when depVarDict is used.
     428        '''
     429        return self.dependentVar
     430       
     431    def OnChoice(self,event):
     432        '''Respond to a selection of a variable type for a label in
     433        an expression
     434        '''
     435        if event: event.Skip()
     436        v = event.GetEventObject().label
     437        sel = self.AllowedChoices[event.GetEventObject().GetSelection()]
     438        if sel == 0:
     439            sv = G2obj.MakeUniqueLabel(v,self.usedVars)
     440            self.varSelect[v] = sel
     441            self.varName[v] = sv
     442            self.varValue[v] = self.varValue.get(v,0.0)
     443        else:
     444            var = self.SelectG2var(sel,v,self.parmLists[sel])
     445            if var is None:
     446                self.OnValidate(None)
     447                return
     448            self.varSelect[v] = sel
     449            self.varName[v] = var
     450        self.OnValidate(None)
     451
     452    def SelectG2var(self,sel,var,parmList):
     453        '''Offer a selection of a GSAS-II variable.
     454
     455        :param int sel: Determines the type of variable to be selected.
     456          where 1 is used for Phase variables, and 2 for Histogram/Phase vars,
     457          3 for Histogram vars and 4 for Global vars.
     458        :returns: a variable name or None (if Cancel is pressed)
     459        '''
     460        if not parmList:
     461            return None
     462        l2 = l1 = 1
     463        for i in parmList:
     464            l1 = max(l1,len(i))
     465            loc,desc = G2obj.VarDescr(i)
     466            l2 = max(l2,len(loc))
     467        fmt = u"{:"+str(l1)+"s} {:"+str(l2)+"s} {:s}"
     468        varListlbl = [fmt.format(i,*G2obj.VarDescr(i)) for i in parmList]
     469
     470        dlg = G2G.G2SingleChoiceDialog(
     471            self,'Select GSAS-II variable for '+str(var)+':',
     472            'Select variable',
     473            varListlbl,monoFont=True)
     474        dlg.SetSize((625,250))
     475        dlg.CenterOnParent()
     476        var = None
     477        if dlg.ShowModal() == wx.ID_OK:
     478            i = dlg.GetSelection()
     479            var = parmList[i]
     480        dlg.Destroy()
     481        return var
     482
     483    def showError(self,msg1,msg2='',msg3=''):
     484        '''Show an error message of 1 to 3 sections. The second
     485        section is shown in an equally-spaced font.
     486       
     487        :param str msg1: msg1 is shown in a the standard font
     488        :param str msg2: msg2 is shown in a equally-spaced (wx.MODERN) font
     489        :param str msg3: msg3 is shown in a the standard font
     490        '''
     491        self.varSizer.Clear(True)
     492        self.OKbtn.Disable()
     493        if self.ExtraBtn: self.ExtraBtn.Disable()
     494        self.varSizer.Clear(True)
     495        self.errbox = wxscroll.ScrolledPanel(self,style=wx.HSCROLL)
     496        self.errbox.SetMinSize((200,130))
     497        self.varSizer.Add(self.errbox,1,wx.ALL|wx.EXPAND,1)
     498        Siz = wx.BoxSizer(wx.VERTICAL)
     499        errMsg1 = wx.StaticText(self.errbox, wx.ID_ANY,"")
     500        Siz.Add(errMsg1, 0, wx.ALIGN_LEFT|wx.LEFT|wx.EXPAND, 5)
     501        errMsg2 = wx.StaticText(self.errbox, wx.ID_ANY,"\n\n")
     502        font1 = wx.Font(errMsg2.GetFont().GetPointSize(),
     503                        wx.MODERN, wx.NORMAL, wx.NORMAL, False)
     504        errMsg2.SetFont(font1)
     505        Siz.Add(errMsg2, 0, wx.ALIGN_LEFT|wx.LEFT|wx.EXPAND, 5)
     506        errMsg3 = wx.StaticText(self.errbox, wx.ID_ANY,"")
     507        Siz.Add(errMsg3, 0, wx.ALIGN_LEFT|wx.LEFT|wx.EXPAND, 5)
     508        self.errbox.SetSizer(Siz,True)
     509        Siz.Fit(self.errbox)
     510        errMsg1.SetLabel(msg1)
     511        errMsg2.SetLabel("  "+msg2)
     512        errMsg2.Wrap(-1)
     513        errMsg3.SetLabel(msg3)
     514        self.Layout()
     515
     516    def OnValidate(self,event):
     517        '''Respond to a press of the Validate button or when a variable
     518        is associated with a label (in :meth:`OnChoice`)
     519        '''
     520        if event: event.Skip()
     521        self.setEvalResult('(expression cannot be evaluated)')
     522        self.timer.Stop()
     523        self.expr = self.exCtrl.GetValue().strip()
     524        if not self.expr:
     525            wx.CallAfter(self.showError,
     526                "Invalid Expression:","","      (an expression must be entered)")
     527            return
     528        exprObj = G2obj.ExpressionObj()
     529        ret = exprObj.ParseExpression(self.expr)
     530        if not ret:
     531            wx.CallAfter(self.showError,*exprObj.lastError)
     532            return
     533        self.exprVarLst,pkgdict = ret
     534        wx.CallLater(100,self.Repaint,exprObj)
     535
     536    def Repaint(self,exprObj):
     537        'Redisplay the variables and continue the validation'
    410538        # create widgets to associate vars with labels and/or show messages
    411539        self.varSizer.Clear(True)
     
    504632        Siz.Add(GridSiz)
    505633        self.varbox.SetSizer(Siz,True)
    506         xwid,yhgt = Siz.Fit(self.varbox)
    507         self.varbox.SetMinSize((xwid,130))
    508         self.varbox.SetAutoLayout(1)
    509         self.varbox.SetupScrolling()
    510         self.varbox.Refresh()
    511         self.Layout()
    512         #self.mainsizer.Fit(self)
    513         self.SendSizeEvent() # force repaint
    514         return
    515 
    516     def OnDepChoice(self,event):
    517         '''Respond to a selection of a variable type for a label in
    518         an expression
    519         '''
    520         sel = self.depChoices[event.GetEventObject().GetSelection()]
    521         var = self.SelectG2var(sel,'Dependent variable',self.depParmLists[sel])
    522         if var is None:
    523             self.dependentVar = None
    524             self.OnValidate(None)
    525             event.GetEventObject().SetSelection(wx.NOT_FOUND)
    526             return
    527         self.dependentVar = var
    528         self.depLabel.SetLabel(var)
    529         self.OnValidate(None)
    530         self.Layout()
    531 
    532     def GetDepVar(self):
    533         '''Returns the name of the dependent variable, when depVarDict is used.
    534         '''
    535         return self.dependentVar
    536        
    537     def OnChoice(self,event):
    538         '''Respond to a selection of a variable type for a label in
    539         an expression
    540         '''
    541         v = event.GetEventObject().label
    542         sel = self.AllowedChoices[event.GetEventObject().GetSelection()]
    543         if sel == 0:
    544             sv = G2obj.MakeUniqueLabel(v,self.usedVars)
    545             self.varSelect[v] = sel
    546             self.varName[v] = sv
    547             self.varValue[v] = self.varValue.get(v,0.0)
    548         else:
    549             var = self.SelectG2var(sel,v,self.parmLists[sel])
    550             if var is None:
    551                 self.OnValidate(None)
     634
     635        # evaluate the expression, displaying errors or the expression value
     636        try:
     637            msg = self.CheckVars()
     638            if msg:
     639                self.setEvalResult(msg)
    552640                return
    553             self.varSelect[v] = sel
    554             self.varName[v] = var
    555         self.OnValidate(None)
    556 
    557     def SelectG2var(self,sel,var,parmList):
    558         '''Offer a selection of a GSAS-II variable.
    559 
    560         :param int sel: Determines the type of variable to be selected.
    561           where 1 is used for Phase variables, and 2 for Histogram/Phase vars,
    562           3 for Histogram vars and 4 for Global vars.
    563         :returns: a variable name or None (if Cancel is pressed)
    564         '''
    565         if not parmList:
    566             return None
    567         l2 = l1 = 1
    568         for i in parmList:
    569             l1 = max(l1,len(i))
    570             loc,desc = G2obj.VarDescr(i)
    571             l2 = max(l2,len(loc))
    572         fmt = u"{:"+str(l1)+"s} {:"+str(l2)+"s} {:s}"
    573         varListlbl = [fmt.format(i,*G2obj.VarDescr(i)) for i in parmList]
    574 
    575         dlg = G2G.G2SingleChoiceDialog(
    576             self,'Select GSAS-II variable for '+str(var)+':',
    577             'Select variable',
    578             varListlbl,monoFont=True)
    579         dlg.SetSize((625,250))
    580         dlg.CenterOnParent()
    581         var = None
    582         if dlg.ShowModal() == wx.ID_OK:
    583             i = dlg.GetSelection()
    584             var = parmList[i]
    585         dlg.Destroy()
    586         return var
    587 
    588     def showError(self,msg1,msg2='',msg3=''):
    589         '''Show an error message of 1 to 3 sections. The second
    590         section is shown in an equally-spaced font.
    591        
    592         :param str msg1: msg1 is shown in a the standard font
    593         :param str msg2: msg2 is shown in a equally-spaced (wx.MODERN) font
    594         :param str msg3: msg3 is shown in a the standard font
    595         '''
    596         self.OKbtn.Disable()
    597         if self.ExtraBtn: self.ExtraBtn.Disable()
    598         self.varSizer.Clear(True)
    599         self.errbox = wxscroll.ScrolledPanel(self,style=wx.HSCROLL)
    600         self.errbox.SetMinSize((200,130))
    601         self.varSizer.Add(self.errbox,1,wx.ALL|wx.EXPAND,1)
    602         Siz = wx.BoxSizer(wx.VERTICAL)
    603         errMsg1 = wx.StaticText(self.errbox, wx.ID_ANY,"")
    604         Siz.Add(errMsg1, 0, wx.ALIGN_LEFT|wx.LEFT|wx.EXPAND, 5)
    605         errMsg2 = wx.StaticText(self.errbox, wx.ID_ANY,"\n\n")
    606         font1 = wx.Font(errMsg2.GetFont().GetPointSize(),
    607                         wx.MODERN, wx.NORMAL, wx.NORMAL, False)
    608         errMsg2.SetFont(font1)
    609         Siz.Add(errMsg2, 0, wx.ALIGN_LEFT|wx.LEFT|wx.EXPAND, 5)
    610         errMsg3 = wx.StaticText(self.errbox, wx.ID_ANY,"")
    611         Siz.Add(errMsg3, 0, wx.ALIGN_LEFT|wx.LEFT|wx.EXPAND, 5)
    612         self.errbox.SetSizer(Siz,True)
    613         Siz.Fit(self.errbox)
    614         errMsg1.SetLabel(msg1)
    615         errMsg2.SetLabel("  "+msg2)
    616         errMsg2.Wrap(-1)
    617         errMsg3.SetLabel(msg3)
    618         self.Layout()
    619 
    620     def OnValidate(self,event):
    621         '''Respond to a press of the Validate button or when a variable
    622         is associated with a label (in :meth:`OnChoice`)
    623         '''
    624         self.setEvalResult('(expression cannot be evaluated)')
    625         self.timer.Stop()
    626         self.expr = self.exCtrl.GetValue().strip()
    627         self.varSizer.Clear(True)
    628         if not self.expr:
    629             self.showError(
    630                 "Invalid Expression:","",
    631                 "(an expression must be entered)")
    632             return
    633         exprObj = G2obj.ExpressionObj()
    634         ret = exprObj.ParseExpression(self.expr)
    635         if not ret:
    636             self.showError(*exprObj.lastError)
    637             return
    638         self.exprVarLst,pkgdict = ret
    639         wx.CallAfter(self.Repaint,exprObj)
    640            
    641     def Repaint(self,exprObj):
    642         'Redisplay the variables and continue the validation'
    643         self.ShowVars() # show widgets to set vars
    644         msg = self.CheckVars()
    645         if msg:
    646             self.setEvalResult(msg)
    647             return
    648         exprObj.LoadExpression(
    649             self.expr,
    650             self.exprVarLst,
    651             self.varSelect,
    652             self.varName,
    653             self.varValue,
    654             self.varRefflag,
    655             )
    656         try:
    657             calcobj = G2obj.ExpressionCalcObj(exprObj)
    658             calcobj.SetupCalc(self.parmDict)
    659             val = calcobj.EvalExpression()
    660         except Exception as msg:
    661             self.setEvalResult("Error in evaluation: "+str(msg))
    662             return
    663         if not np.isfinite(val):
    664             self.setEvalResult("Expression value is infinite or out-of-bounds")
    665             return
    666         s = G2py3.FormatSigFigs(val).rstrip('0')
    667         depVal = ""
    668         if self.depVarDict:
    669             if not self.dependentVar:
    670                 self.setEvalResult("A dependent variable must be selected.")
     641            exprObj.LoadExpression(
     642                self.expr,
     643                self.exprVarLst,
     644                self.varSelect,
     645                self.varName,
     646                self.varValue,
     647                self.varRefflag,
     648                )
     649            try:
     650                calcobj = G2obj.ExpressionCalcObj(exprObj)
     651                calcobj.SetupCalc(self.parmDict)
     652                val = calcobj.EvalExpression()
     653            except Exception as msg:
     654                self.setEvalResult("Error in evaluation: "+str(msg))
    671655                return
    672             depVal = '; Variable "' + self.dependentVar + '" = ' + str(
    673                 self.depVarDict.get(self.dependentVar,'?')
    674                 )
    675         self.setEvalResult("Expression evaluates to: "+str(s)+depVal)
    676         self.OKbtn.Enable()
    677         if self.ExtraBtn: self.ExtraBtn.Enable()
     656            if not np.isfinite(val):
     657                self.setEvalResult("Expression value is infinite or out-of-bounds")
     658                return
     659            s = G2py3.FormatSigFigs(val).rstrip('0')
     660            depVal = ""
     661            if self.depVarDict:
     662                if not self.dependentVar:
     663                    self.setEvalResult("A dependent variable must be selected.")
     664                    return
     665                depVal = '; Variable "' + self.dependentVar + '" = ' + str(
     666                    self.depVarDict.get(self.dependentVar,'?')
     667                    )
     668            self.setEvalResult("Expression evaluates to: "+str(s)+depVal)
     669            self.OKbtn.Enable()
     670            if self.ExtraBtn: self.ExtraBtn.Enable()
     671        finally: 
     672            xwid,yhgt = Siz.Fit(self.varbox)
     673            self.varbox.SetMinSize((xwid,130))
     674            self.varbox.SetAutoLayout(1)
     675            self.varbox.SetupScrolling()
     676            self.varbox.Refresh()
     677            self.Layout()
     678            self.SendSizeEvent() # force repaint
    678679           
    679680#==========================================================================
Note: See TracChangeset for help on using the changeset viewer.