source: trunk/GSASIIexprGUI.py @ 1324

Last change on this file since 1324 was 1324, checked in by toby, 9 years ago

remove blank items from selection menu

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 25.1 KB
Line 
1# -*- coding: utf-8 -*-
2#GSASIIexprGUI - Expression Definition and Evaluation
3########### SVN repository information ###################
4# $Date: 2014-05-05 20:54:51 +0000 (Mon, 05 May 2014) $
5# $Author: toby $
6# $Revision: 1324 $
7# $URL: trunk/GSASIIexprGUI.py $
8# $Id: GSASIIexprGUI.py 1324 2014-05-05 20:54:51Z toby $
9########### SVN repository information ###################
10'''
11*GSASIIexprGUI: Expression Handling*
12-------------------------------------
13
14This module defines a class for defining an expression in terms of values
15in a parameter dictionary via a wx.Dialog. The dialog creates a :class:`GSASII.ExpressionObj`
16which is used to evaluate the expression against a supplied parameter dictionary.
17
18The expression is parsed to find variables used in the expression and then
19the user is asked to assign parameters from the dictionary to each variable.
20
21'''
22# TODO: improve variable browser (search, add parameter descriptions)
23
24import re
25import sys
26import wx
27import wx.lib.scrolledpanel as wxscroll
28import numpy as np
29import GSASIIgrid as G2gd
30import GSASIIpy3 as G2py3
31import GSASIIobj as G2obj
32
33def IndexParmDict(parmDict,wildcard):
34    '''Separate the parameters in parmDict into list of keys by parameter
35    type
36    :param dict parmDict: a dict with GSAS-II parameters
37    :param bool wildcard: True if wildcard versions of parameters should
38      be generated and added to the lists
39    :returns: a dict of lists where key 1 is a list of phase parameters,
40      2 is histogram/phase parms, 3 is histogram parms and 4 are global parameters
41    '''
42    prex = re.compile('[0-9]+::.*')
43    hrex = re.compile(':[0-9]+:.*')
44    parmLists = {}
45    for i in (1,2,3,4):
46        parmLists[i] = []
47    for i in sorted(parmDict.keys()):
48        if i.startswith("::") or i.find(':') == -1: # globals
49            parmLists[4].append(i)
50        elif prex.match(i):
51            parmLists[1].append(i)
52        elif hrex.match(i):
53            parmLists[3].append(i)
54        else:
55            parmLists[2].append(i)
56    if wildcard:
57        for i in (1,2,3,4):
58            parmLists[i] += G2obj.GenWildCard(parmLists[i]) # generate wildcard versions
59    for i in (1,2,3,4):
60        parmLists[i].sort()
61    return parmLists
62
63#==========================================================================
64class ExpressionDialog(wx.Dialog):
65    '''A wx.Dialog that allows a user to input an arbitrary expression
66    to be evaluated and possibly minimized.
67
68    To do this, the user assigns a new (free) or existing
69    GSAS-II parameter to each parameter label used in the expression.
70    The free parameters can optionally be designated to be refined.
71    For example, is an expression is used such as::
72
73    'A*np.exp(-B/C)'
74
75    then A, B and C can each be assigned as Free parameter with a user-selected
76    value or to any existing GSAS-II variable in the parameter dictionary.
77    As the expression is entered it is checked for validity.
78
79    After the :class:`ExpressionDialog` object is created, use :meth:`Show` to
80    run it and obtain a :class:`GSASIIobj.ExpressionObj` object with the user
81    input.
82
83    :param wx.Frame parent: The parent of the Dialog. Can be None,
84      but better is to provide the name of the Frame where the dialog
85      is called.
86    :param dict parmDict: a dict with defined parameters and their values. Each value
87      may be a list with parameter values and a refine flag or may just contain
88      the parameter value (non-float/int values in dict are ignored)
89    :param str exprObj: a :class:`GSASIIobj.ExpressionObj` object with an expression and
90      label assignments or None (default)
91    :param str wintitle: String placed on title bar of dialog;
92      defaults to "Expression Editor"
93    :param str header: String placed at top of dialog to tell the user
94      what they will do here; default is "Enter restraint expression here"
95    :param bool fit: determines if the expression will be used in fitting (default=True).
96      If set to False, and refinement flags are not shown
97      and Free parameters are not offered as an assignment option.
98    :param str VarLabel: an optional variable label to include before the expression
99      input. Ignored if None (default)
100    :param list depVarDict: a dict of choices for the dependent variable to be
101      fitted to the expression and their values. Ignored if None (default).
102    '''
103    def __init__(self, parent, parmDict, exprObj=None,
104                 header='Enter restraint expression here',
105                 wintitle='Expression Editor',
106                 fit=True,VarLabel=None,depVarDict=None):
107        self.fit = fit
108        self.depVarDict = depVarDict
109        self.parmDict = {}
110        '''A copy of the G2 parameter dict (parmDict) except only numerical
111        values are included and only the value (not the vary flag, if present)
112        is included.
113        '''
114        self.exprVarLst = []
115        '''A list containing the variables utilized in the current expression.
116        Placed into a :class:`GSASIIobj.ExpressionObj` object when the dialog is closed
117        with "OK", saving any changes.
118        '''
119        self.varSelect = {}
120        '''A dict that shows the variable type for each label
121        found in the expression.
122
123        * If the value is None or is not defined, the value is not assigned.
124        * If the value is 0, then the varible is "free" -- a new refineable
125          parameter.
126        * Values above 1 determine what variables will be shown
127          when the option is selected.
128        '''
129        self.varName = {}
130        'Name assigned to each variable'
131        self.varValue = {}
132        'Value for a variable (Free parameters only)'
133        self.varRefflag = {}
134        'Refinement flag for a variable (Free parameters only)'
135        self.expr = ''
136        'Expression as a text string'
137        self.depVar = [None,None]
138        'index # and name for dependent variable selection when depVarDict is specified'
139       
140        # process dictionary of values and create an index
141        for key in parmDict:
142            try: # deal with values that are in lists
143                val = parmDict[key][0]
144            except (TypeError,IndexError):
145                val = parmDict[key]
146            if isinstance(val, basestring): continue
147            try:
148                self.parmDict[key] = float(val)
149            except:
150                pass
151        # separate the variables by type
152        self.parmLists = IndexParmDict(self.parmDict,self.fit)
153        self.timer = wx.Timer()
154        self.timer.Bind(wx.EVT_TIMER,self.OnValidate)
155
156        style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER
157        wx.Dialog.__init__(self, parent, wx.ID_ANY, wintitle, style=style)
158        self.mainsizer = wx.BoxSizer(wx.VERTICAL)
159        label = wx.StaticText(self,  wx.ID_ANY, header)
160        self.mainsizer.Add(label, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
161
162        self.exsizer = wx.BoxSizer(wx.HORIZONTAL)
163        if VarLabel:
164            label = wx.StaticText(self,  wx.ID_ANY, VarLabel + ' = ')
165            self.exsizer.Add(label, 0, wx.ALL|wx.EXPAND|wx.ALIGN_CENTER_VERTICAL, 0)
166        elif depVarDict:
167            choice = G2gd.G2ChoiceButton(
168                self,
169                sorted(depVarDict.keys()),
170                self.depVar,0,
171                self.depVar,1,
172                self.RestartTimer)
173            self.exsizer.Add(choice, 0, wx.ALL|wx.EXPAND|wx.ALIGN_CENTER_VERTICAL, 0)
174            label = wx.StaticText(self,  wx.ID_ANY, ' = ')
175            self.exsizer.Add(label, 0, wx.ALL|wx.EXPAND|wx.ALIGN_CENTER_VERTICAL, 0)
176
177        self.exCtrl = wx.TextCtrl(self,  wx.ID_ANY, size=(150,-1),style=wx.TE_PROCESS_ENTER)
178        self.exCtrl.Bind(wx.EVT_CHAR, self.OnChar)
179        self.exCtrl.Bind(wx.EVT_TEXT_ENTER, self.OnValidate)
180        self.exsizer.Add(self.exCtrl, 1, wx.ALL|wx.EXPAND|wx.ALIGN_CENTER_VERTICAL, 0)
181        #self.mainsizer.Add(self.exCtrl, 0, wx.ALL|wx.EXPAND, 5)
182        self.mainsizer.Add(self.exsizer, 0, wx.ALL|wx.EXPAND, 5)
183        self.mainsizer.Add((-1,5),0,wx.EXPAND,1)
184
185        evalSizer = wx.BoxSizer(wx.HORIZONTAL)
186        self.mainsizer.Add(evalSizer,0,wx.ALL|wx.EXPAND,0)
187        btn = wx.Button(self, wx.ID_ANY,"Validate")
188        btn.Bind(wx.EVT_BUTTON,self.OnValidate)
189        evalSizer.Add(btn,0,wx.LEFT|wx.RIGHT,5)
190        self.result = wx.StaticText(self,  wx.ID_ANY, '')
191        evalSizer.Add(self.result, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
192
193        self.varSizer = wx.BoxSizer(wx.HORIZONTAL)
194        self.mainsizer.Add(self.varSizer,1,wx.ALL|wx.EXPAND,1)
195        self.mainsizer.Add((-1,5),0,wx.EXPAND,1)
196
197        btnsizer = wx.StdDialogButtonSizer()
198        self.OKbtn = wx.Button(self, wx.ID_OK)
199        self.OKbtn.SetDefault()
200        self.OKbtn.Disable()
201        btnsizer.AddButton(self.OKbtn)
202        btn = wx.Button(self, wx.ID_CANCEL)
203        btnsizer.AddButton(btn)
204        btnsizer.Realize()
205        self.mainsizer.Add(btnsizer, 0, wx.ALIGN_CENTER|wx.ALL|wx.EXPAND, 5)
206        self.SetSizer(self.mainsizer)
207        self.CenterOnParent()
208        if exprObj:
209            self.expr = exprObj.EditExpression(
210                self.exprVarLst,
211                self.varSelect,
212                self.varName,
213                self.varValue,
214                self.varRefflag,
215                )
216            # set the initial value for the dependent value
217            if self.depVarDict:
218                var = exprObj.GetDepVar()
219                if var in self.depVarDict:
220                    indx = sorted(self.depVarDict.keys()).index(var)
221                    choice.SetSelection(indx)
222                    self.depVar = [indx,var]
223                   
224        self.exCtrl.SetValue(self.expr)
225        self.OnValidate(None)
226        self.SetMinSize((620,300)) # seems like a good size
227        #self.errbox.SetAutoLayout(1)
228        #self.errbox.SetupScrolling()
229        #self.varbox.SetAutoLayout(1)
230        #self.varbox.SetupScrolling()
231        #self.mainsizer.Fit(self)
232
233    def Show(self,mode=True):
234        '''Call to use the dialog after it is created.
235
236        :returns: None (On Cancel) or a new :class:`~GSASIIobj.ExpressionObj`
237        '''
238        self.Layout()
239        self.mainsizer.Fit(self)
240        if self.ShowModal() == wx.ID_OK:
241            # store the edit results in the object and return it
242            exprObj = G2obj.ExpressionObj()
243            exprObj.LoadExpression(
244                self.expr,
245                self.exprVarLst,
246                self.varSelect,
247                self.varName,
248                self.varValue,
249                self.varRefflag,
250                )
251            if self.depVarDict:
252                exprObj.SetDepVar(self.depVar[1])
253            return exprObj
254        else:
255            return None
256       
257    def setEvalResult(self,msg):
258        'Show a string in the expression result area'
259        self.result.SetLabel(msg)
260
261    def RestartTimer(self):
262        '''Cancels any running timer and starts a new one.
263        The timer causes a check of syntax after 2 seconds unless there is further input.
264        Disables the OK button until a validity check is complete.
265        '''
266        if self.timer.IsRunning():
267            self.timer.Stop()
268        self.timer.Start(2000,oneShot=True)
269       
270    def OnChar(self,event):
271        '''Called as each character is entered. Cancels any running timer
272        and starts a new one. The timer causes a check of syntax after 2 seconds
273        without input.
274        Disables the OK button until a validity check is complete.
275        '''
276        self.RestartTimer()
277        self.OKbtn.Disable()
278        event.Skip()
279        return
280   
281    def CheckVars(self):
282        '''Check that appropriate variables are defined for each
283        symbol used in :data:`self.expr`
284
285        :returns: a text error message or None if all needed input is present       
286        '''
287        invalid = 0
288        for v in self.exprVarLst:
289            if self.varSelect.get(v) is None:
290                invalid += 1
291        if invalid==1:
292            return '(a variable is not assigned)'
293        elif invalid:
294            return '('+str(invalid)+' variables are not assigned)'
295        msg = ''
296        for v in self.exprVarLst:
297            varname = self.varName.get(v)
298            if not varname:
299                invalid += 1
300                if msg: msg += "; "
301                msg += 'No variable for '+str(v)
302            elif self.varSelect.get(v) > 0:
303               if '*' in varname:
304                   l = G2obj.LookupWildCard(varname,self.parmDict.keys())
305                   if len(l) == 0:
306                       invalid += 1
307                       if msg: msg += "; "
308                       msg += 'No variables match '+str(varname)
309               elif varname not in self.parmDict.keys():
310                   invalid += 1
311                   if msg: msg += "; "
312                   msg += 'No variables match '+str(varname)
313            else:
314                # value assignment: this check is likely unneeded
315                val = self.varValue.get(v)
316                try:
317                    float(val)
318                except ValueError,TypeError:
319                    invalid += 1
320                    if msg: msg += "; "
321                    if val is None:
322                        msg += 'No value for '+str(v)
323                    else:
324                        msg += 'Value '+str(val)+' invalid for '+str(v)
325        if invalid:
326            return '('+msg+')'       
327        return
328
329    def ShowVars(self):
330        # create widgets to associate vars with labels and/or show messages
331        self.varSizer.Clear(True)
332        self.errbox = wxscroll.ScrolledPanel(self,style=wx.HSCROLL)
333        self.errbox.SetMinSize((100,130))
334        self.varSizer.Add(self.errbox,0,wx.ALL|wx.EXPAND,1)
335        self.varbox = wxscroll.ScrolledPanel(self,style=wx.HSCROLL)
336        self.varSizer.Add(self.varbox,1,wx.ALL|wx.EXPAND,1)
337        Siz = wx.BoxSizer(wx.VERTICAL)
338        Siz.Add(
339            wx.StaticText(self.varbox,wx.ID_ANY,
340                          'Assign variables to labels'),
341            0,wx.EXPAND|wx.ALIGN_CENTER,0)
342        GridSiz = wx.FlexGridSizer(len(self.exprVarLst)+1,5,2,2)
343        GridSiz.Add(
344            wx.StaticText(self.varbox,wx.ID_ANY,'label',style=wx.CENTER),
345            0,wx.ALIGN_CENTER)
346        lbls = ('varib. type\nselection','variable\nname','value')
347        choices = ['Free','Phase','Hist./Phase','Hist.','Global']
348        if self.fit:
349            lbls += ('refine\nflag',)
350        else:
351            lbls += ('',)
352            choices[0] = ''
353        for i in range(1,len(choices)): # remove empty menus from choice list
354            if not len(self.parmLists[i]): choices[i] = ''
355
356        self.AllowedChoices = [i for i in range(len(choices)) if choices[i]]
357        for lbl in lbls:
358            w = wx.StaticText(self.varbox,wx.ID_ANY,lbl,style=wx.CENTER)
359            w.SetMinSize((80,-1))
360            GridSiz.Add(w,0,wx.ALIGN_CENTER)
361
362        # show input for each var in expression.
363        for v in self.exprVarLst:
364            # label
365            GridSiz.Add(wx.StaticText(self.varbox,wx.ID_ANY,v),0,wx.ALIGN_CENTER,0)
366            # assignment type
367            ch = wx.Choice(
368                self.varbox, wx.ID_ANY,
369                choices = [choices[i] for i in self.AllowedChoices]
370                )
371            GridSiz.Add(ch,0,wx.ALIGN_LEFT,0)
372            if v in self.varSelect and self.varSelect.get(v) in self.AllowedChoices:
373                i = self.AllowedChoices.index(self.varSelect[v])
374                ch.SetSelection(i)
375            else:
376                ch.SetSelection(wx.NOT_FOUND)
377            ch.label = v
378            ch.Bind(wx.EVT_CHOICE,self.OnChoice)
379
380            # var name/var assignment
381            if self.varSelect.get(v) is None:
382                GridSiz.Add((-1,-1),0,wx.ALIGN_LEFT|wx.EXPAND,0)
383            elif self.varSelect.get(v) == 0:
384                wid = G2gd.ValidatedTxtCtrl(self.varbox,self.varName,v,
385                                            #OnLeave=self.OnTxtLeave,
386                                            size=(50,-1))
387                GridSiz.Add(wid,0,wx.ALIGN_LEFT|wx.EXPAND,0)
388            else:
389                wid = wx.StaticText(self.varbox,wx.ID_ANY,self.varName[v])
390                GridSiz.Add(wid,0,wx.ALIGN_LEFT,0)
391
392            # value
393            if self.varSelect.get(v) is None:
394                GridSiz.Add((-1,-1),0,wx.ALIGN_RIGHT|wx.EXPAND,0)
395            elif self.varSelect.get(v) == 0:
396                wid = G2gd.ValidatedTxtCtrl(self.varbox,self.varValue,v,
397                                            #OnLeave=self.OnTxtLeave,
398                                            size=(75,-1))
399                GridSiz.Add(wid,0,wx.ALIGN_LEFT|wx.EXPAND,0)
400                wid.Bind(wx.EVT_CHAR,self.OnChar)
401            else:
402                var = self.varName[v]
403                if '*' in var:
404                    #[self.parmDict[v] for v in LookupWildCard(var,self.parmDict.keys())]
405                    #print self.varValue[v]
406                    vs = G2obj.LookupWildCard(var,self.parmDict.keys())
407                    s = '('+str(len(vs))+' values)'
408                elif var in self.parmDict:
409                    val = self.parmDict[var]
410                    s = G2py3.FormatSigFigs(val).rstrip('0')
411                else:
412                    s = '?'
413                wid = wx.StaticText(self.varbox,wx.ID_ANY,s)
414                GridSiz.Add(wid,0,wx.ALIGN_LEFT,0)
415
416            # show a refine flag for Free Vars only
417            if self.varSelect.get(v) == 0 and self.fit:
418                self.varRefflag[v] = self.varRefflag.get(v,True)
419                wid = G2gd.G2CheckBox(self.varbox,'',self.varRefflag,v)
420                GridSiz.Add(wid,0,wx.ALIGN_LEFT|wx.EXPAND,0)
421            else:
422                wid = (-1,-1)
423                GridSiz.Add(wid,0,wx.ALIGN_LEFT|wx.EXPAND,0)
424
425        Siz.Add(GridSiz)
426        self.varbox.SetSizer(Siz,True)
427        xwid,yhgt = Siz.Fit(self.varbox)
428        self.varbox.SetMinSize((xwid,130))
429        self.varbox.SetAutoLayout(1)
430        self.varbox.SetupScrolling()
431        self.varbox.Refresh()
432        self.Layout()
433        return
434
435    def GetDepVar(self):
436        '''Returns the name of the dependent variable, when depVarDict is used.
437        '''
438        return self.depVar[1]
439       
440    def OnChoice(self,event):
441        '''Respond to a selection of a variable type for a label in
442        an expression
443        '''
444        v = event.GetEventObject().label
445        sel = self.AllowedChoices[event.GetEventObject().GetSelection()]
446        self.varSelect[v] = sel
447        if sel == 0:
448            self.varName[v] = str(v)
449            self.varValue[v] = self.varValue.get(v,0.0)
450        else:
451            var = self.SelectG2var(sel,v)
452            if not var:
453                del self.varSelect[v]
454                self.OnValidate(None)
455                return
456            self.varName[v] = var
457        self.OnValidate(None)
458
459    def SelectG2var(self,sel,var):
460        '''Offer a selection of a GSAS-II variable.
461
462        :param int sel: Determines the type of variable to be selected.
463          where 1 is used for Phase variables, and 2 for Histogram/Phase vars,
464          3 for Histogram vars and 4 for Global vars.
465        :returns: a variable name or None (if Cancel is pressed)
466        '''
467        if not self.parmLists[sel]:
468            return None
469        #varListlbl = ["("+i+") "+G2obj.fmtVarDescr(i) for i in self.parmLists[sel]]
470        #varListlbl = self.parmLists[sel]
471        l2 = l1 = 1
472        for i in self.parmLists[sel]:
473            l1 = max(l1,len(i))
474            loc,desc = G2obj.VarDescr(i)
475            l2 = max(l2,len(loc))
476        fmt = u"{:"+str(l1)+"s} {:"+str(l2)+"s} {:s}"
477        varListlbl = [fmt.format(i,*G2obj.VarDescr(i)) for i in self.parmLists[sel]]
478
479        dlg = G2gd.G2SingleChoiceDialog(
480            self,'Select GSAS-II variable for '+str(var)+':',
481            'Select variable',
482            varListlbl,monoFont=True)
483        dlg.SetSize((625,250))
484        dlg.CenterOnParent()
485        var = None
486        if dlg.ShowModal() == wx.ID_OK:
487            i = dlg.GetSelection()
488            var = self.parmLists[sel][i]
489        dlg.Destroy()
490        return var
491
492    def showError(self,msg1,msg2='',msg3=''):
493        '''Show an error message of 1 to 3 sections. The second
494        section is shown in an equally-spaced font.
495       
496        :param str msg1: msg1 is shown in a the standard font
497        :param str msg2: msg2 is shown in a equally-spaced (wx.MODERN) font
498        :param str msg3: msg3 is shown in a the standard font
499        '''
500        self.OKbtn.Disable()
501        self.varSizer.Clear(True)
502        self.errbox = wxscroll.ScrolledPanel(self,style=wx.HSCROLL)
503        self.errbox.SetMinSize((200,130))
504        self.varSizer.Add(self.errbox,1,wx.ALL|wx.EXPAND,1)
505        Siz = wx.BoxSizer(wx.VERTICAL)
506        errMsg1 = wx.StaticText(self.errbox, wx.ID_ANY,"")
507        Siz.Add(errMsg1, 0, wx.ALIGN_LEFT|wx.LEFT|wx.EXPAND, 5)
508        errMsg2 = wx.StaticText(self.errbox, wx.ID_ANY,"\n\n")
509        font1 = wx.Font(errMsg2.GetFont().GetPointSize(),
510                        wx.MODERN, wx.NORMAL, wx.NORMAL, False)
511        errMsg2.SetFont(font1)
512        Siz.Add(errMsg2, 0, wx.ALIGN_LEFT|wx.LEFT|wx.EXPAND, 5)
513        errMsg3 = wx.StaticText(self.errbox, wx.ID_ANY,"")
514        Siz.Add(errMsg3, 0, wx.ALIGN_LEFT|wx.LEFT|wx.EXPAND, 5)
515        self.errbox.SetSizer(Siz,True)
516        Siz.Fit(self.errbox)
517        errMsg1.SetLabel(msg1)
518        errMsg2.SetLabel("  "+msg2)
519        errMsg2.Wrap(-1)
520        errMsg3.SetLabel(msg3)
521        self.Layout()
522
523    def OnValidate(self,event):
524        '''Respond to a press of the Validate button or when a variable
525        is associated with a label (in :meth:`OnChoice`)
526        '''
527        self.setEvalResult('(expression cannot be evaluated)')
528        self.timer.Stop()
529        self.expr = self.exCtrl.GetValue().strip()
530        self.varSizer.Clear(True)
531        if not self.expr: 
532            self.showError(
533                "Invalid Expression:","",
534                "(an expression must be entered)")
535            return
536        exprObj = G2obj.ExpressionObj()
537        ret = exprObj.ParseExpression(self.expr)
538        if not ret:
539            self.showError(*exprObj.lastError)
540            return
541        self.exprVarLst,pkgdict = ret
542        self.ShowVars() # show widgets to set vars
543        msg = self.CheckVars() 
544        if msg:
545            self.setEvalResult(msg)
546            return
547        exprObj.LoadExpression(
548            self.expr,
549            self.exprVarLst,
550            self.varSelect,
551            self.varName,
552            self.varValue,
553            self.varRefflag,
554            )
555        try:
556            calcobj = G2obj.ExpressionCalcObj(exprObj)
557            calcobj.SetupCalc(self.parmDict)
558            val = calcobj.EvalExpression()
559        except Exception as msg:
560            self.setEvalResult("Error in evaluation: "+str(msg))
561            return
562        if not np.isfinite(val):
563            self.setEvalResult("Expression value is infinite or out-of-bounds")
564            return
565        s = G2py3.FormatSigFigs(val).rstrip('0')
566        depVal = ""
567        if self.depVarDict:
568            if not self.depVar[1]:
569                self.setEvalResult("A dependent variable must be selected.")
570                return
571            depVal = '; Variable "' + self.depVar[1] + '" = ' + str(
572                self.depVarDict.get(self.depVar[1],'?')
573                )
574        self.setEvalResult("Expression evaluates to: "+str(s)+depVal)
575        self.OKbtn.Enable()
576       
577if __name__ == "__main__":
578    app = wx.PySimpleApp() # create the App
579    frm = wx.Frame(None)
580    frm.Show()
581    PSvarDict = {'::a':1.0,'::b':1.1,'0::c':1.2}
582    #PSvars = PSvarDict.keys()
583    indepvarDict = {'Temperature':1.0,'Pressure':1.1,'Phase of Moon':1.2,'1:1:HAP':1.3}
584    dlg = ExpressionDialog(frm,indepvarDict,
585                           header="Edit the PseudoVar expression",
586                           fit=False,
587                           depVarDict=PSvarDict,
588                           #VarLabel="New PseudoVar",                           
589                           )
590    print dlg.GetDepVar()
591    newobj = dlg.Show(True)
592    print dlg.GetDepVar()
593    dlg = ExpressionDialog(frm,PSvarDict,
594                           header="Edit the PseudoVar expression",
595                           fit=True)
596    newobj = dlg.Show(True)
597    print dlg.GetDepVar()
598    import sys
599    #sys.exit()
600
601    #app.MainLoop()
602
603
604    import cPickle
605    def showEQ(calcobj):
606        print
607        print calcobj.eObj.expression
608        for v in sorted(calcobj.eObj.freeVars.keys()+calcobj.eObj.assgnVars.keys()):
609            print "  ",v,'=',calcobj.exprDict[v]
610        print calcobj.EvalExpression()
611    print "starting test"
612    obj = G2obj.ExpressionObj()
613    obj.expression = "A*np.exp(B)"
614    obj.assgnVars =  {'B': '0::Afrac:*'}
615    obj.freeVars =  {'A': [u'A', 0.5, True]}
616    obj.CheckVars()
617    parmDict2 = {'0::Afrac:0':1.0, '0::Afrac:1': 1.0}
618    calcobj = G2obj.ExpressionCalcObj(obj)
619    calcobj.SetupCalc(parmDict2)
620    showEQ(calcobj)
621    fp = open('/tmp/obj.pickle','w')
622    cPickle.dump(obj,fp)
623    fp.close()
624   
625    obj.expression = "A*np.exp(-2/B)"
626    obj.assgnVars =  {'A': '0::Afrac:0', 'B': '0::Afrac:1'}
627    obj.freeVars =  {}
628    parmDict1 = {'0::Afrac:0':1.0, '0::Afrac:1': -2.0}
629    calcobj = G2obj.ExpressionCalcObj(obj)
630    calcobj.SetupCalc(parmDict1)
631    showEQ(calcobj)
632
633    fp = open('/tmp/obj.pickle','r')
634    obj = cPickle.load(fp)
635    fp.close()
636    parmDict2 = {'0::Afrac:0':0.0, '0::Afrac:1': 1.0}
637    calcobj = G2obj.ExpressionCalcObj(obj)
638    calcobj.SetupCalc(parmDict2)
639    showEQ(calcobj)
640
641    parmDict2 = {'0::Afrac:0':1.0, '0::Afrac:1': 1.0}
642    calcobj = G2obj.ExpressionCalcObj(obj)
643    calcobj.SetupCalc(parmDict2)
644    showEQ(calcobj)
645   
Note: See TracBrowser for help on using the repository browser.