source: trunk/GSASIIconstrGUI.py @ 831

Last change on this file since 831 was 831, checked in by vondreele, 10 years ago

more on rigid bodies

File size: 38.4 KB
Line 
1# -*- coding: utf-8 -*-
2#GSASIIconstrGUI - constraint GUI routines
3########### SVN repository information ###################
4# $Date: 2012-12-05 15:38:26 -0600 (Wed, 05 Dec 2012) $
5# $Author: vondreele $
6# $Revision: 810 $
7# $URL: https://subversion.xor.aps.anl.gov/pyGSAS/trunk/GSASIIconstrGUI.py $
8# $Id: GSASIIconstrGUI.py 810 2012-12-05 21:38:26Z vondreele $
9########### SVN repository information ###################
10import sys
11import wx
12import wx.grid as wg
13import time
14import random as ran
15import numpy as np
16import numpy.ma as ma
17import os.path
18import GSASIIpath
19GSASIIpath.SetVersionNumber("$Revision: 810 $")
20import GSASIIElem as G2elem
21import GSASIIElemGUI as G2elemGUI
22import GSASIIphsGUI as G2phG
23import GSASIIstruct as G2str
24import GSASIImapvars as G2mv
25import GSASIIgrid as G2gd
26import GSASIIplot as G2plt
27VERY_LIGHT_GREY = wx.Colour(235,235,235)
28
29class MultiIntegerDialog(wx.Dialog):
30   
31    def __init__(self,parent,title,prompts,values):
32        wx.Dialog.__init__(self,parent,-1,title, 
33            pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE)
34        self.panel = wx.Panel(self)         #just a dummy - gets destroyed in Draw!
35        self.values = values
36        self.prompts = prompts
37        self.Draw()
38       
39    def Draw(self):
40       
41        def OnValItem(event):
42            Obj = event.GetEventObject()
43            ind = Indx[Obj.GetId()]
44            try:
45                val = int(Obj.GetValue())
46                if val <= 0:
47                    raise ValueError
48            except ValueError:
49                val = self.values[ind]
50            self.values[ind] = val
51            Obj.SetValue('%d'%(val))
52           
53        self.panel.Destroy()
54        self.panel = wx.Panel(self)
55        mainSizer = wx.BoxSizer(wx.VERTICAL)
56        Indx = {}
57        for ival,[prompt,value] in enumerate(zip(self.prompts,self.values)):
58            mainSizer.Add(wx.StaticText(self.panel,-1,prompt),0,wx.ALIGN_CENTER)
59            valItem = wx.TextCtrl(self.panel,-1,value='%d'%(value),style=wx.TE_PROCESS_ENTER)
60            mainSizer.Add(valItem,0,wx.ALIGN_CENTER)
61            Indx[valItem.GetId()] = ival
62            valItem.Bind(wx.EVT_TEXT_ENTER,OnValItem)
63            valItem.Bind(wx.EVT_KILL_FOCUS,OnValItem)
64        OkBtn = wx.Button(self.panel,-1,"Ok")
65        OkBtn.Bind(wx.EVT_BUTTON, self.OnOk)
66        CancelBtn = wx.Button(self.panel,-1,'Cancel')
67        CancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel)
68        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
69        btnSizer.Add((20,20),1)
70        btnSizer.Add(OkBtn)
71        btnSizer.Add(CancelBtn)
72        btnSizer.Add((20,20),1)
73        mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
74        self.panel.SetSizer(mainSizer)
75        self.panel.Fit()
76        self.Fit()
77
78    def GetValues(self):
79        return self.values
80       
81    def OnOk(self,event):
82        parent = self.GetParent()
83        parent.Raise()
84        self.EndModal(wx.ID_OK)             
85       
86    def OnCancel(self,event):
87        parent = self.GetParent()
88        parent.Raise()
89        self.EndModal(wx.ID_CANCEL)
90       
91################################################################################
92#####  Constraints
93################################################################################           
94       
95def UpdateConstraints(G2frame,data):
96    '''Called when Constraints tree item is selected.
97    Displays the constraints in the data window
98    '''
99    if not data:
100        data.update({'Hist':[],'HAP':[],'Phase':[]})       #empty dict - fill it
101    Histograms,Phases = G2frame.GetUsedHistogramsAndPhasesfromTree()
102    AtomDict = dict([Phases[phase]['pId'],Phases[phase]['Atoms']] for phase in Phases)
103    Natoms,atomIndx,phaseVary,phaseDict,pawleyLookup,FFtable,BLtable = G2str.GetPhaseData(Phases,Print=False)
104    phaseList = []
105    for item in phaseDict:
106        if item.split(':')[2] not in ['Ax','Ay','Az','Amul','AI/A','Atype','SHorder']:
107            phaseList.append(item)
108    phaseList.sort()
109    phaseAtNames = {}
110    phaseAtTypes = {}
111    TypeList = []
112    for item in phaseList:
113        Split = item.split(':')
114        if Split[2][:2] in ['AU','Af','dA']:
115            Id = int(Split[0])
116            phaseAtNames[item] = AtomDict[Id][int(Split[3])][0]
117            phaseAtTypes[item] = AtomDict[Id][int(Split[3])][1]
118            if phaseAtTypes[item] not in TypeList:
119                TypeList.append(phaseAtTypes[item])
120        else:
121            phaseAtNames[item] = ''
122            phaseAtTypes[item] = ''
123           
124    hapVary,hapDict,controlDict = G2str.GetHistogramPhaseData(Phases,Histograms,Print=False)
125    hapList = hapDict.keys()
126    hapList.sort()
127    histVary,histDict,controlDict = G2str.GetHistogramData(Histograms,Print=False)
128    histList = []
129    for item in histDict:
130        if item.split(':')[2] not in ['Omega','Type','Chi','Phi','Azimuth','Gonio. radius','Lam1','Lam2','Back']:
131            histList.append(item)
132    histList.sort()
133    Indx = {}
134    scope = {}                          #filled out later
135    G2frame.Page = [0,'phs']
136   
137    def GetPHlegends(Phases,Histograms):
138        plegend = '\n In p::name'
139        hlegend = '\n In :h:name'
140        phlegend = '\n In p:h:name'
141        for phase in Phases:
142            plegend += '\n p:: = '+str(Phases[phase]['pId'])+':: for '+phase
143            count = 0
144            for histogram in Phases[phase]['Histograms']:
145                if count < 3:
146                    phlegend += '\n p:h: = '+str(Phases[phase]['pId'])+':'+str(Histograms[histogram]['hId'])+': for '+phase+' in '+histogram
147                else:
148                    phlegend += '\n ... etc.'
149                    break
150                count += 1
151        count = 0
152        for histogram in Histograms:
153            if count < 3:
154                hlegend += '\n :h: = :'+str(Histograms[histogram]['hId'])+': for '+histogram
155            else:
156                hlegend += '\n ... etc.'
157                break
158            count += 1
159        return plegend,hlegend,phlegend
160       
161    def FindEquivVarb(name,nameList):
162        outList = []
163        phlist = []
164        items = name.split(':')
165        namelist = [items[2],]
166        if 'dA' in name:
167            namelist = ['dAx','dAy','dAz']
168        elif 'AU' in name:
169            namelist = ['AUiso','AU11','AU22','AU33','AU12','AU13','AU23']
170        for item in nameList:
171            keys = item.split(':')
172            if keys[0] not in phlist:
173                phlist.append(keys[0])
174            if keys[2] in namelist and item != name:
175                outList.append(item)
176        if items[1]:
177            for key in phlist:
178                outList.append(key+':all:'+items[2])
179        return outList
180       
181    def SelectVarbs(page,FrstVarb,varList,legend,constType):
182        '''Select variables used in Constraints after one variable has
183        been selected which determines the appropriate variables to be
184        used here. Then creates the constraint and adds it to the
185        constraints list.
186        Called from OnAddEquivalence, OnAddFunction & OnAddConstraint
187        '''
188        #future -  add 'all:all:name', '0:all:name', etc. to the varList
189        if page[1] == 'phs':
190            atchoice = [item+' for '+phaseAtNames[item] for item in varList]
191            atchoice += [FrstVarb+' for all']
192            atchoice += [FrstVarb+' for all '+atype for atype in TypeList]
193            dlg = wx.MultiChoiceDialog(G2frame,'Select more variables:'+legend,
194                'Constrain '+FrstVarb+' and...',atchoice)
195        else:
196            dlg = wx.MultiChoiceDialog(G2frame,'Select more variables:'+legend,
197                'Constrain '+FrstVarb+' and...',varList)
198        varbs = [FrstVarb,]
199        if dlg.ShowModal() == wx.ID_OK:
200            sel = dlg.GetSelections()
201            try:
202                for x in sel:
203                    if ':all:' in varList[x]:       #a histogram 'all' - supercedes any individual selection
204                        varbs = [FrstVarb,]
205                        items = varList[x].split(':')
206                        for item in varList:
207                            if items[0] == item.split(':')[0] and ':all:' not in item:
208                                varbs.append(item)
209                        break
210                    else:
211                        varbs.append(varList[x])
212            except IndexError:      # one of the 'all' chosen - supercedes any individual selection
213                varbs = [FrstVarb,]
214                Atypes = []
215                for x in sel:
216                    item = atchoice[x]
217                    if 'all' in item:
218                        Atypes.append(item.split('all')[1].strip())
219                if '' in Atypes:
220                    varbs += varList
221                else:
222                    for item in varList:
223                        if phaseAtTypes[item] in Atypes:
224                            varbs.append(item) 
225        dlg.Destroy()
226        if len(varbs) > 1:
227            if 'equivalence' in constType:
228                constr = [[1.0,FrstVarb]]
229                for item in varbs[1:]:
230                    constr += [[1.0,item]]
231                return [constr+[None,None,'e']]      # list of equivalent variables & mults
232            elif 'function' in constType:
233                constr = map(list,zip([1.0 for i in range(len(varbs))],varbs))
234                return [constr+[None,False,'f']]         #just one constraint
235            else:       #'constraint'
236                constr = map(list,zip([1.0 for i in range(len(varbs))],varbs))
237                return [constr+[1.0,None,'c']]          #just one constraint - default sum to one
238        return []
239
240    def CheckAddedConstraint(newcons):
241        '''Check a new constraint that has just been input.
242        If there is an error display a message and give the user a
243        choice to keep or discard the last entry (why keep? -- they
244        may want to delete something else or edit multipliers).
245        Since the varylist is not available, no warning messages
246        should be generated.
247        Returns True if constraint should be added
248        '''
249        allcons = []
250        for key in 'Hist','HAP','Phase':
251            allcons += data[key]
252        allcons += newcons
253        if not len(allcons): return True
254        G2mv.InitVars()   
255        constDictList,fixedList,ignored = G2str.ProcessConstraints(allcons)
256        errmsg, warnmsg = G2mv.CheckConstraints('',constDictList,fixedList)
257        if errmsg:
258            res = G2frame.ErrorDialog('Constraint Error',
259                'Error with newly added constraint:\n'+errmsg+
260                '\n\nDiscard newly added constraint?',parent=G2frame.dataFrame,
261                wtype=wx.YES_NO)
262            return res != wx.ID_YES
263        elif warnmsg:
264            print 'Unexpected contraint warning:\n',warnmsg
265        return True
266
267    def CheckChangedConstraint():
268        '''Check all constraints after an edit has been made.
269        If there is an error display a message and give the user a
270        choice to keep or discard the last edit.
271        Since the varylist is not available, no warning messages
272        should be generated.
273        Returns True if the edit should be retained
274        '''
275        allcons = []
276        for key in 'Hist','HAP','Phase':
277            allcons += data[key]
278        if not len(allcons): return True
279        G2mv.InitVars()   
280        constDictList,fixedList,ignored = G2str.ProcessConstraints(allcons)
281        errmsg, warnmsg = G2mv.CheckConstraints('',constDictList,fixedList)
282        if errmsg:
283            res = G2frame.ErrorDialog('Constraint Error',
284                'Error after editing constraint:\n'+errmsg+
285                '\n\nDiscard last constraint edit?',parent=G2frame.dataFrame,
286                wtype=wx.YES_NO)
287            return res != wx.ID_YES
288        elif warnmsg:
289            print 'Unexpected contraint warning:\n',warnmsg
290        return True
291             
292    def OnAddHold(event):
293        '''add a Hold constraint'''
294        for phase in Phases:
295            Phase = Phases[phase]
296            Atoms = Phase['Atoms']
297        constr = []
298        page = G2frame.Page
299        choice = scope[page[1]]
300        if page[1] == 'phs':
301            atchoice = [item+' for '+phaseAtNames[item] for item in choice[2]]
302            dlg = wx.SingleChoiceDialog(G2frame,'Select 1st variable:'+choice[1],choice[0],atchoice)
303        else:   
304            dlg = wx.SingleChoiceDialog(G2frame,'Select 1st variable:'+choice[1],choice[0],choice[2])
305        if dlg.ShowModal() == wx.ID_OK:
306            sel = dlg.GetSelection()
307            FrstVarb = choice[2][sel]
308            newcons = [[[0.0,FrstVarb],None,None,'h']]
309            if CheckAddedConstraint(newcons):
310                data[choice[3]] += newcons
311        dlg.Destroy()
312        choice[4]()
313       
314    def OnAddEquivalence(event):
315        '''add an Equivalence constraint'''
316        constr = []
317        page = G2frame.Page
318        choice = scope[page[1]]
319        if page[1] == 'phs':
320            atchoice = [item+' for '+phaseAtNames[item] for item in choice[2]]
321            dlg = wx.SingleChoiceDialog(G2frame,'Select 1st variable:'+choice[1],choice[0],atchoice)
322        else:   
323            dlg = wx.SingleChoiceDialog(G2frame,'Select 1st variable:'+choice[1],choice[0],choice[2])
324        if dlg.ShowModal() == wx.ID_OK:
325            sel = dlg.GetSelection()
326            FrstVarb = choice[2][sel]
327            moreVarb = FindEquivVarb(FrstVarb,choice[2])
328            newcons = SelectVarbs(page,FrstVarb,moreVarb,choice[1],'equivalence')
329            if len(newcons) > 0:
330                if CheckAddedConstraint(newcons):
331                    data[choice[3]] += newcons
332        dlg.Destroy()
333        choice[4]()
334   
335    def OnAddFunction(event):
336        '''add a Function (new variable) constraint'''
337        constr = []
338        page = G2frame.Page
339        choice = scope[page[1]]
340        if page[1] == 'phs':
341            atchoice = [item+' for '+phaseAtNames[item] for item in choice[2]]
342            dlg = wx.SingleChoiceDialog(G2frame,'Select 1st variable:'+choice[1],choice[0],atchoice)
343        else:   
344            dlg = wx.SingleChoiceDialog(G2frame,'Select 1st variable:'+choice[1],choice[0],choice[2])
345        if dlg.ShowModal() == wx.ID_OK:
346            sel = dlg.GetSelection()
347            FrstVarb = choice[2][sel]
348            moreVarb = FindEquivVarb(FrstVarb,choice[2])
349            newcons = SelectVarbs(page,FrstVarb,moreVarb,choice[1],'function')
350            if len(newcons) > 0:
351                if CheckAddedConstraint(newcons):
352                    data[choice[3]] += newcons
353        dlg.Destroy()
354        choice[4]()
355                       
356    def OnAddConstraint(event):
357        '''add a constraint equation to the constraints list'''
358        constr = []
359        page = G2frame.Page
360        choice = scope[page[1]]
361        if page[1] == 'phs':
362            atchoice = [item+' for '+phaseAtNames[item] for item in choice[2]]
363            dlg = wx.SingleChoiceDialog(G2frame,'Select 1st variable:'+choice[1],choice[0],atchoice)
364        else:   
365            dlg = wx.SingleChoiceDialog(G2frame,'Select 1st variable:'+choice[1],choice[0],choice[2])
366        if dlg.ShowModal() == wx.ID_OK:
367            sel = dlg.GetSelection()
368            FrstVarb = choice[2][sel]
369            moreVarb = FindEquivVarb(FrstVarb,choice[2])
370            newcons = SelectVarbs(page,FrstVarb,moreVarb,choice[1],'constraint')
371            if len(newcons) > 0:
372                if CheckAddedConstraint(newcons):
373                    data[choice[3]] += newcons
374        dlg.Destroy()
375        choice[4]()
376                       
377    def ConstSizer(name,pageDisplay):
378        '''This creates a sizer displaying all of the constraints entered
379        '''
380        constSizer = wx.FlexGridSizer(1,4,0,0)
381        maxlen = 70 # characters before wrapping a constraint
382        for Id,item in enumerate(data[name]):
383            eqString = ['',]
384            if item[-1] == 'h':
385                constSizer.Add((5,5),0)              # blank space for edit button
386                typeString = ' FIXED   '
387                eqString[-1] = item[0][1]+'   '
388            elif isinstance(item[-1],str):
389                constEdit = wx.Button(pageDisplay,-1,'Edit',style=wx.BU_EXACTFIT)
390                constEdit.Bind(wx.EVT_BUTTON,OnConstEdit)
391                constSizer.Add(constEdit)            # edit button
392                Indx[constEdit.GetId()] = [Id,name]
393                if item[-1] == 'f':
394                    for term in item[:-3]:
395                        if len(eqString[-1]) > maxlen:
396                            eqString.append(' ')
397                        m = term[0]
398                        if eqString[-1] != '':
399                            if m >= 0:
400                                eqString[-1] += ' + '
401                            else:
402                                eqString[-1] += ' - '
403                                m = abs(m)
404                        eqString[-1] += '%.3f*%s '%(m,term[1])
405                    typeString = ' NEWVAR  '
406                    eqString[-1] += ' = New Variable   '
407                elif item[-1] == 'c':
408                    for term in item[:-3]:
409                        if len(eqString[-1]) > maxlen:
410                            eqString.append(' ')
411                        if eqString[-1] != '':
412                            if term[0] > 0:
413                                eqString[-1] += ' + '
414                            else:
415                                eqString[-1] += ' - '
416                        eqString[-1] += '%.3f*%s '%(abs(term[0]),term[1])
417                    typeString = ' CONSTR  '
418                    eqString[-1] += ' = %.3f'%(item[-3])+'  '
419                elif item[-1] == 'e':
420                    for term in item[:-3]:
421                        if term[0] == 0: term[0] = 1.0
422                        if len(eqString[-1]) > maxlen:
423                            eqString.append(' ')
424                        if eqString[-1] == '':
425                            eqString[-1] += '%s '%(term[1])
426                            first = term[0]
427                        else:
428                            eqString[-1] += ' = %.3f*%s '%(first/term[0],term[1])
429                    typeString = ' EQUIV   '
430                else:
431                    print 'Unexpected constraint',item
432            else:
433                print 'Removing old-style constraints'
434                data[name] = []
435                return constSizer
436            constDel = wx.Button(pageDisplay,-1,'Delete',style=wx.BU_EXACTFIT)
437            constDel.Bind(wx.EVT_BUTTON,OnConstDel)
438            Indx[constDel.GetId()] = [Id,name]
439            constSizer.Add(constDel)             # delete button
440            constSizer.Add(wx.StaticText(pageDisplay,-1,typeString),0,wx.ALIGN_CENTER_VERTICAL)
441            EqSizer = wx.BoxSizer(wx.VERTICAL)
442            for s in eqString:
443                EqSizer.Add(wx.StaticText(pageDisplay,-1,s),0,wx.ALIGN_CENTER_VERTICAL)
444            constSizer.Add(EqSizer,0,wx.ALIGN_CENTER_VERTICAL)
445            # if item[-1] == 'f':
446            #     constRef = wx.CheckBox(pageDisplay,-1,label=' Refine?')
447            #     constRef.SetValue(item[-2])
448            #     constRef.Bind(wx.EVT_CHECKBOX,OnConstRef)
449            #     Indx[constRef.GetId()] = item
450            #     constSizer.Add(constRef)
451            # else:
452            #     constSizer.Add((5,5),0)
453        return constSizer
454               
455    # def OnConstRef(event):
456    #     Obj = event.GetEventObject()
457    #     Indx[Obj.GetId()][-2] = Obj.GetValue()
458       
459    def OnConstDel(event):
460        Obj = event.GetEventObject()
461        Id,name = Indx[Obj.GetId()]
462        del(data[name][Id])
463        OnPageChanged(None)       
464       
465    def OnConstEdit(event):
466        '''Called to edit an individual contraint by the Edit button'''
467        Obj = event.GetEventObject()
468        Id,name = Indx[Obj.GetId()]
469        sep = '*'
470        if data[name][Id][-1] == 'f':
471            items = data[name][Id][:-3]+[[],]
472            constType = 'New Variable'
473            lbl = 'Enter value for each term in constraint; sum = new variable'
474        elif data[name][Id][-1] == 'c':
475            items = data[name][Id][:-3]+[
476                [data[name][Id][-3],'fixed value ='],[]]
477            constType = 'Constraint'
478            lbl = 'Edit value for each term in constant constraint sum'
479        elif data[name][Id][-1] == 'e':
480            items = data[name][Id][:-3]+[[],]
481            constType = 'Equivalence'
482            lbl = 'The following terms are set to be equal:'
483            sep = '/'
484        else:
485            return
486        dlg = G2frame.ConstraintDialog(G2frame.dataFrame,constType,lbl,items,sep)
487        try:
488            if dlg.ShowModal() == wx.ID_OK:
489                prev = data[name][Id]
490                result = dlg.GetData()
491                if data[name][Id][-1] == 'c':
492                    data[name][Id][:-3] = result[:-2]
493                    data[name][Id][-3] = result[-2][0]
494                else:
495                    data[name][Id][:-3] = result[:-1]
496                if not CheckChangedConstraint():
497                    data[name][Id] = prev
498        except:
499            import traceback
500            print traceback.format_exc()
501        finally:
502            dlg.Destroy()           
503        OnPageChanged(None)                     
504   
505    def UpdateHAPConstr():
506        '''Responds to press on Histogram/Phase Constraints tab,
507        shows constraints in data window'''
508        HAPConstr.DestroyChildren()
509        HAPDisplay = wx.Panel(HAPConstr)
510        HAPSizer = wx.BoxSizer(wx.VERTICAL)
511        HAPSizer.Add((5,5),0)
512        HAPSizer.Add(ConstSizer('HAP',HAPDisplay))
513        HAPDisplay.SetSizer(HAPSizer,True)
514        Size = HAPSizer.GetMinSize()
515        Size[0] += 40
516        Size[1] = max(Size[1],250) + 20
517        HAPDisplay.SetSize(Size)
518        # scroll bar not working, at least not on Mac
519        HAPConstr.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
520        Size[1] = min(Size[1],250)
521        G2frame.dataFrame.setSizePosLeft(Size)
522       
523    def UpdateHistConstr():
524        '''Responds to press on Histogram Constraints tab,
525        shows constraints in data window'''
526        HistConstr.DestroyChildren()
527        HistDisplay = wx.Panel(HistConstr)
528        HistSizer = wx.BoxSizer(wx.VERTICAL)
529        HistSizer.Add((5,5),0)       
530        HistSizer.Add(ConstSizer('Hist',HistDisplay))
531        HistDisplay.SetSizer(HistSizer,True)
532        Size = HistSizer.GetMinSize()
533        Size[0] += 40
534        Size[1] = max(Size[1],250) + 20
535        HistDisplay.SetSize(Size)
536        HistConstr.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
537        Size[1] = min(Size[1],250)
538        G2frame.dataFrame.setSizePosLeft(Size)
539       
540    def UpdatePhaseConstr():
541        '''Responds to press on Phase Constraint tab,
542        shows constraints in data window'''
543        PhaseConstr.DestroyChildren()
544        PhaseDisplay = wx.Panel(PhaseConstr)
545        PhaseSizer = wx.BoxSizer(wx.VERTICAL)
546        PhaseSizer.Add((5,5),0)       
547        PhaseSizer.Add(ConstSizer('Phase',PhaseDisplay))
548        PhaseDisplay.SetSizer(PhaseSizer,True)
549        Size = PhaseSizer.GetMinSize()
550        Size[0] += 40
551        Size[1] = max(Size[1],250) + 20
552        PhaseDisplay.SetSize(Size)
553        PhaseConstr.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
554        Size[1] = min(Size[1],250)
555        G2frame.dataFrame.setSizePosLeft(Size)
556   
557    def OnPageChanged(event):
558        if event:       #page change event!
559            page = event.GetSelection()
560        else:
561            page = G2frame.dataDisplay.GetSelection()
562        oldPage = G2frame.dataDisplay.ChangeSelection(page)
563        text = G2frame.dataDisplay.GetPageText(page)
564        if text == 'Histogram/Phase constraints':
565            G2frame.Page = [page,'hap']
566            UpdateHAPConstr()
567        elif text == 'Histogram constraints':
568            G2frame.Page = [page,'hst']
569            UpdateHistConstr()
570        elif text == 'Phase constraints':
571            G2frame.Page = [page,'phs']
572            UpdatePhaseConstr()
573
574    def SetStatusLine(text):
575        Status.SetStatusText(text)                                     
576       
577    plegend,hlegend,phlegend = GetPHlegends(Phases,Histograms)
578    scope = {'hst':['Histogram contraints:',hlegend,histList,'Hist',UpdateHistConstr],
579        'hap':['Histogram * Phase contraints:',phlegend,hapList,'HAP',UpdateHAPConstr],
580        'phs':['Phase contraints:',plegend,phaseList,'Phase',UpdatePhaseConstr]}
581    if G2frame.dataDisplay:
582        G2frame.dataDisplay.Destroy()
583    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.ConstraintMenu)
584    G2frame.dataFrame.SetLabel('Constraints')
585    if not G2frame.dataFrame.GetStatusBar():
586        Status = G2frame.dataFrame.CreateStatusBar()
587    SetStatusLine('')
588   
589    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.ConstraintMenu)
590    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddConstraint, id=G2gd.wxID_CONSTRAINTADD)
591    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddFunction, id=G2gd.wxID_FUNCTADD)
592    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddEquivalence, id=G2gd.wxID_EQUIVADD)
593    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddHold, id=G2gd.wxID_HOLDADD)
594    G2frame.dataDisplay = G2gd.GSNoteBook(parent=G2frame.dataFrame,size=G2frame.dataFrame.GetClientSize())
595   
596    PhaseConstr = wx.ScrolledWindow(G2frame.dataDisplay)
597    G2frame.dataDisplay.AddPage(PhaseConstr,'Phase constraints')
598    HAPConstr = wx.ScrolledWindow(G2frame.dataDisplay)
599    G2frame.dataDisplay.AddPage(HAPConstr,'Histogram/Phase constraints')
600    HistConstr = wx.ScrolledWindow(G2frame.dataDisplay)
601    G2frame.dataDisplay.AddPage(HistConstr,'Histogram constraints')
602    UpdatePhaseConstr()
603
604    G2frame.dataDisplay.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, OnPageChanged)
605    # validate all the constrants -- should not see any errors here normally
606    allcons = []
607    for key in 'Hist','HAP','Phase':
608        allcons += data[key]
609    if not len(allcons): return
610    G2mv.InitVars()   
611    constDictList,fixedList,ignored = G2str.ProcessConstraints(allcons)
612    errmsg, warnmsg = G2mv.CheckConstraints('',constDictList,fixedList)
613    if errmsg:
614        G2frame.ErrorDialog('Constraint Error','Error in constraints:\n'+errmsg,
615            parent=G2frame.dataFrame)
616    elif warnmsg:
617        print 'Unexpected contraint warning:\n',warnmsg
618       
619################################################################################
620#### Rigid bodies
621################################################################################
622
623def UpdateRigidBodies(G2frame,data):
624    '''Called when Rigid bodies tree item is selected.
625    Displays the rigid bodies in the data window
626    '''
627    if not data:
628        data.update({'Vector':{},'Residue':{},'Z-matrix':{}})       #empty dict - fill it
629           
630    Indx = {}
631    plotDefaults = {'oldxy':[0.,0.],'Quaternion':[1.,0.,0.,0.],'cameraPos':20.,'viewDir':[0,0,1],}
632
633    def OnPageChanged(event):
634        if event:       #page change event!
635            page = event.GetSelection()
636        else:
637            page = G2frame.dataDisplay.GetSelection()
638        oldPage = G2frame.dataDisplay.ChangeSelection(page)
639        text = G2frame.dataDisplay.GetPageText(page)
640        if text == 'Vector rigid bodies':
641            G2frame.Page = [page,'vrb']
642            UpdateVectorRB()
643        elif text == 'Residue rigid bodies':
644            G2frame.Page = [page,'rrb']
645            UpdateResidueRB()
646        elif text == 'Z-matrix rigid bodies':
647            G2frame.Page = [page,'zrb']
648            UpdateZMatrixRB()
649           
650    def OnAddRigidBody(event):
651        page = G2frame.dataDisplay.GetSelection()
652        if 'Vector' in G2frame.dataDisplay.GetPageText(page):
653            AddVectorRB()
654        elif 'Residue' in G2frame.dataDisplay.GetPageText(page):
655            AddResidueRB()
656        elif 'Z-matrix' in G2frame.dataDisplay.GetPageText(page):
657            AddZMatrixRB()
658           
659    def AddVectorRB():
660        dlg = MultiIntegerDialog(G2frame.dataDisplay,'New Rigid Body',['No. atoms','No. translations'],[1,1])
661        if dlg.ShowModal() == wx.ID_OK:
662            nAtoms,nTrans = dlg.GetValues()
663            vectorRB = data['Vector']
664            rbId = ran.randint(0,sys.maxint)
665            vecMag = [1.0 for i in range(nTrans)]
666            vecRef = [False for i in range(nTrans)]
667            vecVal = [np.zeros((nAtoms,3)) for j in range(nTrans)]
668            rbTypes = ['C' for i in range(nAtoms)]
669            Info = G2elem.GetAtomInfo('C')
670            AtInfo= {'C':[Info['Drad'],Info['Color']]}
671            data['Vector'][rbId] = {'RBname':'UNKRB','VectMag':vecMag,
672                'VectRef':vecRef,'rbTypes':rbTypes,'rbVect':vecVal,'AtInfo':AtInfo}
673        dlg.Destroy()
674        UpdateVectorRB()
675       
676    def AddResidueRB():
677        pass
678       
679    def AddZMatrixRB():
680        pass
681
682    def UpdateVectorRB():
683        SetStatusLine(' You may use e.g. "sind(60)", "cos(60)", "c60" or "s60" for a vector entry')
684        def rbNameSizer(rbId,rbData):
685
686            def OnRBName(event):
687                Obj = event.GetEventObject()
688                rbId = Indx[Obj.GetId()]
689                rbData['RBname'] = Obj.GetValue()
690               
691            def OnDelRB(event):
692                Obj = event.GetEventObject()
693                rbId = Indx[Obj.GetId()]
694                del data['Vector'][rbId]
695                wx.CallAfter(UpdateVectorRB)
696               
697            def OnPlotRB(event):
698                Obj = event.GetEventObject()
699                rbId = Indx[Obj.GetId()]
700                Obj.SetValue(False)
701                G2plt.PlotRigidBody(G2frame,'Vector',data['Vector'][rbId],plotDefaults)
702           
703            nameSizer = wx.BoxSizer(wx.HORIZONTAL)
704            nameSizer.Add(wx.StaticText(VectorRBDisplay,-1,'Rigid body name: '),
705                0,wx.ALIGN_CENTER_VERTICAL)
706            RBname = wx.TextCtrl(VectorRBDisplay,-1,rbData['RBname'])
707            Indx[RBname.GetId()] = rbId
708            RBname.Bind(wx.EVT_TEXT_ENTER,OnRBName)
709            RBname.Bind(wx.EVT_KILL_FOCUS,OnRBName)
710            nameSizer.Add(RBname,0,wx.ALIGN_CENTER_VERTICAL)
711            nameSizer.Add((5,0),)
712            plotRB = wx.CheckBox(VectorRBDisplay,-1,'Plot?')
713            Indx[plotRB.GetId()] = rbId
714            plotRB.Bind(wx.EVT_CHECKBOX,OnPlotRB)
715            nameSizer.Add(plotRB,0,wx.ALIGN_CENTER_VERTICAL)
716            nameSizer.Add((5,0),)
717            delRB = wx.CheckBox(VectorRBDisplay,-1,'Delete?')
718            Indx[delRB.GetId()] = rbId
719            delRB.Bind(wx.EVT_CHECKBOX,OnDelRB)
720            nameSizer.Add(delRB,0,wx.ALIGN_CENTER_VERTICAL)
721            return nameSizer
722           
723        def rbVectMag(rbId,imag,rbData):
724           
725            def OnRBVectorMag(event):
726                Obj = event.GetEventObject()
727                rbId,imag = Indx[Obj.GetId()]
728                try:
729                    val = float(Obj.GetValue())
730                    if val <= 0.:
731                        raise ValueError
732                    rbData['VectMag'][imag] = val
733                except ValueError:
734                    pass
735                Obj.SetValue('%8.3f'%(val))
736                UpdateVectorRB()
737                G2plt.PlotRigidBody(G2frame,'Vector',data['Vector'][rbId],plotDefaults)
738               
739            def OnRBVectorRef(event):
740                Obj = event.GetEventObject()
741                rbId,imag = Indx[Obj.GetId()]
742                rbData['VectRef'][imag] = Obj.GetValue()
743                       
744            magSizer = wx.wx.BoxSizer(wx.HORIZONTAL)
745            magSizer.Add(wx.StaticText(VectorRBDisplay,-1,'Translation magnitude: '),
746                0,wx.ALIGN_CENTER_VERTICAL)
747            magValue = wx.TextCtrl(VectorRBDisplay,-1,'%8.3f'%(rbData['VectMag'][imag]))
748            Indx[magValue.GetId()] = [rbId,imag]
749            magValue.Bind(wx.EVT_TEXT_ENTER,OnRBVectorMag)
750            magValue.Bind(wx.EVT_KILL_FOCUS,OnRBVectorMag)
751            magSizer.Add(magValue,0,wx.ALIGN_CENTER_VERTICAL)
752            magSizer.Add((5,0),)
753            magref = wx.CheckBox(VectorRBDisplay,-1,label=' Refine?') 
754            magref.SetValue(rbData['VectRef'][imag])
755            magref.Bind(wx.EVT_CHECKBOX,OnRBVectorRef)
756            Indx[magref.GetId()] = [rbId,imag]
757            magSizer.Add(magref,0,wx.ALIGN_CENTER_VERTICAL)
758            return magSizer
759           
760        def OnRBVectorVal(event):
761            Obj = event.GetEventObject()
762            rbId,imag,i = Indx[Obj.GetId()]
763            try:
764                val = float(Obj.GetValue())
765                data['Vector'][rbId]['rbVect'][imag][i] = val
766            except ValueError:
767                pass
768            UpdateVectorRB()
769            G2plt.PlotRigidBody(G2frame,'Vector',data['Vector'][rbId],plotDefaults)
770           
771        def rbVectors(rbId,imag,mag,XYZ,rbData):
772
773            def TypeSelect(event):
774                r,c = event.GetRow(),event.GetCol()
775                if vecGrid.GetColLabelValue(c) == 'Type':
776                    PE = G2elemGUI.PickElement(G2frame,oneOnly=True)
777                    if PE.ShowModal() == wx.ID_OK:
778                        if PE.Elem != 'None':
779                            El = PE.Elem.strip().lower().capitalize()
780                            if El not in rbData['rbRadii']:
781                                rbData['rbRadii'][El] = G2elem.GetAtomInfo(El)['Drad']                           
782                            rbData['rbTypes'][r] = El
783                            vecGrid.SetCellValue(r,c,El)
784                    PE.Destroy()
785
786            def ChangeCell(event):
787                r,c =  event.GetRow(),event.GetCol()
788                if r >= 0 and (0 <= c < 3):
789                    try:
790                        val = float(vecGrid.GetCellValue(r,c))
791                        rbData['rbVect'][imag][r][c] = val
792                    except ValueError:
793                        pass
794                wx.CallAfter(UpdateVectorRB)
795
796            vecSizer = wx.BoxSizer()
797            Types = 3*[wg.GRID_VALUE_FLOAT+':10,5',]+[wg.GRID_VALUE_STRING,]+3*[wg.GRID_VALUE_FLOAT+':10,5',]
798            colLabels = ['Vector x','Vector y','Vector z','Type','Cart x','Cart y','Cart z']
799            table = []
800            rowLabels = []
801            for ivec,xyz in enumerate(rbData['rbVect'][imag]):
802                table.append(list(xyz)+[rbData['rbTypes'][ivec],]+list(XYZ[ivec]))
803                rowLabels.append(str(ivec))
804            vecTable = G2gd.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
805            vecGrid = G2gd.GSGrid(VectorRBDisplay)
806            vecGrid.SetTable(vecTable, True)
807            vecGrid.Bind(wg.EVT_GRID_CELL_CHANGE, ChangeCell)
808            vecGrid.Bind(wg.EVT_GRID_CELL_LEFT_DCLICK, TypeSelect)
809            attr = wx.grid.GridCellAttr()
810            attr.SetEditor(G2phG.GridFractionEditor(vecGrid))
811            for c in range(3):
812                vecGrid.SetColAttr(c, attr)
813            for row in range(vecTable.GetNumberRows()):
814                for col in [4,5,6]:
815                    vecGrid.SetCellStyle(row,col,VERY_LIGHT_GREY,True)
816            vecSizer.Add(vecGrid)
817            return vecSizer
818       
819        VectorRB.DestroyChildren()
820        VectorRBDisplay = wx.Panel(VectorRB)
821        VectorRBSizer = wx.BoxSizer(wx.VERTICAL)
822        for rbId in data['Vector']:
823            rbData = data['Vector'][rbId]
824            VectorRBSizer.Add(rbNameSizer(rbId,rbData),0)
825            XYZ = np.array([[0.,0.,0.] for Ty in rbData['rbTypes']])
826            for imag,mag in enumerate(rbData['VectMag']):
827                XYZ += mag*rbData['rbVect'][imag]
828                VectorRBSizer.Add(rbVectMag(rbId,imag,rbData),0)
829                VectorRBSizer.Add(rbVectors(rbId,imag,mag,XYZ,rbData),0)
830            VectorRBSizer.Add((5,5),0)       
831        VectorRBSizer.Layout()   
832        VectorRBDisplay.SetSizer(VectorRBSizer,True)
833        Size = VectorRBSizer.GetMinSize()
834        Size[0] += 40
835        Size[1] = max(Size[1],250) + 20
836        VectorRBDisplay.SetSize(Size)
837        VectorRB.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
838#        Size[1] = min(Size[1],450)
839        G2frame.dataFrame.setSizePosLeft(Size)
840       
841    def UpdateResidueRB():
842        ResidueRB.DestroyChildren()
843        ResidueRBDisplay = wx.Panel(ResidueRB)
844        ResidueRBSizer = wx.BoxSizer(wx.VERTICAL)
845        ResidueRBSizer.Add((5,5),0)       
846#        VectorRBSizer.Add(ConstSizer('Phase',PhaseDisplay))
847        ResidueRBSizer.Layout()   
848        ResidueRBDisplay.SetSizer(ResidueRBSizer,True)
849        Size = ResidueRBSizer.GetMinSize()
850        Size[0] += 40
851        Size[1] = max(Size[1],250) + 20
852        ResidueRBDisplay.SetSize(Size)
853        ResidueRB.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
854#        Size[1] = min(Size[1],250)
855        G2frame.dataFrame.setSizePosLeft(Size)
856       
857    def UpdateZMatrixRB():
858        ZMatrixRB.DestroyChildren()
859        ZMatrixRBDisplay = wx.Panel(ZMatrixRB)
860        ZMatrixRBSizer = wx.BoxSizer(wx.VERTICAL)
861        ZMatrixRBSizer.Add((5,5),0)       
862#        ZMatrixRBSizer.Add(ConstSizer('Phase',PhaseDisplay))
863        ZMatrixRBSizer.Layout()   
864        ZMatrixRBDisplay.SetSizer(ZMatrixRBSizer,True)
865        Size = ZMatrixRBSizer.GetMinSize()
866        Size[0] += 40
867        Size[1] = max(Size[1],250) + 20
868        ZMatrixRBDisplay.SetSize(Size)
869        ZMatrixRB.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
870#        Size[1] = min(Size[1],250)
871        G2frame.dataFrame.setSizePosLeft(Size)
872
873    def SetStatusLine(text):
874        Status.SetStatusText(text)                                     
875
876    if G2frame.dataDisplay:
877        G2frame.dataDisplay.Destroy()
878    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.RigidBodyMenu)
879    G2frame.dataFrame.SetLabel('Rigid bodies')
880    if not G2frame.dataFrame.GetStatusBar():
881        Status = G2frame.dataFrame.CreateStatusBar()
882    SetStatusLine('')
883
884    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.RigidBodyMenu)
885    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddRigidBody, id=G2gd.wxID_RIGIDBODYADD)   
886    G2frame.dataDisplay = G2gd.GSNoteBook(parent=G2frame.dataFrame,size=G2frame.dataFrame.GetClientSize())
887
888    VectorRB = wx.ScrolledWindow(G2frame.dataDisplay)
889    G2frame.dataDisplay.AddPage(VectorRB,'Vector rigid bodies')
890    ResidueRB = wx.ScrolledWindow(G2frame.dataDisplay)
891    G2frame.dataDisplay.AddPage(ResidueRB,'Residue rigid bodies')
892    ZMatrix = wx.ScrolledWindow(G2frame.dataDisplay)
893    G2frame.dataDisplay.AddPage(ZMatrix,'Z-matrix rigid bodies')
894    UpdateVectorRB()
895   
Note: See TracBrowser for help on using the repository browser.