source: trunk/GSASIIrestrGUI.py @ 814

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

implement hot keys for some main menu & menu items
fix crash in general
put a status item in as a reminder for peak fitting options
continue restraint development

File size: 46.2 KB
Line 
1# -*- coding: utf-8 -*-
2#GSASIIrestr - restraint 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/GSASIIrestrGUI.py $
8# $Id: GSASIIrestrGUI.py 810 2012-12-05 21:38:26Z vondreele $
9########### SVN repository information ###################
10import wx
11import wx.grid as wg
12import time
13import numpy as np
14import numpy.ma as ma
15import os.path
16import GSASIIpath
17GSASIIpath.SetVersionNumber("$Revision: 810 $")
18import GSASIImath as G2mth
19import GSASIIlattice as G2lat
20import GSASIIphsGUI as G2phG
21import GSASIIspc as G2spc
22import GSASIIgrid as G2gd
23
24VERY_LIGHT_GREY = wx.Colour(235,235,235)
25
26################################################################################
27#####  Restraints
28################################################################################           
29       
30def UpdateRestraints(G2frame,data,Phases,phaseName):
31    if not len(Phases):
32        print 'There are no phases to form restraints'
33        return
34    phasedata = Phases[phaseName]
35    if phaseName not in data:
36        data[phaseName] = {}
37    restrData = data[phaseName]
38    if 'Bond' not in restrData:
39        restrData['Bond'] = {'wtFactor':1.0,'Bonds':[],'Use':True}
40    if 'Angle' not in restrData:
41        restrData['Angle'] = {'wtFactor':1.0,'Angles':[],'Use':True}
42    if 'Plane' not in restrData:
43        restrData['Plane'] = {'wtFactor':1.0,'Planes':[],'Use':True}
44    if 'Chiral' not in restrData:
45        restrData['Chiral'] = {'wtFactor':1.0,'Volumes':[],'Use':True}
46    if 'Torsion' not in restrData:
47        restrData['Torsion'] = {'wtFactor':1.0,'Coeff':{},'Torsions':[],'Use':True}
48    if 'Rama' not in restrData:
49        restrData['Rama'] = {'wtFactor':1.0,'Coeff':{},'Ramas':[],'Use':True}
50    General = phasedata['General']
51    Cell = General['Cell'][1:7]          #skip flag & volume   
52    Amat,Bmat = G2lat.cell2AB(Cell)
53    SGData = General['SGData']
54    cx,ct = General['AtomPtrs'][:2]
55    Atoms = phasedata['Atoms']
56    AtLookUp = G2mth.FillAtomLookUp(Atoms)
57    if 'macro' in General['Type']:
58        Names = [atom[0]+atom[1]+atom[2]+' '+atom[3] for atom in Atoms]
59        Ids = []
60        Coords = []
61        Types = []
62    else:   
63        Names = ['all '+ name for name in General['AtomTypes']]
64        iBeg = len(Names)
65        Types = [name for name in General['AtomTypes']]
66        Coords = [ [] for type in Types]
67        Ids = [ 0 for type in Types]
68        Names += [atom[ct-1] for atom in Atoms]
69    Types += [atom[ct] for atom in Atoms]
70    Coords += [atom[cx:cx+3] for atom in Atoms]
71    Ids += [atom[-1] for atom in Atoms]
72   
73    def OnSelectPhase(event):
74        dlg = wx.SingleChoiceDialog(G2frame,'Select','Phase',Phases.keys())
75        try:
76            if dlg.ShowModal() == wx.ID_OK:
77                phaseName = Phases.keys()[dlg.GetSelection()]
78                UpdateRestraints(G2frame,data,Phases,phaseName)
79        finally:
80            dlg.Destroy()
81   
82    def getMacroFile(macName):
83        defDir = os.path.join(os.path.split(__file__)[0],'GSASIImacros')
84        dlg = wx.FileDialog(G2frame,message='Choose '+macName+' restraint macro file',
85            defaultDir=defDir,defaultFile="",wildcard="GSAS-II macro file (*.mac)|*.mac",
86            style=wx.OPEN | wx.CHANGE_DIR)
87        try:
88            if dlg.ShowModal() == wx.ID_OK:
89                macfile = dlg.GetPath()
90                macro = open(macfile,'Ur')
91                head = macro.readline()
92                if macName not in head:
93                    print head
94                    print '**** ERROR - wrong restraint macro file selected, try again ****'
95                    macro = []
96            else: # cancel was pressed
97                macxro = []
98        finally:
99            dlg.Destroy()
100        return macro        #advanced past 1st line
101       
102    def OnAddRestraint(event):
103        page = G2frame.dataDisplay.GetSelection()
104        if 'Bond' in G2frame.dataDisplay.GetPageText(page):
105            bondRestData = restrData['Bond']
106            AddBondRestraint(bondRestData)
107        elif 'Angle' in G2frame.dataDisplay.GetPageText(page):
108            angleRestData = restrData['Angle']
109            AddAngleRestraint(angleRestData)
110        elif 'Plane' in G2frame.dataDisplay.GetPageText(page):
111            AddPlaneRestraint()
112        elif 'Chiral' in G2frame.dataDisplay.GetPageText(page):
113            AddChiralRestraint()
114        elif 'Torsion' in G2frame.dataDisplay.GetPageText(page):
115            AddTorsionRestraint()
116        elif 'Rama' in G2frame.dataDisplay.GetPageText(page):
117            AddRamaRestraint()
118           
119    def OnAddAARestraint(event):
120        page = G2frame.dataDisplay.GetSelection()
121        if 'Bond' in G2frame.dataDisplay.GetPageText(page):
122            bondRestData = restrData['Bond']
123            AddAABondRestraint(bondRestData)
124        elif 'Angle' in G2frame.dataDisplay.GetPageText(page):
125            angleRestData = restrData['Angle']
126            AddAAAngleRestraint(angleRestData)
127        elif 'Plane' in G2frame.dataDisplay.GetPageText(page):
128            AddAAPlaneRestraint()
129        elif 'Chiral' in G2frame.dataDisplay.GetPageText(page):
130            AddAAChiralRestraint()
131        elif 'Torsion' in G2frame.dataDisplay.GetPageText(page):
132            AddAATorsionRestraint()
133        elif 'Rama' in G2frame.dataDisplay.GetPageText(page):
134            AddAARamaRestraint()
135           
136    def AddBondRestraint(bondRestData):
137        Radii = dict(zip(General['AtomTypes'],General['BondRadii']))
138        Lists = {'origin':[],'target':[]}
139        for listName in ['origin','target']:
140            dlg = wx.MultiChoiceDialog(G2frame,'Bond restraint '+listName+' for '+General['Name'],
141                    'Select bond restraint '+listName+' atoms',Names)
142            if dlg.ShowModal() == wx.ID_OK:
143                sel = dlg.GetSelections()
144                for x in sel:
145                    if 'all' in Names[x]:
146                        allType = Types[x]
147                        for name,Type,coords,id in zip(Names,Types,Coords,Ids):
148                            if Type == allType and 'all' not in name:
149                                Lists[listName].append([id,Type,coords])
150                    else:
151                        Lists[listName].append([Ids[x],Types[x],Coords[x],])
152        Factor = .85
153        indices = (-1,0,1)
154        Units = np.array([[h,k,l] for h in indices for k in indices for l in indices])
155        origAtoms = Lists['origin']
156        targAtoms = Lists['target']
157        dlg = wx.ProgressDialog("Generating bond restraints","Processed origin atoms",len(origAtoms), 
158            style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_REMAINING_TIME)
159        try:
160            Norig = 0
161            for Oid,Otype,Ocoord in origAtoms:
162                Norig += 1
163                dlg.Update(Norig)
164                for Tid,Ttype,Tcoord in targAtoms:
165                    if 'macro' in General['Type']:
166                        result = [[Tcoord,1,[0,0,0]],]
167                    else:
168                        result = G2spc.GenAtom(Tcoord,SGData,False,Move=False)
169                    BsumR = (Radii[Otype]+Radii[Ttype])*Factor
170                    for Txyz,Top,Tunit in result:
171                        Dx = (Txyz-np.array(Ocoord))+Units
172                        dx = np.inner(Amat,Dx)
173                        dist = ma.masked_less(np.sqrt(np.sum(dx**2,axis=0)),0.5)
174                        IndB = ma.nonzero(ma.masked_greater(dist-BsumR,0.))
175                        if np.any(IndB):
176                            for indb in IndB:
177                                for i in range(len(indb)):
178                                    unit = Units[indb][i]+Tunit
179                                    if np.any(unit):
180                                        Topstr = '%d+%d,%d,%d'%(Top,unit[0],unit[1],unit[2])
181                                    else:
182                                        Topstr = str(Top)
183                                    newBond = [[Oid,Tid],['1',Topstr], \
184                                        ma.getdata(dist[indb])[i],1.54,0.01]
185                                    if newBond not in bondRestData['Bonds']:
186                                        bondRestData['Bonds'].append(newBond)
187        finally:
188            dlg.Destroy()
189        UpdateBondRestr(bondRestData)               
190
191    def AddAABondRestraint(bondRestData):
192        Radii = dict(zip(General['AtomTypes'],General['BondRadii']))
193        macro = getMacroFile('bond')
194        if not macro:
195            return
196        macStr = macro.readline()
197        atoms = zip(Names,Coords,Ids)
198       
199        Factor = .90
200        while macStr:
201            items = macStr.split()
202            if 'F' in items[0]:
203                restrData['Bond']['wtFactor'] = float(items[1])
204            elif 'S' in items[0]:
205                oIds = []
206                oCoords = []
207                tIds = []
208                tCoords = []
209                res = items[1]
210                dist = float(items[2])
211                esd = float(items[3])
212                oAtm,tAtm = items[4:6]
213                for Name,coords,Id in atoms:
214                    names = Name.split()
215                    if res == '*' or res in names[0]:
216                        if oAtm == names[2]:
217                            oIds.append(Id)
218                            oCoords.append(np.array(coords))
219                        if tAtm == names[2]:
220                            tIds.append(Id)
221                            tCoords.append(np.array(coords))
222                for i,[oId,oCoord] in enumerate(zip(oIds,oCoords)):
223                    for tId,tCoord in zip(tIds,tCoords)[i:]:
224                        obsd = np.sqrt(np.sum(np.inner(Amat,tCoord-oCoord)**2))
225                        if dist*Factor < obsd < dist/Factor:
226                            newBond = [[oId,tId],['1','1'],obsd,dist,esd]
227                            if newBond not in bondRestData['Bonds']:
228                                bondRestData['Bonds'].append(newBond)                         
229            macStr = macro.readline()
230        macro.close()
231        UpdateBondRestr(bondRestData)               
232           
233    def AddAngleRestraint(angleRestData):
234        Radii = dict(zip(General['AtomTypes'],zip(General['BondRadii'],General['AngleRadii'])))
235        origAtoms = []
236        dlg = wx.MultiChoiceDialog(G2frame,'Select atom B for angle A-B-C for '+General['Name'],
237                'Select angle restraint origin atoms',Names)
238        if dlg.ShowModal() == wx.ID_OK:
239            sel = dlg.GetSelections()
240            for x in sel:
241                if 'all' in Names[x]:
242                    allType = Types[x]
243                    for name,Type,coords,id in zip(Names,Types,Coords,Ids):
244                        if Type == allType and 'all' not in name:
245                            origAtoms.append([id,Type,coords])
246                else:
247                    origAtoms.append([Ids[x],Types[x],Coords[x]])
248        targAtoms = [[Ids[x+iBeg],Types[x+iBeg],Coords[x+iBeg]] for x in range(len(Names[iBeg:]))]
249
250        Factor = 1.0
251        indices = (-1,0,1)
252        Units = np.array([[h,k,l] for h in indices for k in indices for l in indices])
253        VectA = []
254        for Oid,Otype,Ocoord in origAtoms:
255            IndBlist = []
256            VectB = []
257            for Tid,Ttype,Tcoord in targAtoms:
258                result = G2spc.GenAtom(Tcoord,SGData,False,Move=False)
259                BsumR = (Radii[Otype][0]+Radii[Ttype][0])*Factor
260                AsumR = (Radii[Otype][1]+Radii[Ttype][1])*Factor
261                for Txyz,Top,Tunit in result:
262                    Dx = (Txyz-Ocoord)+Units
263                    dx = np.inner(Amat,Dx)
264                    dist = ma.masked_less(np.sqrt(np.sum(dx**2,axis=0)),0.5)
265                    IndB = ma.nonzero(ma.masked_greater(dist-BsumR,0.))
266                    if np.any(IndB):
267                        for indb in IndB:
268                            for i in range(len(indb)):
269                                if str(dx.T[indb][i]) not in IndBlist:
270                                    IndBlist.append(str(dx.T[indb][i]))
271                                    unit = Units[indb][i]+Tunit
272                                if np.any(unit):
273                                    Topstr = '%d+%d,%d,%d'%(Top,unit[0],unit[1],unit[2])
274                                else:
275                                    Topstr = str(Top)
276                                    tunit = '[%2d%2d%2d]'%(unit[0]+Tunit[0],unit[1]+Tunit[1],unit[2]+Tunit[2])
277                                    Dist = ma.getdata(dist[indb])[i]
278                                    if (Dist-AsumR) <= 0.:
279                                        VectB.append([Oid,'1',Ocoord,Tid,Topstr,Tcoord,Dist])
280            VectA.append(VectB)
281            for Vects in VectA:
282                for i,vecta in enumerate(Vects):                   
283                    for vectb in Vects[:i]:
284                        ids = [vecta[3],vecta[0],vectb[3]]
285                        ops = [vecta[4],vecta[1],vectb[4]]
286                        XYZ = np.array([vecta[5],vecta[2],vectb[5]])
287                        angle = G2mth.getRestAngle(XYZ,Amat)
288                        if angle not in angleRestData['Angles']:
289                            angleRestData['Angles'].append([ids,ops,angle,109.5,1.0])
290        UpdateAngleRestr(angleRestData)               
291
292    def AddAAAngleRestraint(angleRestData):
293        macro = getMacroFile('angle')
294        if not macro:
295            return
296        macStr = macro.readline()
297        while macStr:
298            items = macStr.split()
299            print items
300            if 'F' in items[0]:
301                restrData['Angle']['wtFactor'] = float(items[1])
302            elif 'S' in items[0]:
303                List = []
304                res = items[1]
305                dist = items[2]
306                esd = items[3]
307                oAtm = items[4]
308                tAtm = items[5]
309                for name,Type,coords,id in zip(Names,Types,Coords,Ids):
310                    if res == '*' or res in name:
311                        if oAtm in name:
312                            oCoord = coords
313                            oId = id
314                            oName = name
315                        elif tAtm in name:
316                            tCoord = coords
317                            tId = id
318                            tName = name
319               
320            macStr = macro.readline()
321        macro.close()
322        UpdateAngleRestr(angleRestData)               
323       
324    def AddPlaneRestraint():
325        origAtoms = []
326        dlg = wx.MultiChoiceDialog(G2frame,'Select atom B for angle A-B-C for '+General['Name'],
327                'Select angle restraint origin atoms',Names)
328        if dlg.ShowModal() == wx.ID_OK:
329            sel = dlg.GetSelections()
330            for x in sel:
331                if 'all' in Names[x]:
332                    allType = Types[x]
333                    for name,Type,coords,id in zip(Names,Types,Coords,Ids):
334                        if Type == allType and 'all' not in name:
335                            origAtoms.append([id,Type,coords])
336                else:
337                    origAtoms.append([Ids[x],Types[x],Coords[x]])
338
339    def AddAAPlaneRestraint():
340        macro = getMacroFile('plane')
341        if not macro:
342            return
343        macStr = macro.readline()
344        while macStr:
345            items = macStr.split()
346            print items
347            if 'F' in items[0]:
348                restrData['Plane']['wtFactor'] = float(items[1])
349            elif 'S' in items[0]:
350                List = []
351                res = items[1]
352                dist = items[2]
353                esd = items[3]
354                oAtm = items[4]
355                tAtm = items[5]
356                for name,Type,coords,id in zip(Names,Types,Coords,Ids):
357                    if res == '*' or res in name:
358                        if oAtm in name:
359                            oCoord = coords
360                            oId = id
361                            oName = name
362                        elif tAtm in name:
363                            tCoord = coords
364                            tId = id
365                            tName = name
366               
367            macStr = macro.readline()
368        macro.close()
369
370    def AddChiralRestraint():
371        print 'Chiral restraint'
372       
373    def AddAAChiralRestraint():
374        macro = getMacroFile('chiral')
375        if not macro:
376            return
377        macStr = macro.readline()
378        while macStr:
379            items = macStr.split()
380            print items
381            if 'F' in items[0]:
382                restrData['Chiral']['wtFactor'] = float(items[1])
383            elif 'S' in items[0]:
384                List = []
385                res = items[1]
386                dist = items[2]
387                esd = items[3]
388                oAtm = items[4]
389                tAtm = items[5]
390                for name,Type,coords,id in zip(Names,Types,Coords,Ids):
391                    if res == '*' or res in name:
392                        if oAtm in name:
393                            oCoord = coords
394                            oId = id
395                            oName = name
396                        elif tAtm in name:
397                            tCoord = coords
398                            tId = id
399                            tName = name
400               
401            macStr = macro.readline()
402        macro.close()
403       
404    def AddTorsionRestraint():
405        print 'Torsion restraint'
406       
407    def AddAATorsionRestraint():
408        print 'Add AA Torsion'
409       
410    def AddRamaRestraint():
411        print 'Ramachandran restraint'
412               
413    def AddAARamaRestraint():
414        print 'Add AA Ramachandran'
415       
416    def WtBox(wind,restData):
417       
418        def OnWtFactor(event):
419            try:
420                value = float(wtfactor.GetValue())
421            except ValueError:
422                value = 1.0
423            restData['wtFactor'] = value
424            wtfactor.SetValue('%.2f'%(value))
425           
426        def OnUseData(event):
427            restData['Use'] = Obj.GetValue()
428
429        wtBox = wx.BoxSizer(wx.HORIZONTAL)
430        wtBox.Add(wx.StaticText(wind,-1,'Restraint weight factor:'),0,wx.ALIGN_CENTER_VERTICAL)
431        wtfactor = wx.TextCtrl(wind,-1,value='%.2f'%(restData['wtFactor']),style=wx.TE_PROCESS_ENTER)
432        wtfactor.Bind(wx.EVT_TEXT_ENTER,OnWtFactor)
433        wtfactor.Bind(wx.EVT_KILL_FOCUS,OnWtFactor)
434        wtBox.Add(wtfactor,0,wx.ALIGN_CENTER_VERTICAL)
435        useData = wx.CheckBox(wind,-1,label=' Use?')
436        useData.Bind(wx.EVT_CHECKBOX, OnUseData)
437        useData.SetValue(restData['Use'])       
438        wtBox.Add(useData,0,wx.ALIGN_CENTER_VERTICAL)
439        return wtBox
440       
441    def OnRowSelect(event):
442        r,c =  event.GetRow(),event.GetCol()
443        Obj = event.GetEventObject()
444        if r < 0 and c < 0:
445            if Obj.IsSelection():
446                Obj.ClearSelection()
447            else:
448                for row in range(Bonds.GetNumberRows()):
449                    Obj.SelectRow(row,True)
450        elif c < 0:                   #only row clicks
451            if event.ControlDown():                   
452                if r in Obj.GetSelectedRows():
453                    Obj.DeselectRow(r)
454                else:
455                    Obj.SelectRow(r,True)
456            elif event.ShiftDown():
457                indxs = Obj.GetSelectedRows()
458                Obj.ClearSelection()
459                ibeg = 0
460                if indxs:
461                    ibeg = indxs[-1]
462                for row in range(ibeg,r+1):
463                    Obj.SelectRow(row,True)
464            else:
465                Obj.ClearSelection()
466                Obj.SelectRow(r,True)
467                   
468    def UpdateBondRestr(bondRestData):
469       
470        def OnChangeValue(event):
471            rows = Bonds.GetSelectedRows()
472            if not rows:
473                return
474            Bonds.ClearSelection()
475            val = bondList[rows[0]][3]
476            dlg = G2phG.SingleFloatDialog(G2frame,'New value','Enter new value for bond',val,[0.,5.],'%.4f')
477            if dlg.ShowModal() == wx.ID_OK:
478                parm = dlg.GetValue()
479                for r in rows:
480                    bondList[r][3] = parm
481            dlg.Destroy()
482            UpdateBondRestr(bondRestData)               
483
484        def OnChangeEsd(event):
485            rows = Bonds.GetSelectedRows()
486            if not rows:
487                return
488            Bonds.ClearSelection()
489            val = bondList[rows[0]][4]
490            dlg = G2phG.SingleFloatDialog(G2frame,'New value','Enter new esd for bond',val,[0.,1.],'%.4f')
491            if dlg.ShowModal() == wx.ID_OK:
492                parm = dlg.GetValue()
493                for r in rows:
494                    bondList[r][4] = parm
495            dlg.Destroy()
496            UpdateBondRestr(bondRestData)               
497                               
498        def OnDeleteRestraint(event):
499            rows = Bonds.GetSelectedRows()
500            if not rows:
501                return
502            Bonds.ClearSelection()
503            rows.sort()
504            rows.reverse()
505            for row in rows:
506                bondList.remove(bondList[row])
507            UpdateBondRestr(bondRestData)               
508           
509        BondRestr.DestroyChildren()
510        dataDisplay = wx.Panel(BondRestr)
511        mainSizer = wx.BoxSizer(wx.VERTICAL)
512        mainSizer.Add((5,5),0)
513        mainSizer.Add(WtBox(BondRestr,bondRestData),0,wx.ALIGN_CENTER_VERTICAL)
514
515        bondList = bondRestData['Bonds']
516        if len(bondList) and len(bondList[0]) == 6:   #patch
517            bondList = bondRestData['Bonds'] = []
518        if len(bondList):
519            table = []
520            rowLabels = []
521            Types = [wg.GRID_VALUE_STRING,]+3*[wg.GRID_VALUE_FLOAT+':10,3',]
522            if 'macro' in General['Type']:
523                colLabels = ['(res) A - (res) B','calc','obs','esd']
524                for i,[indx,ops,dcalc,dobs,esd] in enumerate(bondList):
525                    atoms = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,0,4)
526                    name = ''
527                    for atom in atoms:
528                        name += '('+atom[1]+atom[0].strip()+atom[2]+') '+atom[3]+' - '
529                    table.append([name[:-3],dcalc,dobs,esd])
530                    rowLabels.append(str(i))               
531            else:
532                colLabels = ['A+SymOp - B+SymOp','calc','obs','esd']
533                for i,[indx,ops,dcalc,dobs,esd] in enumerate(bondList):
534                    atoms = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,ct-1)
535                    table.append([atoms[0]+'+('+ops[0]+') - '+atoms[1]+'+('+ops[1]+')',dcalc,dobs,esd])
536                    rowLabels.append(str(i))
537            bondTable = G2gd.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
538            Bonds = G2gd.GSGrid(BondRestr)
539            Bonds.SetTable(bondTable, True)
540            Bonds.AutoSizeColumns(False)
541            for r in range(len(bondList)):
542                for c in range(2):
543                    Bonds.SetReadOnly(r,c,True)
544                    Bonds.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
545            Bonds.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK,OnRowSelect)
546            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDeleteRestraint, id=G2gd.wxID_RESTDELETE)
547            G2frame.dataFrame.Bind(wx.EVT_MENU, OnChangeValue, id=G2gd.wxID_RESRCHANGEVAL)
548            G2frame.dataFrame.Bind(wx.EVT_MENU, OnChangeEsd, id=G2gd.wxID_RESTCHANGEESD)
549            mainSizer.Add(Bonds,0,)
550        else:
551            mainSizer.Add(wx.StaticText(BondRestr,-1,'No bond distance restraints for this phase'),0,)
552
553        BondRestr.SetSizer(mainSizer)
554        Size = mainSizer.Fit(G2frame.dataFrame)
555        Size[0] += 5
556        Size[1] += 50       #make room for tab
557        BondRestr.SetSize(Size)
558        BondRestr.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
559        G2frame.dataFrame.setSizePosLeft(Size)
560       
561    def UpdateAngleRestr(angleRestData):
562       
563        def OnColSort(event):
564            r,c = event.GetRow(),event.GetCol()
565            if r < 0 and c == 0:
566                names = G2mth.sortArray(table,0)
567                angles = []
568                for name in names:
569                    idx = table.index(name)
570                    angles.append(angleList[idx])
571                angleRestData['Angles'] = angles
572                UpdateAngleRestr(angleRestData)               
573       
574        def OnChangeValue(event):
575            rows = Angles.GetSelectedRows()
576            if not rows:
577                return
578            Angles.ClearSelection()
579            val = angleList[rows[0]][3]
580            dlg = G2phG.SingleFloatDialog(G2frame,'New value','Enter new value for angle',val,[0.,360.],'%.2f')
581            if dlg.ShowModal() == wx.ID_OK:
582                parm = dlg.GetValue()
583                for r in rows:
584                    angleList[r][3] = parm
585            dlg.Destroy()
586            UpdateAngleRestr(angleRestData)               
587
588        def OnChangeEsd(event):
589            rows = Angles.GetSelectedRows()
590            if not rows:
591                return
592            Angles.ClearSelection()
593            val = angleList[rows[0]][4]
594            dlg = G2phG.SingleFloatDialog(G2frame,'New value','Enter new esd for angle',val,[0.,5.],'%.2f')
595            if dlg.ShowModal() == wx.ID_OK:
596                parm = dlg.GetValue()
597                for r in rows:
598                    angleList[r][4] = parm
599            dlg.Destroy()
600            UpdateAngleRestr(angleRestData)               
601                                           
602        def OnDeleteRestraint(event):
603            rows = Angles.GetSelectedRows()
604            if not rows:
605                return
606            rows.sort()
607            rows.reverse()
608            for row in rows:
609                angleList.remove(angleList[row])
610            UpdateAngleRestr(angleRestData)               
611           
612        AngleRestr.DestroyChildren()
613        dataDisplay = wx.Panel(AngleRestr)
614        mainSizer = wx.BoxSizer(wx.VERTICAL)
615        mainSizer.Add((5,5),0)
616        mainSizer.Add(WtBox(AngleRestr,angleRestData),0,wx.ALIGN_CENTER_VERTICAL)
617
618        angleList = angleRestData['Angles']
619        if len(angleList):
620            table = []
621            rowLabels = []
622            Types = [wg.GRID_VALUE_STRING,]+3*[wg.GRID_VALUE_FLOAT+':10,2',]
623            if 'macro' in General['Type']:
624                colLabels = ['(res) A - (res) B - (res) C','calc','obs','esd']
625                for i,[indx,ops,dcalc,dobs,esd] in enumerate(angleList):
626                    atoms = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,0,4)
627                    name = ''
628                    for atom in atoms:
629                        name += '('+atom[1]+atom[0].strip()+atom[2]+') '+atom[3]+' - '
630                    table.append([name[:-3],dcalc,dobs,esd])
631                    rowLabels.append(str(i))                               
632            else:
633                colLabels = ['A+SymOp - B+SymOp - C+SymOp','calc','obs','esd']
634                for i,[indx,ops,dcalc,dobs,esd] in enumerate(angleList):
635                    atoms = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,ct-1)
636                    table.append([atoms[0]+'+('+ops[0]+') - '+atoms[1]+'+('+ops[1]+') - '+atoms[2]+ \
637                    '+('+ops[2]+')',dcalc,dobs,esd])
638                    rowLabels.append(str(i))
639            angleTable = G2gd.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
640            Angles = G2gd.GSGrid(AngleRestr)
641            Angles.SetTable(angleTable, True)
642            Angles.AutoSizeColumns(False)
643            for r in range(len(angleList)):
644                for c in range(2):
645                    Angles.SetReadOnly(r,c,True)
646                    Angles.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
647            Angles.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK,OnRowSelect)
648            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDeleteRestraint, id=G2gd.wxID_RESTDELETE)
649            G2frame.dataFrame.Bind(wx.EVT_MENU, OnChangeValue, id=G2gd.wxID_RESRCHANGEVAL)
650            G2frame.dataFrame.Bind(wx.EVT_MENU, OnChangeEsd, id=G2gd.wxID_RESTCHANGEESD)
651            mainSizer.Add(Angles,0,)
652        else:
653            mainSizer.Add(wx.StaticText(AngleRestr,-1,'No bond angle restraints for this phase'),0,)
654
655        AngleRestr.SetSizer(mainSizer)
656        Size = mainSizer.Fit(G2frame.dataFrame)
657        Size[0] += 5
658        Size[1] += 50      #make room for tab
659        AngleRestr.SetSize(Size)
660        AngleRestr.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
661        G2frame.dataFrame.setSizePosLeft(Size)
662   
663    def UpdatePlaneRestr(planeRestData):
664       
665        items = G2frame.dataFrame.RestraintEdit.GetMenuItems()
666        for item in items:
667            if item.GetLabel() in ['Change value']:
668                item.Enable(False)
669
670        def OnChangeEsd(event):
671            rows = Planes.GetSelectedRows()
672            if not rows:
673                return
674            Planes.ClearSelection()
675            val = planeList[rows[0]][4]
676            dlg = G2phG.SingleFloatDialog(G2frame,'New value','Enter new esd for plane',val,[0.,5.],'%.2f')
677            if dlg.ShowModal() == wx.ID_OK:
678                parm = dlg.GetValue()
679                for r in rows:
680                    planeList[r][4] = parm
681            dlg.Destroy()
682            UpdatePlaneRestr(planeRestData)               
683                                           
684        def OnDeleteRestraint(event):
685            rows = Planes.GetSelectedRows()
686            if not rows:
687                return
688            rows.sort()
689            rows.reverse()
690            for row in rows:
691                planeList.remove(planeList[row])
692            UpdatePlaneRestr(planeRestData)               
693           
694        PlaneRestr.DestroyChildren()
695        dataDisplay = wx.Panel(PlaneRestr)
696        mainSizer = wx.BoxSizer(wx.VERTICAL)
697        mainSizer.Add((5,5),0)
698        mainSizer.Add(WtBox(PlaneRestr,planeRestData),0,wx.ALIGN_CENTER_VERTICAL)
699
700        planeList = planeRestData['Planes']
701        if len(planeList):
702            table = []
703            rowLabels = []
704            Types = [wg.GRID_VALUE_STRING,]+3*[wg.GRID_VALUE_FLOAT+':10,2',]
705            if 'macro' in General['Type']:
706                colLabels = ['(res) atom','calc','obs','esd']
707                for i,[indx,ops,dcalc,dobs,esd] in enumerate(planeList):
708                    atoms = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,0,4)
709                    name = ''
710                    for a,atom in enumerate(atoms):
711                        name += '('+atom[1]+atom[0].strip()+atom[2]+') '+atom[3]+' - '
712                        if (a+1)%3 == 0:
713                            name += '\n'
714                    table.append([name[:-3],dcalc,dobs,esd])
715                    rowLabels.append(str(i))
716            else:                               
717                colLabels = ['atom+SymOp','calc','obs','esd']
718                for i,[indx,ops,dcalc,dobs,esd] in enumerate(planeList):
719                    atoms = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,ct-1)
720                    atString = ''
721                    for a,atom in enumerate(atoms):
722                        atString += atom+'+ ('+ops[a]+'),'
723                        if (a+1)%3 == 0:
724                            atString += '\n'
725                    table.append([atString[:-1],dcalc,dobs,esd])
726                    rowLabels.append(str(i))
727            planeTable = G2gd.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
728            Planes = G2gd.GSGrid(PlaneRestr)
729            Planes.SetTable(planeTable, True)
730            Planes.AutoSizeColumns(False)
731            Planes.AutoSizeRows(False)
732            for r in range(len(planeList)):
733                for c in range(3):
734                    Planes.SetReadOnly(r,c,True)
735                    Planes.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
736            Planes.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK,OnRowSelect)
737            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDeleteRestraint, id=G2gd.wxID_RESTDELETE)
738            G2frame.dataFrame.Bind(wx.EVT_MENU, OnChangeEsd, id=G2gd.wxID_RESTCHANGEESD)
739            mainSizer.Add(Planes,0,)
740        else:
741            mainSizer.Add(wx.StaticText(PlaneRestr,-1,'No plane restraints for this phase'),0,)
742
743        PlaneRestr.SetSizer(mainSizer)
744        Size = mainSizer.Fit(G2frame.dataFrame)
745        Size[0] += 5
746        Size[1] += 50       #make room for tab
747        PlaneRestr.SetSize(Size)
748        PlaneRestr.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
749        G2frame.dataFrame.setSizePosLeft(Size)
750   
751    def UpdateChiralRestr(chiralRestData):
752
753        def OnDeleteRestraint(event):
754            rows = Volumes.GetSelectedRows()
755            if not rows:
756                return
757            rows.sort()
758            rows.reverse()
759            for row in rows:
760                volumeList.remove(volumeList[row])
761            UpdateChiralRestr(chiralRestData)               
762           
763        def OnChangeValue(event):
764            rows = Volumes.GetSelectedRows()
765            if not rows:
766                return
767            Volumes.ClearSelection()
768            val = volumeList[rows[0]][3]
769            dlg = G2phG.SingleFloatDialog(G2frame,'New value','Enter new value for chiral volume',val,[0.,360.],'%.2f')
770            if dlg.ShowModal() == wx.ID_OK:
771                parm = dlg.GetValue()
772                for r in rows:
773                    volumeList[r][3] = parm
774            dlg.Destroy()
775            UpdateChiralRestr(chiralRestData)               
776
777        def OnChangeEsd(event):
778            rows = Volumes.GetSelectedRows()
779            if not rows:
780                return
781            Volumes.ClearSelection()
782            val = volumeList[rows[0]][4]
783            dlg = G2phG.SingleFloatDialog(G2frame,'New value','Enter new esd for chiral volume',val,[0.,5.],'%.2f')
784            if dlg.ShowModal() == wx.ID_OK:
785                parm = dlg.GetValue()
786                for r in rows:
787                    volumeList[r][4] = parm
788            dlg.Destroy()
789            UpdateChiralRestr(chiralRestData)               
790                                           
791        ChiralRestr.DestroyChildren()
792        dataDisplay = wx.Panel(ChiralRestr)
793        mainSizer = wx.BoxSizer(wx.VERTICAL)
794        mainSizer.Add((5,5),0)
795        mainSizer.Add(WtBox(ChiralRestr,chiralRestData),0,wx.ALIGN_CENTER_VERTICAL)
796
797        volumeList = chiralRestData['Volumes']
798        if len(volumeList):
799            table = []
800            rowLabels = []
801            Types = [wg.GRID_VALUE_STRING,]+3*[wg.GRID_VALUE_FLOAT+':10,2',]
802            if 'macro' in General['Type']:
803                colLabels = ['(res) O (res) A (res) B (res) C','calc','obs','esd']
804                for i,[indx,ops,dcalc,dobs,esd] in enumerate(volumeList):
805                    atoms = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,0,4)
806                    name = ''
807                    for atom in atoms:
808                        name += '('+atom[1]+atom[0].strip()+atom[2]+') '+atom[3]+' '
809                    table.append([name,dcalc,dobs,esd])
810                    rowLabels.append(str(i))
811            else:
812                colLabels = ['O+SymOp  A+SymOp  B+SymOp  C+SymOp)','calc','obs','esd']
813                for i,[indx,ops,dcalc,dobs,esd] in enumerate(volumeList):
814                    atoms = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,ct-1)
815                    table.append([atoms[0]+'+('+ops[0]+') '+atoms[1]+'+('+ops[1]+') '+atoms[2]+ \
816                    '+('+ops[2]+') '+atoms[3]+'+('+ops[3]+')',dcalc,dobs,esd])
817                    rowLabels.append(str(i))
818            volumeTable = G2gd.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
819            Volumes = G2gd.GSGrid(ChiralRestr)
820            Volumes.SetTable(volumeTable, True)
821            Volumes.AutoSizeColumns(False)
822            for r in range(len(volumeList)):
823                for c in range(2):
824                    Volumes.SetReadOnly(r,c,True)
825                    Volumes.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
826            Volumes.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK,OnRowSelect)
827            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDeleteRestraint, id=G2gd.wxID_RESTDELETE)
828            G2frame.dataFrame.Bind(wx.EVT_MENU, OnChangeValue, id=G2gd.wxID_RESRCHANGEVAL)
829            G2frame.dataFrame.Bind(wx.EVT_MENU, OnChangeEsd, id=G2gd.wxID_RESTCHANGEESD)
830            mainSizer.Add(Volumes,0,)
831        else:
832            mainSizer.Add(wx.StaticText(ChiralRestr,-1,'No chiral volume restraints for this phase'),0,)
833
834        ChiralRestr.SetSizer(mainSizer)
835        Size = mainSizer.Fit(G2frame.dataFrame)
836        Size[0] += 5
837        Size[1] += 50       #make room for tab
838        ChiralRestr.SetSize(Size)
839        ChiralRestr.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
840        G2frame.dataFrame.setSizePosLeft(Size)
841   
842    def UpdateTorsionRestr(torsionRestData):
843
844        def OnDeleteRestraint(event):
845            rows = Torsions.GetSelectedRows()
846            if not rows:
847                return
848            rows.sort()
849            rows.reverse()
850            for row in rows:
851                torsionList.remove(torsionList[row])
852            UpdateTorsionRestr(torsionRestData)               
853           
854        TorsionRestr.DestroyChildren()
855        dataDisplay = wx.Panel(TorsionRestr)
856        mainSizer = wx.BoxSizer(wx.VERTICAL)
857        mainSizer.Add((5,5),0)
858        mainSizer.Add(WtBox(TorsionRestr,torsionRestData),0,wx.ALIGN_CENTER_VERTICAL)
859
860        torsionList = torsionRestData['Torsions']
861        if len(torsionList):
862            table = []
863            rowLabels = []
864            Types = 2*[wg.GRID_VALUE_STRING,]+3*[wg.GRID_VALUE_FLOAT+':10,2',]
865            if 'macro' in General['Type']:
866                colLabels = ['(res) A (res) B (res) C (res) D','coef name','calc','obs','esd']
867                for i,[indx,ops,cofName,dcalc,dobs,esd] in enumerate(torsionList):
868                    atoms = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,0,4)
869                    name = ''
870                    for atom in atoms:
871                        name += '('+atom[1]+atom[0].strip()+atom[2]+') '+atom[3]+' '
872                    table.append([name,cofName,dcalc,dobs,esd])
873                    rowLabels.append(str(i))
874            else:
875                colLabels = ['A+SymOp  B+SymOp  C+SymOp  D+SymOp)','coef name','calc','obs','esd']
876                for i,[indx,ops,cofName,dcalc,dobs,esd] in enumerate(torsionList):
877                    atoms = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,ct-1)
878                    table.append([atoms[0]+'+('+ops[0]+') '+atoms[1]+'+('+ops[1]+') '+atoms[2]+ \
879                    '+('+ops[2]+') '+atoms[3]+'+('+ops[3]+')',cofName,dcalc,dobs,esd])
880                    rowLabels.append(str(i))
881            torsionTable = G2gd.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
882            Torsions = G2gd.GSGrid(TorsionRestr)
883            Torsions.SetTable(torsionTable, True)
884            Torsions.AutoSizeColumns(False)
885            for r in range(len(torsionList)):
886                for c in range(2):
887                    Torsions.SetReadOnly(r,c,True)
888                    Torsions.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
889            Torsions.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK,OnRowSelect)
890            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDeleteRestraint, id=G2gd.wxID_RESTDELETE)
891            G2frame.dataFrame.Bind(wx.EVT_MENU, OnChangeEsd, id=G2gd.wxID_RESTCHANGEESD)
892            mainSizer.Add(Torsions,0,)
893        else:
894            mainSizer.Add(wx.StaticText(TorsionRestr,-1,'No torsion restraints for this phase'),0,)
895
896        TorsionRestr.SetSizer(mainSizer)
897        Size = mainSizer.Fit(G2frame.dataFrame)
898        Size[0] += 5
899        Size[1] += 50       #make room for tab
900        TorsionRestr.SetSize(Size)
901        TorsionRestr.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
902        G2frame.dataFrame.setSizePosLeft(Size)
903
904    def UpdateRamaRestr(ramaRestData):
905
906        def OnDeleteRestraint(event):
907            rows = Volumes.GetSelectedRows()
908            if not rows:
909                return
910            rows.sort()
911            rows.reverse()
912            for row in rows:
913                ramaList.remove(ramaList[row])
914            UpdateRamaRestr(ramaRestData)               
915           
916        RamaRestr.DestroyChildren()
917        dataDisplay = wx.Panel(RamaRestr)
918        mainSizer = wx.BoxSizer(wx.VERTICAL)
919        mainSizer.Add((5,5),0)
920        mainSizer.Add(WtBox(RamaRestr,ramaRestData),0,wx.ALIGN_CENTER_VERTICAL)
921
922        ramaList = ramaRestData['Ramas']
923        if len(ramaList):
924            table = []
925            rowLabels = []
926            Types = 2*[wg.GRID_VALUE_STRING,]+3*[wg.GRID_VALUE_FLOAT+':10,2',]
927            if 'macro' in General['Type']:
928                colLabels = ['(res) A (res) B (res) C (res) D (res) E','coef name','calc','obs','esd']
929                for i,[indx,ops,cofName,dcalc,dobs,esd] in enumerate(ramaList):
930                    atoms = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,0,4)
931                    name = ''
932                    for atom in atoms:
933                        name += '('+atom[1]+atom[0].strip()+atom[2]+') '+atom[3]+' '
934                    table.append([name,cofName,dcalc,dobs,esd])
935                    rowLabels.append(str(i))
936            else:
937                colLabels = ['A+SymOp  B+SymOp  C+SymOp  D+SymOp  E+SymOp)','coef name','calc','obs','esd']
938                for i,[indx,ops,cofName,dcalc,dobs,esd] in enumerate(ramaList):
939                    atoms = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,ct-1)
940                    table.append([atoms[0]+'+('+ops[0]+') '+atoms[1]+'+('+ops[1]+') '+atoms[2]+ \
941                    '+('+ops[2]+') '+atoms[3]+'+('+ops[3]+')',cofName,dcalc,dobs,esd])
942                    rowLabels.append(str(i))
943            ramaTable = G2gd.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
944            Ramas = G2gd.GSGrid(RamaRestr)
945            Ramas.SetTable(ramaTable, True)
946            Ramas.AutoSizeColumns(False)
947            for r in range(len(ramaList)):
948                for c in range(2):
949                    Ramas.SetReadOnly(r,c,True)
950                    Ramas.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
951            Ramas.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK,OnRowSelect)
952            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDeleteRestraint, id=G2gd.wxID_RESTDELETE)
953            G2frame.dataFrame.Bind(wx.EVT_MENU, OnChangeEsd, id=G2gd.wxID_RESTCHANGEESD)
954            mainSizer.Add(Ramas,0,)
955        else:
956            mainSizer.Add(wx.StaticText(RamaRestr,-1,'No Ramachandran restraints for this phase'),0,)
957
958        RamaRestr.SetSizer(mainSizer)
959        Size = mainSizer.Fit(G2frame.dataFrame)
960        Size[0] += 5
961        Size[1] += 50       #make room for tab
962        RamaRestr.SetSize(Size)
963        RamaRestr.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
964        G2frame.dataFrame.setSizePosLeft(Size)
965
966    def OnPageChanged(event):
967        page = event.GetSelection()
968        text = G2frame.dataDisplay.GetPageText(page)
969        if text == 'Bond restraints':
970            G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.RestraintMenu)
971            bondRestData = restrData['Bond']
972            UpdateBondRestr(bondRestData)
973        elif text == 'Angle restraints':
974            G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.RestraintMenu)
975            angleRestData = restrData['Angle']
976            UpdateAngleRestr(angleRestData)
977        elif text == 'Plane restraints':
978            G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.RestraintMenu)
979            planeRestData = restrData['Plane']
980            UpdatePlaneRestr(planeRestData)
981        elif text == 'Chiral restraints':
982            G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.RestraintMenu)
983            chiralRestData = restrData['Chiral']
984            UpdateChiralRestr(chiralRestData)
985        elif text == 'Torsion restraints':
986            G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.RestraintMenu)
987            torsionRestData = restrData['Torsion']
988            UpdateTorsionRestr(torsionRestData)
989        elif text == 'Ramachandran restraints':
990            G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.RestraintMenu)
991            ramaRestData = restrData['Rama']
992            UpdateRamaRestr(ramaRestData)
993        event.Skip()
994
995    def SetStatusLine(text):
996        Status.SetStatusText(text)                                     
997       
998    if G2frame.dataDisplay:
999        G2frame.dataDisplay.Destroy()
1000       
1001    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.RestraintMenu)
1002    G2frame.dataFrame.SetLabel('restraints for '+phaseName)
1003    if not G2frame.dataFrame.GetStatusBar():
1004        Status = G2frame.dataFrame.CreateStatusBar()
1005    SetStatusLine('')
1006   
1007    G2frame.dataFrame.RestraintEdit.Enable(G2gd.wxID_RESTSELPHASE,False)
1008    if len(Phases) > 1:
1009        G2frame.dataFrame.RestraintEdit.Enable(G2gd.wxID_RESTSELPHASE,True)
1010        G2frame.dataFrame.Bind(wx.EVT_MENU, OnSelectPhase, id=G2gd.wxID_RESTSELPHASE)
1011    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddRestraint, id=G2gd.wxID_RESTRAINTADD)
1012    if 'macro' in phasedata['General']['Type']:
1013        G2frame.dataFrame.RestraintEdit.Enable(G2gd.wxID_AARESTRAINTADD,True)
1014        G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddAARestraint, id=G2gd.wxID_AARESTRAINTADD)
1015    G2frame.dataDisplay = G2gd.GSNoteBook(parent=G2frame.dataFrame,size=G2frame.dataFrame.GetClientSize())
1016   
1017    BondRestr = wx.ScrolledWindow(G2frame.dataDisplay)
1018    G2frame.dataDisplay.AddPage(BondRestr,'Bond restraints')
1019    AngleRestr = wx.ScrolledWindow(G2frame.dataDisplay)
1020    G2frame.dataDisplay.AddPage(AngleRestr,'Angle restraints')
1021    PlaneRestr = wx.ScrolledWindow(G2frame.dataDisplay)
1022    G2frame.dataDisplay.AddPage(PlaneRestr,'Plane restraints')
1023    ChiralRestr = wx.ScrolledWindow(G2frame.dataDisplay)
1024    G2frame.dataDisplay.AddPage(ChiralRestr,'Chiral restraints')
1025    TorsionRestr = wx.ScrolledWindow(G2frame.dataDisplay)
1026    G2frame.dataDisplay.AddPage(TorsionRestr,'Torsion restraints')
1027    RamaRestr = wx.ScrolledWindow(G2frame.dataDisplay)
1028    G2frame.dataDisplay.AddPage(RamaRestr,'Ramachandran restraints')
1029   
1030    UpdateBondRestr(restrData['Bond'])
1031
1032    G2frame.dataDisplay.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, OnPageChanged)
Note: See TracBrowser for help on using the repository browser.