source: trunk/GSASIIconstrGUI.py @ 836

Last change on this file since 836 was 836, checked in by vondreele, 9 years ago

finish restraint rigid body input & display

File size: 49.6 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':{'AtInfo':{}},'Residue':{'AtInfo':{}},'Z-matrix':{'AtInfo':{}}})       #empty dict - fill it
629           
630    Indx = {}
631    plotDefaults = {'oldxy':[0.,0.],'Quaternion':[1.,0.,0.,0.],'cameraPos':30.,'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 getMacroFile(macName):
651        defDir = os.path.join(os.path.split(__file__)[0],'GSASIImacros')
652        dlg = wx.FileDialog(G2frame,message='Choose '+macName+' rigid body macro file',
653            defaultDir=defDir,defaultFile="",wildcard="GSAS-II macro file (*.mac)|*.mac",
654            style=wx.OPEN | wx.CHANGE_DIR)
655        try:
656            if dlg.ShowModal() == wx.ID_OK:
657                macfile = dlg.GetPath()
658                macro = open(macfile,'Ur')
659                head = macro.readline()
660                if macName not in head:
661                    print head
662                    print '**** ERROR - wrong restraint macro file selected, try again ****'
663                    macro = []
664            else: # cancel was pressed
665                macxro = []
666        finally:
667            dlg.Destroy()
668        return macro        #advanced past 1st line
669       
670    def OnAddRigidBody(event):
671        page = G2frame.dataDisplay.GetSelection()
672        if 'Vector' in G2frame.dataDisplay.GetPageText(page):
673            AddVectorRB()
674        elif 'Residue' in G2frame.dataDisplay.GetPageText(page):
675            AddResidueRB()
676        elif 'Z-matrix' in G2frame.dataDisplay.GetPageText(page):
677            AddZMatrixRB()
678           
679    def AddVectorRB():
680        AtInfo = data['Vector']['AtInfo']
681        dlg = MultiIntegerDialog(G2frame.dataDisplay,'New Rigid Body',['No. atoms','No. translations'],[1,1])
682        if dlg.ShowModal() == wx.ID_OK:
683            nAtoms,nTrans = dlg.GetValues()
684            vectorRB = data['Vector']
685            rbId = ran.randint(0,sys.maxint)
686            vecMag = [1.0 for i in range(nTrans)]
687            vecRef = [False for i in range(nTrans)]
688            vecVal = [np.zeros((nAtoms,3)) for j in range(nTrans)]
689            rbTypes = ['C' for i in range(nAtoms)]
690            Info = G2elem.GetAtomInfo('C')
691            AtInfo['C'] = [Info['Drad'],Info['Color']]
692            data['Vector'][rbId] = {'RBname':'UNKRB','VectMag':vecMag,
693                'VectRef':vecRef,'rbTypes':rbTypes,'rbVect':vecVal}
694        dlg.Destroy()
695        UpdateVectorRB()
696       
697    def AddResidueRB():
698        AtInfo = data['Residue']['AtInfo']
699        macro = getMacroFile('rigid body')
700        if not macro:
701            return
702        macStr = macro.readline()
703        while macStr:
704            items = macStr.split()
705            if 'I' == items[0]:
706                rbId = ran.randint(0,sys.maxint)
707                rbName = items[1]
708                rbTypes = []
709                rbXYZ = []
710                rbSeq = []
711                atNames = []
712                nAtms,nSeq,nOrig,mRef,nRef = [int(items[i]) for i in [2,3,4,5,6]]
713                for iAtm in range(nAtms):
714                    macStr = macro.readline().split()
715                    atName = macStr[0]
716                    atType = macStr[1]
717                    atNames.append(atName)
718                    rbXYZ.append([float(macStr[i]) for i in [2,3,4]])
719                    rbTypes.append(atType)
720                    if atType not in AtInfo:
721                        Info = G2elem.GetAtomInfo(atType)
722                        AtInfo[atType] = [Info['Drad'],Info['Color']]
723                rbXYZ = np.array(rbXYZ)-np.array(rbXYZ[nOrig-1])
724                for iSeq in range(nSeq):
725                    macStr = macro.readline().split()
726                    mSeq = int(macStr[0])
727                    rbseq = []
728                    for jSeq in range(mSeq):
729                        macStr = macro.readline().split()
730                        iBeg = int(macStr[0])-1
731                        iFin = int(macStr[1])-1
732                        angle = 0.0
733                        nMove = int(macStr[2])
734                        iMove = [int(macStr[i])-1 for i in range(3,nMove+3)]
735                        rbseq.append([iBeg,iFin,angle,iMove])
736                    rbSeq.append(rbseq)
737                data['Residue'][rbId] = {'RBname':rbName,'rbXYZ':rbXYZ,'rbTypes':rbTypes,
738                    'atNames':atNames,'rbRef':[nOrig-1,mRef-1,nRef-1],'rbSeq':rbSeq,'SelSeq':[0,0,0]}
739                print 'Residue '+rbName+' added'
740            macStr = macro.readline()
741        macro.close()
742        UpdateResidueRB()
743       
744    def AddZMatrixRB():
745        pass
746
747    def UpdateVectorRB():
748        AtInfo = data['Vector']['AtInfo']
749        SetStatusLine(' You may use e.g. "sind(60)", "cos(60)", "c60" or "s60" for a vector entry')
750        def rbNameSizer(rbId,rbData):
751
752            def OnRBName(event):
753                Obj = event.GetEventObject()
754                rbId = Indx[Obj.GetId()]
755                rbData['RBname'] = Obj.GetValue()
756               
757            def OnDelRB(event):
758                Obj = event.GetEventObject()
759                rbId = Indx[Obj.GetId()]
760                del data['Vector'][rbId]
761                wx.CallAfter(UpdateVectorRB)
762               
763            def OnPlotRB(event):
764                Obj = event.GetEventObject()
765                rbId = Indx[Obj.GetId()]
766                Obj.SetValue(False)
767                G2plt.PlotRigidBody(G2frame,'Vector',AtInfo,rbData,plotDefaults)
768           
769            nameSizer = wx.BoxSizer(wx.HORIZONTAL)
770            nameSizer.Add(wx.StaticText(VectorRBDisplay,-1,'Rigid body name: '),
771                0,wx.ALIGN_CENTER_VERTICAL)
772            RBname = wx.TextCtrl(VectorRBDisplay,-1,rbData['RBname'])
773            Indx[RBname.GetId()] = rbId
774            RBname.Bind(wx.EVT_TEXT_ENTER,OnRBName)
775            RBname.Bind(wx.EVT_KILL_FOCUS,OnRBName)
776            nameSizer.Add(RBname,0,wx.ALIGN_CENTER_VERTICAL)
777            nameSizer.Add((5,0),)
778            plotRB = wx.CheckBox(VectorRBDisplay,-1,'Plot?')
779            Indx[plotRB.GetId()] = rbId
780            plotRB.Bind(wx.EVT_CHECKBOX,OnPlotRB)
781            nameSizer.Add(plotRB,0,wx.ALIGN_CENTER_VERTICAL)
782            nameSizer.Add((5,0),)
783            delRB = wx.CheckBox(VectorRBDisplay,-1,'Delete?')
784            Indx[delRB.GetId()] = rbId
785            delRB.Bind(wx.EVT_CHECKBOX,OnDelRB)
786            nameSizer.Add(delRB,0,wx.ALIGN_CENTER_VERTICAL)
787            return nameSizer
788           
789        def rbVectMag(rbId,imag,rbData):
790           
791            def OnRBVectorMag(event):
792                Obj = event.GetEventObject()
793                rbId,imag = Indx[Obj.GetId()]
794                try:
795                    val = float(Obj.GetValue())
796                    if val <= 0.:
797                        raise ValueError
798                    rbData['VectMag'][imag] = val
799                except ValueError:
800                    pass
801                Obj.SetValue('%8.3f'%(val))
802                UpdateVectorRB()
803                G2plt.PlotRigidBody(G2frame,'Vector',AtInfo,data['Vector'][rbId],plotDefaults)
804               
805            def OnRBVectorRef(event):
806                Obj = event.GetEventObject()
807                rbId,imag = Indx[Obj.GetId()]
808                rbData['VectRef'][imag] = Obj.GetValue()
809                       
810            magSizer = wx.wx.BoxSizer(wx.HORIZONTAL)
811            magSizer.Add(wx.StaticText(VectorRBDisplay,-1,'Translation magnitude: '),
812                0,wx.ALIGN_CENTER_VERTICAL)
813            magValue = wx.TextCtrl(VectorRBDisplay,-1,'%8.3f'%(rbData['VectMag'][imag]))
814            Indx[magValue.GetId()] = [rbId,imag]
815            magValue.Bind(wx.EVT_TEXT_ENTER,OnRBVectorMag)
816            magValue.Bind(wx.EVT_KILL_FOCUS,OnRBVectorMag)
817            magSizer.Add(magValue,0,wx.ALIGN_CENTER_VERTICAL)
818            magSizer.Add((5,0),)
819            magref = wx.CheckBox(VectorRBDisplay,-1,label=' Refine?') 
820            magref.SetValue(rbData['VectRef'][imag])
821            magref.Bind(wx.EVT_CHECKBOX,OnRBVectorRef)
822            Indx[magref.GetId()] = [rbId,imag]
823            magSizer.Add(magref,0,wx.ALIGN_CENTER_VERTICAL)
824            return magSizer
825           
826        def rbVectors(rbId,imag,mag,XYZ,rbData):
827
828            def TypeSelect(event):
829                AtInfo = data['Vector']['AtInfo']
830                r,c = event.GetRow(),event.GetCol()
831                if vecGrid.GetColLabelValue(c) == 'Type':
832                    PE = G2elemGUI.PickElement(G2frame,oneOnly=True)
833                    if PE.ShowModal() == wx.ID_OK:
834                        if PE.Elem != 'None':
835                            El = PE.Elem.strip().lower().capitalize()
836                            if El not in AtInfo:
837                                Info = G2elem.GetAtomInfo(El)
838                                AtInfo[El] = [Info['Drad']['Color']]
839                            rbData['rbTypes'][r] = El
840                            vecGrid.SetCellValue(r,c,El)
841                    PE.Destroy()
842
843            def ChangeCell(event):
844                r,c =  event.GetRow(),event.GetCol()
845                if r >= 0 and (0 <= c < 3):
846                    try:
847                        val = float(vecGrid.GetCellValue(r,c))
848                        rbData['rbVect'][imag][r][c] = val
849                    except ValueError:
850                        pass
851                wx.CallAfter(UpdateVectorRB)
852
853            vecSizer = wx.BoxSizer()
854            Types = 3*[wg.GRID_VALUE_FLOAT+':10,5',]+[wg.GRID_VALUE_STRING,]+3*[wg.GRID_VALUE_FLOAT+':10,5',]
855            colLabels = ['Vector x','Vector y','Vector z','Type','Cart x','Cart y','Cart z']
856            table = []
857            rowLabels = []
858            for ivec,xyz in enumerate(rbData['rbVect'][imag]):
859                table.append(list(xyz)+[rbData['rbTypes'][ivec],]+list(XYZ[ivec]))
860                rowLabels.append(str(ivec))
861            vecTable = G2gd.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
862            vecGrid = G2gd.GSGrid(VectorRBDisplay)
863            vecGrid.SetTable(vecTable, True)
864            vecGrid.Bind(wg.EVT_GRID_CELL_CHANGE, ChangeCell)
865            vecGrid.Bind(wg.EVT_GRID_CELL_LEFT_DCLICK, TypeSelect)
866            attr = wx.grid.GridCellAttr()
867            attr.SetEditor(G2phG.GridFractionEditor(vecGrid))
868            for c in range(3):
869                vecGrid.SetColAttr(c, attr)
870            for row in range(vecTable.GetNumberRows()):
871                for col in [4,5,6]:
872                    vecGrid.SetCellStyle(row,col,VERY_LIGHT_GREY,True)
873            vecGrid.SetMargins(0,0)
874            vecGrid.AutoSizeColumns(False)
875            vecSizer.Add(vecGrid)
876            return vecSizer
877       
878        VectorRB.DestroyChildren()
879        VectorRBDisplay = wx.Panel(VectorRB)
880        VectorRBSizer = wx.BoxSizer(wx.VERTICAL)
881        for rbId in data['Vector']:
882            if rbId != 'AtInfo':
883                rbData = data['Vector'][rbId]
884                VectorRBSizer.Add(rbNameSizer(rbId,rbData),0)
885                XYZ = np.array([[0.,0.,0.] for Ty in rbData['rbTypes']])
886                for imag,mag in enumerate(rbData['VectMag']):
887                    XYZ += mag*rbData['rbVect'][imag]
888                    VectorRBSizer.Add(rbVectMag(rbId,imag,rbData),0)
889                    VectorRBSizer.Add(rbVectors(rbId,imag,mag,XYZ,rbData),0)
890                VectorRBSizer.Add((5,5),0)       
891        VectorRBSizer.Layout()   
892        VectorRBDisplay.SetSizer(VectorRBSizer,True)
893        Size = VectorRBSizer.GetMinSize()
894        Size[0] += 40
895        Size[1] = max(Size[1],250) + 20
896        VectorRBDisplay.SetSize(Size)
897        VectorRB.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
898#        Size[1] = min(Size[1],450)
899        G2frame.dataFrame.setSizePosLeft(Size)
900       
901    def UpdateResidueRB():
902        AtInfo = data['Residue']['AtInfo']
903        Indx = {}
904
905        def rbNameSizer(rbId,rbData):
906
907            def OnRBName(event):
908                Obj = event.GetEventObject()
909                rbId = Indx[Obj.GetId()]
910                rbData['RBname'] = Obj.GetValue()
911               
912            def OnDelRB(event):
913                Obj = event.GetEventObject()
914                rbId = Indx[Obj.GetId()]
915                del data['Residue'][rbId]
916                wx.CallAfter(UpdateResidueRB)
917               
918            def OnPlotRB(event):
919                Obj = event.GetEventObject()
920                rbId = Indx[Obj.GetId()]
921                Obj.SetValue(False)
922                G2plt.PlotRigidBody(G2frame,'Residue',AtInfo,rbData,plotDefaults)
923           
924            nameSizer = wx.BoxSizer(wx.HORIZONTAL)
925            nameSizer.Add(wx.StaticText(ResidueRBDisplay,-1,'Residue name: '),
926                0,wx.ALIGN_CENTER_VERTICAL)
927            RBname = wx.TextCtrl(ResidueRBDisplay,-1,rbData['RBname'])
928            Indx[RBname.GetId()] = rbId
929            RBname.Bind(wx.EVT_TEXT_ENTER,OnRBName)
930            RBname.Bind(wx.EVT_KILL_FOCUS,OnRBName)
931            nameSizer.Add(RBname,0,wx.ALIGN_CENTER_VERTICAL)
932            nameSizer.Add((5,0),)
933            plotRB = wx.CheckBox(ResidueRBDisplay,-1,'Plot?')
934            Indx[plotRB.GetId()] = rbId
935            plotRB.Bind(wx.EVT_CHECKBOX,OnPlotRB)
936            nameSizer.Add(plotRB,0,wx.ALIGN_CENTER_VERTICAL)
937            nameSizer.Add((5,0),)
938            delRB = wx.CheckBox(ResidueRBDisplay,-1,'Delete?')
939            Indx[delRB.GetId()] = rbId
940            delRB.Bind(wx.EVT_CHECKBOX,OnDelRB)
941            nameSizer.Add(delRB,0,wx.ALIGN_CENTER_VERTICAL)
942            return nameSizer
943           
944        def rbResidues(rbId,XYZ,rbData):
945           
946            def TypeSelect(event):
947                AtInfo = data['Residue']['AtInfo']
948                r,c = event.GetRow(),event.GetCol()
949                if vecGrid.GetColLabelValue(c) == 'Type':
950                    PE = G2elemGUI.PickElement(G2frame,oneOnly=True)
951                    if PE.ShowModal() == wx.ID_OK:
952                        if PE.Elem != 'None':
953                            El = PE.Elem.strip().lower().capitalize()
954                            if El not in AtInfo:
955                                Info = G2elem.GetAtomInfo(El)
956                                AtInfo[El] = [Info['Drad']['Color']]
957                            rbData['rbTypes'][r] = El
958                            vecGrid.SetCellValue(r,c,El)
959                    PE.Destroy()
960
961            def ChangeCell(event):
962                r,c =  event.GetRow(),event.GetCol()
963                if r >= 0 and (0 <= c < 3):
964                    try:
965                        val = float(vecGrid.GetCellValue(r,c))
966                        rbData['rbVect'][imag][r][c] = val
967                    except ValueError:
968                        pass
969
970            vecSizer = wx.BoxSizer()
971            Types = 2*[wg.GRID_VALUE_STRING,]+3*[wg.GRID_VALUE_FLOAT+':10,5',]
972            colLabels = ['Name','Type','Cart x','Cart y','Cart z']
973            table = []
974            rowLabels = []
975            for ivec,xyz in enumerate(rbData['rbXYZ']):
976                table.append([rbData['atNames'][ivec],]+[rbData['rbTypes'][ivec],]+list(xyz))
977                rowLabels.append(str(ivec))
978            vecTable = G2gd.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
979            vecGrid = G2gd.GSGrid(ResidueRBDisplay)
980            vecGrid.SetTable(vecTable, True)
981            vecGrid.Bind(wg.EVT_GRID_CELL_CHANGE, ChangeCell)
982            vecGrid.Bind(wg.EVT_GRID_CELL_LEFT_DCLICK, TypeSelect)
983            attr = wx.grid.GridCellAttr()
984            attr.SetEditor(G2phG.GridFractionEditor(vecGrid))
985            for c in range(3):
986                vecGrid.SetColAttr(c, attr)
987            for row in range(vecTable.GetNumberRows()):
988                for col in [4,5,6]:
989                    vecGrid.SetCellStyle(row,col,VERY_LIGHT_GREY,True)
990            vecGrid.SetMargins(0,0)
991            vecGrid.AutoSizeColumns(False)
992            vecSizer.Add(vecGrid)
993            return vecSizer
994           
995        def SeqSizer(angSlide,rbId,iSeq,Seq,atNames):
996           
997            def ChangeAngle(event):
998                Obj = event.GetEventObject()
999                rbId,iSeq,iseq,Seq = Indx[Obj.GetId()]
1000                val = Seq[iseq][2]
1001                try:
1002                    val = float(Obj.GetValue())
1003                    Seq[iseq][2] = val
1004                except ValueError:
1005                    pass
1006                Obj.SetValue('%8.2f'%(val))
1007                G2plt.PlotRigidBody(G2frame,'Residue',AtInfo,data['Residue'][rbId],plotDefaults)
1008               
1009            def OnRadBtn(event):
1010                Obj = event.GetEventObject()
1011                isel,Seq,iSeq,ang = Indx[Obj.GetId()]
1012                data['Residue'][rbId]['SelSeq'] = [iSeq,isel,ang]
1013                angSlide.SetValue(int(100*Seq[isel][2]))
1014           
1015            seqSizer = wx.FlexGridSizer(0,4,2,2)
1016            seqSizer.AddGrowableCol(3,0)
1017            for isel,sel in enumerate(Seq):
1018                iBeg,iFin,angle,iMove = sel
1019                ang = wx.TextCtrl(ResidueRBDisplay,-1,'%8.2f'%(angle),size=(50,20))
1020                if not iSeq:
1021                    radBt = wx.RadioButton(ResidueRBDisplay,-1,'',style=wx.RB_GROUP)
1022                    data['Residue'][rbId]['SelSeq'] = [iSeq,isel,ang]
1023                else:
1024                    radBt = wx.RadioButton(ResidueRBDisplay,-1,'')
1025                radBt.Bind(wx.EVT_RADIOBUTTON,OnRadBtn)                   
1026                seqSizer.Add(radBt)
1027                bond = wx.TextCtrl(ResidueRBDisplay,-1,'%s %s'%(atNames[iBeg],atNames[iFin]),size=(50,20))
1028                seqSizer.Add(bond,0,wx.ALIGN_CENTER_VERTICAL)
1029                Indx[radBt.GetId()] = [isel,Seq,iSeq,ang]
1030                Indx[ang.GetId()] = [rbId,iSeq,isel,Seq]
1031                ang.Bind(wx.EVT_TEXT_ENTER,ChangeAngle)
1032                ang.Bind(wx.EVT_KILL_FOCUS,ChangeAngle)
1033                seqSizer.Add(ang,0,wx.ALIGN_CENTER_VERTICAL)
1034                atms = ''
1035                for i in iMove:   
1036                    atms += ' %s,'%(atNames[i])
1037                moves = wx.TextCtrl(ResidueRBDisplay,-1,atms[:-1],size=(200,20))
1038                seqSizer.Add(moves,1,wx.ALIGN_CENTER_VERTICAL|wx.EXPAND|wx.RIGHT)
1039            return seqSizer
1040           
1041        def SlideSizer():
1042           
1043            def OnSlider(event):
1044                Obj = event.GetEventObject()
1045                rbData = Indx[Obj.GetId()]
1046                iSeq,isel,ang = rbData['SelSeq']
1047                val = float(Obj.GetValue())/100.
1048                rbData['rbSeq'][iSeq][isel][2] = val
1049                ang.SetValue('%8.2f'%(val))
1050                G2plt.PlotRigidBody(G2frame,'Residue',AtInfo,rbData,plotDefaults)
1051           
1052            slideSizer = wx.BoxSizer(wx.HORIZONTAL)
1053            slideSizer.Add(wx.StaticText(ResidueRBDisplay,-1,'Selected torsion angle:'),0)
1054            iSeq,isel,ang = rbData['SelSeq']
1055            angSlide = wx.Slider(ResidueRBDisplay,-1,
1056                int(100*rbData['rbSeq'][iSeq][isel][2]),0,36000,size=(200,20),
1057                style=wx.SL_HORIZONTAL)
1058            angSlide.Bind(wx.EVT_SLIDER, OnSlider)
1059            Indx[angSlide.GetId()] = rbData
1060            slideSizer.Add(angSlide,0)           
1061            return slideSizer,angSlide           
1062           
1063        ResidueRB.DestroyChildren()
1064        ResidueRBDisplay = wx.Panel(ResidueRB)
1065        ResidueRBSizer = wx.BoxSizer(wx.VERTICAL)
1066        rbKeys = data['Residue'].keys()
1067        rbKeys.remove('AtInfo')
1068        rbNames = [data['Residue'][k]['RBname'] for k in rbKeys]
1069        rbIds = dict(zip(rbNames,rbKeys))
1070        rbNames.sort()
1071        for name in rbNames:
1072            rbId = rbIds[name]
1073            rbData = data['Residue'][rbId]
1074            ResidueRBSizer.Add(rbNameSizer(rbId,rbData),0)
1075            XYZ = np.array([[0.,0.,0.] for Ty in rbData['rbTypes']])
1076            ResidueRBSizer.Add(rbResidues(rbId,XYZ,rbData),0)
1077            ResidueRBSizer.Add((5,5),0)
1078            slideSizer,angSlide = SlideSizer()
1079            for iSeq,Seq in enumerate(rbData['rbSeq']):
1080                ResidueRBSizer.Add(wx.StaticText(ResidueRBDisplay,-1,'Seq: %d'%(iSeq)),
1081                    0,wx.ALIGN_CENTER_VERTICAL)
1082                ResidueRBSizer.Add(wx.StaticText(ResidueRBDisplay,-1,
1083                    'Sel  Bond             Angle      Riding atoms'),
1084                    0,wx.ALIGN_CENTER_VERTICAL)                       
1085                ResidueRBSizer.Add(SeqSizer(angSlide,rbId,iSeq,Seq,rbData['atNames']))
1086            ResidueRBSizer.Add(slideSizer,)
1087        ResidueRBSizer.Add((5,25),)
1088        ResidueRBSizer.Layout()   
1089        ResidueRBDisplay.SetSizer(ResidueRBSizer,True)
1090        Size = ResidueRBSizer.GetMinSize()
1091        Size[0] += 40
1092        Size[1] = max(Size[1],250) + 20
1093        ResidueRBDisplay.SetSize(Size)
1094        ResidueRB.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
1095        G2frame.dataFrame.setSizePosLeft(Size)
1096       
1097    def UpdateZMatrixRB():
1098        ZMatrixRB.DestroyChildren()
1099        ZMatrixRBDisplay = wx.Panel(ZMatrixRB)
1100        ZMatrixRBSizer = wx.BoxSizer(wx.VERTICAL)
1101        ZMatrixRBSizer.Add((5,5),0)       
1102#        ZMatrixRBSizer.Add(ConstSizer('Phase',PhaseDisplay))
1103        ZMatrixRBSizer.Layout()   
1104        ZMatrixRBDisplay.SetSizer(ZMatrixRBSizer,True)
1105        Size = ZMatrixRBSizer.GetMinSize()
1106        Size[0] += 40
1107        Size[1] = max(Size[1],250) + 20
1108        ZMatrixRBDisplay.SetSize(Size)
1109        ZMatrixRB.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
1110#        Size[1] = min(Size[1],250)
1111        G2frame.dataFrame.setSizePosLeft(Size)
1112
1113    def SetStatusLine(text):
1114        Status.SetStatusText(text)                                     
1115
1116    if G2frame.dataDisplay:
1117        G2frame.dataDisplay.Destroy()
1118    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.RigidBodyMenu)
1119    G2frame.dataFrame.SetLabel('Rigid bodies')
1120    if not G2frame.dataFrame.GetStatusBar():
1121        Status = G2frame.dataFrame.CreateStatusBar()
1122    SetStatusLine('')
1123
1124    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.RigidBodyMenu)
1125    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddRigidBody, id=G2gd.wxID_RIGIDBODYADD)   
1126    G2frame.dataDisplay = G2gd.GSNoteBook(parent=G2frame.dataFrame,size=G2frame.dataFrame.GetClientSize())
1127
1128    VectorRB = wx.ScrolledWindow(G2frame.dataDisplay)
1129    G2frame.dataDisplay.AddPage(VectorRB,'Vector rigid bodies')
1130    ResidueRB = wx.ScrolledWindow(G2frame.dataDisplay)
1131    G2frame.dataDisplay.AddPage(ResidueRB,'Residue rigid bodies')
1132    ZMatrix = wx.ScrolledWindow(G2frame.dataDisplay)
1133    G2frame.dataDisplay.AddPage(ZMatrix,'Z-matrix rigid bodies')
1134    UpdateVectorRB()
1135   
Note: See TracBrowser for help on using the repository browser.