source: trunk/GSASIIrestrGUI.py @ 815

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

another hot key
more restraint development

File size: 57.6 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,'Range':0.9,'Bonds':[],'Use':True}
40    if 'Angle' not in restrData:
41        restrData['Angle'] = {'wtFactor':1.0,'Range':0.85,'Angles':[],'Use':True}
42    if 'Plane' not in restrData:
43        restrData['Plane'] = {'wtFactor':1.0,'Range':0.9,'Planes':[],'Use':True}
44    if 'Chiral' not in restrData:
45        restrData['Chiral'] = {'wtFactor':1.0,'Range':0.9,'Volumes':[],'Use':True}
46    if 'Torsion' not in restrData:
47        restrData['Torsion'] = {'wtFactor':1.0,'Range':0.9,'Coeff':{},'Torsions':[],'Use':True}
48    if 'Rama' not in restrData:
49        restrData['Rama'] = {'wtFactor':1.0,'Range':0.9,'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        restName = G2frame.dataDisplay.GetPageText(page)
105        if 'Bond' in G2frame.dataDisplay.GetPageText(page):
106            AddBondRestraint(restrData['Bond'])
107        elif 'Angle' in G2frame.dataDisplay.GetPageText(page):
108            AddAngleRestraint(restrData['Angle'])
109        elif 'Plane' in G2frame.dataDisplay.GetPageText(page):
110            AddPlaneRestraint(restrData['Plane'])
111        elif 'Chiral' in G2frame.dataDisplay.GetPageText(page):
112            AddChiralRestraint(restrData['Chiral'])
113        elif 'Torsion' in G2frame.dataDisplay.GetPageText(page):
114            AddTorsionRestraint(restrData['Torsion'])
115        elif 'Rama' in G2frame.dataDisplay.GetPageText(page):
116            AddRamaRestraint(restrData['Rama'])
117           
118    def OnAddAARestraint(event):
119        page = G2frame.dataDisplay.GetSelection()
120        if 'Bond' in G2frame.dataDisplay.GetPageText(page):
121            AddAABondRestraint(restrData['Bond'])
122        elif 'Angle' in G2frame.dataDisplay.GetPageText(page):
123            AddAAAngleRestraint(restrData['Angle'])
124        elif 'Plane' in G2frame.dataDisplay.GetPageText(page):
125            AddAAPlaneRestraint(restrData['Plane'])
126        elif 'Chiral' in G2frame.dataDisplay.GetPageText(page):
127            AddAAChiralRestraint(restrData['Chiral'])
128        elif 'Torsion' in G2frame.dataDisplay.GetPageText(page):
129            AddAATorsionRestraint(restrData['Torsion'])
130        elif 'Rama' in G2frame.dataDisplay.GetPageText(page):
131            AddAARamaRestraint(restrData['Rama'])
132           
133    def AddBondRestraint(bondRestData):
134        Radii = dict(zip(General['AtomTypes'],General['BondRadii']))
135        Lists = {'origin':[],'target':[]}
136        for listName in ['origin','target']:
137            dlg = wx.MultiChoiceDialog(G2frame,'Bond restraint '+listName+' for '+General['Name'],
138                    'Select bond restraint '+listName+' atoms',Names)
139            if dlg.ShowModal() == wx.ID_OK:
140                sel = dlg.GetSelections()
141                for x in sel:
142                    if 'all' in Names[x]:
143                        allType = Types[x]
144                        for name,Type,coords,id in zip(Names,Types,Coords,Ids):
145                            if Type == allType and 'all' not in name:
146                                Lists[listName].append([id,Type,coords])
147                    else:
148                        Lists[listName].append([Ids[x],Types[x],Coords[x],])
149        Factor = bondRestData['Range']
150        indices = (-1,0,1)
151        Units = np.array([[h,k,l] for h in indices for k in indices for l in indices])
152        origAtoms = Lists['origin']
153        targAtoms = Lists['target']
154        dlg = wx.ProgressDialog("Generating bond restraints","Processed origin atoms",len(origAtoms), 
155            style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_REMAINING_TIME)
156        try:
157            Norig = 0
158            for Oid,Otype,Ocoord in origAtoms:
159                Norig += 1
160                dlg.Update(Norig)
161                for Tid,Ttype,Tcoord in targAtoms:
162                    if 'macro' in General['Type']:
163                        result = [[Tcoord,1,[0,0,0]],]
164                    else:
165                        result = G2spc.GenAtom(Tcoord,SGData,False,Move=False)
166                    BsumR = (Radii[Otype]+Radii[Ttype])*Factor
167                    for Txyz,Top,Tunit in result:
168                        Dx = (Txyz-np.array(Ocoord))+Units
169                        dx = np.inner(Amat,Dx)
170                        dist = ma.masked_less(np.sqrt(np.sum(dx**2,axis=0)),0.5)
171                        IndB = ma.nonzero(ma.masked_greater(dist-BsumR,0.))
172                        if np.any(IndB):
173                            for indb in IndB:
174                                for i in range(len(indb)):
175                                    unit = Units[indb][i]+Tunit
176                                    if np.any(unit):
177                                        Topstr = '%d+%d,%d,%d'%(Top,unit[0],unit[1],unit[2])
178                                    else:
179                                        Topstr = str(Top)
180                                    newBond = [[Oid,Tid],['1',Topstr],1.54,0.01]
181                                    if newBond not in bondRestData['Bonds']:
182                                        bondRestData['Bonds'].append(newBond)
183        finally:
184            dlg.Destroy()
185        UpdateBondRestr(bondRestData)               
186
187    def AddAABondRestraint(bondRestData):
188        Radii = dict(zip(General['AtomTypes'],General['BondRadii']))
189        macro = getMacroFile('bond')
190        if not macro:
191            return
192        macStr = macro.readline()
193        atoms = zip(Names,Coords,Ids)
194       
195        Factor = bondRestData['Range']
196        while macStr:
197            items = macStr.split()
198            if 'F' in items[0]:
199                restrData['Bond']['wtFactor'] = float(items[1])
200            elif 'S' in items[0]:
201                oIds = []
202                oCoords = []
203                tIds = []
204                tCoords = []
205                res = items[1]
206                dist = float(items[2])
207                esd = float(items[3])
208                oAtm,tAtm = items[4:6]
209                for Name,coords,Id in atoms:
210                    names = Name.split()
211                    if res == '*' or res in names[0]:
212                        if oAtm == names[2]:
213                            oIds.append(Id)
214                            oCoords.append(np.array(coords))
215                        if tAtm == names[2]:
216                            tIds.append(Id)
217                            tCoords.append(np.array(coords))
218                for i,[oId,oCoord] in enumerate(zip(oIds,oCoords)):
219                    for tId,tCoord in zip(tIds,tCoords)[i:]:
220                        obsd = np.sqrt(np.sum(np.inner(Amat,tCoord-oCoord)**2))
221                        if dist*Factor < obsd < dist/Factor:
222                            newBond = [[oId,tId],['1','1'],dist,esd]
223                            if newBond not in bondRestData['Bonds']:
224                                bondRestData['Bonds'].append(newBond)                         
225            macStr = macro.readline()
226        macro.close()
227        UpdateBondRestr(bondRestData)               
228           
229    def AddAngleRestraint(angleRestData):
230        Radii = dict(zip(General['AtomTypes'],zip(General['BondRadii'],General['AngleRadii'])))
231        origAtoms = []
232        dlg = wx.MultiChoiceDialog(G2frame,'Select atom B for angle A-B-C for '+General['Name'],
233                'Select angle restraint origin atoms',Names)
234        if dlg.ShowModal() == wx.ID_OK:
235            sel = dlg.GetSelections()
236            for x in sel:
237                if 'all' in Names[x]:
238                    allType = Types[x]
239                    for name,Type,coords,id in zip(Names,Types,Coords,Ids):
240                        if Type == allType and 'all' not in name:
241                            origAtoms.append([id,Type,coords])
242                else:
243                    origAtoms.append([Ids[x],Types[x],Coords[x]])
244        targAtoms = [[Ids[x+iBeg],Types[x+iBeg],Coords[x+iBeg]] for x in range(len(Names[iBeg:]))]
245
246        Factor = angleRestData['Range']
247        indices = (-1,0,1)
248        Units = np.array([[h,k,l] for h in indices for k in indices for l in indices])
249        VectA = []
250        for Oid,Otype,Ocoord in origAtoms:
251            IndBlist = []
252            VectB = []
253            for Tid,Ttype,Tcoord in targAtoms:
254                result = G2spc.GenAtom(Tcoord,SGData,False,Move=False)
255                BsumR = (Radii[Otype][0]+Radii[Ttype][0])*Factor
256                AsumR = (Radii[Otype][1]+Radii[Ttype][1])*Factor
257                for Txyz,Top,Tunit in result:
258                    Dx = (Txyz-Ocoord)+Units
259                    dx = np.inner(Amat,Dx)
260                    dist = ma.masked_less(np.sqrt(np.sum(dx**2,axis=0)),0.5)
261                    IndB = ma.nonzero(ma.masked_greater(dist-BsumR,0.))
262                    if np.any(IndB):
263                        for indb in IndB:
264                            for i in range(len(indb)):
265                                if str(dx.T[indb][i]) not in IndBlist:
266                                    IndBlist.append(str(dx.T[indb][i]))
267                                    unit = Units[indb][i]+Tunit
268                                if np.any(unit):
269                                    Topstr = '%d+%d,%d,%d'%(Top,unit[0],unit[1],unit[2])
270                                else:
271                                    Topstr = str(Top)
272                                    tunit = '[%2d%2d%2d]'%(unit[0]+Tunit[0],unit[1]+Tunit[1],unit[2]+Tunit[2])
273                                    Dist = ma.getdata(dist[indb])[i]
274                                    if (Dist-AsumR) <= 0.:
275                                        VectB.append([Oid,'1',Ocoord,Tid,Topstr,Tcoord,Dist])
276            VectA.append(VectB)
277            for Vects in VectA:
278                for i,vecta in enumerate(Vects):                   
279                    for vectb in Vects[:i]:
280                        ids = [vecta[3],vecta[0],vectb[3]]
281                        ops = [vecta[4],vecta[1],vectb[4]]
282                        XYZ = np.array([vecta[5],vecta[2],vectb[5]])
283                        angle = G2mth.getRestAngle(XYZ,Amat)
284                        if angle not in angleRestData['Angles']:
285                            angleRestData['Angles'].append([ids,ops,109.5,1.0])
286        UpdateAngleRestr(angleRestData)               
287
288    def AddAAAngleRestraint(angleRestData):
289        macro = getMacroFile('angle')
290        if not macro:
291            return
292        atoms = zip(Names,Coords,Ids)
293        macStr = macro.readline()
294        while macStr:
295            items = macStr.split()
296            if 'F' in items[0]:
297                restrData['Angle']['wtFactor'] = float(items[1])
298            elif 'S' in items[0]:
299                res = items[1]
300                value = float(items[2])
301                esd = float(items[3])
302                Atms = items[4:7]
303                pAtms = ['','','']
304                for i,atm in enumerate(Atms):
305                    if '+' in atm:
306                        pAtms[i] = atm.strip('+')
307                ids = np.array([0,0,0])
308                coords = [[],[],[]]
309                rNum = -1
310                for name,coord,id in atoms:
311                    names = name.split()
312                    tNum = int(names[0].split(':')[0])
313                    if res in names[0]:
314                        try:
315                            ipos = Atms.index(names[2])
316                            ids[ipos] = id
317                            coords[ipos] = coord
318                        except ValueError:
319                            continue
320                    elif res == '*':
321                        try:
322                            ipos = Atms.index(names[2])
323                            if not np.all(ids):
324                                rNum = int(names[0].split(':')[0])
325                            ids[ipos] = id
326                            coords[ipos] = coord
327                        except ValueError:
328                            try:
329                                if tNum == rNum+1:
330                                    ipos = pAtms.index(names[2])
331                                    ids[ipos] = id
332                                    coords[ipos] = coord
333                            except ValueError:
334                                continue
335                    if np.all(ids):
336                        angle = [list(ids),['1','1','1'],value,esd]
337                        if angle not in angleRestData['Angles']:
338                            angleRestData['Angles'].append(angle)
339                        ids = np.array([0,0,0])
340                        coords = [[],[],[]]
341            macStr = macro.readline()
342        macro.close()
343        UpdateAngleRestr(angleRestData)               
344       
345    def AddPlaneRestraint():
346        origAtoms = []
347        dlg = wx.MultiChoiceDialog(G2frame,'Select atom B for angle A-B-C for '+General['Name'],
348                'Select angle restraint origin atoms',Names)
349        if dlg.ShowModal() == wx.ID_OK:
350            sel = dlg.GetSelections()
351            for x in sel:
352                if 'all' in Names[x]:
353                    allType = Types[x]
354                    for name,Type,coords,id in zip(Names,Types,Coords,Ids):
355                        if Type == allType and 'all' not in name:
356                            origAtoms.append([id,Type,coords])
357                else:
358                    origAtoms.append([Ids[x],Types[x],Coords[x]])
359
360    def AddAAPlaneRestraint(planeRestData):
361        macro = getMacroFile('plane')
362        if not macro:
363            return
364        atoms = zip(Names,Coords,Ids)
365        macStr = macro.readline()
366        while macStr:
367            items = macStr.split()
368            if 'F' in items[0]:
369                restrData['Plane']['wtFactor'] = float(items[1])
370            elif 'S' in items[0]:
371                res = items[1]
372                esd = float(items[2])
373                Atms = items[3:]
374                pAtms = ['' for i in Atms]
375                for i,atm in enumerate(Atms):
376                    if '+' in atm:
377                        pAtms[i] = atm.strip('+')
378                rNum = -1
379                ids = np.zeros(len(Atms))
380                coords = [[] for i in range(len(Atms))]
381                ops = ['1' for i in range(len(Atms))]
382                for name,coord,id in atoms:
383                    names = name.split()
384                    tNum = int(names[0].split(':')[0])
385                    if res in names[0]:
386                        try:
387                            ipos = Atms.index(names[2])
388                            ids[ipos] = id
389                            coords[ipos] = coord
390                        except ValueError:
391                            continue
392                    elif res == '*':
393                        try:
394                            ipos = Atms.index(names[2])
395                            if not np.all(ids):
396                                rNum = int(names[0].split(':')[0])
397                            ids[ipos] = id
398                            coords[ipos] = coord
399                        except ValueError:
400                            try:
401                                if tNum == rNum+1:
402                                    ipos = pAtms.index(names[2])
403                                    ids[ipos] = id
404                                    coords[ipos] = coord
405                            except ValueError:
406                                continue
407                    if np.all(ids):
408                        plane = [list(ids),ops,0.0,esd]
409                        if plane not in planeRestData['Planes']:
410                            planeRestData['Planes'].append(plane)
411                        ids = np.zeros(len(Atms))
412                        coords = [[] for i in range(len(Atms))]
413            macStr = macro.readline()
414        macro.close()
415        UpdatePlaneRestr(planeRestData)               
416
417    def AddChiralRestraint():
418        print 'Chiral restraint'
419       
420    def AddAAChiralRestraint(chiralRestData):
421        macro = getMacroFile('chiral')
422        if not macro:
423            return
424        atoms = zip(Names,Coords,Ids)
425        macStr = macro.readline()
426        while macStr:
427            items = macStr.split()
428            if 'F' in items[0]:
429                restrData['Chiral']['wtFactor'] = float(items[1])
430            elif 'S' in items[0]:
431                res = items[1]
432                value = float(items[2])
433                esd = float(items[3])
434                Atms = items[4:8]
435                ids = np.array([0,0,0,0])
436                coords = [[],[],[],[]]
437                for name,coord,id in atoms:
438                    names = name.split()
439                    if res in names[0]:
440                        try:
441                            ipos = Atms.index(names[2])
442                            ids[ipos] = id
443                            coords[ipos] = coord
444                        except ValueError:
445                            pass
446                        if np.all(ids):
447                            chiral = [list(ids),['1','1','1','1'],value,esd]
448                            if chiral not in chiralRestData['Volumes']:
449                                chiralRestData['Volumes'].append(chiral)
450                            ids = np.array([0,0,0,0])
451                            coords = [[],[],[],[]]
452            macStr = macro.readline()
453        macro.close()
454        UpdateChiralRestr(chiralRestData)               
455       
456    def AddTorsionRestraint():
457        print 'Torsion restraint'
458       
459    def AddAATorsionRestraint(torsionRestData):
460        macro = getMacroFile('torsion')
461        if not macro:
462            return
463        atoms = zip(Names,Coords,Ids)
464        macStr = macro.readline()[:-1]
465        while macStr:
466            items = macStr.split()
467            if 'F' in items[0]:
468                restrData['Torsion']['wtFactor'] = float(items[1])
469            elif 'A' in items[0]:
470                name = items[10]
471                coeff = np.zeros(9)
472                for i,item in enumerate(items[1:10]):
473                    coeff[i] = float(item)
474                torsionRestData['Coeff'][name] = coeff
475            elif 'S' in items[0]:
476                Name = items[1]
477                res = items[2]
478                esd = float(items[3])
479                Atms = items[4:8]
480                pAtms = ['','','','']
481                for i,atm in enumerate(Atms):
482                    if '+' in atm:
483                        pAtms[i] = atm.strip('+')
484                ids = np.array([0,0,0,0])
485                coords = [[],[],[],[]]
486                rNum = -1
487                for name,coord,id in atoms:
488                    names = name.split()
489                    tNum = int(names[0].split(':')[0])
490                    if res in names[0]:
491                        try:
492                            ipos = Atms.index(names[2])
493                            ids[ipos] = id
494                            coords[ipos] = coord
495                        except ValueError:
496                            continue
497                    elif res == '*':
498                        try:
499                            ipos = Atms.index(names[2])
500                            if not np.all(ids):
501                                rNum = int(names[0].split(':')[0])
502                            ids[ipos] = id
503                            coords[ipos] = coord
504                        except ValueError:
505                            try:
506                                if tNum == rNum+1:
507                                    ipos = pAtms.index(names[2])
508                                    ids[ipos] = id
509                                    coords[ipos] = coord
510                            except ValueError:
511                                continue
512                    if np.all(ids):
513                        torsion = [list(ids),['1','1','1','1'],Name,esd]
514                        if torsion not in torsionRestData['Torsions']:
515                            torsionRestData['Torsions'].append(torsion)
516                        ids = np.array([0,0,0,0])
517                        coords = [[],[],[],[]]
518            macStr = macro.readline()
519        macro.close()
520        UpdateTorsionRestr(torsionRestData)                       
521       
522    def AddRamaRestraint():
523        print 'Ramachandran restraint'
524               
525    def AddAARamaRestraint(ramaRestData):
526        macro = getMacroFile('ramachandran')
527        if not macro:
528            return
529        atoms = zip(Names,Coords,Ids)
530        macStr = macro.readline()
531        while macStr:
532            items = macStr.split()
533            if 'F' in items[0]:
534                restrData['Rama']['wtFactor'] = float(items[1])
535            elif 'A' in items[0]:
536                nTerms = int(items[1])
537                name = items[2]
538                coeff = np.zeros((nTerms,6))
539                for i in range(nTerms):
540                    macStr = macro.readline()
541                    items = macStr.split()
542                    coeff[i] = np.fromstring([item for item in items])
543                ramaRestData['Coeff'][name] = coeff
544            elif 'S' in items[0]:
545                name = items[1]
546                res = items[2]
547                esd = float(items[3])
548                Atms = items[4:9]
549                orNum = -1
550                ids = np.array([0,0,0,0,0])
551                coords = [[],[],[],[],[]]
552                for name,coord,id in atoms:
553                    names = name.split()
554                    if res in names[0]:
555                        rNum = int(names[0].split(res)[0])
556                        try:
557                            ipos = Atms.index(names[2])
558                            ids[ipos] = id
559                            coords[ipos] = coord
560                        except ValueError:
561                            pass
562                        if np.all(ids):
563                            orNum = rNum
564                            torsionRestData['Rama'].append([list(ids),['1','1','1','1'],name,esd])
565                            ids = np.array([0,0,0,0,0])
566                            coords = [[],[],[],[],[]]
567            macStr = macro.readline()
568        macro.close()
569        UpdateRamaRestr(ramaRestData)               
570       
571       
572    def WtBox(wind,restData):
573        if 'Range' not in restData: restData['Range'] = 0.9     #patch
574       
575        def OnWtFactor(event):
576            try:
577                value = float(wtfactor.GetValue())
578            except ValueError:
579                value = 1.0
580            restData['wtFactor'] = value
581            wtfactor.SetValue('%.2f'%(value))
582           
583        def OnRange(event):
584            try:
585                value = float(sRange.GetValue())
586            except ValueError:
587                value = 1.0
588            restData['Range'] = value
589            sRange.SetValue('%.2f'%(value))
590           
591        def OnUseData(event):
592            restData['Use'] = Obj.GetValue()
593
594        wtBox = wx.BoxSizer(wx.HORIZONTAL)
595        wtBox.Add(wx.StaticText(wind,-1,'Restraint weight factor:'),0,wx.ALIGN_CENTER_VERTICAL)
596        wtfactor = wx.TextCtrl(wind,-1,value='%.2f'%(restData['wtFactor']),style=wx.TE_PROCESS_ENTER)
597        wtfactor.Bind(wx.EVT_TEXT_ENTER,OnWtFactor)
598        wtfactor.Bind(wx.EVT_KILL_FOCUS,OnWtFactor)
599        wtBox.Add(wtfactor,0,wx.ALIGN_CENTER_VERTICAL)
600        useData = wx.CheckBox(wind,-1,label=' Use?')
601        useData.Bind(wx.EVT_CHECKBOX, OnUseData)
602        useData.SetValue(restData['Use'])       
603        wtBox.Add(useData,0,wx.ALIGN_CENTER_VERTICAL)
604        if 'Bond' in restData or 'Angle' in restData:
605            wtBox.Add(wx.StaticText(wind,-1,'Search range:'),0,wx.ALIGN_CENTER_VERTICAL)
606            sRange = wx.TextCtrl(wind,-1,value='%.2f'%(restData['Range']),style=wx.TE_PROCESS_ENTER)
607            sRange.Bind(wx.EVT_TEXT_ENTER,OnRange)
608            sRange.Bind(wx.EVT_KILL_FOCUS,OnRange)
609            wtBox.Add(sRange,0,wx.ALIGN_CENTER_VERTICAL)
610        return wtBox
611       
612    def OnRowSelect(event):
613        r,c =  event.GetRow(),event.GetCol()
614        Obj = event.GetEventObject()
615        if r < 0 and c < 0:
616            if Obj.IsSelection():
617                Obj.ClearSelection()
618            else:
619                for row in range(Bonds.GetNumberRows()):
620                    Obj.SelectRow(row,True)
621        elif c < 0:                   #only row clicks
622            if event.ControlDown():                   
623                if r in Obj.GetSelectedRows():
624                    Obj.DeselectRow(r)
625                else:
626                    Obj.SelectRow(r,True)
627            elif event.ShiftDown():
628                indxs = Obj.GetSelectedRows()
629                Obj.ClearSelection()
630                ibeg = 0
631                if indxs:
632                    ibeg = indxs[-1]
633                for row in range(ibeg,r+1):
634                    Obj.SelectRow(row,True)
635            else:
636                Obj.ClearSelection()
637                Obj.SelectRow(r,True)
638                   
639    def UpdateBondRestr(bondRestData):
640       
641        def OnChangeValue(event):
642            rows = Bonds.GetSelectedRows()
643            if not rows:
644                return
645            Bonds.ClearSelection()
646            val = bondList[rows[0]][3]
647            dlg = G2phG.SingleFloatDialog(G2frame,'New value','Enter new value for bond',val,[0.,5.],'%.4f')
648            if dlg.ShowModal() == wx.ID_OK:
649                parm = dlg.GetValue()
650                for r in rows:
651                    bondList[r][3] = parm
652            dlg.Destroy()
653            UpdateBondRestr(bondRestData)               
654
655        def OnChangeEsd(event):
656            rows = Bonds.GetSelectedRows()
657            if not rows:
658                return
659            Bonds.ClearSelection()
660            val = bondList[rows[0]][4]
661            dlg = G2phG.SingleFloatDialog(G2frame,'New value','Enter new esd for bond',val,[0.,1.],'%.4f')
662            if dlg.ShowModal() == wx.ID_OK:
663                parm = dlg.GetValue()
664                for r in rows:
665                    bondList[r][4] = parm
666            dlg.Destroy()
667            UpdateBondRestr(bondRestData)               
668                               
669        def OnDeleteRestraint(event):
670            rows = Bonds.GetSelectedRows()
671            if not rows:
672                return
673            Bonds.ClearSelection()
674            rows.sort()
675            rows.reverse()
676            for row in rows:
677                bondList.remove(bondList[row])
678            UpdateBondRestr(bondRestData)               
679           
680        BondRestr.DestroyChildren()
681        dataDisplay = wx.Panel(BondRestr)
682        mainSizer = wx.BoxSizer(wx.VERTICAL)
683        mainSizer.Add((5,5),0)
684        mainSizer.Add(WtBox(BondRestr,bondRestData),0,wx.ALIGN_CENTER_VERTICAL)
685
686        bondList = bondRestData['Bonds']
687        if len(bondList) and len(bondList[0]) == 6:   #patch
688            bondList = bondRestData['Bonds'] = []
689        if len(bondList):
690            table = []
691            rowLabels = []
692            Types = [wg.GRID_VALUE_STRING,]+3*[wg.GRID_VALUE_FLOAT+':10,3',]
693            if 'macro' in General['Type']:
694                colLabels = ['(res) A - (res) B','calc','obs','esd']
695                for i,[indx,ops,obs,esd] in enumerate(bondList):
696                    atoms = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,0,4)
697                    name = ''
698                    for atom in atoms:
699                        name += '('+atom[1]+atom[0].strip()+atom[2]+') '+atom[3]+' - '
700                    XYZ = np.array(G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,cx,3))
701                    calc = G2mth.getRestDist(XYZ,Amat)
702                    table.append([name[:-3],calc,obs,esd])
703                    rowLabels.append(str(i))               
704            else:
705                colLabels = ['A+SymOp - B+SymOp','calc','obs','esd']
706                for i,[indx,ops,obs,esd] in enumerate(bondList):
707                    names = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,ct-1)
708                    XYZ = np.array(G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,cx,3))
709                    XYZ = G2mth.getSyXYZ(XYZ,ops,SGData)
710                    calc = G2mth.getRestDist(XYZ,Amat)
711                    table.append([names[0]+'+('+ops[0]+') - '+names[1]+'+('+ops[1]+')',calc,obs,esd])
712                    rowLabels.append(str(i))
713            bondTable = G2gd.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
714            Bonds = G2gd.GSGrid(BondRestr)
715            Bonds.SetTable(bondTable, True)
716            Bonds.AutoSizeColumns(False)
717            for r in range(len(bondList)):
718                for c in range(2):
719                    Bonds.SetReadOnly(r,c,True)
720                    Bonds.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
721            Bonds.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK,OnRowSelect)
722            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDeleteRestraint, id=G2gd.wxID_RESTDELETE)
723            G2frame.dataFrame.Bind(wx.EVT_MENU, OnChangeValue, id=G2gd.wxID_RESRCHANGEVAL)
724            G2frame.dataFrame.Bind(wx.EVT_MENU, OnChangeEsd, id=G2gd.wxID_RESTCHANGEESD)
725            mainSizer.Add(Bonds,0,)
726        else:
727            mainSizer.Add(wx.StaticText(BondRestr,-1,'No bond distance restraints for this phase'),0,)
728
729        BondRestr.SetSizer(mainSizer)
730        Size = mainSizer.Fit(G2frame.dataFrame)
731        Size[0] = 600
732        Size[1] += 50       #make room for tab
733        BondRestr.SetSize(Size)
734        BondRestr.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
735        G2frame.dataFrame.SetSize(Size)
736       
737    def UpdateAngleRestr(angleRestData):
738       
739        def OnChangeValue(event):
740            rows = Angles.GetSelectedRows()
741            if not rows:
742                return
743            Angles.ClearSelection()
744            val = angleList[rows[0]][3]
745            dlg = G2phG.SingleFloatDialog(G2frame,'New value','Enter new value for angle',val,[0.,360.],'%.2f')
746            if dlg.ShowModal() == wx.ID_OK:
747                parm = dlg.GetValue()
748                for r in rows:
749                    angleList[r][3] = parm
750            dlg.Destroy()
751            UpdateAngleRestr(angleRestData)               
752
753        def OnChangeEsd(event):
754            rows = Angles.GetSelectedRows()
755            if not rows:
756                return
757            Angles.ClearSelection()
758            val = angleList[rows[0]][4]
759            dlg = G2phG.SingleFloatDialog(G2frame,'New value','Enter new esd for angle',val,[0.,5.],'%.2f')
760            if dlg.ShowModal() == wx.ID_OK:
761                parm = dlg.GetValue()
762                for r in rows:
763                    angleList[r][4] = parm
764            dlg.Destroy()
765            UpdateAngleRestr(angleRestData)               
766                                           
767        def OnDeleteRestraint(event):
768            rows = Angles.GetSelectedRows()
769            if not rows:
770                return
771            rows.sort()
772            rows.reverse()
773            for row in rows:
774                angleList.remove(angleList[row])
775            UpdateAngleRestr(angleRestData)               
776           
777        AngleRestr.DestroyChildren()
778        dataDisplay = wx.Panel(AngleRestr)
779        mainSizer = wx.BoxSizer(wx.VERTICAL)
780        mainSizer.Add((5,5),0)
781        mainSizer.Add(WtBox(AngleRestr,angleRestData),0,wx.ALIGN_CENTER_VERTICAL)
782
783        angleList = angleRestData['Angles']
784        if len(angleList):
785            table = []
786            rowLabels = []
787            Types = [wg.GRID_VALUE_STRING,]+3*[wg.GRID_VALUE_FLOAT+':10,2',]
788            if 'macro' in General['Type']:
789                colLabels = ['(res) A - (res) B - (res) C','calc','obs','esd']
790                for i,[indx,ops,obs,esd] in enumerate(angleList):
791                    atoms = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,0,4)
792                    name = ''
793                    for atom in atoms:
794                        name += '('+atom[1]+atom[0].strip()+atom[2]+') '+atom[3]+' - '
795                    XYZ = np.array(G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,cx,3))
796                    calc = G2mth.getRestAngle(XYZ,Amat)
797                    table.append([name[:-3],calc,obs,esd])
798                    rowLabels.append(str(i))                               
799            else:
800                colLabels = ['A+SymOp - B+SymOp - C+SymOp','calc','obs','esd']
801                for i,[indx,ops,obs,esd] in enumerate(angleList):
802                    atoms = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,ct-1)
803                    name = atoms[0]+'+('+ops[0]+') - '+atoms[1]+'+('+ops[1]+') - '+atoms[2]+ \
804                    '+('+ops[2]+')'
805                    XYZ = np.array(G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,cx,3))
806                    XYZ = G2mth.getSyXYZ(XYZ,ops,SGData)
807                    calc = G2mth.getRestAngle(XYZ,Amat)
808                    table.append([name,calc,obs,esd])
809                    rowLabels.append(str(i))
810            angleTable = G2gd.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
811            Angles = G2gd.GSGrid(AngleRestr)
812            Angles.SetTable(angleTable, True)
813            Angles.AutoSizeColumns(False)
814            for r in range(len(angleList)):
815                for c in range(2):
816                    Angles.SetReadOnly(r,c,True)
817                    Angles.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
818            Angles.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK,OnRowSelect)
819            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDeleteRestraint, id=G2gd.wxID_RESTDELETE)
820            G2frame.dataFrame.Bind(wx.EVT_MENU, OnChangeValue, id=G2gd.wxID_RESRCHANGEVAL)
821            G2frame.dataFrame.Bind(wx.EVT_MENU, OnChangeEsd, id=G2gd.wxID_RESTCHANGEESD)
822            mainSizer.Add(Angles,0,)
823        else:
824            mainSizer.Add(wx.StaticText(AngleRestr,-1,'No bond angle restraints for this phase'),0,)
825
826        AngleRestr.SetSizer(mainSizer)
827        Size = mainSizer.Fit(G2frame.dataFrame)
828        Size[0] = 600
829        Size[1] += 50      #make room for tab
830        AngleRestr.SetSize(Size)
831        AngleRestr.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
832        G2frame.dataFrame.SetSize(Size)
833#        G2frame.dataFrame.setSizePosLeft(Size)
834   
835    def UpdatePlaneRestr(planeRestData):
836       
837        items = G2frame.dataFrame.RestraintEdit.GetMenuItems()
838        for item in items:
839            if item.GetLabel() in ['Change value']:
840                item.Enable(False)
841
842        def OnChangeEsd(event):
843            rows = Planes.GetSelectedRows()
844            if not rows:
845                return
846            Planes.ClearSelection()
847            val = planeList[rows[0]][4]
848            dlg = G2phG.SingleFloatDialog(G2frame,'New value','Enter new esd for plane',val,[0.,5.],'%.2f')
849            if dlg.ShowModal() == wx.ID_OK:
850                parm = dlg.GetValue()
851                for r in rows:
852                    planeList[r][4] = parm
853            dlg.Destroy()
854            UpdatePlaneRestr(planeRestData)               
855                                           
856        def OnDeleteRestraint(event):
857            rows = Planes.GetSelectedRows()
858            if not rows:
859                return
860            rows.sort()
861            rows.reverse()
862            for row in rows:
863                planeList.remove(planeList[row])
864            UpdatePlaneRestr(planeRestData)               
865           
866        PlaneRestr.DestroyChildren()
867        dataDisplay = wx.Panel(PlaneRestr)
868        mainSizer = wx.BoxSizer(wx.VERTICAL)
869        mainSizer.Add((5,5),0)
870        mainSizer.Add(WtBox(PlaneRestr,planeRestData),0,wx.ALIGN_CENTER_VERTICAL)
871
872        planeList = planeRestData['Planes']
873        if len(planeList):
874            table = []
875            rowLabels = []
876            Types = [wg.GRID_VALUE_STRING,]+3*[wg.GRID_VALUE_FLOAT+':10,2',]
877            if 'macro' in General['Type']:
878                colLabels = ['(res) atom','calc','obs','esd']
879                for i,[indx,ops,obs,esd] in enumerate(planeList):
880                    atoms = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,0,4)
881                    name = ''
882                    for a,atom in enumerate(atoms):
883                        name += '('+atom[1]+atom[0].strip()+atom[2]+') '+atom[3]+' - '
884                        if (a+1)%3 == 0:
885                            name += '\n'
886                    XYZ = np.array(G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,cx,3))
887                    calc = G2mth.getRestPlane(XYZ,Amat)
888                    table.append([name[:-3],calc,obs,esd])
889                    rowLabels.append(str(i))
890            else:                               
891                colLabels = ['atom+SymOp','calc','obs','esd']
892                for i,[indx,ops,obs,esd] in enumerate(planeList):
893                    atoms = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,ct-1)
894                    XYZ = np.array(G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,cx,3))
895                    XYZ = G2mth.getSyXYZ(XYZ,ops,SGData)
896                    calc = G2mth.getRestPlane(XYZ,Amat)
897                    name = ''
898                    for a,atom in enumerate(atoms):
899                        name += atom+'+ ('+ops[a]+'),'
900                        if (a+1)%3 == 0:
901                            name += '\n'
902                    table.append([name[:-1],calc,obs,esd])
903                    rowLabels.append(str(i))
904            planeTable = G2gd.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
905            Planes = G2gd.GSGrid(PlaneRestr)
906            Planes.SetTable(planeTable, True)
907            Planes.AutoSizeColumns(False)
908            Planes.AutoSizeRows(False)
909            for r in range(len(planeList)):
910                for c in range(3):
911                    Planes.SetReadOnly(r,c,True)
912                    Planes.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
913            Planes.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK,OnRowSelect)
914            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDeleteRestraint, id=G2gd.wxID_RESTDELETE)
915            G2frame.dataFrame.Bind(wx.EVT_MENU, OnChangeEsd, id=G2gd.wxID_RESTCHANGEESD)
916            mainSizer.Add(Planes,0,)
917        else:
918            mainSizer.Add(wx.StaticText(PlaneRestr,-1,'No plane restraints for this phase'),0,)
919
920        PlaneRestr.SetSizer(mainSizer)
921        Size = mainSizer.Fit(G2frame.dataFrame)
922        Size[0] = 600
923        Size[1] += 50       #make room for tab
924        PlaneRestr.SetSize(Size)
925        PlaneRestr.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
926        G2frame.dataFrame.SetSize(Size)
927#        G2frame.dataFrame.setSizePosLeft(Size)
928   
929    def UpdateChiralRestr(chiralRestData):
930
931        def OnDeleteRestraint(event):
932            rows = Volumes.GetSelectedRows()
933            if not rows:
934                return
935            rows.sort()
936            rows.reverse()
937            for row in rows:
938                volumeList.remove(volumeList[row])
939            UpdateChiralRestr(chiralRestData)               
940           
941        def OnChangeValue(event):
942            rows = Volumes.GetSelectedRows()
943            if not rows:
944                return
945            Volumes.ClearSelection()
946            val = volumeList[rows[0]][3]
947            dlg = G2phG.SingleFloatDialog(G2frame,'New value','Enter new value for chiral volume',val,[0.,360.],'%.2f')
948            if dlg.ShowModal() == wx.ID_OK:
949                parm = dlg.GetValue()
950                for r in rows:
951                    volumeList[r][3] = parm
952            dlg.Destroy()
953            UpdateChiralRestr(chiralRestData)               
954
955        def OnChangeEsd(event):
956            rows = Volumes.GetSelectedRows()
957            if not rows:
958                return
959            Volumes.ClearSelection()
960            val = volumeList[rows[0]][4]
961            dlg = G2phG.SingleFloatDialog(G2frame,'New value','Enter new esd for chiral volume',val,[0.,5.],'%.2f')
962            if dlg.ShowModal() == wx.ID_OK:
963                parm = dlg.GetValue()
964                for r in rows:
965                    volumeList[r][4] = parm
966            dlg.Destroy()
967            UpdateChiralRestr(chiralRestData)               
968                                           
969        ChiralRestr.DestroyChildren()
970        dataDisplay = wx.Panel(ChiralRestr)
971        mainSizer = wx.BoxSizer(wx.VERTICAL)
972        mainSizer.Add((5,5),0)
973        mainSizer.Add(WtBox(ChiralRestr,chiralRestData),0,wx.ALIGN_CENTER_VERTICAL)
974
975        volumeList = chiralRestData['Volumes']
976        if len(volumeList):
977            table = []
978            rowLabels = []
979            Types = [wg.GRID_VALUE_STRING,]+3*[wg.GRID_VALUE_FLOAT+':10,2',]
980            if 'macro' in General['Type']:
981                colLabels = ['(res) O (res) A (res) B (res) C','calc','obs','esd']
982                for i,[indx,ops,obs,esd] in enumerate(volumeList):
983                    atoms = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,0,4)
984                    name = ''
985                    for atom in atoms:
986                        name += '('+atom[1]+atom[0].strip()+atom[2]+') '+atom[3]+' '
987                    XYZ = np.array(G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,cx,3))
988                    calc = G2mth.getRestChiral(XYZ,Amat)
989                    table.append([name,calc,obs,esd])
990                    rowLabels.append(str(i))
991            else:
992                colLabels = ['O+SymOp  A+SymOp  B+SymOp  C+SymOp)','calc','obs','esd']
993                for i,[indx,ops,obs,esd] in enumerate(volumeList):
994                    atoms = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,ct-1)
995                    name = atoms[0]+'+('+ops[0]+') '+atoms[1]+'+('+ops[1]+') '+atoms[2]+ \
996                        '+('+ops[2]+') '+atoms[3]+'+('+ops[3]+')'
997                    XYZ = np.array(G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,cx,3))
998                    XYZ = G2mth.getSyXYZ(XYZ,ops,SGData)
999                    calc = G2mth.getRestChiral(XYZ,Amat)
1000                    table.append([name,calc,obs,esd])
1001                    rowLabels.append(str(i))
1002            volumeTable = G2gd.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
1003            Volumes = G2gd.GSGrid(ChiralRestr)
1004            Volumes.SetTable(volumeTable, True)
1005            Volumes.AutoSizeColumns(False)
1006            for r in range(len(volumeList)):
1007                for c in range(2):
1008                    Volumes.SetReadOnly(r,c,True)
1009                    Volumes.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
1010            Volumes.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK,OnRowSelect)
1011            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDeleteRestraint, id=G2gd.wxID_RESTDELETE)
1012            G2frame.dataFrame.Bind(wx.EVT_MENU, OnChangeValue, id=G2gd.wxID_RESRCHANGEVAL)
1013            G2frame.dataFrame.Bind(wx.EVT_MENU, OnChangeEsd, id=G2gd.wxID_RESTCHANGEESD)
1014            mainSizer.Add(Volumes,0,)
1015        else:
1016            mainSizer.Add(wx.StaticText(ChiralRestr,-1,'No chiral volume restraints for this phase'),0,)
1017
1018        ChiralRestr.SetSizer(mainSizer)
1019        Size = mainSizer.Fit(G2frame.dataFrame)
1020        Size[0] = 600
1021        Size[1] += 50       #make room for tab
1022        ChiralRestr.SetSize(Size)
1023        ChiralRestr.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
1024        G2frame.dataFrame.SetSize(Size)
1025#        G2frame.dataFrame.setSizePosLeft(Size)
1026   
1027    def UpdateTorsionRestr(torsionRestData):
1028
1029        def OnDeleteRestraint(event):
1030            rows = Torsions.GetSelectedRows()
1031            if not rows:
1032                return
1033            rows.sort()
1034            rows.reverse()
1035            for row in rows:
1036                torsionList.remove(torsionList[row])
1037            UpdateTorsionRestr(torsionRestData)               
1038           
1039        def OnChangeEsd(event):
1040            rows = Torsions.GetSelectedRows()
1041            if not rows:
1042                return
1043            Torsions.ClearSelection()
1044            val = torsionList[rows[0]][4]
1045            dlg = G2phG.SingleFloatDialog(G2frame,'New value','Enter new esd for torsion restraints',val,[0.,5.],'%.2f')
1046            if dlg.ShowModal() == wx.ID_OK:
1047                parm = dlg.GetValue()
1048                for r in rows:
1049                    volumeList[r][4] = parm
1050            dlg.Destroy()
1051            UpdateTorsionRestr(torsionRestData)               
1052                                           
1053        TorsionRestr.DestroyChildren()
1054        dataDisplay = wx.Panel(TorsionRestr)
1055        mainSizer = wx.BoxSizer(wx.VERTICAL)
1056        mainSizer.Add((5,5),0)
1057        mainSizer.Add(WtBox(TorsionRestr,torsionRestData),0,wx.ALIGN_CENTER_VERTICAL)
1058        mainSizer.Add(wx.StaticText(TorsionRestr,-1,'Torsion function coefficients:'),0,wx.ALIGN_CENTER_VERTICAL)
1059       
1060        coeffDict = torsionRestData['Coeff']
1061        if len(coeffDict):
1062            table = []
1063            rowLabels = []
1064            Types = 9*[wg.GRID_VALUE_FLOAT+':10,4',]
1065            colLabels = ['Mag A','Pos A','Width A','Mag B','Pos B','Width B','Mag C','Pos C','Width C']
1066            for item in coeffDict:
1067                rowLabels.append(item)
1068                table.append(coeffDict[item])
1069            coeffTable = G2gd.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
1070            Coeff = G2gd.GSGrid(TorsionRestr)
1071            Coeff.SetTable(coeffTable, True)
1072            Coeff.AutoSizeColumns(False)
1073            for r in range(len(coeffDict)):
1074                for c in range(9):
1075                    Coeff.SetReadOnly(r,c,True)
1076                    Coeff.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
1077            mainSizer.Add(Coeff,0,)
1078        mainSizer.Add((5,5))
1079        torsionList = torsionRestData['Torsions']
1080        mainSizer.Add(wx.StaticText(TorsionRestr,-1,'Torsion restraints:'),0,wx.ALIGN_CENTER_VERTICAL)
1081        if len(torsionList):
1082            table = []
1083            rowLabels = []
1084            Types = 2*[wg.GRID_VALUE_STRING,]+3*[wg.GRID_VALUE_FLOAT+':10,2',]
1085            if 'macro' in General['Type']:
1086                colLabels = ['(res) A (res) B (res) C (res) D','coef name','torsion','obs E','esd']
1087                for i,[indx,ops,cofName,esd] in enumerate(torsionList):
1088                    atoms = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,0,4)
1089                    name = ''
1090                    for atom in atoms:
1091                        name += '('+atom[1]+atom[0].strip()+atom[2]+') '+atom[3]+' '
1092                    XYZ = np.array(G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,cx,3))
1093                    tor,calc = G2mth.getRestTorsion(XYZ,Amat,coeffDict[cofName])
1094                    table.append([name,cofName,tor,calc,esd])
1095                    rowLabels.append(str(i))
1096            else:
1097                colLabels = ['A+SymOp  B+SymOp  C+SymOp  D+SymOp)','coef name','torsion','obs E','esd']
1098                for i,[indx,ops,cofName,esd] in enumerate(torsionList):
1099                    atoms = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,ct-1)
1100                    XYZ = np.array(G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,cx,3))
1101                    XYZ = G2mth.getSyXYZ(XYZ,ops,SGData)
1102                    tor,calc = G2mth.getRestTorsion(XYZ,Amat,coeffDict[cofName])
1103                    table.append([atoms[0]+'+('+ops[0]+') '+atoms[1]+'+('+ops[1]+') '+atoms[2]+ \
1104                    '+('+ops[2]+') '+atoms[3]+'+('+ops[3]+')',cofName,tor,calc,esd])
1105                    rowLabels.append(str(i))
1106            torsionTable = G2gd.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
1107            Torsions = G2gd.GSGrid(TorsionRestr)
1108            Torsions.SetTable(torsionTable, True)
1109            Torsions.AutoSizeColumns(False)
1110            for r in range(len(torsionList)):
1111                for c in range(2):
1112                    Torsions.SetReadOnly(r,c,True)
1113                    Torsions.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
1114            Torsions.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK,OnRowSelect)
1115            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDeleteRestraint, id=G2gd.wxID_RESTDELETE)
1116            G2frame.dataFrame.Bind(wx.EVT_MENU, OnChangeEsd, id=G2gd.wxID_RESTCHANGEESD)
1117            mainSizer.Add(Torsions,0,)
1118        else:
1119            mainSizer.Add(wx.StaticText(TorsionRestr,-1,'No torsion restraints for this phase'),0,)
1120
1121        TorsionRestr.SetSizer(mainSizer)
1122        Size = mainSizer.Fit(G2frame.dataFrame)
1123        Size[0] = 600
1124        Size[1] += 50       #make room for tab
1125        TorsionRestr.SetSize(Size)
1126        TorsionRestr.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
1127        G2frame.dataFrame.SetSize(Size)
1128#        G2frame.dataFrame.setSizePosLeft(Size)
1129
1130    def UpdateRamaRestr(ramaRestData):
1131
1132        def OnDeleteRestraint(event):
1133            rows = Volumes.GetSelectedRows()
1134            if not rows:
1135                return
1136            rows.sort()
1137            rows.reverse()
1138            for row in rows:
1139                ramaList.remove(ramaList[row])
1140            UpdateRamaRestr(ramaRestData)               
1141           
1142        RamaRestr.DestroyChildren()
1143        dataDisplay = wx.Panel(RamaRestr)
1144        mainSizer = wx.BoxSizer(wx.VERTICAL)
1145        mainSizer.Add((5,5),0)
1146        mainSizer.Add(WtBox(RamaRestr,ramaRestData),0,wx.ALIGN_CENTER_VERTICAL)
1147
1148        ramaList = ramaRestData['Ramas']
1149        if len(ramaList):
1150            table = []
1151            rowLabels = []
1152            Types = 2*[wg.GRID_VALUE_STRING,]+3*[wg.GRID_VALUE_FLOAT+':10,2',]
1153            if 'macro' in General['Type']:
1154                colLabels = ['(res) A (res) B (res) C (res) D (res) E','coef name','calc','obs','esd']
1155                for i,[indx,ops,cofName,dcalc,dobs,esd] in enumerate(ramaList):
1156                    atoms = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,0,4)
1157                    name = ''
1158                    for atom in atoms:
1159                        name += '('+atom[1]+atom[0].strip()+atom[2]+') '+atom[3]+' '
1160                    table.append([name,cofName,dcalc,dobs,esd])
1161                    rowLabels.append(str(i))
1162            else:
1163                colLabels = ['A+SymOp  B+SymOp  C+SymOp  D+SymOp  E+SymOp)','coef name','calc','obs','esd']
1164                for i,[indx,ops,cofName,dcalc,dobs,esd] in enumerate(ramaList):
1165                    atoms = G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,ct-1)
1166                    table.append([atoms[0]+'+('+ops[0]+') '+atoms[1]+'+('+ops[1]+') '+atoms[2]+ \
1167                    '+('+ops[2]+') '+atoms[3]+'+('+ops[3]+')',cofName,dcalc,dobs,esd])
1168                    rowLabels.append(str(i))
1169            ramaTable = G2gd.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
1170            Ramas = G2gd.GSGrid(RamaRestr)
1171            Ramas.SetTable(ramaTable, True)
1172            Ramas.AutoSizeColumns(False)
1173            for r in range(len(ramaList)):
1174                for c in range(2):
1175                    Ramas.SetReadOnly(r,c,True)
1176                    Ramas.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
1177            Ramas.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK,OnRowSelect)
1178            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDeleteRestraint, id=G2gd.wxID_RESTDELETE)
1179            G2frame.dataFrame.Bind(wx.EVT_MENU, OnChangeEsd, id=G2gd.wxID_RESTCHANGEESD)
1180            mainSizer.Add(Ramas,0,)
1181        else:
1182            mainSizer.Add(wx.StaticText(RamaRestr,-1,'No Ramachandran restraints for this phase'),0,)
1183
1184        RamaRestr.SetSizer(mainSizer)
1185        Size = mainSizer.Fit(G2frame.dataFrame)
1186        Size[0] = 600
1187        Size[1] += 50       #make room for tab
1188        RamaRestr.SetSize(Size)
1189        RamaRestr.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
1190        G2frame.dataFrame.SetSize(Size)
1191#        G2frame.dataFrame.setSizePosLeft(Size)
1192
1193    def OnPageChanged(event):
1194        page = event.GetSelection()
1195        text = G2frame.dataDisplay.GetPageText(page)
1196        if text == 'Bond restraints':
1197            G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.RestraintMenu)
1198            bondRestData = restrData['Bond']
1199            UpdateBondRestr(bondRestData)
1200        elif text == 'Angle restraints':
1201            G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.RestraintMenu)
1202            angleRestData = restrData['Angle']
1203            UpdateAngleRestr(angleRestData)
1204        elif text == 'Plane restraints':
1205            G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.RestraintMenu)
1206            planeRestData = restrData['Plane']
1207            UpdatePlaneRestr(planeRestData)
1208        elif text == 'Chiral restraints':
1209            G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.RestraintMenu)
1210            chiralRestData = restrData['Chiral']
1211            UpdateChiralRestr(chiralRestData)
1212        elif text == 'Torsion restraints':
1213            G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.RestraintMenu)
1214            torsionRestData = restrData['Torsion']
1215            UpdateTorsionRestr(torsionRestData)
1216        elif text == 'Ramachandran restraints':
1217            G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.RestraintMenu)
1218            ramaRestData = restrData['Rama']
1219            UpdateRamaRestr(ramaRestData)
1220        event.Skip()
1221
1222    def SetStatusLine(text):
1223        Status.SetStatusText(text)                                     
1224       
1225    if G2frame.dataDisplay:
1226        G2frame.dataDisplay.Destroy()
1227       
1228    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.RestraintMenu)
1229    G2frame.dataFrame.SetLabel('restraints for '+phaseName)
1230    if not G2frame.dataFrame.GetStatusBar():
1231        Status = G2frame.dataFrame.CreateStatusBar()
1232    SetStatusLine('')
1233   
1234    G2frame.dataFrame.RestraintEdit.Enable(G2gd.wxID_RESTSELPHASE,False)
1235    if len(Phases) > 1:
1236        G2frame.dataFrame.RestraintEdit.Enable(G2gd.wxID_RESTSELPHASE,True)
1237        G2frame.dataFrame.Bind(wx.EVT_MENU, OnSelectPhase, id=G2gd.wxID_RESTSELPHASE)
1238    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddRestraint, id=G2gd.wxID_RESTRAINTADD)
1239    if 'macro' in phasedata['General']['Type']:
1240        G2frame.dataFrame.RestraintEdit.Enable(G2gd.wxID_AARESTRAINTADD,True)
1241        G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddAARestraint, id=G2gd.wxID_AARESTRAINTADD)
1242    G2frame.dataDisplay = G2gd.GSNoteBook(parent=G2frame.dataFrame,size=G2frame.dataFrame.GetClientSize())
1243   
1244    BondRestr = wx.ScrolledWindow(G2frame.dataDisplay)
1245    G2frame.dataDisplay.AddPage(BondRestr,'Bond restraints')
1246    AngleRestr = wx.ScrolledWindow(G2frame.dataDisplay)
1247    G2frame.dataDisplay.AddPage(AngleRestr,'Angle restraints')
1248    PlaneRestr = wx.ScrolledWindow(G2frame.dataDisplay)
1249    G2frame.dataDisplay.AddPage(PlaneRestr,'Plane restraints')
1250    ChiralRestr = wx.ScrolledWindow(G2frame.dataDisplay)
1251    G2frame.dataDisplay.AddPage(ChiralRestr,'Chiral restraints')
1252    TorsionRestr = wx.ScrolledWindow(G2frame.dataDisplay)
1253    G2frame.dataDisplay.AddPage(TorsionRestr,'Torsion restraints')
1254    RamaRestr = wx.ScrolledWindow(G2frame.dataDisplay)
1255    G2frame.dataDisplay.AddPage(RamaRestr,'Ramachandran restraints')
1256   
1257    UpdateBondRestr(restrData['Bond'])
1258
1259    G2frame.dataDisplay.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, OnPageChanged)
Note: See TracBrowser for help on using the repository browser.