source: trunk/GSASIIphsGUI.py @ 851

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

more rigid body stuff, plotting, RB placement, import of more types of coordinate files
Z-matrix RB deleted (it will be imported & converted)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 192.9 KB
Line 
1# -*- coding: utf-8 -*-
2#GSASII - phase data display routines
3########### SVN repository information ###################
4# $Date: 2013-02-15 21:04:56 +0000 (Fri, 15 Feb 2013) $
5# $Author: vondreele $
6# $Revision: 851 $
7# $URL: trunk/GSASIIphsGUI.py $
8# $Id: GSASIIphsGUI.py 851 2013-02-15 21:04:56Z vondreele $
9########### SVN repository information ###################
10import wx
11import wx.grid as wg
12import wx.lib.gridmovers as wgmove
13import wx.wizard as wz
14import matplotlib as mpl
15import math
16import copy
17import time
18import sys
19import random as ran
20import cPickle
21import GSASIIpath
22GSASIIpath.SetVersionNumber("$Revision: 851 $")
23import GSASIIlattice as G2lat
24import GSASIIspc as G2spc
25import GSASIIElem as G2elem
26import GSASIIElemGUI as G2elemGUI
27import GSASIIddataGUI as G2ddG
28import GSASIIplot as G2plt
29import GSASIIgrid as G2gd
30import GSASIIIO as G2IO
31import GSASIIstruct as G2str
32import GSASIImath as G2mth
33import GSASIIpwd as G2pwd
34import numpy as np
35import numpy.linalg as nl
36import numpy.ma as ma
37
38VERY_LIGHT_GREY = wx.Colour(235,235,235)
39WHITE = wx.Colour(255,255,255)
40BLACK = wx.Colour(0,0,0)
41mapDefault = {'MapType':'','RefList':'','Resolution':0.5,'Show bonds':True,
42                'rho':[],'rhoMax':0.,'mapSize':10.0,'cutOff':50.,'Flip':False}
43# trig functions in degrees
44sind = lambda x: np.sin(x*np.pi/180.)
45tand = lambda x: np.tan(x*np.pi/180.)
46cosd = lambda x: np.cos(x*np.pi/180.)
47asind = lambda x: 180.*np.arcsin(x)/np.pi
48acosd = lambda x: 180.*np.arccos(x)/np.pi
49
50def UpdatePhaseData(G2frame,Item,data,oldPage):
51   
52#patch
53    if 'RBModels' not in data:
54        data['RBModels'] = {}
55#end patch   
56
57    global rbAtmDict   
58    rbAtmDict = {}
59    if G2frame.dataDisplay:
60        G2frame.dataDisplay.Destroy()
61    PhaseName = G2frame.PatternTree.GetItemText(Item)
62    G2gd.SetDataMenuBar(G2frame)
63    G2frame.dataFrame.SetLabel('Phase Data for '+PhaseName)
64    G2frame.dataFrame.CreateStatusBar()
65    G2frame.dataDisplay = G2gd.GSNoteBook(parent=G2frame.dataFrame,size=G2frame.dataFrame.GetClientSize())
66
67    def SetupGeneral():
68        generalData = data['General']
69        atomData = data['Atoms']
70        generalData['AtomTypes'] = []
71        generalData['Isotopes'] = {}
72# various patches
73        if 'Isotope' not in generalData:
74            generalData['Isotope'] = {}
75        if 'Data plot type' not in generalData:
76            generalData['Data plot type'] = 'Mustrain'
77        if 'POhkl' not in generalData:
78            generalData['POhkl'] = [0,0,1]
79        if 'Map' not in generalData:
80            generalData['Map'] = mapDefault
81        if 'Flip' not in generalData:
82            generalData['Flip'] = {'RefList':'','Resolution':0.5,'Norm element':'None',
83                'k-factor':0.1,'k-Max':20.}
84        if 'doPawley' not in generalData:
85            generalData['doPawley'] = False
86        if 'Pawley dmin' not in generalData:
87            generalData['Pawley dmin'] = 1.0
88        if 'Pawley neg wt' not in generalData:
89            generalData['Pawley neg wt'] = 0.0
90        if 'MCSA controls' not in generalData:
91            generalData['MCSA controls'] = {'Data source':'','Annealing':[50.0,0.001,0.90,1000],
92            'dmin':2.0,'Algolrithm':'Normal','Jump coeff':[0.95,0.5]} #'Normal','Random jump','Tremayne jump'
93# end of patches
94        generalData['NoAtoms'] = {}
95        generalData['BondRadii'] = []
96        generalData['AngleRadii'] = []
97        generalData['vdWRadii'] = []
98        generalData['AtomMass'] = []
99        generalData['Color'] = []
100        generalData['Mydir'] = G2frame.dirname
101        cx,ct,cs,cia = [3,1,7,9]
102        if generalData['Type'] =='macromolecular':
103            cx,ct,cs,cia = [6,4,10,12]
104        generalData['AtomPtrs'] = [cx,ct,cs,cia]
105        for atom in atomData:
106            atom[ct] = atom[ct].lower().capitalize()              #force to standard form
107            if generalData['AtomTypes'].count(atom[ct]):
108                generalData['NoAtoms'][atom[ct]] += atom[cs-1]*float(atom[cs+1])
109            elif atom[ct] != 'UNK':
110                Info = G2elem.GetAtomInfo(atom[ct])
111                generalData['AtomTypes'].append(atom[ct])
112                generalData['Z'] = Info['Z']
113                generalData['Isotopes'][atom[ct]] = Info['Isotopes']
114                generalData['BondRadii'].append(Info['Drad'])
115                generalData['AngleRadii'].append(Info['Arad'])
116                generalData['vdWRadii'].append(Info['Vdrad'])
117                if atom[ct] in generalData['Isotope']:
118                    generalData['AtomMass'].append(Info['Isotopes'][generalData['Isotope'][atom[ct]]][0])
119                else:
120                    generalData['Isotope'][atom[ct]] = 'Nat. Abund.'
121                    generalData['AtomMass'].append(Info['Mass'])
122                generalData['NoAtoms'][atom[ct]] = atom[cs-1]*float(atom[cs+1])
123                generalData['Color'].append(Info['Color'])
124        F000X = 0.
125        F000N = 0.
126        for i,elem in enumerate(generalData['AtomTypes']):
127            F000X += generalData['NoAtoms'][elem]*generalData['Z']
128            isotope = generalData['Isotope'][elem]
129            F000N += generalData['NoAtoms'][elem]*generalData['Isotopes'][elem][isotope][1]
130        generalData['F000X'] = F000X
131        generalData['F000N'] = F000N
132       
133
134################################################################################
135##### General phase routines
136################################################################################
137
138    def UpdateGeneral():
139       
140        ''' default dictionary structure for phase data: (taken from GSASII.py)
141        'General':{
142            'Name':PhaseName
143            'Type':'nuclear'
144            'SGData':SGData
145            'Cell':[False,10.,10.,10.,90.,90.,90,1000.]
146            'AtomPtrs':[]
147            'Histogram list':['',]
148            'Pawley dmin':1.0,
149            'Pawley neg wt':0.0}
150        'Atoms':[]
151        'Drawing':{}
152        '''
153       
154        phaseTypes = ['nuclear','modulated','magnetic','macromolecular']
155        SetupGeneral()
156        generalData = data['General']
157        Map = generalData['Map']
158        Flip = generalData['Flip']
159        MCSA = generalData['MCSA controls'] 
160        PWDR = any(['PWDR' in item for item in data['Histograms'].keys()])
161       
162        def NameSizer():
163                   
164            def OnPhaseName(event):
165                oldName = generalData['Name']
166                generalData['Name'] = NameTxt.GetValue()
167                G2frame.G2plotNB.Rename(oldName,generalData['Name'])
168                G2frame.dataFrame.SetLabel('Phase Data for '+generalData['Name'])
169                G2frame.PatternTree.SetItemText(Item,generalData['Name'])
170                #Hmm, need to change phase name key in Reflection Lists for each histogram
171                           
172            def OnPhaseType(event):
173                if not generalData['AtomTypes']:             #can change only if no atoms!
174                    generalData['Type'] = TypeTxt.GetValue()
175                    wx.CallAfter(UpdateGeneral)
176                else:
177                    TypeTxt.SetValue(generalData['Type'])               
178               
179            def OnSpaceGroup(event):
180                SpcGp = SGTxt.GetValue()
181                SGErr,SGData = G2spc.SpcGroup(SpcGp)
182                # try a lookup on the user-supplied name
183                if SGErr:
184                    SpGrpNorm = G2spc.StandardizeSpcName(SpcGp)
185                    if SpGrpNorm:
186                        E,SGData = G2spc.SpcGroup(SpGrpNorm)
187                        if not E: SGErr = False
188                if SGErr:
189                    text = [G2spc.SGErrors(SGErr)+'\nSpace Group set to previous']
190                    SGTxt.SetValue(generalData['SGData']['SpGrp'])
191                    msg = 'Space Group Error'
192                    Style = wx.ICON_EXCLAMATION
193                else:
194                    text = G2spc.SGPrint(SGData)
195                    generalData['SGData'] = SGData
196                    msg = 'Space Group Information'
197                    Style = wx.ICON_INFORMATION
198                Text = ''
199                for line in text:
200                    Text += line+'\n'
201                wx.MessageBox(Text,caption=msg,style=Style)
202#                dataDisplay.DestroyChildren()           #needed to clear away bad cellSizer, etc.
203                wx.CallAfter(UpdateGeneral)
204               
205            nameSizer = wx.BoxSizer(wx.HORIZONTAL)
206            nameSizer.Add(wx.StaticText(dataDisplay,-1,' Phase name: '),0,wx.ALIGN_CENTER_VERTICAL)
207            NameTxt = wx.TextCtrl(dataDisplay,-1,value=generalData['Name'],style=wx.TE_PROCESS_ENTER)
208            NameTxt.Bind(wx.EVT_TEXT_ENTER,OnPhaseName)
209            NameTxt.Bind(wx.EVT_KILL_FOCUS,OnPhaseName)
210            nameSizer.Add(NameTxt,0,wx.ALIGN_CENTER_VERTICAL)
211            nameSizer.Add(wx.StaticText(dataDisplay,-1,'  Phase type: '),0,wx.ALIGN_CENTER_VERTICAL)
212            TypeTxt = wx.ComboBox(dataDisplay,-1,value=generalData['Type'],choices=phaseTypes,
213                style=wx.CB_READONLY|wx.CB_DROPDOWN)
214            TypeTxt.Bind(wx.EVT_COMBOBOX, OnPhaseType)
215            nameSizer.Add(TypeTxt,0,wx.ALIGN_CENTER_VERTICAL)
216            nameSizer.Add(wx.StaticText(dataDisplay,-1,'  Space group: '),0,wx.ALIGN_CENTER_VERTICAL)
217            SGTxt = wx.TextCtrl(dataDisplay,-1,value=generalData['SGData']['SpGrp'],style=wx.TE_PROCESS_ENTER)
218            SGTxt.Bind(wx.EVT_TEXT_ENTER,OnSpaceGroup)
219            nameSizer.Add(SGTxt,0,wx.ALIGN_CENTER_VERTICAL)
220            return nameSizer
221           
222        def CellSizer():
223           
224            cellGUIlist = [[['m3','m3m'],4,zip([" Unit cell: a = "," Vol = "],["%.5f","%.3f"],[True,False],[0,0])],
225            [['3R','3mR'],6,zip([" a = "," alpha = "," Vol = "],["%.5f","%.3f","%.3f"],[True,True,False],[0,2,0])],
226            [['3','3m1','31m','6/m','6/mmm','4/m','4/mmm'],6,zip([" a = "," c = "," Vol = "],["%.5f","%.5f","%.3f"],[True,True,False],[0,2,0])],
227            [['mmm'],8,zip([" a = "," b = "," c = "," Vol = "],["%.5f","%.5f","%.5f","%.3f"],
228                [True,True,True,False],[0,1,2,0])],
229            [['2/m'+'a'],10,zip([" a = "," b = "," c = "," alpha = "," Vol = "],
230                ["%.5f","%.5f","%.5f","%.3f","%.3f"],[True,True,True,True,False],[0,1,2,4,0])],
231            [['2/m'+'b'],10,zip([" a = "," b = "," c = "," beta = "," Vol = "],
232                ["%.5f","%.5f","%.5f","%.3f","%.3f"],[True,True,True,True,False],[0,1,2,4,0])],
233            [['2/m'+'c'],10,zip([" a = "," b = "," c = "," gamma = "," Vol = "],
234                ["%.5f","%.5f","%.5f","%.3f","%.3f"],[True,True,True,True,False],[0,1,2,4,0])],
235            [['-1'],8,zip([" a = "," b = "," c = "," Vol = "," alpha = "," beta = "," gamma = "],
236                ["%.5f","%.5f","%.5f","%.3f","%.3f","%.3f","%.3f"],
237                [True,True,True,False,True,True,True],[0,1,2,0,3,4,5])]]
238               
239            def OnCellRef(event):
240                generalData['Cell'][0] = cellRef.GetValue()
241               
242            def OnCellChange(event):
243                SGData = generalData['SGData']
244                laue = SGData['SGLaue']
245                if laue == '2/m':
246                    laue += SGData['SGUniq']
247                cell = generalData['Cell']
248                Obj = event.GetEventObject()
249                ObjId = cellList.index(Obj.GetId())
250                try:
251                    value = max(1.0,float(Obj.GetValue()))
252                except ValueError:
253                    if ObjId < 3:               #bad cell edge - reset
254                        value = controls[6+ObjId]
255                    else:                       #bad angle
256                        value = 90.
257                if laue in ['m3','m3m']:
258                    cell[1] = cell[2] = cell[3] = value
259                    cell[4] = cell[5] = cell[6] = 90.0
260                    Obj.SetValue("%.5f"%(cell[1]))
261                elif laue in ['3R','3mR']:
262                    if ObjId == 0:
263                        cell[1] = cell[2] = cell[3] = value
264                        Obj.SetValue("%.5f"%(cell[1]))
265                    else:
266                        cell[4] = cell[5] = cell[6] = value
267                        Obj.SetValue("%.5f"%(cell[4]))
268                elif laue in ['3','3m1','31m','6/m','6/mmm','4/m','4/mmm']:                   
269                    cell[4] = cell[5] = 90.
270                    cell[6] = 120.
271                    if laue in ['4/m','4/mmm']:
272                        cell[6] = 90.
273                    if ObjId == 0:
274                        cell[1] = cell[2] = value
275                        Obj.SetValue("%.5f"%(cell[1]))
276                    else:
277                        cell[3] = value
278                        Obj.SetValue("%.5f"%(cell[3]))
279                elif laue in ['mmm']:
280                    cell[ObjId+1] = value
281                    cell[4] = cell[5] = cell[6] = 90.
282                    Obj.SetValue("%.5f"%(cell[ObjId+1]))
283                elif laue in ['2/m'+'a']:
284                    cell[5] = cell[6] = 90.
285                    if ObjId != 3:
286                        cell[ObjId+1] = value
287                        Obj.SetValue("%.5f"%(cell[ObjId+1]))
288                    else:
289                        cell[4] = value
290                        Obj.SetValue("%.3f"%(cell[4]))
291                elif laue in ['2/m'+'b']:
292                    cell[4] = cell[6] = 90.
293                    if ObjId != 3:
294                        cell[ObjId+1] = value
295                        Obj.SetValue("%.5f"%(cell[ObjId+1]))
296                    else:
297                        cell[5] = value
298                        Obj.SetValue("%.3f"%(cell[5]))
299                elif laue in ['2/m'+'c']:
300                    cell[5] = cell[6] = 90.
301                    if ObjId != 3:
302                        cell[ObjId+1] = value
303                        Obj.SetValue("%.5f"%(cell[ObjId+1]))
304                    else:
305                        cell[6] = value
306                        Obj.SetValue("%.3f"%(cell[6]))
307                else:
308                    cell[ObjId+1] = value
309                    if ObjId < 3:
310                        Obj.SetValue("%.5f"%(cell[1+ObjId]))
311                    else:
312                        Obj.SetValue("%.3f"%(cell[1+ObjId]))                       
313                cell[7] = G2lat.calc_V(G2lat.cell2A(cell[1:7]))
314                volVal.SetValue("%.3f"%(cell[7]))
315                density,mattCoeff = G2mth.getDensity(generalData)
316                if denSizer:
317                    denSizer[1].SetValue('%.3f'%(density))
318                    if denSizer[2]:
319                        denSizer[2].SetValue('%.3f'%(mattCoeff))
320                generalData['Cell'] = cell
321           
322            cell = generalData['Cell']
323            laue = generalData['SGData']['SGLaue']
324            if laue == '2/m':
325                laue += generalData['SGData']['SGUniq']
326            for cellGUI in cellGUIlist:
327                if laue in cellGUI[0]:
328                    useGUI = cellGUI
329            cellSizer = wx.FlexGridSizer(2,useGUI[1]+1,5,5)
330            if PWDR:
331                cellRef = wx.CheckBox(dataDisplay,-1,label='Refine unit cell:')
332                cellSizer.Add(cellRef,0,wx.ALIGN_CENTER_VERTICAL)
333                cellRef.Bind(wx.EVT_CHECKBOX, OnCellRef)
334                cellRef.SetValue(cell[0])
335            cellList = []
336            for txt,fmt,ifEdit,Id in useGUI[2]:
337                cellSizer.Add(wx.StaticText(dataDisplay,label=txt),0,wx.ALIGN_CENTER_VERTICAL)
338                if ifEdit:          #a,b,c,etc.
339                    cellVal = wx.TextCtrl(dataDisplay,value=(fmt%(cell[Id+1])),
340                        style=wx.TE_PROCESS_ENTER)
341                    cellVal.Bind(wx.EVT_TEXT_ENTER,OnCellChange)       
342                    cellVal.Bind(wx.EVT_KILL_FOCUS,OnCellChange)
343                    cellSizer.Add(cellVal,0,wx.ALIGN_CENTER_VERTICAL)
344                    cellList.append(cellVal.GetId())
345                else:               #volume
346                    volVal = wx.TextCtrl(dataDisplay,value=(fmt%(cell[7])),style=wx.TE_READONLY)
347                    volVal.SetBackgroundColour(VERY_LIGHT_GREY)
348                    cellSizer.Add(volVal,0,wx.ALIGN_CENTER_VERTICAL)
349            return cellSizer
350           
351        def ElemSizer():
352           
353            def OnIsotope(event):
354                Obj = event.GetEventObject()
355                item = Indx[Obj.GetId()]
356                isotope = Obj.GetValue()
357                generalData['Isotope'][item] = isotope
358                indx = generalData['AtomTypes'].index(item)
359                data['General']['AtomMass'][indx] = generalData['Isotopes'][item][isotope][0]
360                density,mattCoeff = G2mth.getDensity(generalData)
361                denSizer[1].SetValue('%.3f'%(density))
362                if denSizer[2]:
363                    denSizer[2].SetValue('%.3f'%(mattCoeff))
364               
365            elemSizer = wx.FlexGridSizer(8,len(generalData['AtomTypes'])+1,1,1)
366            elemSizer.Add(wx.StaticText(dataDisplay,label=' Elements'),0,wx.ALIGN_CENTER_VERTICAL)
367            for elem in generalData['AtomTypes']:
368                typTxt = wx.TextCtrl(dataDisplay,value=elem,style=wx.TE_READONLY)
369                typTxt.SetBackgroundColour(VERY_LIGHT_GREY)
370                elemSizer.Add(typTxt,0,wx.ALIGN_CENTER_VERTICAL)
371            elemSizer.Add(wx.StaticText(dataDisplay,label=' Isotope'),0,wx.ALIGN_CENTER_VERTICAL)
372            for elem in generalData['AtomTypes']:
373                choices = generalData['Isotopes'][elem].keys()
374                isoSel = wx.ComboBox(dataDisplay,-1,value=generalData['Isotope'][elem],choices=choices,
375                    style=wx.CB_READONLY|wx.CB_DROPDOWN)
376                isoSel.Bind(wx.EVT_COMBOBOX,OnIsotope)
377                Indx[isoSel.GetId()] = elem
378                elemSizer.Add(isoSel,1,wx.ALIGN_CENTER_VERTICAL|wx.EXPAND)
379            elemSizer.Add(wx.StaticText(dataDisplay,label=' No. per cell'),0,wx.ALIGN_CENTER_VERTICAL)
380            for elem in generalData['AtomTypes']:
381                numbTxt = wx.TextCtrl(dataDisplay,value='%.1f'%(generalData['NoAtoms'][elem]),
382                    style=wx.TE_READONLY)
383                numbTxt.SetBackgroundColour(VERY_LIGHT_GREY)
384                elemSizer.Add(numbTxt,0,wx.ALIGN_CENTER_VERTICAL)
385            elemSizer.Add(wx.StaticText(dataDisplay,label=' Atom weight'),0,wx.ALIGN_CENTER_VERTICAL)
386            for wt in generalData['AtomMass']:
387                wtTxt = wx.TextCtrl(dataDisplay,value='%.3f'%(wt),style=wx.TE_READONLY)
388                wtTxt.SetBackgroundColour(VERY_LIGHT_GREY)
389                elemSizer.Add(wtTxt,0,wx.ALIGN_CENTER_VERTICAL)
390            elemSizer.Add(wx.StaticText(dataDisplay,label=' Bond radii'),0,wx.ALIGN_CENTER_VERTICAL)
391            for rad in generalData['BondRadii']:
392                bondRadii = wx.TextCtrl(dataDisplay,value='%.2f'%(rad),style=wx.TE_READONLY)
393                bondRadii.SetBackgroundColour(VERY_LIGHT_GREY)
394                elemSizer.Add(bondRadii,0,wx.ALIGN_CENTER_VERTICAL)
395            elemSizer.Add(wx.StaticText(dataDisplay,label=' Angle radii'),0,wx.ALIGN_CENTER_VERTICAL)
396            for rad in generalData['AngleRadii']:
397                elemTxt = wx.TextCtrl(dataDisplay,value='%.2f'%(rad),style=wx.TE_READONLY)
398                elemTxt.SetBackgroundColour(VERY_LIGHT_GREY)
399                elemSizer.Add(elemTxt,0,wx.ALIGN_CENTER_VERTICAL)
400            elemSizer.Add(wx.StaticText(dataDisplay,label=' van der Waals radii'),0,wx.ALIGN_CENTER_VERTICAL)
401            for rad in generalData['vdWRadii']:
402                elemTxt = wx.TextCtrl(dataDisplay,value='%.2f'%(rad),style=wx.TE_READONLY)
403                elemTxt.SetBackgroundColour(VERY_LIGHT_GREY)
404                elemSizer.Add(elemTxt,0,wx.ALIGN_CENTER_VERTICAL)
405            elemSizer.Add(wx.StaticText(dataDisplay,label=' Default color'),0,wx.ALIGN_CENTER_VERTICAL)
406            for R,G,B in generalData['Color']:
407                colorTxt = wx.TextCtrl(dataDisplay,value='',style=wx.TE_READONLY)
408                colorTxt.SetBackgroundColour(wx.Colour(R,G,B))
409                elemSizer.Add(colorTxt,0,wx.ALIGN_CENTER_VERTICAL)
410            return elemSizer
411       
412        def DenSizer():
413           
414            mass = G2mth.getMass(generalData)
415            density,mattCoeff = G2mth.getDensity(generalData)
416            denSizer = wx.BoxSizer(wx.HORIZONTAL)
417            denSizer.Add(wx.StaticText(dataDisplay,-1,' Density: '),0,wx.ALIGN_CENTER_VERTICAL)
418            denTxt = wx.TextCtrl(dataDisplay,-1,'%.3f'%(density),style=wx.TE_READONLY)
419            denTxt.SetBackgroundColour(VERY_LIGHT_GREY)
420            denSizer.Add(denTxt,0,wx.ALIGN_CENTER_VERTICAL)
421            mattTxt = None       
422            if generalData['Type'] == 'macromolecular' and mass > 0.0:
423                denSizer.Add(wx.StaticText(dataDisplay,-1,' Matthews coeff.: '),
424                    0,wx.ALIGN_CENTER_VERTICAL)
425                mattTxt = wx.TextCtrl(dataDisplay,-1,'%.3f'%(mattCoeff),style=wx.TE_READONLY)
426                mattTxt.SetBackgroundColour(VERY_LIGHT_GREY)
427                denSizer.Add(mattTxt,0,wx.ALIGN_CENTER_VERTICAL)
428            return denSizer,denTxt,mattTxt
429           
430        def PawleySizer():
431           
432            def OnPawleyRef(event):
433                generalData['doPawley'] = pawlRef.GetValue()
434           
435            def OnPawleyVal(event):
436                try:
437                    dmin = float(pawlVal.GetValue())
438                    if 0.25 <= dmin <= 20.:
439                        generalData['Pawley dmin'] = dmin
440                except ValueError:
441                    pass
442                pawlVal.SetValue("%.3f"%(generalData['Pawley dmin']))          #reset in case of error               
443           
444            def OnPawleyNegWt(event):
445                try:
446                    wt = float(pawlNegWt.GetValue())
447                    if 0. <= wt <= 1.:
448                        generalData['Pawley neg wt'] = wt
449                except ValueError:
450                    pass
451                pawlNegWt.SetValue("%.2f"%(generalData['Pawley neg wt']))          #reset in case of error               
452
453            pawleySizer = wx.BoxSizer(wx.HORIZONTAL)
454            pawleySizer.Add(wx.StaticText(dataDisplay,label=' Pawley controls: '),0,wx.ALIGN_CENTER_VERTICAL)
455            pawlRef = wx.CheckBox(dataDisplay,-1,label=' Do Pawley refinement?')
456            pawlRef.SetValue(generalData['doPawley'])
457            pawlRef.Bind(wx.EVT_CHECKBOX,OnPawleyRef)
458            pawleySizer.Add(pawlRef,0,wx.ALIGN_CENTER_VERTICAL)
459            pawleySizer.Add(wx.StaticText(dataDisplay,label=' Pawley dmin: '),0,wx.ALIGN_CENTER_VERTICAL)
460            pawlVal = wx.TextCtrl(dataDisplay,value='%.3f'%(generalData['Pawley dmin']),style=wx.TE_PROCESS_ENTER)
461            pawlVal.Bind(wx.EVT_TEXT_ENTER,OnPawleyVal)       
462            pawlVal.Bind(wx.EVT_KILL_FOCUS,OnPawleyVal)
463            pawleySizer.Add(pawlVal,0,wx.ALIGN_CENTER_VERTICAL)
464            pawleySizer.Add(wx.StaticText(dataDisplay,label=' Pawley neg. wt.: '),0,wx.ALIGN_CENTER_VERTICAL)
465            pawlNegWt = wx.TextCtrl(dataDisplay,value='%.2f'%(generalData['Pawley neg wt']),style=wx.TE_PROCESS_ENTER)
466            pawlNegWt.Bind(wx.EVT_TEXT_ENTER,OnPawleyNegWt)       
467            pawlNegWt.Bind(wx.EVT_KILL_FOCUS,OnPawleyNegWt)
468            pawleySizer.Add(pawlNegWt,0,wx.ALIGN_CENTER_VERTICAL)
469            return pawleySizer
470           
471        def MapSizer():
472           
473            def OnMapType(event):
474                Map['MapType'] = mapType.GetValue()
475               
476            def OnRefList(event):
477                Map['RefList'] = refList.GetValue()
478               
479            def OnResVal(event):
480                try:
481                    res = float(mapRes.GetValue())
482                    if 0.25 <= res <= 20.:
483                        Map['Resolution'] = res
484                except ValueError:
485                    pass
486                mapRes.SetValue("%.2f"%(Map['Resolution']))          #reset in case of error
487           
488            def OnCutOff(event):
489                try:
490                    res = float(cutOff.GetValue())
491                    if 10.0 <= res <= 100.:
492                        Map['cutOff'] = res
493                except ValueError:
494                    pass
495                cutOff.SetValue("%.1f"%(Map['cutOff']))          #reset in case of error
496           
497            #patch
498            if 'cutOff' not in Map:
499                Map['cutOff'] = 100.0
500            mapTypes = ['Fobs','Fcalc','delt-F','2*Fo-Fc','Patterson']
501            refList = data['Histograms'].keys()
502            if not generalData['AtomTypes']:
503                 mapTypes = ['Patterson',]
504                 Map['MapType'] = 'Patterson'
505            mapSizer = wx.BoxSizer(wx.VERTICAL)
506            lineSizer = wx.BoxSizer(wx.HORIZONTAL)
507            lineSizer.Add(wx.StaticText(dataDisplay,label=' Fourier map controls: Map type: '),0,wx.ALIGN_CENTER_VERTICAL)
508            mapType = wx.ComboBox(dataDisplay,-1,value=Map['MapType'],choices=mapTypes,
509                style=wx.CB_READONLY|wx.CB_DROPDOWN)
510            mapType.Bind(wx.EVT_COMBOBOX,OnMapType)
511            lineSizer.Add(mapType,0,wx.ALIGN_CENTER_VERTICAL)
512            lineSizer.Add(wx.StaticText(dataDisplay,label=' Reflection set from: '),0,wx.ALIGN_CENTER_VERTICAL)
513            refList = wx.ComboBox(dataDisplay,-1,value=Map['RefList'],choices=refList,
514                style=wx.CB_READONLY|wx.CB_DROPDOWN)
515            refList.Bind(wx.EVT_COMBOBOX,OnRefList)
516            lineSizer.Add(refList,0,wx.ALIGN_CENTER_VERTICAL)
517            mapSizer.Add(lineSizer,0,wx.ALIGN_CENTER_VERTICAL)
518            line2Sizer = wx.BoxSizer(wx.HORIZONTAL)
519            line2Sizer.Add(wx.StaticText(dataDisplay,label=' Resolution: '),0,wx.ALIGN_CENTER_VERTICAL)
520            mapRes =  wx.TextCtrl(dataDisplay,value='%.2f'%(Map['Resolution']),style=wx.TE_PROCESS_ENTER)
521            mapRes.Bind(wx.EVT_TEXT_ENTER,OnResVal)       
522            mapRes.Bind(wx.EVT_KILL_FOCUS,OnResVal)
523            line2Sizer.Add(mapRes,0,wx.ALIGN_CENTER_VERTICAL)
524            line2Sizer.Add(wx.StaticText(dataDisplay,label=' Peak cutoff %: '),0,wx.ALIGN_CENTER_VERTICAL)
525            cutOff =  wx.TextCtrl(dataDisplay,value='%.1f'%(Map['cutOff']),style=wx.TE_PROCESS_ENTER)
526            cutOff.Bind(wx.EVT_TEXT_ENTER,OnCutOff)       
527            cutOff.Bind(wx.EVT_KILL_FOCUS,OnCutOff)
528            line2Sizer.Add(cutOff,0,wx.ALIGN_CENTER_VERTICAL)
529            mapSizer.Add(line2Sizer,0,wx.ALIGN_CENTER_VERTICAL)
530            return mapSizer
531               
532        def FlipSizer():
533            if 'k-Max' not in Flip: Flip['k-Max'] = 20.
534           
535            def OnRefList(event):
536                Flip['RefList'] = refList.GetValue()
537               
538            def OnNormElem(event):
539                PE = G2elemGUI.PickElement(G2frame,ifNone=True)
540                if PE.ShowModal() == wx.ID_OK:
541                    Flip['Norm element'] = PE.Elem.strip()
542                    normElem.SetLabel(Flip['Norm element'])
543                PE.Destroy()               
544               
545            def OnResVal(event):
546                try:
547                    res = float(flipRes.GetValue())
548                    if 0.25 <= res <= 20.:
549                        Flip['Resolution'] = res
550                except ValueError:
551                    pass
552                flipRes.SetValue("%.2f"%(Flip['Resolution']))          #reset in case of error
553           
554            def OnkFactor(event):
555                try:
556                    res = float(kFactor.GetValue())
557                    if 0.1 <= res <= 1.2:
558                        Flip['k-factor'] = res
559                except ValueError:
560                    pass
561                kFactor.SetValue("%.3f"%(Flip['k-factor']))          #reset in case of error
562           
563            def OnkMax(event):
564                try:
565                    res = float(kMax.GetValue())
566                    if res >= 10.:
567                        Flip['k-Max'] = res
568                except ValueError:
569                    pass
570                kMax.SetValue("%.1f"%(Flip['k-Max']))          #reset in case of error
571
572            refList = data['Histograms'].keys()
573            flipSizer = wx.BoxSizer(wx.VERTICAL)
574            lineSizer = wx.BoxSizer(wx.HORIZONTAL)
575            lineSizer.Add(wx.StaticText(dataDisplay,label=' Charge flip controls: Reflection set from: '),0,wx.ALIGN_CENTER_VERTICAL)
576            refList = wx.ComboBox(dataDisplay,-1,value=Flip['RefList'],choices=refList,
577                style=wx.CB_READONLY|wx.CB_DROPDOWN)
578            refList.Bind(wx.EVT_COMBOBOX,OnRefList)
579            lineSizer.Add(refList,0,wx.ALIGN_CENTER_VERTICAL)
580            lineSizer.Add(wx.StaticText(dataDisplay,label=' Normalizing element: '),0,wx.ALIGN_CENTER_VERTICAL)
581            normElem = wx.Button(dataDisplay,label=Flip['Norm element'],style=wx.TE_READONLY)
582            normElem.Bind(wx.EVT_BUTTON,OnNormElem)
583            lineSizer.Add(normElem,0,wx.ALIGN_CENTER_VERTICAL)
584            flipSizer.Add(lineSizer,0,wx.ALIGN_CENTER_VERTICAL)
585            line2Sizer = wx.BoxSizer(wx.HORIZONTAL)
586            line2Sizer.Add(wx.StaticText(dataDisplay,label=' Resolution: '),0,wx.ALIGN_CENTER_VERTICAL)
587            flipRes =  wx.TextCtrl(dataDisplay,value='%.2f'%(Flip['Resolution']),style=wx.TE_PROCESS_ENTER)
588            flipRes.Bind(wx.EVT_TEXT_ENTER,OnResVal)       
589            flipRes.Bind(wx.EVT_KILL_FOCUS,OnResVal)
590            line2Sizer.Add(flipRes,0,wx.ALIGN_CENTER_VERTICAL)
591            line2Sizer.Add(wx.StaticText(dataDisplay,label=' k-Factor (0.1-1.2): '),0,wx.ALIGN_CENTER_VERTICAL)
592            kFactor =  wx.TextCtrl(dataDisplay,value='%.3f'%(Flip['k-factor']),style=wx.TE_PROCESS_ENTER)
593            kFactor.Bind(wx.EVT_TEXT_ENTER,OnkFactor)       
594            kFactor.Bind(wx.EVT_KILL_FOCUS,OnkFactor)
595            line2Sizer.Add(kFactor,0,wx.ALIGN_CENTER_VERTICAL)
596            line2Sizer.Add(wx.StaticText(dataDisplay,label=' k-Max (>=10.0): '),0,wx.ALIGN_CENTER_VERTICAL)
597            kMax = wx.TextCtrl(dataDisplay,value='%.1f'%(Flip['k-Max']),style=wx.TE_PROCESS_ENTER)
598            kMax.Bind(wx.EVT_TEXT_ENTER,OnkMax)       
599            kMax.Bind(wx.EVT_KILL_FOCUS,OnkMax)
600            line2Sizer.Add(kMax,0,wx.ALIGN_CENTER_VERTICAL)
601            flipSizer.Add(line2Sizer,0,wx.ALIGN_CENTER_VERTICAL)
602            return flipSizer
603           
604        def MCSASizer():
605            Ind = {}
606           
607            def OnRefList(event):
608                MCSA['Data source'] = refList.GetValue()
609           
610            def OnDmin(event):
611                try:
612                    val = float(dmin.GetValue())
613                    if 1.0 <= val < 5.0:
614                        MCSA['dmin'] = val
615                except ValueError:
616                    pass
617                dmin.SetValue("%.3f"%(MCSA['dmin']))          #reset in case of error
618           
619            def OnAlist(event):
620                MCSA['Algolrithm'] = Alist.GetValue()
621                if 'Tremayne' in MCSA['Algolrithm']:
622                    wx.CallAfter(UpdateGeneral)
623           
624            def OnAjump(event):
625                Obj = event.GetEventObject()
626                ind = Indx[Obj.GetId()]
627                try:
628                    val = float(Obj.GetValue())
629                    if .0 <= val <= 1.0:
630                        MCSA['Jump coeff'][ind] = val
631                except ValueError:
632                    pass
633                Obj.SetValue("%.3f"%(MCSA['Jump coeff'][ind]))          #reset in case of error
634           
635            def OnAnneal(event):
636                Obj = event.GetEventObject()
637                ind,fmt = Indx[Obj.GetId()]
638                if ind < 3:
639                    try:
640                        val = float(Obj.GetValue())
641                        if .0 <= val:
642                            MCSA['Annealing'][ind] = val
643                    except ValueError:
644                        pass
645                else:
646                    try:
647                        val = int(Obj.GetValue())
648                        if 1 <= val:
649                            MCSA['Annealing'][3] = val
650                    except ValueError:
651                        pass
652                   
653                Obj.SetValue(fmt%(MCSA['Annealing'][ind]))          #reset in case of error
654                       
655            refList = []
656            if len(data['Pawley ref']):
657                refList = ['Pawley reflections']
658            for item in data['Histograms'].keys():
659                if 'HKLF' in item:
660                    refList.append(item)
661            mcsaSizer = wx.BoxSizer(wx.VERTICAL)
662            lineSizer = wx.BoxSizer(wx.HORIZONTAL)
663            lineSizer.Add(wx.StaticText(dataDisplay,label=' Monte Carlo/Simulated Annealing controls: Reflection set from: '),0,wx.ALIGN_CENTER_VERTICAL)
664            refList = wx.ComboBox(dataDisplay,-1,value=MCSA['Data source'],choices=refList,
665                style=wx.CB_READONLY|wx.CB_DROPDOWN)
666            refList.Bind(wx.EVT_COMBOBOX,OnRefList)
667            lineSizer.Add(refList,0,wx.ALIGN_CENTER_VERTICAL)
668            lineSizer.Add(wx.StaticText(dataDisplay,label=' d-min: '),0,wx.ALIGN_CENTER_VERTICAL)
669            dmin = wx.TextCtrl(dataDisplay,-1,value='%.3f'%(MCSA['dmin']),style=wx.TE_PROCESS_ENTER)
670            dmin.Bind(wx.EVT_TEXT_ENTER,OnDmin)       
671            dmin.Bind(wx.EVT_KILL_FOCUS,OnDmin)
672            lineSizer.Add(dmin,0,wx.ALIGN_CENTER_VERTICAL)
673            mcsaSizer.Add(lineSizer)
674            mcsaSizer.Add((5,5),)
675            line2Sizer = wx.BoxSizer(wx.HORIZONTAL)
676            Achoice = ['Normal','Random jump','Tremayne jump']
677            line2Sizer.Add(wx.StaticText(dataDisplay,label=' MC/SA algorithm: '),0,wx.ALIGN_CENTER_VERTICAL)
678            Alist = wx.ComboBox(dataDisplay,-1,value=MCSA['Algolrithm'],choices=Achoice,
679                style=wx.CB_READONLY|wx.CB_DROPDOWN)
680            Alist.Bind(wx.EVT_COMBOBOX,OnAlist)
681            line2Sizer.Add(Alist,0,wx.ALIGN_CENTER_VERTICAL)
682            if 'Tremayne' in MCSA['Algolrithm']:
683                for i,name in enumerate([' A-jump: ',' B-jump: ']):
684                    line2Sizer.Add(wx.StaticText(dataDisplay,label=name),0,wx.ALIGN_CENTER_VERTICAL)
685                    Ajump =  wx.TextCtrl(dataDisplay,-1,value='%.3f'%(MCSA['Jump coeff'][i]),style=wx.TE_PROCESS_ENTER)
686                    Ajump.Bind(wx.EVT_TEXT_ENTER,OnAjump)       
687                    Ajump.Bind(wx.EVT_KILL_FOCUS,OnAjump)
688                    Indx[Ajump.GetId()] = i
689                    line2Sizer.Add(Ajump,0,wx.ALIGN_CENTER_VERTICAL)
690            mcsaSizer.Add(line2Sizer)
691            mcsaSizer.Add((5,5),)
692            line3Sizer = wx.BoxSizer(wx.HORIZONTAL)
693            line3Sizer.Add(wx.StaticText(dataDisplay,label=' Annealing schedule: '),0,wx.ALIGN_CENTER_VERTICAL)
694            names = [' Start temp: ',' Final temp: ',' Slope: ',' No. trials: ']
695            fmts = ['%.1f','%.5f','%.2f','%d']
696            for i,[name,fmt] in enumerate(zip(names,fmts)):
697                line3Sizer.Add(wx.StaticText(dataDisplay,label=name),0,wx.ALIGN_CENTER_VERTICAL)
698                anneal =  wx.TextCtrl(dataDisplay,-1,value=fmt%(MCSA['Annealing'][i]),style=wx.TE_PROCESS_ENTER)
699                anneal.Bind(wx.EVT_TEXT_ENTER,OnAnneal)       
700                anneal.Bind(wx.EVT_KILL_FOCUS,OnAnneal)
701                Indx[anneal.GetId()] = [i,fmt]
702                line3Sizer.Add(anneal,0,wx.ALIGN_CENTER_VERTICAL)
703            mcsaSizer.Add(line3Sizer)           
704            return mcsaSizer
705               
706        General.DestroyChildren()
707        dataDisplay = wx.Panel(General)
708        mainSizer = wx.BoxSizer(wx.VERTICAL)
709        mainSizer.Add((5,5),0)
710        mainSizer.Add(NameSizer(),0)
711        mainSizer.Add((5,5),0)       
712        mainSizer.Add(CellSizer(),0)
713        mainSizer.Add((5,5),0)
714       
715        Indx = {}
716        denSizer = None
717        if len(generalData['AtomTypes']):
718            denSizer = DenSizer()
719            mainSizer.Add(denSizer[0])
720            mainSizer.Add((5,5),0)           
721            mainSizer.Add(ElemSizer())
722        mainSizer.Add(wx.StaticText(dataDisplay,-1,150*'-'),0,)
723           
724        mainSizer.Add(PawleySizer())
725        mainSizer.Add(wx.StaticText(dataDisplay,-1,150*'-'),0,)
726       
727        mainSizer.Add(MapSizer())
728        mainSizer.Add(wx.StaticText(dataDisplay,-1,150*'-'),0,)
729
730        mainSizer.Add(FlipSizer())
731        mainSizer.Add(wx.StaticText(dataDisplay,-1,150*'-'),0,)
732
733        mainSizer.Add(MCSASizer())
734
735        dataDisplay.SetSizer(mainSizer)
736        Size = mainSizer.Fit(G2frame.dataFrame)
737        Size[1] += 35                           #compensate for status bar
738        dataDisplay.SetSize(Size)
739        G2frame.dataFrame.SetStatusText('')
740        G2frame.dataFrame.setSizePosLeft(Size)
741
742################################################################################
743#####  Atom routines
744################################################################################
745
746    def FillAtomsGrid(Atoms):
747
748        G2frame.dataFrame.setSizePosLeft([700,300])
749        generalData = data['General']
750        atomData = data['Atoms']
751        DData = data['Drawing']
752        resRBData = data['RBModels'].get('Residue',[])
753        vecRBData = data['RBModels'].get('Vector',[])
754        rbAtmDict = {}
755        for rbObj in resRBData:
756            exclList = ['X' for i in range(len(rbObj['Ids']))]
757            rbAtmDict.update(dict(zip(rbObj['Ids'],exclList)))
758        # for vector one exclList will be 'x' or 'xu' if TLS used in RB
759        Items = [G2gd.wxID_ATOMSEDITINSERT,G2gd.wxID_ATOMSEDITDELETE,G2gd.wxID_ATOMSREFINE, 
760            G2gd.wxID_ATOMSMODIFY,G2gd.wxID_ATOMSTRANSFORM,G2gd.wxID_ATOMVIEWINSERT,G2gd.wxID_ATOMMOVE]
761        if atomData:
762            for item in Items:   
763                G2frame.dataFrame.AtomsMenu.Enable(item,True)
764        else:
765            for item in Items:
766                G2frame.dataFrame.AtomsMenu.Enable(item,False)
767        Items = [G2gd.wxID_ATOMVIEWINSERT, G2gd.wxID_ATOMSVIEWADD,G2gd.wxID_ATOMMOVE]
768        if 'showABC' in data['Drawing']:
769            for item in Items:
770                G2frame.dataFrame.AtomsMenu.Enable(item,True)
771        else:
772            for item in Items:
773                G2frame.dataFrame.AtomsMenu.Enable(item,False)
774
775        AAchoice = ": ,ALA,ARG,ASN,ASP,CYS,GLN,GLU,GLY,HIS,ILE,LEU,LYS,MET,PHE,PRO,SER,THR,TRP,TYR,VAL,MSE,HOH,UNK"
776        Types = [wg.GRID_VALUE_STRING,wg.GRID_VALUE_STRING,wg.GRID_VALUE_CHOICE+": ,X,XU,U,F,FX,FXU,FU",]+ \
777            3*[wg.GRID_VALUE_FLOAT+':10,5',]+[wg.GRID_VALUE_FLOAT+':10,4', #x,y,z,frac
778            wg.GRID_VALUE_STRING,wg.GRID_VALUE_STRING,wg.GRID_VALUE_CHOICE+":I,A",]
779        Types += 7*[wg.GRID_VALUE_FLOAT+':10,5',]
780        colLabels = ['Name','Type','refine','x','y','z','frac','site sym','mult','I/A','Uiso','U11','U22','U33','U12','U13','U23']
781        if generalData['Type'] == 'magnetic':
782            colLabels += ['Mx','My','Mz']
783            Types[2] = wg.GRID_VALUE_CHOICE+": ,X,XU,U,M,MX,MXU,MU,F,FX,FXU,FU,FM,FMX,FMU,"
784            Types += 3*[wg.GRID_VALUE_FLOAT+':10,4',]
785        elif generalData['Type'] == 'macromolecular':
786            colLabels = ['res no','residue','chain'] + colLabels
787            Types = [wg.GRID_VALUE_STRING,
788                wg.GRID_VALUE_CHOICE+AAchoice,
789                wg.GRID_VALUE_STRING] + Types
790        elif generalData['Type'] == 'modulated':
791            Types += []
792            colLabels += []
793
794        def RefreshAtomGrid(event):
795
796            r,c =  event.GetRow(),event.GetCol()
797            if r < 0 and c < 0:
798                for row in range(Atoms.GetNumberRows()):
799                    Atoms.SelectRow(row,True)                   
800            if r < 0:                          #double click on col label! Change all atoms!
801                sel = -1
802                noSkip = True
803                if Atoms.GetColLabelValue(c) == 'refine':
804                    Type = generalData['Type']
805                    if Type in ['nuclear','macromolecular']:
806                        choice = ['F - site fraction','X - coordinates','U - thermal parameters']
807                    elif Type in ['magnetic',]:
808                        choice = ['F - site fraction','X - coordinates','U - thermal parameters','M - magnetic moment']
809                    dlg = wx.MultiChoiceDialog(G2frame,'Select','Refinement controls',choice)
810                    if dlg.ShowModal() == wx.ID_OK:
811                        sel = dlg.GetSelections()
812                        parms = ''
813                        for x in sel:
814                            parms += choice[x][0]
815                    dlg.Destroy()
816                elif Atoms.GetColLabelValue(c) == 'I/A':
817                    choice = ['Isotropic','Anisotropic']
818                    dlg = wx.SingleChoiceDialog(G2frame,'Select','Thermal Motion',choice)
819                    if dlg.ShowModal() == wx.ID_OK:
820                        sel = dlg.GetSelection()
821                        parms = choice[sel][0]
822                    dlg.Destroy()
823                elif Atoms.GetColLabelValue(c) == 'Type':
824                    choice = generalData['AtomTypes']
825                    dlg = wx.SingleChoiceDialog(G2frame,'Select','Atom types',choice)
826                    if dlg.ShowModal() == wx.ID_OK:
827                        sel = dlg.GetSelection()
828                        parms = choice[sel]
829                        noSkip = False
830                        Atoms.ClearSelection()
831                        for row in range(Atoms.GetNumberRows()):
832                            if parms == atomData[row][c]:
833                                Atoms.SelectRow(row,True)
834                    dlg.Destroy()
835                    SetupGeneral()
836                elif Atoms.GetColLabelValue(c) == 'residue':
837                    choice = []
838                    for r in range(Atoms.GetNumberRows()):
839                        if str(atomData[r][c]) not in choice:
840                            choice.append(str(atomData[r][c]))
841                    choice.sort()
842                    dlg = wx.SingleChoiceDialog(G2frame,'Select','Residue',choice)
843                    if dlg.ShowModal() == wx.ID_OK:
844                        sel = dlg.GetSelection()
845                        parms = choice[sel]
846                        noSkip = False
847                        Atoms.ClearSelection()
848                        for row in range(Atoms.GetNumberRows()):
849                            if parms == atomData[row][c]:
850                                Atoms.SelectRow(row,True)
851                    dlg.Destroy()
852                elif Atoms.GetColLabelValue(c) == 'res no':
853                    choice = []
854                    for r in range(Atoms.GetNumberRows()):
855                        if str(atomData[r][c]) not in choice:
856                            choice.append(str(atomData[r][c]))
857                    dlg = wx.SingleChoiceDialog(G2frame,'Select','Residue no.',choice)
858                    if dlg.ShowModal() == wx.ID_OK:
859                        sel = dlg.GetSelection()
860                        parms = choice[sel]
861                        noSkip = False
862                        Atoms.ClearSelection()
863                        for row in range(Atoms.GetNumberRows()):
864                            if int(parms) == atomData[row][c]:
865                                Atoms.SelectRow(row,True)
866                    dlg.Destroy()
867                elif Atoms.GetColLabelValue(c) == 'chain':
868                    choice = []
869                    for r in range(Atoms.GetNumberRows()):
870                        if atomData[r][c] not in choice:
871                            choice.append(atomData[r][c])
872                    dlg = wx.SingleChoiceDialog(G2frame,'Select','Chain',choice)
873                    if dlg.ShowModal() == wx.ID_OK:
874                        sel = dlg.GetSelection()
875                        parms = choice[sel]
876                        noSkip = False
877                        Atoms.ClearSelection()
878                        for row in range(Atoms.GetNumberRows()):
879                            if parms == atomData[row][c]:
880                                Atoms.SelectRow(row,True)
881                    dlg.Destroy()
882                elif Atoms.GetColLabelValue(c) == 'Uiso':       #this needs to ask for value
883                    pass                                        #& then change all 'I' atoms
884                if sel >= 0 and noSkip:
885                    ui = colLabels.index('U11')
886                    us = colLabels.index('Uiso')
887                    ss = colLabels.index('site sym')
888                    for r in range(Atoms.GetNumberRows()):
889                        ID = atomData[r][-1]
890                        if parms != atomData[r][c] and Atoms.GetColLabelValue(c) == 'I/A':
891                            if parms == 'A':                #'I' --> 'A'
892                                Uiso = float(Atoms.GetCellValue(r,us))
893                                sytsym = atomData[r][ss]
894                                CSI = G2spc.GetCSuinel(sytsym)
895                                atomData[r][ui:ui+6] = Uiso*np.array(CSI[3])
896                                atomData[r][us] = 0.0
897                                Atoms.SetCellStyle(r,us,VERY_LIGHT_GREY,True)
898                                for i in range(6):
899                                    ci = ui+i
900                                    Atoms.SetCellStyle(r,ci,VERY_LIGHT_GREY,True)
901                                    if CSI[2][i]:
902                                        Atoms.SetCellStyle(r,ci,WHITE,False)
903                            else:                           #'A' --> 'I'
904                                Uij = atomData[r][ui:ui+6]
905                                Uiso = (Uij[0]+Uij[1]+Uij[2])/3.0
906                                atomData[r][us] = Uiso
907                                Atoms.SetCellStyle(r,us,WHITE,False)
908                                for i in range(6):
909                                    ci = ui+i
910                                    atomData[r][ci] = 0.0
911                                    Atoms.SetCellStyle(r,ci,VERY_LIGHT_GREY,True)
912                        if not Atoms.IsReadOnly(r,c):
913                            if Atoms.GetColLabelValue(c) == 'refine':
914                                atomData[r][c] = parms.replace(rbAtmDict.get(atomData[r][-1],''),'')
915                            else: 
916                                atomData[r][c] = parms
917                        if 'Atoms' in data['Drawing']:
918                            DrawAtomsReplaceByID(data['Drawing'],atomData[r],ID)
919                    wx.CallAfter(Paint)
920                   
921        def ChangeAtomCell(event):
922           
923            def chkUij(Uij,CSI): #needs to do something!!!
924                return Uij
925
926            r,c =  event.GetRow(),event.GetCol()
927            if r >= 0 and c >= 0:
928                ID = atomData[r][-1]
929                if Atoms.GetColLabelValue(c) in ['x','y','z']:
930                    ci = colLabels.index('x')
931                    XYZ = atomData[r][ci:ci+3]
932                    if None in XYZ:
933                        XYZ = [0,0,0]
934                    SScol = colLabels.index('site sym')
935                    Mulcol = colLabels.index('mult')
936                    E,SGData = G2spc.SpcGroup(generalData['SGData']['SpGrp'])
937                    Sytsym,Mult = G2spc.SytSym(XYZ,SGData)
938                    atomData[r][SScol] = Sytsym
939                    atomData[r][Mulcol] = Mult
940                    if atomData[r][colLabels.index('I/A')] == 'A':
941                        ui = colLabels.index('U11')
942                        CSI = G2spc.GetCSuinel(Sytsym)
943                        atomData[r][ui:ui+6] = chkUij(atomData[r][ui:ui+6],Sytsym)
944                        for i in range(6):
945                            ci = i+ui
946                            Atoms.SetCellStyle(r,ci,VERY_LIGHT_GREY,True)
947                            if CSI[2][i]:
948                                Atoms.SetCellStyle(r,ci,WHITE,False)
949                    SetupGeneral()
950                elif Atoms.GetColLabelValue(c) == 'I/A':            #note use of text color to make it vanish!
951                    if atomData[r][c] == 'I':
952                        Uij = atomData[r][c+2:c+8]
953                        atomData[r][c+1] = (Uij[0]+Uij[1]+Uij[2])/3.0
954                        Atoms.SetCellStyle(r,c+1,WHITE,False)
955                        Atoms.SetCellTextColour(r,c+1,BLACK)
956                        for i in range(6):
957                            ci = i+colLabels.index('U11')
958                            Atoms.SetCellStyle(r,ci,VERY_LIGHT_GREY,True)
959                            Atoms.SetCellTextColour(r,ci,VERY_LIGHT_GREY)
960                            atomData[r][ci] = 0.0
961                    else:
962                        value = atomData[r][c+1]
963                        CSI = G2spc.GetCSuinel(atomData[r][colLabels.index('site sym')])
964                        atomData[r][c+1] =  0.0
965                        Atoms.SetCellStyle(r,c+1,VERY_LIGHT_GREY,True)
966                        Atoms.SetCellTextColour(r,c+1,VERY_LIGHT_GREY)
967                        for i in range(6):
968                            ci = i+colLabels.index('U11')
969                            atomData[r][ci] = value*CSI[3][i]
970                            Atoms.SetCellStyle(r,ci,VERY_LIGHT_GREY,True)
971                            Atoms.SetCellTextColour(r,ci,BLACK)
972                            if CSI[2][i]:
973                                Atoms.SetCellStyle(r,ci,WHITE,False)
974                elif Atoms.GetColLabelValue(c) in ['U11','U22','U33','U12','U13','U23']:
975                    value = atomData[r][c]
976                    CSI = G2spc.GetCSuinel(atomData[r][colLabels.index('site sym')])
977                    iUij = CSI[0][c-colLabels.index('U11')]
978                    for i in range(6):
979                        if iUij == CSI[0][i]:
980                            atomData[r][i+colLabels.index('U11')] = value*CSI[1][i]
981                elif Atoms.GetColLabelValue(c) == 'refine':
982                    atomData[r][c] = atomData[r][c].replace(rbAtmDict.get(atomData[r][-1],''),'')
983                if 'Atoms' in data['Drawing']:
984                    DrawAtomsReplaceByID(data['Drawing'],atomData[r],ID)
985                wx.CallAfter(Paint)
986
987        def AtomTypeSelect(event):
988            r,c =  event.GetRow(),event.GetCol()
989            if Atoms.GetColLabelValue(c) == 'Type':
990                PE = G2elemGUI.PickElement(G2frame)
991                if PE.ShowModal() == wx.ID_OK:
992                    if PE.Elem != 'None':                       
993                        atomData[r][c] = PE.Elem.strip()
994                        name = atomData[r][c]
995                        if len(name) in [2,4]:
996                            atomData[r][c-1] = name[:2]+'(%d)'%(r+1)
997                        else:
998                            atomData[r][c-1] = name[:1]+'(%d)'%(r+1)
999                PE.Destroy()
1000                SetupGeneral()
1001                wx.CallAfter(Paint)
1002                value = Atoms.GetCellValue(r,c)
1003                atomData[r][c] = value
1004                ID = atomData[r][-1]
1005                if 'Atoms' in data['Drawing']:
1006                    DrawAtomsReplaceByID(data['Drawing'],atomData[r],ID)
1007                SetupGeneral()
1008            else:
1009                event.Skip()
1010
1011        def RowSelect(event):
1012            r,c =  event.GetRow(),event.GetCol()
1013            if not event.AltDown():
1014                Atoms.frm = -1
1015                G2frame.dataFrame.SetStatusText('')                   
1016            if r < 0 and c < 0:
1017                if Atoms.IsSelection():
1018                    Atoms.ClearSelection()
1019            elif c < 0:                   #only row clicks
1020                if event.ControlDown():                   
1021                    if r in Atoms.GetSelectedRows():
1022                        Atoms.DeselectRow(r)
1023                    else:
1024                        Atoms.SelectRow(r,True)
1025                elif event.ShiftDown():
1026                    indxs = Atoms.GetSelectedRows()
1027                    Atoms.ClearSelection()
1028                    ibeg = 0
1029                    if indxs:
1030                        ibeg = indxs[-1]
1031                    for row in range(ibeg,r+1):
1032                        Atoms.SelectRow(row,True)
1033                elif event.AltDown():
1034                    if atomData[r][-1] in rbAtmDict:
1035                        G2frame.dataFrame.SetStatusText('**** ERROR - atom is in a rigid body and can not be moved ****')
1036                        Atoms.frm = -1
1037                        Atoms.ClearSelection()
1038                    else:   
1039                        if Atoms.frm < 0:           #pick atom to be moved
1040                            Atoms.frm = r
1041                            Atoms.SelectRow(r,True)
1042                            n = colLabels.index('Name')
1043                            G2frame.dataFrame.SetStatusText('Atom '+atomData[r][n]+' is to be moved')
1044                        else:                       #move it
1045                            item = atomData.pop(Atoms.frm)
1046                            atomData.insert(r,item)
1047                            Atoms.frm = -1
1048                            G2frame.dataFrame.SetStatusText('')
1049                            wx.CallAfter(Paint)
1050                else:
1051                    Atoms.ClearSelection()
1052                    Atoms.SelectRow(r,True)
1053               
1054        def ChangeSelection(event):
1055            r,c =  event.GetRow(),event.GetCol()
1056            if r < 0 and c < 0:
1057                Atoms.ClearSelection()
1058            if c < 0:
1059                if r in Atoms.GetSelectedRows():
1060                    Atoms.DeselectRow(r)
1061                else:
1062                    Atoms.SelectRow(r,True)
1063            if r < 0:
1064                if c in Atoms.GetSelectedCols():
1065                    Atoms.DeselectCol(c)
1066                else:
1067                    Atoms.SelectCol(c,True)
1068                   
1069        def Paint():
1070       
1071            table = []
1072            rowLabels = []
1073            for i,atom in enumerate(atomData):
1074                table.append(atom)
1075                rowLabels.append(str(i))
1076            atomTable = G2gd.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
1077            Atoms.SetTable(atomTable, True)
1078            Atoms.frm = -1           
1079            colType = colLabels.index('Type')
1080            colR = colLabels.index('refine')
1081            colSS = colLabels.index('site sym')
1082            colX = colLabels.index('x')
1083            colIA = colLabels.index('I/A')
1084            colU11 = colLabels.index('U11')
1085            colUiso = colLabels.index('Uiso')
1086            attr = wx.grid.GridCellAttr()
1087            attr.IncRef()               #fix from Jim Hester
1088            attr.SetEditor(G2gd.GridFractionEditor(Atoms))
1089            for c in range(colX,colX+3):
1090                Atoms.SetColAttr(c, attr)
1091            for i in range(colU11-1,colU11+6):
1092                Atoms.SetColSize(i,50)           
1093            for row in range(Atoms.GetNumberRows()):
1094                atId = atomData[row][-1]
1095                if 'X' in rbAtmDict.get(atId,''):
1096                    for c in range(0,colX+3):
1097                        if c != colR:
1098                            Atoms.SetCellStyle(row,c,VERY_LIGHT_GREY,True)                       
1099                Atoms.SetReadOnly(row,colType,True)
1100                Atoms.SetReadOnly(row,colSS,True)                         #site sym
1101                Atoms.SetReadOnly(row,colSS+1,True)                       #Mult
1102                if Atoms.GetCellValue(row,colIA) == 'A':
1103                    CSI = G2spc.GetCSuinel(atomData[row][colLabels.index('site sym')])
1104                    Atoms.SetCellStyle(row,colUiso,VERY_LIGHT_GREY,True)
1105                    Atoms.SetCellTextColour(row,colUiso,VERY_LIGHT_GREY)
1106                    for i in range(6):
1107                        ci = colU11+i
1108                        Atoms.SetCellTextColour(row,ci,BLACK)
1109                        Atoms.SetCellStyle(row,ci,VERY_LIGHT_GREY,True)
1110                        if CSI[2][i]:
1111                            Atoms.SetCellStyle(row,ci,WHITE,False)
1112                else:
1113                    Atoms.SetCellStyle(row,colUiso,WHITE,False)
1114                    Atoms.SetCellTextColour(row,colUiso,BLACK)
1115                    for i in range(6):
1116                        ci = colU11+i
1117                        Atoms.SetCellStyle(row,ci,VERY_LIGHT_GREY,True)
1118                        Atoms.SetCellTextColour(row,ci,VERY_LIGHT_GREY)
1119            Atoms.AutoSizeColumns(False)
1120
1121        SGData = data['General']['SGData']
1122        G2frame.dataFrame.SetStatusText('')
1123        if SGData['SGPolax']:
1124            G2frame.dataFrame.SetStatusText('Warning: The location of the origin is arbitrary in '+SGData['SGPolax'])
1125        Atoms.Bind(wg.EVT_GRID_CELL_CHANGE, ChangeAtomCell)
1126        Atoms.Bind(wg.EVT_GRID_CELL_LEFT_DCLICK, AtomTypeSelect)
1127        Atoms.Bind(wg.EVT_GRID_LABEL_LEFT_DCLICK, RefreshAtomGrid)
1128        Atoms.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK, RowSelect)
1129        Atoms.Bind(wg.EVT_GRID_LABEL_RIGHT_CLICK, ChangeSelection)
1130        Atoms.SetMargins(0,0)
1131        Paint()
1132
1133    def OnAtomAdd(event):
1134        AtomAdd(0,0,0)
1135        FillAtomsGrid(Atoms)
1136        event.StopPropagation()
1137       
1138    def OnAtomViewAdd(event):
1139        try:
1140            drawData = data['Drawing']
1141            x,y,z = drawData['viewPoint'][0]
1142            AtomAdd(x,y,z)
1143        except:
1144            AtomAdd(0,0,0)
1145        FillAtomsGrid(Atoms)
1146        event.StopPropagation()
1147               
1148    def AtomAdd(x,y,z,El='H',Name='UNK'):
1149        atomData = data['Atoms']
1150        generalData = data['General']
1151        Ncol = Atoms.GetNumberCols()
1152        atId = ran.randint(0,sys.maxint)
1153        E,SGData = G2spc.SpcGroup(generalData['SGData']['SpGrp'])
1154        Sytsym,Mult = G2spc.SytSym([x,y,z],SGData)
1155        if generalData['Type'] == 'macromolecular':
1156            atomData.append([0,Name,'',Name,El,'',x,y,z,1,Sytsym,Mult,'I',0.10,0,0,0,0,0,0,atId])
1157        elif generalData['Type'] == 'nuclear':
1158            atomData.append([Name,El,'',x,y,z,1,Sytsym,Mult,'I',0.01,0,0,0,0,0,0,atId])
1159        elif generalData['Type'] == 'magnetic':
1160            atomData.append([Name,El,'',x,y,z,1,Sytsym,Mult,0,'I',0.01,0,0,0,0,0,0,0,0,0,atId])
1161        SetupGeneral()
1162        if 'Atoms' in data['Drawing']:           
1163            DrawAtomAdd(data['Drawing'],atomData[-1])
1164            G2plt.PlotStructure(G2frame,data)
1165
1166    def OnAtomInsert(event):
1167        AtomInsert(0,0,0)
1168        FillAtomsGrid(Atoms)
1169        event.StopPropagation()
1170       
1171    def OnAtomViewInsert(event):
1172        if 'Drawing' in data:
1173            drawData = data['Drawing']
1174            x,y,z = drawData['viewPoint'][0]
1175            AtomAdd(x,y,z)
1176            FillAtomsGrid(Atoms)
1177        event.StopPropagation()
1178       
1179    def OnRBAppend(event):
1180        rbData = G2frame.PatternTree.GetItemPyData(   
1181            G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Rigid bodies'))
1182        general = data['General']
1183        atomData = data['Atoms']
1184        Amat,Bmat = G2lat.cell2AB(general['Cell'][1:7])
1185        rbNames = {}
1186        for rbVec in rbData['Vector']:
1187            if rbVec != 'AtInfo':
1188                rbNames[rbData['Vector'][rbVec]['RBname']] =['Vector',rbVec]
1189        for rbRes in rbData['Residue']:
1190            if rbRes != 'AtInfo':
1191                rbNames[rbData['Residue'][rbRes]['RBname']] = ['Residue',rbRes]
1192        if not rbNames:
1193            print '**** ERROR - no rigid bodies defined ****'
1194            return
1195       
1196    def OnAtomMove(event):
1197        drawData = data['Drawing']
1198        atomData = data['Atoms']
1199        x,y,z = drawData['viewPoint'][0]
1200        colLabels = [Atoms.GetColLabelValue(c) for c in range(Atoms.GetNumberCols())]
1201        cx = colLabels.index('x')
1202        indx = Atoms.GetSelectedRows()
1203        if len(indx) != 1:
1204            print '**** ERROR - only one atom can be moved ****'
1205        elif atomData[indx[0]][-1] in rbAtmDict:
1206            print '**** ERROR - Atoms in rigid bodies can not be moved ****'
1207        else:
1208            atomData[indx[0]][cx:cx+3] = [x,y,z]
1209            SetupGeneral()
1210            FillAtomsGrid(Atoms)
1211            ID = atomData[indx[0]][-1]
1212            DrawAtomsReplaceByID(data['Drawing'],atomData[indx[0]],ID)
1213            G2plt.PlotStructure(G2frame,data)
1214        event.StopPropagation()
1215           
1216    def DrawAtomsReplaceByID(drawingData,atom,ID):
1217        IDs = [ID,]
1218        atomData = drawingData['Atoms']
1219        indx = G2mth.FindAtomIndexByIDs(atomData,IDs)
1220        for ind in indx:
1221            atomData[ind] = MakeDrawAtom(atom,atomData[ind])
1222               
1223    def MakeDrawAtom(atom,oldatom=None):
1224        AA3letter = ['ALA','ARG','ASN','ASP','CYS','GLN','GLU','GLY','HIS','ILE',
1225            'LEU','LYS','MET','PHE','PRO','SER','THR','TRP','TYR','VAL','MSE','HOH','WAT','UNK']
1226        AA1letter = ['A','R','N','D','C','Q','E','G','H','I',
1227            'L','K','M','F','P','S','T','W','Y','V','M',' ',' ',' ']
1228        generalData = data['General']
1229        SGData = generalData['SGData']
1230        if generalData['Type'] == 'nuclear':
1231            if oldatom:
1232                opr = oldatom[5]
1233                if atom[9] == 'A':                   
1234                    X,U = G2spc.ApplyStringOps(opr,SGData,atom[3:6],atom[11:17])
1235                    atomInfo = [atom[:2]+list(X)+oldatom[5:9]+atom[9:11]+list(U)+oldatom[17:]][0]
1236                else:
1237                    X = G2spc.ApplyStringOps(opr,SGData,atom[3:6])
1238                    atomInfo = [atom[:2]+list(X)+oldatom[5:9]+atom[9:]+oldatom[17:]][0]
1239            else:
1240                atomInfo = [atom[:2]+atom[3:6]+['1',]+['vdW balls',]+
1241                    ['',]+[[255,255,255],]+atom[9:]+[[],[]]][0]
1242            ct,cs = [1,8]         #type & color
1243        elif generalData['Type'] == 'macromolecular':
1244            try:
1245                oneLetter = AA3letter.index(atom[1])
1246            except ValueError:
1247                oneLetter = -1
1248            atomInfo = [[atom[1].strip()+atom[0],]+
1249                [AA1letter[oneLetter]+atom[0],]+atom[2:5]+
1250                atom[6:9]+['1',]+['sticks',]+['',]+[[255,255,255],]+atom[12:]+[[],[]]][0]
1251            ct,cs = [4,11]         #type & color
1252        elif generalData['Type'] == 'magnetic':
1253            if oldatom:
1254                atomInfo = [atom[:2]+oldatom[3:]][0]
1255            else:
1256                atomInfo = [atom[:2]+atom[3:6]+['vdW balls',]+['',]+atom[9:]+[[],[]]][0]
1257            ct,cs = [1,8]         #type & color
1258    #     elif generalData['Type'] == 'modulated':
1259    #        ?????   for future
1260        atNum = generalData['AtomTypes'].index(atom[ct])
1261        atomInfo[cs] = list(generalData['Color'][atNum])
1262        return atomInfo
1263       
1264    def AtomInsert(x,y,z):
1265        indx = Atoms.GetSelectedRows()
1266        if indx:
1267            indx = indx[0]
1268            atomData = data['Atoms']
1269            generalData = data['General']
1270            Ncol = Atoms.GetNumberCols()
1271            E,SGData = G2spc.SpcGroup(generalData['SGData']['SpGrp'])
1272            Sytsym,Mult = G2spc.SytSym([0,0,0],SGData)
1273            atId = ran.randint(0,sys.maxint)
1274            if generalData['Type'] == 'macromolecular':
1275                atomData.insert(indx,[0,'UNK','','UNK','UNK','',x,y,z,1,Sytsym,Mult,'I',0.10,0,0,0,0,0,0,atId])
1276            elif generalData['Type'] == 'nuclear':
1277                atomData.insert(indx,['UNK','UNK','',x,y,z,1,Sytsym,Mult,'I',0.01,0,0,0,0,0,0,atId])
1278            elif generalData['Type'] == 'magnetic':
1279                atomData.insert(indx,['UNK','UNK','',x,y,z,1,Sytsym,Mult,0,'I',0.01,0,0,0,0,0,0,0,0,0,atId])
1280            SetupGeneral()
1281
1282    def AtomDelete(event):
1283        indx = Atoms.GetSelectedRows()
1284        IDs = []
1285        if indx:
1286            atomData = data['Atoms']
1287            indx.reverse()
1288            for ind in indx:
1289                atom = atomData[ind]
1290                if atom[-1] in rbAtmDict:
1291                    G2frame.dataFrame.SetStatusText('**** ERROR - atom is in a rigid body and can not be deleted ****')
1292                else:
1293                    IDs.append(atom[-1])
1294                    del atomData[ind]
1295            if 'Atoms' in data['Drawing']:
1296                DrawAtomsDeleteByIDs(IDs)
1297                wx.CallAfter(FillAtomsGrid,Atoms)
1298                G2plt.PlotStructure(G2frame,data)
1299            SetupGeneral()
1300        event.StopPropagation()
1301
1302    def AtomRefine(event):
1303        colLabels = [Atoms.GetColLabelValue(c) for c in range(Atoms.GetNumberCols())]
1304        c = colLabels.index('refine')
1305        indx = Atoms.GetSelectedRows()
1306        if indx:
1307            atomData = data['Atoms']
1308            generalData = data['General']
1309            Type = generalData['Type']
1310            if Type in ['nuclear','macromolecular']:
1311                choice = ['F - site fraction','X - coordinates','U - thermal parameters']
1312            elif Type == 'magnetic':
1313                choice = ['F - site fraction','X - coordinates','U - thermal parameters','M - magnetic moment']
1314            dlg = wx.MultiChoiceDialog(G2frame,'Select','Refinement controls',choice)
1315            if dlg.ShowModal() == wx.ID_OK:
1316                sel = dlg.GetSelections()
1317                parms = ''
1318                for x in sel:
1319                    parms += choice[x][0]
1320                for r in indx:
1321                    if not Atoms.IsReadOnly(r,c):
1322                        atomData[r][c] = parms
1323                Atoms.ForceRefresh()
1324            dlg.Destroy()
1325
1326    def AtomModify(event):
1327        indx = Atoms.GetSelectedRows()
1328        if indx:
1329            atomData = data['Atoms']
1330            generalData = data['General']
1331            colLabels = [Atoms.GetColLabelValue(c) for c in range(Atoms.GetNumberCols())]
1332            choices = ['Type','Name','x','y','z','frac','I/A','Uiso']
1333            dlg = wx.SingleChoiceDialog(G2frame,'Select','Atom parameter',choices)
1334            parm = ''
1335            if dlg.ShowModal() == wx.ID_OK:
1336                sel = dlg.GetSelection()
1337                parm = choices[sel]
1338                cid = colLabels.index(parm)
1339            dlg.Destroy()
1340            if parm in ['Type']:
1341                dlg = G2elemGUI.PickElement(G2frame)
1342                if dlg.ShowModal() == wx.ID_OK:
1343                    if dlg.Elem not in ['None']:
1344                        El = dlg.Elem.strip()
1345                        for r in indx:                       
1346                            if not Atoms.IsReadOnly(r,cid):
1347                                atomData[r][cid] = El
1348                                if len(El) in [2,4]:
1349                                    atomData[r][cid-1] = El[:2]+'(%d)'%(r+1)
1350                                else:
1351                                    atomData[r][cid-1] = El[:1]+'(%d)'%(r+1)
1352                        SetupGeneral()
1353                        if 'Atoms' in data['Drawing']:
1354                            for r in indx:
1355                                ID = atomData[r][-1]
1356                                DrawAtomsReplaceByID(data['Drawing'],atomData[r],ID)
1357                    FillAtomsGrid(Atoms)
1358                dlg.Destroy()
1359            elif parm in ['Name',]:
1360                dlg = wx.MessageDialog(G2frame,'Do you really want to rename the selected atoms?','Rename', 
1361                    wx.YES_NO | wx.ICON_QUESTION)
1362                try:
1363                    result = dlg.ShowModal()
1364                    if result == wx.ID_YES:
1365                        for r in indx:
1366                            if not Atoms.IsReadOnly(r,cid+1):
1367                                El = atomData[r][cid+1]
1368                                if len(El) in [2,4]:
1369                                    atomData[r][cid] = El[:2]+'(%d)'%(r+1)
1370                                else:
1371                                    atomData[r][cid] = El[:1]+'(%d)'%(r+1)
1372                    FillAtomsGrid(Atoms)
1373                finally:
1374                    dlg.Destroy()
1375                   
1376            elif parm in ['I/A']:
1377                choices = ['Isotropic','Anisotropic']
1378                dlg = wx.SingleChoiceDialog(G2frame,'Select','Thermal parameter model',choices)
1379                if dlg.ShowModal() == wx.ID_OK:
1380                    sel = dlg.GetSelection()
1381                    parm = choices[sel][0]
1382                    for r in indx:                       
1383                        if not Atoms.IsReadOnly(r,cid):
1384                            atomData[r][cid] = parm
1385                    FillAtomsGrid(Atoms)
1386                dlg.Destroy()
1387            elif parm in ['frac','Uiso']:
1388                limits = [0.,1.]
1389                val = 1.0
1390                if  parm in ['Uiso']:
1391                    limits = [0.,0.25]
1392                    val = 0.01
1393                dlg = G2gd.SingleFloatDialog(G2frame,'New value','Enter new value for '+parm,val,limits)
1394                if dlg.ShowModal() == wx.ID_OK:
1395                    parm = dlg.GetValue()
1396                    for r in indx:                       
1397                        if not Atoms.IsReadOnly(r,cid):
1398                            atomData[r][cid] = parm
1399                    SetupGeneral()
1400                    FillAtomsGrid(Atoms)
1401                dlg.Destroy()
1402            elif parm in ['x','y','z']:
1403                limits = [-1.,1.]
1404                val = 0.
1405                dlg = G2gd.SingleFloatDialog(G2frame,'Atom shift','Enter shift for '+parm,val,limits)
1406                if dlg.ShowModal() == wx.ID_OK:
1407                    parm = dlg.GetValue()
1408                    for r in indx:                       
1409                        if not Atoms.IsReadOnly(r,cid):
1410                            atomData[r][cid] += parm
1411                    SetupGeneral()
1412                    FillAtomsGrid(Atoms)
1413                dlg.Destroy()
1414
1415    def AtomTransform(event):
1416        indx = Atoms.GetSelectedRows()
1417        if indx:
1418            generalData = data['General']
1419            colLabels = [Atoms.GetColLabelValue(c) for c in range(Atoms.GetNumberCols())]
1420            cx = colLabels.index('x')
1421            cuia = colLabels.index('I/A')
1422            cuij = colLabels.index('U11')
1423            css = colLabels.index('site sym')
1424            atomData = data['Atoms']
1425            generalData = data['General']
1426            SGData = generalData['SGData']
1427            dlg = G2gd.SymOpDialog(G2frame,SGData,True,True)
1428            New = False
1429            try:
1430                if dlg.ShowModal() == wx.ID_OK:
1431                    Inv,Cent,Opr,Cell,New,Force = dlg.GetSelection()
1432                    Cell = np.array(Cell)
1433                    cent = SGData['SGCen'][Cent]
1434                    M,T = SGData['SGOps'][Opr]
1435                    for ind in indx:
1436                        XYZ = np.array(atomData[ind][cx:cx+3])
1437                        XYZ = np.inner(M,XYZ)+T
1438                        if Inv:
1439                            XYZ = -XYZ
1440                        XYZ = XYZ+cent+Cell
1441                        if Force:
1442                            XYZ = G2spc.MoveToUnitCell(XYZ)
1443                        if New:
1444                            atom = copy.copy(atomData[ind])
1445                        else:
1446                            atom = atomData[ind]
1447                        atom[cx:cx+3] = XYZ
1448                        atom[css:css+2] = G2spc.SytSym(XYZ,SGData)
1449                        if atom[cuia] == 'A':
1450                            Uij = atom[cuij:cuij+6]
1451                            U = G2spc.Uij2U(Uij)
1452                            U = np.inner(np.inner(M,U),M)
1453                            Uij = G2spc.U2Uij(U)
1454                            atom[cuij:cuij+6] = Uij
1455                        if New:
1456                            atomData.append(atom)
1457            finally:
1458                dlg.Destroy()
1459            Atoms.ClearSelection()
1460            if New:
1461                FillAtomsGrid(Atoms)
1462            else:
1463                Atoms.ForceRefresh()
1464
1465    def OnDistAngle(event):
1466        indx = Atoms.GetSelectedRows()
1467        Oxyz = []
1468        xyz = []
1469        DisAglData = {}
1470        DisAglCtls = {}
1471        if indx:
1472            generalData = data['General']
1473            DisAglData['OrigIndx'] = indx
1474            if 'DisAglCtls' in generalData:
1475                DisAglCtls = generalData['DisAglCtls']
1476            dlg = G2gd.DisAglDialog(G2frame,DisAglCtls,generalData)
1477            if dlg.ShowModal() == wx.ID_OK:
1478                DisAglCtls = dlg.GetData()
1479            dlg.Destroy()
1480            generalData['DisAglCtls'] = DisAglCtls
1481            atomData = data['Atoms']
1482            colLabels = [Atoms.GetColLabelValue(c) for c in range(Atoms.GetNumberCols())]
1483            cx = colLabels.index('x')
1484            cn = colLabels.index('Name')
1485            for i,atom in enumerate(atomData):
1486                xyz.append([i,]+atom[cn:cn+2]+atom[cx:cx+3])
1487                if i in indx:
1488                    Oxyz.append([i,]+atom[cn:cn+2]+atom[cx:cx+3])
1489            DisAglData['OrigAtoms'] = Oxyz
1490            DisAglData['TargAtoms'] = xyz
1491            generalData = data['General']
1492            DisAglData['SGData'] = generalData['SGData']
1493            DisAglData['Cell'] = generalData['Cell'][1:] #+ volume
1494            if 'pId' in data:
1495                DisAglData['pId'] = data['pId']
1496                DisAglData['covData'] = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.root, 'Covariance'))
1497            try:
1498                G2str.DistAngle(DisAglCtls,DisAglData)
1499            except KeyError:        # inside DistAngle for missing atom types in DisAglCtls
1500                print '**** ERROR - try again but do "Reset" to fill in missing atom types ****'
1501                       
1502################################################################################
1503#Structure drawing GUI stuff               
1504################################################################################
1505
1506    def SetupDrawingData():
1507        generalData = data['General']
1508        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])
1509        atomData = data['Atoms']
1510        AA3letter = ['ALA','ARG','ASN','ASP','CYS','GLN','GLU','GLY','HIS','ILE',
1511            'LEU','LYS','MET','PHE','PRO','SER','THR','TRP','TYR','VAL','MSE','HOH','WAT','UNK']
1512        AA1letter = ['A','R','N','D','C','Q','E','G','H','I',
1513            'L','K','M','F','P','S','T','W','Y','V','M',' ',' ',' ']
1514        defaultDrawing = {'Atoms':[],'viewPoint':[[0.5,0.5,0.5],[]],'showHydrogen':True,
1515            'backColor':[0,0,0],'depthFog':False,'Zclip':50.0,'cameraPos':50.,'Zstep':0.5,
1516            'radiusFactor':0.85,'contourLevel':1.,'bondRadius':0.1,'ballScale':0.33,
1517            'vdwScale':0.67,'ellipseProb':50,'sizeH':0.50,'unitCellBox':True,
1518            'showABC':True,'selectedAtoms':[],'Atoms':[],'oldxy':[],
1519            'bondList':{},'viewDir':[1,0,0]}
1520        V0 = np.array([0,0,1])
1521        V = np.inner(Amat,V0)
1522        V /= np.sqrt(np.sum(V**2))
1523        A = np.arccos(np.sum(V*V0))
1524        defaultDrawing['Quaternion'] = G2mth.AV2Q(A,[0,1,0])
1525        try:
1526            drawingData = data['Drawing']
1527        except KeyError:
1528            data['Drawing'] = {}
1529            drawingData = data['Drawing']
1530        if not drawingData:                 #fill with defaults if empty
1531            drawingData.update(defaultDrawing)
1532        if 'Zstep' not in drawingData:
1533            drawingData['Zstep'] = 0.5
1534        if 'contourLevel' not in drawingData:
1535            drawingData['contourLevel'] = 1.
1536        if 'viewDir' not in drawingData:
1537            drawingData['viewDir'] = [0,0,1]
1538        if 'Quaternion' not in drawingData:
1539            drawingData['Quaternion'] = G2mth.AV2Q(2*np.pi,np.inner(Amat,[0,0,1]))
1540        cx,ct,cs,ci = [0,0,0,0]
1541        if generalData['Type'] == 'nuclear':
1542            cx,ct,cs,ci = [2,1,6,17]         #x, type, style & index
1543        elif generalData['Type'] == 'macromolecular':
1544            cx,ct,cs,ci = [5,4,9,20]         #x, type, style & index
1545        elif generalData['Type'] == 'magnetic':
1546            cx,ct,cs,ci = [2,1,6,20]         #x, type, style & index
1547#        elif generalData['Type'] == 'modulated':
1548#           ?????   for future
1549        drawingData['atomPtrs'] = [cx,ct,cs,ci]
1550        if not drawingData.get('Atoms'):
1551            for atom in atomData:
1552                DrawAtomAdd(drawingData,atom)
1553            data['Drawing'] = drawingData
1554           
1555    def DrawAtomAdd(drawingData,atom):
1556        drawingData['Atoms'].append(MakeDrawAtom(atom))
1557       
1558    def OnRestraint(event):       
1559        indx = drawAtoms.GetSelectedRows()
1560        restData = G2frame.PatternTree.GetItemPyData(   
1561            G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Restraints'))
1562        drawingData = data['Drawing']
1563        generalData = data['General']
1564        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])           
1565        cx,ct,cs,ci = drawingData['atomPtrs']
1566        atomData = drawingData['Atoms']
1567        atNames = []
1568        atXYZ = []
1569        atSymOp = []
1570        atIndx = []
1571        for item in indx:
1572            atXYZ.append(np.array(atomData[item][cx:cx+3]))
1573            atSymOp.append(atomData[item][cs-1])
1574            atIndx.append(atomData[item][ci])
1575        if event.GetId() == G2gd.wxID_DRAWRESTRBOND and len(indx) == 2:
1576            try:
1577                bondData = restData[PhaseName]['Bond']
1578            except KeyError:
1579                bondData = {'wtFactor':1.0,'Bonds':[],'Use':True}
1580                restData[PhaseName] = {}
1581                restData[PhaseName]['Bond'] = bondData
1582            dist = G2mth.getRestDist(atXYZ,Amat)
1583            bondData['Bonds'].append([atIndx,atSymOp,1.54,0.01])
1584        elif event.GetId() == G2gd.wxID_DRAWRESTRANGLE and len(indx) == 3:
1585            try:
1586                angleData = restData[PhaseName]['Angle']
1587            except KeyError:
1588                angleData = {'wtFactor':1.0,'Angles':[],'Use':True}
1589                restData[PhaseName] = {}
1590                restData[PhaseName]['Angle'] = angleData
1591            angle = G2mth.getRestAngle(atXYZ,Amat)
1592            angleData['Angles'].append([atIndx,atSymOp,109.5,1.0])           
1593        elif event.GetId() == G2gd.wxID_DRAWRESTRPLANE and len(indx) > 3:
1594            try:
1595                planeData = restData[PhaseName]['Plane']
1596            except KeyError:
1597                planeData = {'wtFactor':1.0,'Planes':[],'Use':True}
1598                restData[PhaseName] = {}
1599                restData[PhaseName]['Plane'] = planeData
1600            plane = G2mth.getRestPlane(atXYZ,Amat)
1601            planeData['Planes'].append([atIndx,atSymOp,0.0,0.01])           
1602        elif event.GetId() == G2gd.wxID_DRAWRESTRCHIRAL and len(indx) == 4:
1603            try:
1604                chiralData = restData[PhaseName]['Chiral']
1605            except KeyError:
1606                chiralData = {'wtFactor':1.0,'Volumes':[],'Use':True}
1607                restData[PhaseName] = {}
1608                restData[PhaseName]['Chiral'] = chiralData
1609            volume = G2mth.getRestChiral(atXYZ,Amat)
1610            chiralData['Volumes'].append([atIndx,atSymOp,2.5,0.1])           
1611        else:
1612            print '**** ERROR wrong number of atoms selected for this restraint'
1613            return
1614        G2frame.PatternTree.SetItemPyData(   
1615            G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Restraints'),restData)
1616
1617    def OnDefineRB(event):
1618        indx = drawAtoms.GetSelectedRows()
1619        indx.sort()
1620        RBData = G2frame.PatternTree.GetItemPyData(   
1621            G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Rigid bodies'))
1622        drawingData = data['Drawing']
1623        generalData = data['General']
1624        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])           
1625        cx,ct,cs,ci = drawingData['atomPtrs']
1626        atomData = drawingData['Atoms']
1627        rbXYZ = []
1628        rbType = []
1629        atNames = []
1630        AtInfo = RBData['Residue']['AtInfo']
1631        for i,item in enumerate(indx):
1632            rbtype = atomData[item][ct]
1633            atNames.append(rbtype+str(i))
1634            rbType.append(rbtype)
1635            if rbtype not in AtInfo:
1636                Info = G2elem.GetAtomInfo(rbtype)
1637                AtInfo[rbtype] = [Info['Drad'],Info['Color']]
1638            rbXYZ.append(np.inner(np.array(atomData[item][cx:cx+3]),Amat))
1639        rbXYZ = np.array(rbXYZ)
1640        rbXYZ -= rbXYZ[0]
1641        rbId = ran.randint(0,sys.maxint)
1642        RBData['Residue'][rbId] = {'RBname':'UNKRB','rbXYZ':rbXYZ,'rbTypes':rbType,
1643            'atNames':atNames,'rbRef':[0,1,2],'rbSeq':[],'SelSeq':[0,0],'useCount':0}
1644        G2frame.dataFrame.SetStatusText('New rigid body UNKRB added to set of Residue rigid bodies')
1645
1646################################################################################
1647##### Atom draw routines
1648################################################################################
1649           
1650    def UpdateDrawAtoms():
1651        G2frame.dataFrame.SetStatusText('')
1652        generalData = data['General']
1653        SetupDrawingData()
1654        drawingData = data['Drawing']
1655        cx,ct,cs,ci = drawingData['atomPtrs']
1656        atomData = drawingData['Atoms']
1657        Types = [wg.GRID_VALUE_STRING,wg.GRID_VALUE_STRING,]+3*[wg.GRID_VALUE_FLOAT+':10,5',]+ \
1658            [wg.GRID_VALUE_STRING,wg.GRID_VALUE_CHOICE+": ,lines,vdW balls,sticks,balls & sticks,ellipsoids,polyhedra",
1659            wg.GRID_VALUE_CHOICE+": ,type,name,number",wg.GRID_VALUE_STRING,wg.GRID_VALUE_STRING,]
1660        styleChoice = [' ','lines','vdW balls','sticks','balls & sticks','ellipsoids','polyhedra']
1661        labelChoice = [' ','type','name','number']
1662        colLabels = ['Name','Type','x','y','z','Sym Op','Style','Label','Color','I/A']
1663        if generalData['Type'] == 'macromolecular':
1664            colLabels = ['Residue','1-letter','Chain'] + colLabels
1665            Types = 3*[wg.GRID_VALUE_STRING,]+Types
1666            Types[8] = wg.GRID_VALUE_CHOICE+": ,lines,vdW balls,sticks,balls & sticks,ellipsoids,backbone,ribbons,schematic"
1667            styleChoice = [' ','lines','vdW balls','sticks','balls & sticks','ellipsoids','backbone','ribbons','schematic']
1668            labelChoice = [' ','type','name','number','residue','1-letter','chain']
1669            Types[9] = wg.GRID_VALUE_CHOICE+": ,type,name,number,residue,1-letter,chain"
1670#        elif generalData['Type'] == 'modulated':
1671#            Types += []
1672#            colLabels += []
1673
1674        def RefreshAtomGrid(event):
1675
1676            def SetChoice(name,c,n=0):
1677                choice = []
1678                for r in range(len(atomData)):
1679                    if n:
1680                        srchStr = str(atomData[r][c][:n])
1681                    else:
1682                        srchStr = str(atomData[r][c])
1683                    if srchStr not in choice:
1684                        if n:
1685                            choice.append(str(atomData[r][c][:n]))
1686                        else:
1687                            choice.append(str(atomData[r][c]))
1688                choice.sort()
1689
1690                dlg = wx.MultiChoiceDialog(G2frame,'Select',name,choice)
1691                if dlg.ShowModal() == wx.ID_OK:
1692                    sel = dlg.GetSelections()
1693                    parms = []
1694                    for x in sel:
1695                        parms.append(choice[x])
1696                    noSkip = False
1697                    drawAtoms.ClearSelection()
1698                    drawingData['selectedAtoms'] = []
1699                    for row in range(len(atomData)):
1700                        test = atomData[row][c]
1701                        if n:
1702                            test = test[:n]
1703                        if  test in parms:
1704                            drawAtoms.SelectRow(row,True)
1705                            drawingData['selectedAtoms'].append(row)
1706                    G2plt.PlotStructure(G2frame,data)                   
1707                dlg.Destroy()
1708               
1709            r,c =  event.GetRow(),event.GetCol()
1710            if r < 0 and c < 0:
1711                for row in range(drawAtoms.GetNumberRows()):
1712                    drawingData['selectedAtoms'].append(row)
1713                    drawAtoms.SelectRow(row,True)                   
1714            elif r < 0:                          #dclick on col label
1715                sel = -1
1716                Parms = False
1717                noSkip = True
1718                if drawAtoms.GetColLabelValue(c) == 'Style':
1719                    dlg = wx.SingleChoiceDialog(G2frame,'Select','Atom drawing style',styleChoice)
1720                    if dlg.ShowModal() == wx.ID_OK:
1721                        sel = dlg.GetSelection()
1722                        parms = styleChoice[sel]
1723                        for r in range(len(atomData)):
1724                            atomData[r][c] = parms
1725                            drawAtoms.SetCellValue(r,c,parms)
1726                        FindBondsDraw()
1727                        G2plt.PlotStructure(G2frame,data)
1728                    dlg.Destroy()
1729                elif drawAtoms.GetColLabelValue(c) == 'Label':
1730                    dlg = wx.SingleChoiceDialog(G2frame,'Select','Atom labelling style',labelChoice)
1731                    if dlg.ShowModal() == wx.ID_OK:
1732                        sel = dlg.GetSelection()
1733                        parms = labelChoice[sel]
1734                        for r in range(len(atomData)):
1735                            atomData[r][c] = parms
1736                            drawAtoms.SetCellValue(r,c,parms)
1737                    dlg.Destroy()                   
1738                elif drawAtoms.GetColLabelValue(c) == 'Color':
1739                    dlg = wx.ColourDialog(G2frame)
1740                    if dlg.ShowModal() == wx.ID_OK:
1741                        color = dlg.GetColourData().GetColour()
1742                        attr = wg.GridCellAttr()                #needs to be here - gets lost if outside loop!
1743                        attr.SetReadOnly(True)
1744                        attr.SetBackgroundColour(color)
1745                        for r in range(len(atomData)):
1746                            atomData[r][c] = color
1747                            drawingData['Atoms'][r][c] = color
1748                            drawAtoms.SetAttr(r,c,attr)
1749                        UpdateDrawAtoms()
1750                    dlg.Destroy()
1751                elif drawAtoms.GetColLabelValue(c) == 'Residue':
1752                    SetChoice('Residue',c,3)
1753                elif drawAtoms.GetColLabelValue(c) == '1-letter':
1754                    SetChoice('1-letter',c,1)
1755                elif drawAtoms.GetColLabelValue(c) == 'Chain':
1756                    SetChoice('Chain',c)
1757                elif drawAtoms.GetColLabelValue(c) == 'Name':
1758                    SetChoice('Name',c)
1759                elif drawAtoms.GetColLabelValue(c) == 'Sym Op':
1760                    SetChoice('Name',c)
1761                elif drawAtoms.GetColLabelValue(c) == 'Type':
1762                    SetChoice('Type',c)
1763                elif drawAtoms.GetColLabelValue(c) in ['x','y','z','I/A']:
1764                    drawAtoms.ClearSelection()
1765            else:
1766                if drawAtoms.GetColLabelValue(c) in ['Style','Label']:
1767                    atomData[r][c] = drawAtoms.GetCellValue(r,c)
1768                    FindBondsDraw()
1769                elif drawAtoms.GetColLabelValue(c) == 'Color':
1770                    dlg = wx.ColourDialog(G2frame)
1771                    if dlg.ShowModal() == wx.ID_OK:
1772                        color = dlg.GetColourData().GetColour()
1773                        attr = wg.GridCellAttr()                #needs to be here - gets lost if outside loop!
1774                        attr.SetReadOnly(True)
1775                        attr.SetBackgroundColour(color)
1776                        atomData[r][c] = color
1777                        drawingData['Atoms'][r][c] = color
1778                        drawAtoms.SetAttr(i,cs+2,attr)
1779                    dlg.Destroy()
1780                    UpdateDrawAtoms()
1781            G2plt.PlotStructure(G2frame,data)
1782                   
1783        def RowSelect(event):
1784            r,c =  event.GetRow(),event.GetCol()
1785            if r < 0 and c < 0:
1786                if drawAtoms.IsSelection():
1787                    drawAtoms.ClearSelection()
1788            elif c < 0:                   #only row clicks
1789                if event.ControlDown():                   
1790                    if r in drawAtoms.GetSelectedRows():
1791                        drawAtoms.DeselectRow(r)
1792                    else:
1793                        drawAtoms.SelectRow(r,True)
1794                elif event.ShiftDown():
1795                    indxs = drawAtoms.GetSelectedRows()
1796                    drawAtoms.ClearSelection()
1797                    ibeg = 0
1798                    if indxs:
1799                        ibeg = indxs[-1]
1800                    for row in range(ibeg,r+1):
1801                        drawAtoms.SelectRow(row,True)
1802                else:
1803                    drawAtoms.ClearSelection()
1804                    drawAtoms.SelectRow(r,True)               
1805            drawingData['selectedAtoms'] = []
1806            drawingData['selectedAtoms'] = drawAtoms.GetSelectedRows()
1807            G2plt.PlotStructure(G2frame,data)                   
1808               
1809        table = []
1810        rowLabels = []
1811        for i,atom in enumerate(drawingData['Atoms']):
1812            table.append(atom[:colLabels.index('I/A')+1])
1813            rowLabels.append(str(i))
1814
1815        atomTable = G2gd.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
1816        drawAtoms.SetTable(atomTable, True)
1817        drawAtoms.SetMargins(0,0)
1818        drawAtoms.AutoSizeColumns(True)
1819        drawAtoms.SetColSize(colLabels.index('Style'),80)
1820        drawAtoms.SetColSize(colLabels.index('Color'),50)
1821        drawAtoms.Bind(wg.EVT_GRID_CELL_CHANGE, RefreshAtomGrid)
1822        drawAtoms.Bind(wg.EVT_GRID_LABEL_LEFT_DCLICK, RefreshAtomGrid)
1823        drawAtoms.Bind(wg.EVT_GRID_CELL_LEFT_DCLICK, RefreshAtomGrid)
1824        drawAtoms.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK, RowSelect)
1825        for i,atom in enumerate(drawingData['Atoms']):
1826            attr = wg.GridCellAttr()                #needs to be here - gets lost if outside loop!
1827            attr.SetReadOnly(True)
1828            attr.SetBackgroundColour(atom[cs+2])
1829            drawAtoms.SetAttr(i,cs+2,attr)
1830            drawAtoms.SetCellValue(i,cs+2,'')
1831        indx = drawingData['selectedAtoms']
1832        if indx:
1833            for r in range(len(atomData)):
1834                if r in indx:
1835                    drawAtoms.SelectRow(r)
1836        for c in range(len(colLabels)):
1837           attr = wg.GridCellAttr()                #needs to be here - gets lost if outside loop!
1838           attr.SetReadOnly(True)
1839           attr.SetBackgroundColour(VERY_LIGHT_GREY)
1840           if colLabels[c] not in ['Style','Label','Color']:
1841                drawAtoms.SetColAttr(c,attr)
1842        G2frame.dataFrame.setSizePosLeft([600,300])
1843       
1844        FindBondsDraw()
1845        drawAtoms.ClearSelection()
1846        G2plt.PlotStructure(G2frame,data)
1847
1848    def DrawAtomStyle(event):
1849        indx = drawAtoms.GetSelectedRows()
1850        if indx:
1851            generalData = data['General']
1852            atomData = data['Drawing']['Atoms']
1853            cx,ct,cs,ci = data['Drawing']['atomPtrs']
1854            styleChoice = [' ','lines','vdW balls','sticks','balls & sticks','ellipsoids','polyhedra']
1855            if generalData['Type'] == 'macromolecular':
1856                styleChoice = [' ','lines','vdW balls','sticks','balls & sticks','ellipsoids',
1857                'backbone','ribbons','schematic']
1858            dlg = wx.SingleChoiceDialog(G2frame,'Select','Atom drawing style',styleChoice)
1859            if dlg.ShowModal() == wx.ID_OK:
1860                sel = dlg.GetSelection()
1861                parms = styleChoice[sel]
1862                for r in indx:
1863                    atomData[r][cs] = parms
1864                    drawAtoms.SetCellValue(r,cs,parms)
1865            dlg.Destroy()
1866            FindBondsDraw()
1867            drawAtoms.ClearSelection()
1868            G2plt.PlotStructure(G2frame,data)
1869
1870    def DrawAtomLabel(event):
1871        indx = drawAtoms.GetSelectedRows()
1872        if indx:
1873            generalData = data['General']
1874            atomData = data['Drawing']['Atoms']
1875            cx,ct,cs,ci = data['Drawing']['atomPtrs']
1876            styleChoice = [' ','type','name','number']
1877            if generalData['Type'] == 'macromolecular':
1878                styleChoice = [' ','type','name','number','residue','1-letter','chain']
1879            dlg = wx.SingleChoiceDialog(G2frame,'Select','Atom label style',styleChoice)
1880            if dlg.ShowModal() == wx.ID_OK:
1881                sel = dlg.GetSelection()
1882                parms = styleChoice[sel]
1883                for r in indx:
1884                    atomData[r][cs+1] = parms
1885                    drawAtoms.SetCellValue(r,cs+1,parms)
1886            dlg.Destroy()
1887            drawAtoms.ClearSelection()
1888            G2plt.PlotStructure(G2frame,data)
1889           
1890    def DrawAtomColor(event):
1891
1892        indx = drawAtoms.GetSelectedRows()
1893        if indx:
1894            if len(indx) > 1:
1895                G2frame.dataFrame.SetStatusText('Select Custom Color, change color, Add to Custom Colors, then OK')
1896            else:
1897                G2frame.dataFrame.SetStatusText('Change color, Add to Custom Colors, then OK')
1898            generalData = data['General']
1899            atomData = data['Drawing']['Atoms']
1900            cx,ct,cs,ci = data['Drawing']['atomPtrs']
1901            atmColors = []
1902            atmTypes = []
1903            for r in indx:
1904                if atomData[r][cs+2] not in atmColors:
1905                    atmColors.append(atomData[r][cs+2])
1906                    atmTypes.append(atomData[r][ct])
1907                    if len(atmColors) > 16:
1908                        break
1909            colors = wx.ColourData()
1910            colors.SetChooseFull(True)
1911            dlg = wx.ColourDialog(G2frame)
1912            if dlg.ShowModal() == wx.ID_OK:
1913                for i in range(len(atmColors)):                   
1914                    atmColors[i] = dlg.GetColourData().GetColour()
1915                colorDict = dict(zip(atmTypes,atmColors))
1916                for r in indx:
1917                    color = colorDict[atomData[r][ct]]
1918                    atomData[r][cs+2] = color
1919                    attr = wg.GridCellAttr()                #needs to be here - gets lost if outside loop!
1920                    attr.SetBackgroundColour(color)
1921                    drawAtoms.SetAttr(r,cs+2,attr)
1922                    data['Drawing']['Atoms'][r][cs+2] = color
1923            drawAtoms.ClearSelection()
1924            dlg.Destroy()
1925            G2frame.dataFrame.SetStatusText('')
1926            G2plt.PlotStructure(G2frame,data)
1927           
1928    def ResetAtomColors(event):
1929        generalData = data['General']
1930        atomData = data['Drawing']['Atoms']
1931        cx,ct,cs,ci = data['Drawing']['atomPtrs']
1932        for atom in atomData:           
1933            atNum = generalData['AtomTypes'].index(atom[ct])
1934            atom[cs+2] = list(generalData['Color'][atNum])
1935        UpdateDrawAtoms()
1936        drawAtoms.ClearSelection()
1937        G2plt.PlotStructure(G2frame,data)       
1938       
1939    def SetViewPoint(event):
1940        indx = drawAtoms.GetSelectedRows()
1941        if indx:
1942            atomData = data['Drawing']['Atoms']
1943            cx = data['Drawing']['atomPtrs'][0]
1944            data['Drawing']['viewPoint'] = [atomData[indx[0]][cx:cx+3],[indx[0],0]]
1945            drawAtoms.ClearSelection()                                  #do I really want to do this?
1946            G2plt.PlotStructure(G2frame,data)
1947           
1948    def noDuplicate(xyz,atomData):                  #be careful where this is used - it's slow
1949        cx = data['Drawing']['atomPtrs'][0]
1950        if True in [np.allclose(np.array(xyz),np.array(atom[cx:cx+3]),atol=0.0002) for atom in atomData]:
1951            return False
1952        else:
1953            return True
1954               
1955    def AddSymEquiv(event):
1956        indx = drawAtoms.GetSelectedRows()
1957        indx.sort()
1958        if indx:
1959            colLabels = [drawAtoms.GetColLabelValue(c) for c in range(drawAtoms.GetNumberCols())]
1960            cx = colLabels.index('x')
1961            cuia = colLabels.index('I/A')
1962            cuij = cuia+2
1963            atomData = data['Drawing']['Atoms']
1964            generalData = data['General']
1965            SGData = generalData['SGData']
1966            dlg = G2gd.SymOpDialog(G2frame,SGData,False,True)
1967            try:
1968                if dlg.ShowModal() == wx.ID_OK:
1969                    Inv,Cent,Opr,Cell,New,Force = dlg.GetSelection()
1970                    Cell = np.array(Cell)
1971                    cent = SGData['SGCen'][Cent]
1972                    M,T = SGData['SGOps'][Opr]
1973                    for ind in indx:
1974                        XYZ = np.array(atomData[ind][cx:cx+3])
1975                        XYZ = np.inner(M,XYZ)+T
1976                        if Inv:
1977                            XYZ = -XYZ
1978                        XYZ = XYZ+cent+Cell
1979                        if Force:
1980                            XYZ = G2spc.MoveToUnitCell(XYZ)
1981                        if noDuplicate(XYZ,atomData):
1982                            atom = copy.copy(atomData[ind])
1983                            atom[cx:cx+3] = XYZ
1984                            atomOp = atom[cx+3]
1985                            newOp = str(((Opr+1)+100*Cent)*(1-2*Inv))+'+'+ \
1986                                str(int(Cell[0]))+','+str(int(Cell[1]))+','+str(int(Cell[2]))                           
1987                            atom[cx+3] = G2spc.StringOpsProd(atomOp,newOp,SGData)
1988                            if atom[cuia] == 'A':
1989                                Uij = atom[cuij:cuij+6]
1990                                U = G2spc.Uij2U(Uij)
1991                                U = np.inner(np.inner(M,U),M)
1992                                Uij = G2spc.U2Uij(U)
1993                                atom[cuij:cuij+6] = Uij
1994                            atomData.append(atom)
1995            finally:
1996                dlg.Destroy()
1997            UpdateDrawAtoms()
1998            drawAtoms.ClearSelection()
1999            G2plt.PlotStructure(G2frame,data)
2000           
2001    def TransformSymEquiv(event):
2002        indx = drawAtoms.GetSelectedRows()
2003        indx.sort()
2004        if indx:
2005            atomData = data['Drawing']['Atoms']
2006            colLabels = [drawAtoms.GetColLabelValue(c) for c in range(drawAtoms.GetNumberCols())]
2007            cx = colLabels.index('x')
2008            cuia = colLabels.index('I/A')
2009            cuij = cuia+2
2010            atomData = data['Drawing']['Atoms']
2011            generalData = data['General']
2012            SGData = generalData['SGData']
2013            dlg = G2gd.SymOpDialog(G2frame,SGData,False,True)
2014            try:
2015                if dlg.ShowModal() == wx.ID_OK:
2016                    Inv,Cent,Opr,Cell,New,Force = dlg.GetSelection()
2017                    Cell = np.array(Cell)
2018                    cent = SGData['SGCen'][Cent]
2019                    M,T = SGData['SGOps'][Opr]
2020                    for ind in indx:
2021                        XYZ = np.array(atomData[ind][cx:cx+3])
2022                        XYZ = np.inner(M,XYZ)+T
2023                        if Inv:
2024                            XYZ = -XYZ
2025                        XYZ = XYZ+cent+Cell
2026                        if Force:
2027                            XYZ = G2spc.MoveToUnitCell(XYZ)
2028                        atom = atomData[ind]
2029                        atom[cx:cx+3] = XYZ
2030                        atomOp = atom[cx+3]
2031                        newOp = str(((Opr+1)+100*Cent)*(1-2*Inv))+'+'+ \
2032                            str(int(Cell[0]))+','+str(int(Cell[1]))+','+str(int(Cell[2]))
2033                        atom[cx+3] = G2spc.StringOpsProd(atomOp,newOp,SGData)
2034                        if atom[cuia] == 'A':
2035                            Uij = atom[cuij:cuij+6]
2036                            U = G2spc.Uij2U(Uij)
2037                            U = np.inner(np.inner(M,U),M)
2038                            Uij = G2spc.U2Uij(U)
2039                            atom[cuij:cuij+6] = Uij
2040                    data['Drawing']['Atoms'] = atomData
2041            finally:
2042                dlg.Destroy()
2043            UpdateDrawAtoms()
2044            drawAtoms.ClearSelection()
2045            G2plt.PlotStructure(G2frame,data)
2046           
2047    def FillCoordSphere(event):
2048        generalData = data['General']
2049        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])
2050        radii = generalData['BondRadii']
2051        atomTypes = generalData['AtomTypes']
2052        try:
2053            indH = atomTypes.index('H')
2054            radii[indH] = 0.5
2055        except:
2056            pass           
2057        indx = drawAtoms.GetSelectedRows()
2058        if indx:
2059            indx.sort()
2060            atomData = data['Drawing']['Atoms']
2061            numAtoms = len(atomData)
2062            cx,ct,cs,ci = data['Drawing']['atomPtrs']
2063            generalData = data['General']
2064            SGData = generalData['SGData']
2065            cellArray = G2lat.CellBlock(1)
2066            wx.BeginBusyCursor()
2067            try:
2068                for ind in indx:
2069                    atomA = atomData[ind]
2070                    xyzA = np.array(atomA[cx:cx+3])
2071                    indA = atomTypes.index(atomA[ct])
2072                    for atomB in atomData[:numAtoms]:
2073                        indB = atomTypes.index(atomB[ct])
2074                        sumR = radii[indA]+radii[indB]
2075                        xyzB = np.array(atomB[cx:cx+3])
2076                        for xyz in cellArray+xyzB:
2077                            dist = np.sqrt(np.sum(np.inner(Amat,xyz-xyzA)**2))
2078                            if 0 < dist <= data['Drawing']['radiusFactor']*sumR:
2079                                if noDuplicate(xyz,atomData):
2080                                    oprB = atomB[cx+3]
2081                                    C = xyz-xyzB
2082                                    newOp = '1+'+str(int(round(C[0])))+','+str(int(round(C[1])))+','+str(int(round(C[2])))
2083                                    newAtom = atomB[:]
2084                                    newAtom[cx:cx+3] = xyz
2085                                    newAtom[cx+3] = G2spc.StringOpsProd(oprB,newOp,SGData)
2086                                    atomData.append(newAtom)
2087            finally:
2088                wx.EndBusyCursor()
2089            data['Drawing']['Atoms'] = atomData
2090            UpdateDrawAtoms()
2091            drawAtoms.ClearSelection()
2092            G2plt.PlotStructure(G2frame,data)
2093           
2094    def FillUnitCell(event):
2095        indx = drawAtoms.GetSelectedRows()
2096        indx.sort()
2097        if indx:
2098            atomData = data['Drawing']['Atoms']
2099            colLabels = [drawAtoms.GetColLabelValue(c) for c in range(drawAtoms.GetNumberCols())]
2100            cx = colLabels.index('x')
2101            cuia = colLabels.index('I/A')
2102            cuij = cuia+2
2103            generalData = data['General']
2104            SGData = generalData['SGData']
2105            wx.BeginBusyCursor()
2106            try:
2107                for ind in indx:
2108                    atom = atomData[ind]
2109                    XYZ = np.array(atom[cx:cx+3])
2110                    if atom[cuia] == 'A':
2111                        Uij = atom[cuij:cuij+6]
2112                        result = G2spc.GenAtom(XYZ,SGData,False,Uij,False)
2113                        for item in result:
2114                            atom = copy.copy(atomData[ind])
2115                            atom[cx:cx+3] = item[0]
2116                            atom[cx+3] = str(item[2])+'+' \
2117                                +str(item[3][0])+','+str(item[3][1])+','+str(item[3][2])
2118                            atom[cuij:cuij+6] = item[1]
2119                            Opp = G2spc.Opposite(item[0])
2120                            for xyz in Opp:
2121                                if noDuplicate(xyz,atomData):
2122                                    cell = np.asarray(np.rint(xyz-atom[cx:cx+3]),dtype=np.int32)
2123                                    cell = '1'+'+'+ \
2124                                        str(cell[0])+','+str(cell[1])+','+str(cell[2])
2125                                    atom[cx:cx+3] = xyz
2126                                    atom[cx+3] = G2spc.StringOpsProd(cell,atom[cx+3],SGData)
2127                                    atomData.append(atom[:])
2128                    else:
2129                        result = G2spc.GenAtom(XYZ,SGData,False,Move=False)
2130                        for item in result:
2131                            atom = copy.copy(atomData[ind])
2132                            atom[cx:cx+3] = item[0]
2133                            atom[cx+3] = str(item[1])+'+' \
2134                                +str(item[2][0])+','+str(item[2][1])+','+str(item[2][2])
2135                            Opp = G2spc.Opposite(item[0])
2136                            for xyz in Opp:
2137                                if noDuplicate(xyz,atomData):
2138                                    cell = np.asarray(np.rint(xyz-atom[cx:cx+3]),dtype=np.int32)
2139                                    cell = '1'+'+'+ \
2140                                        str(cell[0])+','+str(cell[1])+','+str(cell[2])
2141                                    atom[cx:cx+3] = xyz
2142                                    atom[cx+3] = G2spc.StringOpsProd(cell,atom[cx+3],SGData)
2143                                    atomData.append(atom[:])               
2144                    data['Drawing']['Atoms'] = atomData
2145            finally:
2146                wx.EndBusyCursor()
2147            UpdateDrawAtoms()
2148            drawAtoms.ClearSelection()
2149            G2plt.PlotStructure(G2frame,data)
2150           
2151    def FindBondsToo():                         #works but slow for large structures - keep as reference
2152        cx,ct,cs,ci = data['Drawing']['atomPtrs']
2153        atomData = data['Drawing']['Atoms']
2154        generalData = data['General']
2155        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])
2156        radii = generalData['BondRadii']
2157        atomTypes = generalData['AtomTypes']
2158        try:
2159            indH = atomTypes.index('H')
2160            radii[indH] = 0.5
2161        except:
2162            pass           
2163        for atom in atomData:
2164            atom[-1] = []
2165        Atoms = []
2166        for i,atom in enumerate(atomData):
2167            Atoms.append([i,np.array(atom[cx:cx+3]),atom[cs],radii[atomTypes.index(atom[ct])]])
2168        for atomA in Atoms:
2169            if atomA[2] in ['lines','sticks','ellipsoids','balls & sticks','polyhedra']:
2170                for atomB in Atoms:                   
2171                    Dx = atomB[1]-atomA[1]
2172                    DX = np.inner(Amat,Dx)
2173                    dist = np.sqrt(np.sum(DX**2))
2174                    sumR = atomA[3]+atomB[3]
2175                    if 0.5 < dist <= 0.85*sumR:
2176                        i = atomA[0]
2177                        if atomA[2] == 'polyhedra':
2178                            atomData[i][-1].append(DX)
2179                        elif atomB[1] != 'polyhedra':
2180                            j = atomB[0]
2181                            atomData[i][-1].append(Dx*atomA[3]/sumR)
2182                            atomData[j][-1].append(-Dx*atomB[3]/sumR)
2183                   
2184    def FindBondsDraw():                    #uses numpy & masks - very fast even for proteins!
2185        import numpy.ma as ma
2186        cx,ct,cs,ci = data['Drawing']['atomPtrs']
2187        hydro = data['Drawing']['showHydrogen']
2188        atomData = data['Drawing']['Atoms']
2189        generalData = data['General']
2190        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])
2191        radii = generalData['BondRadii']
2192        atomTypes = generalData['AtomTypes']
2193        try:
2194            indH = atomTypes.index('H')
2195            radii[indH] = 0.5
2196        except:
2197            pass           
2198        for atom in atomData:
2199            atom[-2] = []               #clear out old bonds/polyhedra
2200            atom[-1] = []
2201        Indx = range(len(atomData))
2202        Atoms = []
2203        Styles = []
2204        Radii = []
2205        for atom in atomData:
2206            Atoms.append(np.array(atom[cx:cx+3]))
2207            Styles.append(atom[cs])
2208            try:
2209                if not hydro and atom[ct] == 'H':
2210                    Radii.append(0.0)
2211                else:
2212                    Radii.append(radii[atomTypes.index(atom[ct])])
2213            except ValueError:          #changed atom type!
2214                Radii.append(0.20)
2215        Atoms = np.array(Atoms)
2216        Radii = np.array(Radii)
2217        IASR = zip(Indx,Atoms,Styles,Radii)
2218        for atomA in IASR:
2219            if atomA[2] in ['lines','sticks','ellipsoids','balls & sticks','polyhedra']:
2220                Dx = Atoms-atomA[1]
2221                dist = ma.masked_less(np.sqrt(np.sum(np.inner(Amat,Dx)**2,axis=0)),0.5) #gets rid of G2frame & disorder "bonds" < 0.5A
2222                sumR = atomA[3]+Radii
2223                IndB = ma.nonzero(ma.masked_greater(dist-data['Drawing']['radiusFactor']*sumR,0.))                 #get indices of bonded atoms
2224                i = atomA[0]
2225                for j in IndB[0]:
2226                    if Styles[i] == 'polyhedra':
2227                        atomData[i][-2].append(np.inner(Amat,Dx[j]))
2228                    elif Styles[j] != 'polyhedra' and j > i:
2229                        atomData[i][-2].append(Dx[j]*Radii[i]/sumR[j])
2230                        atomData[j][-2].append(-Dx[j]*Radii[j]/sumR[j])
2231                if Styles[i] == 'polyhedra':
2232                    Bonds = atomData[i][-2]
2233                    Faces = []
2234                    if len(Bonds) > 2:
2235                        FaceGen = G2lat.uniqueCombinations(Bonds,3)     #N.B. this is a generator
2236                        for face in FaceGen:
2237                            vol = nl.det(face)
2238                            if abs(vol) > 1. or len(Bonds) == 3:
2239                                if vol < 0.:
2240                                    face = [face[0],face[2],face[1]]
2241                                face = np.array(face)
2242                                if not np.array([np.array(nl.det(face-bond))+0.0001 < 0 for bond in Bonds]).any():
2243                                    norm = np.cross(face[1]-face[0],face[2]-face[0])
2244                                    norm /= np.sqrt(np.sum(norm**2))
2245                                    Faces.append([face,norm])
2246                        atomData[i][-1] = Faces
2247                       
2248    def DrawAtomsDelete(event):   
2249        indx = drawAtoms.GetSelectedRows()
2250        indx.sort()
2251        if indx:
2252            atomData = data['Drawing']['Atoms']
2253            indx.reverse()
2254            for ind in indx:
2255                del atomData[ind]
2256            UpdateDrawAtoms()
2257            drawAtoms.ClearSelection()
2258            G2plt.PlotStructure(G2frame,data)
2259        event.StopPropagation()
2260       
2261    def OnReloadDrawAtoms(event):
2262        data['Drawing']['Atoms'] = []
2263        UpdateDrawAtoms()
2264        drawAtoms.ClearSelection()
2265        G2plt.PlotStructure(G2frame,data)
2266        event.StopPropagation()
2267       
2268    def DrawAtomsDeleteByIDs(IDs):
2269        atomData = data['Drawing']['Atoms']
2270        indx = G2mth.FindAtomIndexByIDs(atomData,IDs)
2271        indx.reverse()
2272        for ind in indx:
2273            del atomData[ind]
2274           
2275    def ChangeDrawAtomsByIDs(colName,IDs,value):
2276        atomData = data['Drawing']['Atoms']
2277        cx,ct,cs,ci = data['Drawing']['atomPtrs']
2278        if colName == 'Name':
2279            col = ct-1
2280        elif colName == 'Type':
2281            col = ct
2282        elif colName == 'I/A':
2283            col = cs
2284        indx = G2mth.FindAtomIndexByIDs(atomData,IDs)
2285        for ind in indx:
2286            atomData[ind][col] = value
2287               
2288    def OnDrawPlane(event):
2289        indx = drawAtoms.GetSelectedRows()
2290        if len(indx) < 4:
2291            print '**** ERROR - need 4+ atoms for plane calculation'
2292            return
2293        PlaneData = {}
2294        drawingData = data['Drawing']
2295        atomData = drawingData['Atoms']
2296        colLabels = [drawAtoms.GetColLabelValue(c) for c in range(drawAtoms.GetNumberCols())]
2297        cx = colLabels.index('x')
2298        cn = colLabels.index('Name')
2299        xyz = []
2300        for i,atom in enumerate(atomData):
2301            if i in indx:
2302                xyz.append([i,]+atom[cn:cn+2]+atom[cx:cx+3])
2303        generalData = data['General']
2304        PlaneData['Name'] = generalData['Name']
2305        PlaneData['Atoms'] = xyz
2306        PlaneData['Cell'] = generalData['Cell'][1:] #+ volume
2307        G2str.BestPlane(PlaneData)
2308       
2309    def OnDrawDistVP(event):
2310        # distance to view point
2311        indx = drawAtoms.GetSelectedRows()
2312        if not indx:
2313            print '***** ERROR - no atoms selected'
2314            return
2315        generalData = data['General']
2316        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])           
2317        drawingData = data['Drawing']
2318        viewPt = np.array(drawingData['viewPoint'][0])
2319        print ' Distance from view point at %.3f %.3f %.3f to:'%(viewPt[0],viewPt[1],viewPt[2])
2320        atomDData = drawingData['Atoms']
2321        colLabels = [drawAtoms.GetColLabelValue(c) for c in range(drawAtoms.GetNumberCols())]
2322        cx = colLabels.index('x')
2323        cn = colLabels.index('Name')
2324        for i in indx:
2325            atom = atomDData[i]
2326            Dx = np.array(atom[cx:cx+3])-viewPt
2327            dist = np.sqrt(np.sum(np.inner(Amat,Dx)**2,axis=0))
2328            print 'Atom: %8s (%12s) distance = %.3f'%(atom[cn],atom[cx+3],dist)
2329   
2330    def OnDrawDAT(event):
2331        #distance, angle, torsion
2332        indx = drawAtoms.GetSelectedRows()
2333        if len(indx) not in [2,3,4]:
2334            print '**** ERROR - wrong number of atoms for distance, angle or torsion calculation'
2335            return
2336        DATData = {}
2337        ocx,oct,ocs,cia = data['General']['AtomPtrs']
2338        drawingData = data['Drawing']
2339        atomData = data['Atoms']
2340        atomDData = drawingData['Atoms']
2341        colLabels = [drawAtoms.GetColLabelValue(c) for c in range(drawAtoms.GetNumberCols())]
2342        cx = colLabels.index('x')
2343        cn = colLabels.index('Name')
2344        cid = colLabels.index('I/A')+8
2345        xyz = []
2346        Oxyz = []
2347        DATData['Natoms'] = len(indx)
2348        for i in indx:
2349            atom = atomDData[i]
2350            xyz.append([i,]+atom[cn:cn+2]+atom[cx:cx+4]) #also gets Sym Op
2351            id = G2mth.FindAtomIndexByIDs(atomData,[atom[cid],],False)[0]
2352            Oxyz.append([id,]+atomData[id][cx+1:cx+4])
2353        DATData['Datoms'] = xyz
2354        DATData['Oatoms'] = Oxyz
2355        generalData = data['General']
2356        DATData['Name'] = generalData['Name']
2357        DATData['SGData'] = generalData['SGData']
2358        DATData['Cell'] = generalData['Cell'][1:] #+ volume
2359        if 'pId' in data:
2360            DATData['pId'] = data['pId']
2361            DATData['covData'] = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.root, 'Covariance'))
2362        G2str.DisAglTor(DATData)
2363               
2364################################################################################
2365#### Draw Options page
2366################################################################################
2367
2368    def UpdateDrawOptions():
2369        import copy
2370        import wx.lib.colourselect as wcs
2371        generalData = data['General']
2372        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])
2373        SetupDrawingData()
2374        drawingData = data['Drawing']
2375        if generalData['Type'] == 'nuclear':
2376            pickChoice = ['Atoms','Bonds','Torsions','Planes']
2377        elif generalData['Type'] == 'macromolecular':
2378            pickChoice = ['Atoms','Residues','Chains','Bonds','Torsions','Planes','phi/psi']
2379
2380        def SlopSizer():
2381           
2382            def OnCameraPos(event):
2383                drawingData['cameraPos'] = cameraPos.GetValue()
2384                cameraPosTxt.SetLabel(' Camera Distance: '+'%.2f'%(drawingData['cameraPos']))
2385                ZclipTxt.SetLabel(' Z clipping: '+'%.2fA'%(drawingData['Zclip']*drawingData['cameraPos']/100.))
2386                G2plt.PlotStructure(G2frame,data)
2387
2388            def OnZclip(event):
2389                drawingData['Zclip'] = Zclip.GetValue()
2390                ZclipTxt.SetLabel(' Z clipping: '+'%.2fA'%(drawingData['Zclip']*drawingData['cameraPos']/100.))
2391                G2plt.PlotStructure(G2frame,data)
2392               
2393            def OnZstep(event):
2394                try:
2395                    step = float(Zstep.GetValue())
2396                    if not (0.01 <= step <= 1.0):
2397                        raise ValueError
2398                except ValueError:
2399                    step = drawingData['Zstep']
2400                drawingData['Zstep'] = step
2401                Zstep.SetValue('%.2fA'%(drawingData['Zstep']))
2402               
2403            def OnMoveZ(event):
2404                move = MoveZ.GetValue()*drawingData['Zstep']
2405                MoveZ.SetValue(0)
2406                VP = np.inner(Amat,np.array(drawingData['viewPoint'][0]))
2407                VD = np.inner(Amat,np.array(drawingData['viewDir']))
2408                VD /= np.sqrt(np.sum(VD**2))
2409                VP += move*VD
2410                VP = np.inner(Bmat,VP)
2411                drawingData['viewPoint'][0] = VP
2412                panel = dataDisplay.GetChildren()
2413                names = [child.GetName() for child in panel]
2414                panel[names.index('viewPoint')].SetValue('%.3f %.3f %.3f'%(VP[0],VP[1],VP[2]))               
2415                G2plt.PlotStructure(G2frame,data)
2416               
2417            def OnVdWScale(event):
2418                drawingData['vdwScale'] = vdwScale.GetValue()/100.
2419                vdwScaleTxt.SetLabel(' van der Waals scale: '+'%.2f'%(drawingData['vdwScale']))
2420                G2plt.PlotStructure(G2frame,data)
2421   
2422            def OnEllipseProb(event):
2423                drawingData['ellipseProb'] = ellipseProb.GetValue()
2424                ellipseProbTxt.SetLabel(' Ellipsoid probability: '+'%d%%'%(drawingData['ellipseProb']))
2425                G2plt.PlotStructure(G2frame,data)
2426   
2427            def OnBallScale(event):
2428                drawingData['ballScale'] = ballScale.GetValue()/100.
2429                ballScaleTxt.SetLabel(' Ball scale: '+'%.2f'%(drawingData['ballScale']))
2430                G2plt.PlotStructure(G2frame,data)
2431
2432            def OnBondRadius(event):
2433                drawingData['bondRadius'] = bondRadius.GetValue()/100.
2434                bondRadiusTxt.SetLabel(' Bond radius, A: '+'%.2f'%(drawingData['bondRadius']))
2435                G2plt.PlotStructure(G2frame,data)
2436               
2437            def OnContourLevel(event):
2438                drawingData['contourLevel'] = contourLevel.GetValue()/100.
2439                contourLevelTxt.SetLabel(' Contour level: '+'%.2f'%(drawingData['contourLevel']*generalData['Map']['rhoMax']))
2440                G2plt.PlotStructure(G2frame,data)
2441
2442            def OnMapSize(event):
2443                drawingData['mapSize'] = mapSize.GetValue()/10.
2444                mapSizeTxt.SetLabel(' Map radius, A: '+'%.1f'%(drawingData['mapSize']))
2445                G2plt.PlotStructure(G2frame,data)
2446
2447           
2448            slopSizer = wx.BoxSizer(wx.HORIZONTAL)
2449            slideSizer = wx.FlexGridSizer(7,2)
2450            slideSizer.AddGrowableCol(1,1)
2451   
2452            cameraPosTxt = wx.StaticText(dataDisplay,-1,
2453                ' Camera Distance: '+'%.2f'%(drawingData['cameraPos']),name='cameraPos')
2454            slideSizer.Add(cameraPosTxt,0,wx.ALIGN_CENTER_VERTICAL)
2455            cameraPos = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=drawingData['cameraPos'],name='cameraSlider')
2456            cameraPos.SetRange(10,500)
2457            cameraPos.Bind(wx.EVT_SLIDER, OnCameraPos)
2458            slideSizer.Add(cameraPos,1,wx.EXPAND|wx.RIGHT)
2459           
2460            ZclipTxt = wx.StaticText(dataDisplay,-1,' Z clipping: '+'%.2fA'%(drawingData['Zclip']*drawingData['cameraPos']/100.))
2461            slideSizer.Add(ZclipTxt,0,wx.ALIGN_CENTER_VERTICAL)
2462            Zclip = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=drawingData['Zclip'])
2463            Zclip.SetRange(1,99)
2464            Zclip.Bind(wx.EVT_SLIDER, OnZclip)
2465            slideSizer.Add(Zclip,1,wx.EXPAND|wx.RIGHT)
2466           
2467            ZstepSizer = wx.BoxSizer(wx.HORIZONTAL)
2468            ZstepSizer.Add(wx.StaticText(dataDisplay,-1,' Z step:'),0,wx.ALIGN_CENTER_VERTICAL)
2469            Zstep = wx.TextCtrl(dataDisplay,value='%.2f'%(drawingData['Zstep']),
2470                style=wx.TE_PROCESS_ENTER)
2471            Zstep.Bind(wx.EVT_TEXT_ENTER,OnZstep)
2472            Zstep.Bind(wx.EVT_KILL_FOCUS,OnZstep)
2473            ZstepSizer.Add(Zstep,0,wx.ALIGN_CENTER_VERTICAL)
2474            slideSizer.Add(ZstepSizer)
2475            MoveSizer = wx.BoxSizer(wx.HORIZONTAL)
2476            MoveSizer.Add(wx.StaticText(dataDisplay,-1,'   Press to step:'),0,wx.ALIGN_CENTER_VERTICAL)
2477            MoveZ = wx.SpinButton(dataDisplay,style=wx.SP_HORIZONTAL,size=wx.Size(100,20))
2478            MoveZ.SetValue(0)
2479            MoveZ.SetRange(-1,1)
2480            MoveZ.Bind(wx.EVT_SPIN, OnMoveZ)
2481            MoveSizer.Add(MoveZ)
2482            slideSizer.Add(MoveSizer,1,wx.EXPAND|wx.RIGHT)
2483           
2484            vdwScaleTxt = wx.StaticText(dataDisplay,-1,' van der Waals scale: '+'%.2f'%(drawingData['vdwScale']))
2485            slideSizer.Add(vdwScaleTxt,0,wx.ALIGN_CENTER_VERTICAL)
2486            vdwScale = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=int(100*drawingData['vdwScale']))
2487            vdwScale.Bind(wx.EVT_SLIDER, OnVdWScale)
2488            slideSizer.Add(vdwScale,1,wx.EXPAND|wx.RIGHT)
2489   
2490            ellipseProbTxt = wx.StaticText(dataDisplay,-1,' Ellipsoid probability: '+'%d%%'%(drawingData['ellipseProb']))
2491            slideSizer.Add(ellipseProbTxt,0,wx.ALIGN_CENTER_VERTICAL)
2492            ellipseProb = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=drawingData['ellipseProb'])
2493            ellipseProb.SetRange(1,99)
2494            ellipseProb.Bind(wx.EVT_SLIDER, OnEllipseProb)
2495            slideSizer.Add(ellipseProb,1,wx.EXPAND|wx.RIGHT)
2496   
2497            ballScaleTxt = wx.StaticText(dataDisplay,-1,' Ball scale: '+'%.2f'%(drawingData['ballScale']))
2498            slideSizer.Add(ballScaleTxt,0,wx.ALIGN_CENTER_VERTICAL)
2499            ballScale = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=int(100*drawingData['ballScale']))
2500            ballScale.Bind(wx.EVT_SLIDER, OnBallScale)
2501            slideSizer.Add(ballScale,1,wx.EXPAND|wx.RIGHT)
2502   
2503            bondRadiusTxt = wx.StaticText(dataDisplay,-1,' Bond radius, A: '+'%.2f'%(drawingData['bondRadius']))
2504            slideSizer.Add(bondRadiusTxt,0,wx.ALIGN_CENTER_VERTICAL)
2505            bondRadius = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=int(100*drawingData['bondRadius']))
2506            bondRadius.SetRange(1,25)
2507            bondRadius.Bind(wx.EVT_SLIDER, OnBondRadius)
2508            slideSizer.Add(bondRadius,1,wx.EXPAND|wx.RIGHT)
2509           
2510            if generalData['Map']['rhoMax']:
2511                contourLevelTxt = wx.StaticText(dataDisplay,-1,' Contour level: '+'%.2f'%(drawingData['contourLevel']*generalData['Map']['rhoMax']))
2512                slideSizer.Add(contourLevelTxt,0,wx.ALIGN_CENTER_VERTICAL)
2513                contourLevel = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=int(100*drawingData['contourLevel']))
2514                contourLevel.SetRange(1,100)
2515                contourLevel.Bind(wx.EVT_SLIDER, OnContourLevel)
2516                slideSizer.Add(contourLevel,1,wx.EXPAND|wx.RIGHT)
2517                mapSizeTxt = wx.StaticText(dataDisplay,-1,' Map radius, A: '+'%.1f'%(drawingData['mapSize']))
2518                slideSizer.Add(mapSizeTxt,0,wx.ALIGN_CENTER_VERTICAL)
2519                mapSize = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=int(10*drawingData['mapSize']))
2520                mapSize.SetRange(1,100)
2521                mapSize.Bind(wx.EVT_SLIDER, OnMapSize)
2522                slideSizer.Add(mapSize,1,wx.EXPAND|wx.RIGHT)
2523           
2524            slopSizer.Add(slideSizer,1,wx.EXPAND|wx.RIGHT)
2525            slopSizer.Add((10,5),0)
2526            slopSizer.SetMinSize(wx.Size(350,10))
2527            return slopSizer
2528           
2529        def ShowSizer():
2530           
2531            def OnBackColor(event):
2532                drawingData['backColor'] = event.GetValue()
2533                G2plt.PlotStructure(G2frame,data)
2534   
2535            def OnShowABC(event):
2536                drawingData['showABC'] = showABC.GetValue()
2537                G2plt.PlotStructure(G2frame,data)
2538   
2539            def OnShowUnitCell(event):
2540                drawingData['unitCellBox'] = unitCellBox.GetValue()
2541                G2plt.PlotStructure(G2frame,data)
2542   
2543            def OnShowHyd(event):
2544                drawingData['showHydrogen'] = showHydrogen.GetValue()
2545                FindBondsDraw()
2546                G2plt.PlotStructure(G2frame,data)
2547               
2548            def OnViewPoint(event):
2549                Obj = event.GetEventObject()
2550                viewPt = Obj.GetValue().split()
2551                try:
2552                    VP = [float(viewPt[i]) for i in range(3)]
2553                except (ValueError,IndexError):
2554                    VP = drawingData['viewPoint'][0]
2555                Obj.SetValue('%.3f %.3f %.3f'%(VP[0],VP[1],VP[2]))
2556                drawingData['viewPoint'][0] = VP
2557                G2plt.PlotStructure(G2frame,data)
2558               
2559            def OnViewDir(event):
2560                Obj = event.GetEventObject()
2561                viewDir = Obj.GetValue().split()
2562                try:
2563                    Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])
2564                    VD = np.array([float(viewDir[i]) for i in range(3)])
2565                    VC = np.inner(Amat,VD)
2566                    VC /= np.sqrt(np.sum(VC**2))
2567                    V = np.array(drawingData['viewDir'])
2568                    VB = np.inner(Amat,V)
2569                    VB /= np.sqrt(np.sum(VB**2))
2570                    VX = np.cross(VC,VB)
2571                    A = acosd(max((2.-np.sum((VB-VC)**2))/2.,-1.))
2572                    QV = G2mth.AVdeg2Q(A,VX)
2573                    Q = drawingData['Quaternion']
2574                    drawingData['Quaternion'] = G2mth.prodQQ(Q,QV)
2575                except (ValueError,IndexError):
2576                    VD = drawingData['viewDir']
2577                Obj.SetValue('%.3f %.3f %.3f'%(VD[0],VD[1],VD[2]))
2578                drawingData['viewDir'] = VD
2579                G2plt.PlotStructure(G2frame,data)
2580                               
2581            showSizer = wx.BoxSizer(wx.VERTICAL)           
2582            lineSizer = wx.BoxSizer(wx.HORIZONTAL)
2583            lineSizer.Add(wx.StaticText(dataDisplay,-1,' Background color:'),0,wx.ALIGN_CENTER_VERTICAL)
2584            backColor = wcs.ColourSelect(dataDisplay, -1,colour=drawingData['backColor'],size=wx.Size(25,25))
2585            backColor.Bind(wcs.EVT_COLOURSELECT, OnBackColor)
2586            lineSizer.Add(backColor,0,wx.ALIGN_CENTER_VERTICAL)
2587            lineSizer.Add(wx.StaticText(dataDisplay,-1,' View Dir.:'),0,wx.ALIGN_CENTER_VERTICAL)
2588            VD = drawingData['viewDir']
2589            viewDir = wx.TextCtrl(dataDisplay,value='%.3f %.3f %.3f'%(VD[0],VD[1],VD[2]),
2590                style=wx.TE_PROCESS_ENTER,size=wx.Size(140,20),name='viewDir')
2591            viewDir.Bind(wx.EVT_TEXT_ENTER,OnViewDir)
2592            viewDir.Bind(wx.EVT_KILL_FOCUS,OnViewDir)
2593            lineSizer.Add(viewDir,0,wx.ALIGN_CENTER_VERTICAL)
2594            showSizer.Add(lineSizer)
2595            showSizer.Add((0,5),0)
2596           
2597            lineSizer = wx.BoxSizer(wx.HORIZONTAL)
2598            showABC = wx.CheckBox(dataDisplay,-1,label=' Show view point?')
2599            showABC.Bind(wx.EVT_CHECKBOX, OnShowABC)
2600            showABC.SetValue(drawingData['showABC'])
2601            lineSizer.Add(showABC,0,wx.ALIGN_CENTER_VERTICAL)
2602            lineSizer.Add(wx.StaticText(dataDisplay,-1,' View Point:'),0,wx.ALIGN_CENTER_VERTICAL)
2603            VP = drawingData['viewPoint'][0]
2604            viewPoint = wx.TextCtrl(dataDisplay,value='%.3f %.3f %.3f'%(VP[0],VP[1],VP[2]),
2605                style=wx.TE_PROCESS_ENTER,size=wx.Size(140,20),name='viewPoint')
2606            viewPoint.Bind(wx.EVT_TEXT_ENTER,OnViewPoint)
2607            viewPoint.Bind(wx.EVT_KILL_FOCUS,OnViewPoint)
2608            lineSizer.Add(viewPoint,0,wx.ALIGN_CENTER_VERTICAL)
2609            showSizer.Add(lineSizer)
2610            showSizer.Add((0,5),0)
2611           
2612            line2Sizer = wx.BoxSizer(wx.HORIZONTAL)
2613   
2614            unitCellBox = wx.CheckBox(dataDisplay,-1,label=' Show unit cell?')
2615            unitCellBox.Bind(wx.EVT_CHECKBOX, OnShowUnitCell)
2616            unitCellBox.SetValue(drawingData['unitCellBox'])
2617            line2Sizer.Add(unitCellBox,0,wx.ALIGN_CENTER_VERTICAL)
2618   
2619            showHydrogen = wx.CheckBox(dataDisplay,-1,label=' Show hydrogens?')
2620            showHydrogen.Bind(wx.EVT_CHECKBOX, OnShowHyd)
2621            showHydrogen.SetValue(drawingData['showHydrogen'])
2622            line2Sizer.Add(showHydrogen,0,wx.ALIGN_CENTER_VERTICAL)
2623            showSizer.Add(line2Sizer)
2624            return showSizer
2625           
2626        def RadSizer():
2627           
2628            def OnSizeHatoms(event):
2629                try:
2630                    value = max(0.1,min(1.2,float(sizeH.GetValue())))
2631                except ValueError:
2632                    value = 0.5
2633                drawingData['sizeH'] = value
2634                sizeH.SetValue("%.2f"%(value))
2635                G2plt.PlotStructure(G2frame,data)
2636               
2637            def OnRadFactor(event):
2638                try:
2639                    value = max(0.1,min(1.2,float(radFactor.GetValue())))
2640                except ValueError:
2641                    value = 0.85
2642                drawingData['radiusFactor'] = value
2643                radFactor.SetValue("%.2f"%(value))
2644                FindBondsDraw()
2645                G2plt.PlotStructure(G2frame,data)
2646           
2647            radSizer = wx.BoxSizer(wx.HORIZONTAL)
2648            radSizer.Add(wx.StaticText(dataDisplay,-1,' Hydrogen radius, A:  '),0,wx.ALIGN_CENTER_VERTICAL)
2649            sizeH = wx.TextCtrl(dataDisplay,-1,value='%.2f'%(drawingData['sizeH']),size=wx.Size(60,20),style=wx.TE_PROCESS_ENTER)
2650            sizeH.Bind(wx.EVT_TEXT_ENTER,OnSizeHatoms)
2651            sizeH.Bind(wx.EVT_KILL_FOCUS,OnSizeHatoms)
2652            radSizer.Add(sizeH,0,wx.ALIGN_CENTER_VERTICAL)
2653   
2654            radSizer.Add(wx.StaticText(dataDisplay,-1,' Bond search factor:  '),0,wx.ALIGN_CENTER_VERTICAL)
2655            radFactor = wx.TextCtrl(dataDisplay,value='%.2f'%(drawingData['radiusFactor']),size=wx.Size(60,20),style=wx.TE_PROCESS_ENTER)
2656            radFactor.Bind(wx.EVT_TEXT_ENTER,OnRadFactor)
2657            radFactor.Bind(wx.EVT_KILL_FOCUS,OnRadFactor)
2658            radSizer.Add(radFactor,0,wx.ALIGN_CENTER_VERTICAL)
2659            return radSizer
2660
2661        G2frame.dataFrame.SetStatusText('')
2662        drawOptions.DestroyChildren()
2663        dataDisplay = wx.Panel(drawOptions)
2664        mainSizer = wx.BoxSizer(wx.VERTICAL)
2665        mainSizer.Add((5,5),0)
2666        mainSizer.Add(wx.StaticText(dataDisplay,-1,' Drawing controls:'),0,wx.ALIGN_CENTER_VERTICAL)
2667        mainSizer.Add((5,5),0)       
2668        mainSizer.Add(SlopSizer(),0)
2669        mainSizer.Add((5,5),0)
2670        mainSizer.Add(ShowSizer(),0,)
2671        mainSizer.Add((5,5),0)
2672        mainSizer.Add(RadSizer(),0,)
2673
2674        dataDisplay.SetSizer(mainSizer)
2675        Size = mainSizer.Fit(G2frame.dataFrame)
2676        Size[1] += 35                           #compensate for status bar
2677        dataDisplay.SetSize(Size)
2678        G2frame.dataFrame.setSizePosLeft(Size)
2679
2680################################################################################
2681####  Texture routines
2682################################################################################
2683       
2684    def UpdateTexture():
2685        G2frame.dataFrame.SetStatusText('')
2686        generalData = data['General']       
2687        SGData = generalData['SGData']
2688        try:
2689            textureData = generalData['SH Texture']
2690        except KeyError:            #fix old files!
2691            textureData = generalData['SH Texture'] = {'Order':0,'Model':'cylindrical',
2692                'Sample omega':[False,0.0],'Sample chi':[False,0.0],'Sample phi':[False,0.0],
2693                'SH Coeff':[False,{}],'SHShow':False,'PFhkl':[0,0,1],
2694                'PFxyz':[0,0,1.],'PlotType':'Pole figure'}
2695        if 'SHShow' not in textureData:     #another fix
2696            textureData.update({'SHShow':False,'PFhkl':[0,0,1],'PFxyz':[0,0,1.],'PlotType':'Pole figure'})
2697        try:                        #another fix!
2698            x = textureData['PlotType']
2699        except KeyError:
2700            textureData.update({'PFxyz':[0,0,1.],'PlotType':'Pole figure'})
2701        shModels = ['cylindrical','none','shear - 2/m','rolling - mmm']
2702        SamSym = dict(zip(shModels,['0','-1','2/m','mmm']))
2703        if generalData['doPawley'] and G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Sequental results'):
2704            G2frame.dataFrame.RefineTexture.Enable(True)
2705        shAngles = ['omega','chi','phi']
2706       
2707        def SetSHCoef():
2708            cofNames = G2lat.GenSHCoeff(SGData['SGLaue'],SamSym[textureData['Model']],textureData['Order'])
2709            newSHCoef = dict(zip(cofNames,np.zeros(len(cofNames))))
2710            SHCoeff = textureData['SH Coeff'][1]
2711            for cofName in SHCoeff:
2712                if cofName in  cofNames:
2713                    newSHCoef[cofName] = SHCoeff[cofName]
2714            return newSHCoef
2715       
2716        def OnShOrder(event):
2717            Obj = event.GetEventObject()
2718            textureData['Order'] = int(Obj.GetValue())
2719            textureData['SH Coeff'][1] = SetSHCoef()
2720            wx.CallAfter(UpdateTexture)
2721            G2plt.PlotTexture(G2frame,data)
2722                       
2723        def OnShModel(event):
2724            Obj = event.GetEventObject()
2725            textureData['Model'] = Obj.GetValue()
2726            textureData['SH Coeff'][1] = SetSHCoef()
2727            wx.CallAfter(UpdateTexture)
2728            G2plt.PlotTexture(G2frame,data)
2729           
2730        def OnSHRefine(event):
2731            Obj = event.GetEventObject()
2732            textureData['SH Coeff'][0] = Obj.GetValue()
2733           
2734        def OnSHShow(event):
2735            Obj = event.GetEventObject()
2736            textureData['SHShow'] = Obj.GetValue()
2737            wx.CallAfter(UpdateTexture)
2738           
2739        def OnProjSel(event):
2740            Obj = event.GetEventObject()
2741            G2frame.Projection = Obj.GetValue()
2742            G2plt.PlotTexture(G2frame,data)
2743           
2744        def OnColorSel(event):
2745            Obj = event.GetEventObject()
2746            G2frame.ContourColor = Obj.GetValue()
2747            G2plt.PlotTexture(G2frame,data)
2748           
2749        def OnAngRef(event):
2750            Obj = event.GetEventObject()
2751            textureData[angIndx[Obj.GetId()]][0] = Obj.GetValue()
2752           
2753        def OnAngValue(event):
2754            Obj = event.GetEventObject()
2755            try:
2756                value =  float(Obj.GetValue())
2757            except ValueError:
2758                value = textureData[valIndx[Obj.GetId()]][1]
2759            Obj.SetValue('%8.2f'%(value))
2760            textureData[valIndx[Obj.GetId()]][1] = value
2761           
2762        def OnODFValue(event): 
2763            Obj = event.GetEventObject()
2764            try:
2765                value =  float(Obj.GetValue())
2766            except ValueError:
2767                value = textureData['SH Coeff'][1][ODFIndx[Obj.GetId()]]
2768            Obj.SetValue('%8.3f'%(value))
2769            textureData['SH Coeff'][1][ODFIndx[Obj.GetId()]] = value
2770            G2plt.PlotTexture(G2frame,data)
2771           
2772        def OnPfType(event):
2773            Obj = event.GetEventObject()
2774            textureData['PlotType'] = Obj.GetValue()
2775            wx.CallAfter(UpdateTexture)
2776            G2plt.PlotTexture(G2frame,data)
2777           
2778        def OnPFValue(event):
2779            Obj = event.GetEventObject()
2780            Saxis = Obj.GetValue().split()
2781            if textureData['PlotType'] in ['Pole figure','Axial pole distribution']:               
2782                try:
2783                    hkl = [int(Saxis[i]) for i in range(3)]
2784                except (ValueError,IndexError):
2785                    hkl = textureData['PFhkl']
2786                if not np.any(np.array(hkl)):       #can't be all zeros!
2787                    hkl = textureData['PFhkl']
2788                Obj.SetValue('%d %d %d'%(hkl[0],hkl[1],hkl[2]))
2789                textureData['PFhkl'] = hkl
2790            else:
2791                try:
2792                    xyz = [float(Saxis[i]) for i in range(3)]
2793                except (ValueError,IndexError):
2794                    xyz = textureData['PFxyz']
2795                if not np.any(np.array(xyz)):       #can't be all zeros!
2796                    xyz = textureData['PFxyz']
2797                Obj.SetValue('%3.1f %3.1f %3.1f'%(xyz[0],xyz[1],xyz[2]))
2798                textureData['PFxyz'] = xyz
2799            G2plt.PlotTexture(G2frame,data)
2800
2801        if Texture.GetSizer():
2802            Texture.GetSizer().Clear(True)
2803        mainSizer = wx.BoxSizer(wx.VERTICAL)
2804        titleSizer = wx.BoxSizer(wx.HORIZONTAL)
2805        titleSizer.Add(wx.StaticText(Texture,-1,'Spherical harmonics texture data for '+PhaseName+':'),0,wx.ALIGN_CENTER_VERTICAL)
2806        titleSizer.Add(wx.StaticText(Texture,-1,
2807            ' Texture Index J = %7.3f'%(G2lat.textureIndex(textureData['SH Coeff'][1]))),
2808            0,wx.ALIGN_CENTER_VERTICAL)
2809        mainSizer.Add(titleSizer,0)
2810        mainSizer.Add((0,5),0)
2811        shSizer = wx.FlexGridSizer(1,6,5,5)
2812        shSizer.Add(wx.StaticText(Texture,-1,'Texture model: '),0,wx.ALIGN_CENTER_VERTICAL)
2813        shModel = wx.ComboBox(Texture,-1,value=textureData['Model'],choices=shModels,
2814            style=wx.CB_READONLY|wx.CB_DROPDOWN)
2815        shModel.Bind(wx.EVT_COMBOBOX,OnShModel)
2816        shSizer.Add(shModel,0,wx.ALIGN_CENTER_VERTICAL)
2817        shSizer.Add(wx.StaticText(Texture,-1,'  Harmonic order: '),0,wx.ALIGN_CENTER_VERTICAL)
2818        shOrder = wx.ComboBox(Texture,-1,value=str(textureData['Order']),choices=[str(2*i) for i in range(18)],
2819            style=wx.CB_READONLY|wx.CB_DROPDOWN)
2820        shOrder.Bind(wx.EVT_COMBOBOX,OnShOrder)
2821        shSizer.Add(shOrder,0,wx.ALIGN_CENTER_VERTICAL)
2822        shRef = wx.CheckBox(Texture,-1,label=' Refine texture?')
2823        shRef.SetValue(textureData['SH Coeff'][0])
2824        shRef.Bind(wx.EVT_CHECKBOX, OnSHRefine)
2825        shSizer.Add(shRef,0,wx.ALIGN_CENTER_VERTICAL)
2826        shShow = wx.CheckBox(Texture,-1,label=' Show coeff.?')
2827        shShow.SetValue(textureData['SHShow'])
2828        shShow.Bind(wx.EVT_CHECKBOX, OnSHShow)
2829        shSizer.Add(shShow,0,wx.ALIGN_CENTER_VERTICAL)
2830        mainSizer.Add(shSizer,0,0)
2831        mainSizer.Add((0,5),0)
2832        PTSizer = wx.FlexGridSizer(2,4,5,5)
2833        PTSizer.Add(wx.StaticText(Texture,-1,' Texture plot type: '),0,wx.ALIGN_CENTER_VERTICAL)
2834        choices = ['Axial pole distribution','Pole figure','Inverse pole figure']           
2835        pfType = wx.ComboBox(Texture,-1,value=str(textureData['PlotType']),choices=choices,
2836            style=wx.CB_READONLY|wx.CB_DROPDOWN)
2837        pfType.Bind(wx.EVT_COMBOBOX,OnPfType)
2838        PTSizer.Add(pfType,0,wx.ALIGN_CENTER_VERTICAL)
2839        if 'Axial' not in textureData['PlotType']:
2840            PTSizer.Add(wx.StaticText(Texture,-1,' Projection type: '),0,wx.ALIGN_CENTER_VERTICAL)
2841            projSel = wx.ComboBox(Texture,-1,value=G2frame.Projection,choices=['equal area','stereographic','3D display'],
2842                style=wx.CB_READONLY|wx.CB_DROPDOWN)
2843            projSel.Bind(wx.EVT_COMBOBOX,OnProjSel)
2844            PTSizer.Add(projSel,0,wx.ALIGN_CENTER_VERTICAL)
2845        if textureData['PlotType'] in ['Pole figure','Axial pole distribution']:
2846            PTSizer.Add(wx.StaticText(Texture,-1,' Pole figure HKL: '),0,wx.ALIGN_CENTER_VERTICAL)
2847            PH = textureData['PFhkl']
2848            pfVal = wx.TextCtrl(Texture,-1,'%d %d %d'%(PH[0],PH[1],PH[2]),style=wx.TE_PROCESS_ENTER)
2849        else:
2850            PTSizer.Add(wx.StaticText(Texture,-1,' Inverse pole figure XYZ: '),0,wx.ALIGN_CENTER_VERTICAL)
2851            PX = textureData['PFxyz']
2852            pfVal = wx.TextCtrl(Texture,-1,'%3.1f %3.1f %3.1f'%(PX[0],PX[1],PX[2]),style=wx.TE_PROCESS_ENTER)
2853        pfVal.Bind(wx.EVT_TEXT_ENTER,OnPFValue)
2854        pfVal.Bind(wx.EVT_KILL_FOCUS,OnPFValue)
2855        PTSizer.Add(pfVal,0,wx.ALIGN_CENTER_VERTICAL)
2856        if 'Axial' not in textureData['PlotType']:
2857            PTSizer.Add(wx.StaticText(Texture,-1,' Color scheme'),0,wx.ALIGN_CENTER_VERTICAL)
2858            choice = [m for m in mpl.cm.datad.keys() if not m.endswith("_r")]
2859            choice.sort()
2860            colorSel = wx.ComboBox(Texture,-1,value=G2frame.ContourColor,choices=choice,
2861                style=wx.CB_READONLY|wx.CB_DROPDOWN)
2862            colorSel.Bind(wx.EVT_COMBOBOX,OnColorSel)
2863            PTSizer.Add(colorSel,0,wx.ALIGN_CENTER_VERTICAL)       
2864        mainSizer.Add(PTSizer,0,wx.ALIGN_CENTER_VERTICAL)
2865        mainSizer.Add((0,5),0)
2866        if textureData['SHShow']:
2867            mainSizer.Add(wx.StaticText(Texture,-1,'Spherical harmonic coefficients: '),0,wx.ALIGN_CENTER_VERTICAL)
2868            mainSizer.Add((0,5),0)
2869            ODFSizer = wx.FlexGridSizer(2,8,2,2)
2870            ODFIndx = {}
2871            ODFkeys = textureData['SH Coeff'][1].keys()
2872            ODFkeys.sort()
2873            for item in ODFkeys:
2874                ODFSizer.Add(wx.StaticText(Texture,-1,item),0,wx.ALIGN_CENTER_VERTICAL)
2875                ODFval = wx.TextCtrl(Texture,wx.ID_ANY,'%8.3f'%(textureData['SH Coeff'][1][item]),style=wx.TE_PROCESS_ENTER)
2876                ODFIndx[ODFval.GetId()] = item
2877                ODFval.Bind(wx.EVT_TEXT_ENTER,OnODFValue)
2878                ODFval.Bind(wx.EVT_KILL_FOCUS,OnODFValue)
2879                ODFSizer.Add(ODFval,0,wx.ALIGN_CENTER_VERTICAL)
2880            mainSizer.Add(ODFSizer,0,wx.ALIGN_CENTER_VERTICAL)
2881            mainSizer.Add((0,5),0)
2882        mainSizer.Add((0,5),0)
2883        mainSizer.Add(wx.StaticText(Texture,-1,'Sample orientation angles: '),0,wx.ALIGN_CENTER_VERTICAL)
2884        mainSizer.Add((0,5),0)
2885        angSizer = wx.BoxSizer(wx.HORIZONTAL)
2886        angIndx = {}
2887        valIndx = {}
2888        for item in ['Sample omega','Sample chi','Sample phi']:
2889            angRef = wx.CheckBox(Texture,-1,label=item+': ')
2890            angRef.SetValue(textureData[item][0])
2891            angIndx[angRef.GetId()] = item
2892            angRef.Bind(wx.EVT_CHECKBOX, OnAngRef)
2893            angSizer.Add(angRef,0,wx.ALIGN_CENTER_VERTICAL)
2894            angVal = wx.TextCtrl(Texture,wx.ID_ANY,'%8.2f'%(textureData[item][1]),style=wx.TE_PROCESS_ENTER)
2895            valIndx[angVal.GetId()] = item
2896            angVal.Bind(wx.EVT_TEXT_ENTER,OnAngValue)
2897            angVal.Bind(wx.EVT_KILL_FOCUS,OnAngValue)
2898            angSizer.Add(angVal,0,wx.ALIGN_CENTER_VERTICAL)
2899            angSizer.Add((5,0),0)
2900        mainSizer.Add(angSizer,0,wx.ALIGN_CENTER_VERTICAL)
2901        Texture.SetSizer(mainSizer,True)
2902        mainSizer.Fit(G2frame.dataFrame)
2903        Size = mainSizer.GetMinSize()
2904        Size[0] += 40
2905        Size[1] = max(Size[1],250) + 35
2906        Texture.SetSize(Size)
2907        Texture.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
2908        Size[1] = min(Size[1],450)
2909        G2frame.dataFrame.setSizePosLeft(Size)
2910
2911################################################################################
2912##### DData routines - GUI stuff in GSASIIddataGUI.py
2913################################################################################
2914       
2915    def OnHklfAdd(event):
2916        UseList = data['Histograms']
2917        keyList = UseList.keys()
2918        TextList = []
2919        if G2frame.PatternTree.GetCount():
2920            item, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
2921            while item:
2922                name = G2frame.PatternTree.GetItemText(item)
2923                if name not in keyList and 'HKLF' in name:
2924                    TextList.append(name)
2925                item, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)                       
2926            dlg = wx.MultiChoiceDialog(G2frame, 'Which new data to use?', 'Use data', TextList, wx.CHOICEDLG_STYLE)
2927            try:
2928                if dlg.ShowModal() == wx.ID_OK:
2929                    result = dlg.GetSelections()
2930                    for i in result:
2931                        histoName = TextList[i]
2932                        UseList[histoName] = {'Histogram':histoName,'Show':False,'Scale':[1.0,True],
2933                            'Babinet':{'BabA':[0.0,False],'BabU':[0.0,False]},
2934                            'Extinction':['Lorentzian','None',
2935                            {'Tbar':0.1,'Cos2TM':0.955,'Eg':[1.e-10,False],'Es':[1.e-10,False],'Ep':[1.e-10,False]},]}                       
2936                    data['Histograms'] = UseList
2937                    wx.BeginBusyCursor()
2938                    UpdateHKLFdata(histoName)
2939                    wx.EndBusyCursor()
2940                    wx.CallAfter(G2ddG.UpdateDData,G2frame,DData,data)
2941            finally:
2942                dlg.Destroy()
2943               
2944    def UpdateHKLFdata(histoName):
2945        generalData = data['General']
2946        Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,histoName)
2947        reflData = G2frame.PatternTree.GetItemPyData(Id)[1]
2948        SGData = generalData['SGData']
2949        Cell = generalData['Cell'][1:7]
2950        G,g = G2lat.cell2Gmat(Cell)
2951        for ref in reflData:
2952            H = ref[:3]
2953            ref[4] = np.sqrt(1./G2lat.calc_rDsq2(H,G))
2954            iabsnt,ref[3],ref[11],ref[12] = G2spc.GenHKLf(H,SGData)
2955        G2frame.PatternTree.SetItemPyData(Id,[histoName,reflData])
2956       
2957    def OnPwdrAdd(event):
2958        generalData = data['General']
2959        SGData = generalData['SGData']
2960        UseList = data['Histograms']
2961        newList = []
2962        NShkl = len(G2spc.MustrainNames(SGData))
2963        NDij = len(G2spc.HStrainNames(SGData))
2964        keyList = UseList.keys()
2965        TextList = ['All PWDR']
2966        if G2frame.PatternTree.GetCount():
2967            item, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
2968            while item:
2969                name = G2frame.PatternTree.GetItemText(item)
2970                if name not in keyList and 'PWDR' in name:
2971                    TextList.append(name)
2972                item, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
2973            dlg = wx.MultiChoiceDialog(G2frame, 'Which new data to use?', 'Use data', TextList, wx.CHOICEDLG_STYLE)
2974            try:
2975                if dlg.ShowModal() == wx.ID_OK:
2976                    result = dlg.GetSelections()
2977                    for i in result: newList.append(TextList[i])
2978                    if 'All PWDR' in newList:
2979                        newList = TextList[1:]
2980                    for histoName in newList:
2981                        pId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,histoName)
2982                        UseList[histoName] = {'Histogram':histoName,'Show':False,
2983                            'Scale':[1.0,False],'Pref.Ori.':['MD',1.0,False,[0,0,1],0,{}],
2984                            'Size':['isotropic',[1.,1.,1.],[False,False,False],[0,0,1],
2985                                [1.,1.,1.,0.,0.,0.],6*[False,]],
2986                            'Mustrain':['isotropic',[1000.0,1000.0,1.0],[False,False,False],[0,0,1],
2987                                NShkl*[0.01,],NShkl*[False,]],
2988                            'HStrain':[NDij*[0.0,],NDij*[False,]],                         
2989                            'Extinction':[0.0,False],'Babinet':{'BabA':[0.0,False],'BabU':[0.0,False]}}
2990                        refList = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,pId,'Reflection Lists'))
2991                        refList[generalData['Name']] = []                       
2992                    data['Histograms'] = UseList
2993                    wx.CallAfter(G2ddG.UpdateDData,G2frame,DData,data)
2994            finally:
2995                dlg.Destroy()
2996       
2997    def OnDataDelete(event):
2998        UseList = data['Histograms']
2999        keyList = ['All',]+UseList.keys()
3000        keyList.sort()
3001        DelList = []
3002        if UseList:
3003            DelList = []
3004            dlg = wx.MultiChoiceDialog(G2frame, 
3005                'Which histogram to delete from this phase?', 'Delete histogram', 
3006                keyList, wx.CHOICEDLG_STYLE)
3007            try:
3008                if dlg.ShowModal() == wx.ID_OK:
3009                    result = dlg.GetSelections()
3010                    for i in result: 
3011                        DelList.append(keyList[i])
3012                    if 'All' in DelList:
3013                        DelList = keyList[1:]
3014                    for i in DelList:
3015                        del UseList[i]
3016                    wx.CallAfter(G2ddG.UpdateDData,G2frame,DData,data)
3017            finally:
3018                dlg.Destroy()
3019               
3020################################################################################
3021##### Rigid bodies
3022################################################################################
3023
3024    def FillRigidBodyGrid(refresh=False):
3025        if refresh:
3026            RigidBodies.DestroyChildren()
3027        AtLookUp = G2mth.FillAtomLookUp(data['Atoms'])
3028        general = data['General']
3029        cx = general['AtomPtrs'][0]
3030        Amat,Bmat = G2lat.cell2AB(general['Cell'][1:7])
3031        RBData = G2frame.PatternTree.GetItemPyData(   
3032            G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Rigid bodies'))['Residue']
3033        Indx = {}
3034       
3035        def ResrbSizer(RBObj):
3036           
3037            def OnOrigRef(event):
3038                RBObj['Orig'][1] = Ocheck.GetValue()
3039             
3040            def OnOrienRef(event):
3041                RBObj['Orient'][1] = Qcheck.GetValue()
3042                Qcheck.Setvalue(RBObj['Orient'][1])
3043               
3044            def OnTorsionRef(event):
3045                Obj = event.GetEventObject()
3046                item = Indx[Obj.GetId()]
3047                RBObj['Torsions'][item][1] = Obj.GetValue()               
3048               
3049            def OnTorsion(event):
3050                Obj = event.GetEventObject()
3051                item = Indx[Obj.GetId()]
3052                try:
3053                    val = float(Obj.GetValue())
3054                    RBObj['Torsions'][item][0] = val
3055                    newXYZ = G2mth.UpdateResRBAtoms(Bmat,RBObj,RBData)
3056                    for i,id in enumerate(RBObj['Ids']):
3057                        data['Atoms'][AtLookUp[id]][cx:cx+3] = newXYZ[i]
3058                except ValueError:
3059                    pass
3060                Obj.SetValue("%10.3f"%(RBObj['Torsions'][item][0]))               
3061                data['Drawing']['Atoms'] = []
3062                UpdateDrawAtoms()
3063                drawAtoms.ClearSelection()
3064                G2plt.PlotStructure(G2frame,data)
3065               
3066            def OnDelRB(event):
3067                RBId = RBObj['RBId']
3068                RBData[RBId]['useCount'] -= 1               
3069                del RBObj
3070                wx.CallAfter(FillRigidBodyGrid,True)
3071             
3072            resrbSizer = wx.BoxSizer(wx.VERTICAL)
3073            resrbSizer.Add(wx.StaticText(RigidBodies,-1,120*'-'))
3074            topLine = wx.BoxSizer(wx.HORIZONTAL)
3075            topLine.Add(wx.StaticText(RigidBodies,-1,
3076                'Name: '+RBObj['RBname']+RBObj['numChain']+'   '),0,wx.ALIGN_CENTER_VERTICAL)
3077            delRB = wx.CheckBox(RigidBodies,-1,'Delete?')
3078            delRB.Bind(wx.EVT_CHECKBOX,OnDelRB)
3079            topLine.Add(delRB,0,wx.ALIGN_CENTER_VERTICAL)
3080            resrbSizer.Add(topLine)
3081            topSizer = wx.FlexGridSizer(2,2,5,5)
3082            Orig = RBObj['Orig'][0]
3083            Orien = RBObj['Orient'][0]
3084            topSizer.Add(wx.StaticText(RigidBodies,-1,
3085                ' %s %8.5f %8.5f %8.5f'%(       'Origin     :',Orig[0],Orig[1],Orig[2])))
3086            Ocheck = wx.CheckBox(RigidBodies,-1,'Refine?')
3087            Ocheck.Bind(wx.EVT_CHECKBOX,OnOrigRef)
3088            Ocheck.SetValue(RBObj['Orig'][1])
3089            topSizer.Add(Ocheck,0,wx.ALIGN_CENTER_VERTICAL)
3090            topSizer.Add(wx.StaticText(RigidBodies,-1,
3091                ' %s %8.5f %8.5f %8.5f %8.5f  Refine?'%('Orientation:',Orien[0], \
3092                Orien[1],Orien[2],Orien[3])),0,wx.ALIGN_CENTER_VERTICAL)
3093            Qcheck = wx.ComboBox(RigidBodies,-1,value='',choices=[' ','A','Q'],
3094                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3095            Qcheck.Bind(wx.EVT_CHECKBOX,OnOrienRef)
3096            Qcheck.SetValue(RBObj['Orient'][1])
3097            topSizer.Add(Qcheck)
3098            resrbSizer.Add(topSizer)
3099            resrbSizer.Add(wx.StaticText(RigidBodies,-1,' Torsions:'),0,wx.ALIGN_CENTER_VERTICAL)
3100            torSizer = wx.FlexGridSizer(1,6,5,5)
3101            for itors,tors in enumerate(RBObj['Torsions']):
3102                torSizer.Add(wx.StaticText(RigidBodies,-1,'Torsion '+'%d'%(itors)),0,wx.ALIGN_CENTER_VERTICAL)
3103                torsTxt = wx.TextCtrl(RigidBodies,-1,value='%.3f'%(tors[0]),style=wx.TE_PROCESS_ENTER)
3104                torsTxt.Bind(wx.EVT_TEXT_ENTER,OnTorsion)
3105                torsTxt.Bind(wx.EVT_KILL_FOCUS,OnTorsion)
3106                Indx[torsTxt.GetId()] = itors
3107                torSizer.Add(torsTxt)
3108                torCheck = wx.CheckBox(RigidBodies,-1,'Refine?')
3109                torCheck.Bind(wx.EVT_CHECKBOX,OnTorsionRef)
3110                torCheck.SetValue(tors[1])
3111                Indx[torCheck.GetId()] = itors
3112                torSizer.Add(torCheck,0,wx.ALIGN_CENTER_VERTICAL)
3113            resrbSizer.Add(torSizer)
3114            return resrbSizer       
3115       
3116        G2frame.dataFrame.SetStatusText('')
3117        mainSizer = wx.BoxSizer(wx.VERTICAL)
3118        if not data['RBModels']:
3119            mainSizer.Add((5,5),0)
3120            mainSizer.Add(wx.StaticText(RigidBodies,-1,'No rigid body models:'),0,wx.ALIGN_CENTER_VERTICAL)
3121            mainSizer.Add((5,5),0)
3122        if 'Residue' in data['RBModels']:
3123            mainSizer.Add((5,5),0)
3124            mainSizer.Add(wx.StaticText(RigidBodies,-1,'Residue rigid bodies:'),0,wx.ALIGN_CENTER_VERTICAL)
3125            mainSizer.Add((5,5),0)
3126            for RBObj in data['RBModels']['Residue']:
3127                mainSizer.Add(ResrbSizer(RBObj))
3128
3129        RigidBodies.SetSizer(mainSizer)
3130        mainSizer.FitInside(G2frame.dataFrame)
3131        Size = mainSizer.GetMinSize()
3132        Size[0] += 40
3133        Size[1] = max(Size[1],290) + 35
3134        RigidBodies.SetSize(Size)
3135        RigidBodies.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
3136        Size[1] = min(Size[1],450)
3137        G2frame.dataFrame.setSizePosLeft(Size)
3138               
3139    def OnRBAssign(event):
3140       
3141        rbData = G2frame.PatternTree.GetItemPyData(   
3142            G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Rigid bodies'))
3143        rbNames = {}
3144        for rbVec in rbData['Vector']:
3145            if rbVec != 'AtInfo':
3146                rbNames[rbData['Vector'][rbVec]['RBname']] =['Vector',rbVec]
3147        for rbRes in rbData['Residue']:
3148            if rbRes != 'AtInfo':
3149                rbNames[rbData['Residue'][rbRes]['RBname']] = ['Residue',rbRes]
3150        if not rbNames:
3151            print '**** ERROR - no rigid bodies defined ****'
3152            return
3153        general = data['General']
3154        Amat,Bmat = G2lat.cell2AB(general['Cell'][1:7])
3155        cx,ct = general['AtomPtrs'][:2]
3156        atomData = data['Atoms']
3157        Indx = {}
3158        atInd = [0,1,2]
3159        data['testRBObj'] = {}
3160           
3161        def Draw():
3162           
3163            def OnOk(event):
3164                #more stuff here substituting rigid body for atoms
3165                del data['testRBObj']
3166                FillRigidBodyGrid(True)
3167               
3168            def OnCancel(event):
3169                del data['testRBObj']
3170                FillRigidBodyGrid(True)
3171               
3172            def OnRBSel(event):
3173                selection = rbSel.GetValue()
3174                rbType,rbId = rbNames[selection]
3175                data['testRBObj']['rbAtTypes'] = rbData[rbType][rbId]['rbTypes']
3176                data['testRBObj']['AtInfo'] = rbData[rbType]['AtInfo']
3177                data['testRBObj']['rbType'] = rbType
3178                data['testRBObj']['rbData'] = rbData
3179                data['testRBObj']['Sizers'] = {}
3180                if rbType == 'Vector':
3181                    rbRef = [0,1,2]
3182                elif rbType == 'Residue':
3183                    rbRef = rbData[rbType][rbId]['rbRef']
3184                data['testRBObj']['rbRef'] = rbRef
3185                refType = []
3186                refName = []
3187                for ref in rbRef:
3188                    reftype = data['testRBObj']['rbAtTypes'][ref]
3189                    refType.append(reftype)
3190                    refName.append(reftype+' '+str(rbRef[0]))
3191                atNames = [{},{},{}]
3192                for iatm,atom in enumerate(atomData):
3193                    for i,reftype in enumerate(refType):
3194                        if atom[ct] == reftype:
3195                            atNames[i][atom[ct-1]] = iatm
3196                data['testRBObj']['atNames'] = atNames
3197                data['testRBObj']['rbObj'] = {'Orig':[[0,0,0],False],'Orient':[[0,0,0,1.],' '],
3198                    'RBId':rbId,'Torsions':[],'numChain':'','RBname':rbData[rbType][rbId]['RBname']}               
3199                for item in rbData[rbType][rbId].get('rbSeq',[]):
3200                    data['testRBObj']['rbObj']['Torsions'].append([0.0,False])
3201                Draw()
3202               
3203            def OnOrigX(event):
3204                Obj = event.GetEventObject()
3205                item = Indx[Obj.GetId()]
3206                try:
3207                    val = float(Obj.GetValue())
3208                    data['testRBObj']['rbObj']['Orig'][0][item] = val
3209                except ValueError:
3210                    pass
3211                Draw()
3212               
3213            def OnOrien(event):
3214                Obj = event.GetEventObject()
3215                item = Indx[Obj.GetId()]
3216                Q = data['testRBObj']['rbObj']['Orient'][0]
3217                try:
3218                    val = float(Obj.GetValue())
3219                    Q[item] = val
3220                    if not any(Q):
3221                        raise ValueError
3222                    Q = G2mth.normQ(Q)
3223                    data['testRBObj']['rbObj']['Orient'][0] = Q
3224                except ValueError:
3225                    pass
3226                Draw()               
3227               
3228            def OnAtOrigPick(event):
3229                Obj = event.GetEventObject()
3230                item = Indx[Obj.GetId()]
3231                atName = Obj.GetValue()
3232                atInd[0] = atNames[item][atName]
3233                data['testRBObj']['rbObj']['Orig'][0] = atomData[atNames[item][atName]][cx:cx+3]
3234                Draw()
3235               
3236            def OnAtQPick(event):
3237                Obj = event.GetEventObject()
3238                item = Indx[Obj.GetId()]
3239                atName = Obj.GetValue()
3240                atInd[item] = atNames[item][atName]
3241                rbType = data['testRBObj']['rbType']
3242                rbObj = data['testRBObj']['rbObj']
3243                rbId = rbObj['RBId']
3244                rbRef = data['testRBObj']['rbRef']
3245                rbXYZ = rbData[rbType][rbId]['rbXYZ']
3246                VAR = rbXYZ[rbRef[1]]-rbXYZ[rbRef[0]]
3247                VBR = rbXYZ[rbRef[2]]-rbXYZ[rbRef[0]]
3248                Orig = np.array(data['testRBObj']['rbObj']['Orig'][0])               
3249                VAC = np.inner(Amat,np.array(atomData[atInd[1]][cx:cx+3])-Orig)
3250                VBC = np.inner(Amat,np.array(atomData[atInd[2]][cx:cx+3])-Orig)
3251                VCC = np.cross(VAR,VAC)
3252                QuatA = G2mth.makeQuat(VAR,VAC,VCC)[0]
3253                VAR = G2mth.prodQVQ(QuatA,VAR)
3254                VBR = G2mth.prodQVQ(QuatA,VBR)
3255                QuatB = G2mth.makeQuat(VBR,VBC,VAR)[0]
3256                QuatC = G2mth.prodQQ(QuatB,QuatA)
3257                data['testRBObj']['rbObj']['Orient'] = [QuatC,' ']
3258                Draw()
3259
3260            if len(data['testRBObj']):
3261                G2plt.PlotStructure(G2frame,data)
3262                   
3263            RigidBodies.DestroyChildren()
3264            mainSizer = wx.BoxSizer(wx.VERTICAL)
3265            mainSizer.Add((5,5),0)
3266            mainSizer.Add(wx.StaticText(RigidBodies,-1,'Assign rigid body:'),0,wx.ALIGN_CENTER_VERTICAL)
3267            mainSizer.Add((5,5),0)
3268            if data['testRBObj']:
3269                Xsizers = []
3270                Osizers = []
3271                OriSizer = wx.FlexGridSizer(1,6,5,5)
3272                Orig = data['testRBObj']['rbObj']['Orig'][0]
3273                Orien = data['testRBObj']['rbObj']['Orient'][0]
3274                rbRef = data['testRBObj']['rbRef']
3275                refName = []
3276                for ref in rbRef:
3277                    refName.append(data['testRBObj']['rbAtTypes'][ref]+str(ref))
3278                atNames = data['testRBObj']['atNames']
3279                OriSizer.Add(wx.StaticText(RigidBodies,-1,'Origin x,y,z: '),0,wx.ALIGN_CENTER_VERTICAL)
3280                for ix,x in enumerate(Orig):
3281                    origX = wx.TextCtrl(RigidBodies,-1,value='%10.5f'%(x),style=wx.TE_PROCESS_ENTER)
3282                    origX.Bind(wx.EVT_TEXT_ENTER,OnOrigX)
3283                    origX.Bind(wx.EVT_KILL_FOCUS,OnOrigX)
3284                    Indx[origX.GetId()] = ix
3285                    OriSizer.Add(origX,0,wx.ALIGN_CENTER_VERTICAL)
3286                    Xsizers.append(origX)
3287                if len(atomData):
3288                    OriSizer.Add(wx.StaticText(RigidBodies,-1,'Select match to '+refName[0]+': '),0,wx.ALIGN_CENTER_VERTICAL)               
3289                    atPick = wx.ComboBox(RigidBodies,-1,value=atomData[atInd[0]][ct-1],
3290                        choices=atNames[0].keys(),style=wx.CB_READONLY|wx.CB_DROPDOWN)
3291                    atPick.Bind(wx.EVT_COMBOBOX, OnAtOrigPick)
3292                    Indx[atPick.GetId()] = 0
3293                    OriSizer.Add(atPick,0,wx.ALIGN_CENTER_VERTICAL)
3294                    data['testRBObj']['Sizers']['Xsizers'] = Xsizers
3295                else:
3296                    OriSizer.Add((5,0),)
3297                    OriSizer.Add((5,0),)                   
3298                OriSizer.Add(wx.StaticText(RigidBodies,-1,'Orientation quaternion: '),0,wx.ALIGN_CENTER_VERTICAL)
3299                for ix,x in enumerate(Orien):
3300                    orien = wx.TextCtrl(RigidBodies,-1,value='%8.4f'%(x),style=wx.TE_PROCESS_ENTER)
3301                    orien.Bind(wx.EVT_TEXT_ENTER,OnOrien)
3302                    orien.Bind(wx.EVT_KILL_FOCUS,OnOrien)
3303                    Indx[orien.GetId()] = ix
3304                    OriSizer.Add(orien,0,wx.ALIGN_CENTER_VERTICAL)
3305                    Osizers.append(orien)
3306                data['testRBObj']['Sizers']['Osizers'] = Osizers
3307                OriSizer.Add((5,0),)
3308                if len(atomData):
3309                    OriSizer.Add(wx.StaticText(RigidBodies,-1,'Orientation setting: '),0,wx.ALIGN_CENTER_VERTICAL)
3310                    for i in [1,2]:
3311                        OriSizer.Add(wx.StaticText(RigidBodies,-1,'Select match to '+refName[i]+': '),0,wx.ALIGN_CENTER_VERTICAL)
3312                        atPick = wx.ComboBox(RigidBodies,-1,value=atomData[atInd[i]][ct-1],
3313                            choices=atNames[i].keys(),style=wx.CB_READONLY|wx.CB_DROPDOWN)
3314                        atPick.Bind(wx.EVT_COMBOBOX, OnAtQPick)
3315                        Indx[atPick.GetId()] = i
3316                        OriSizer.Add(atPick,0,wx.ALIGN_CENTER_VERTICAL)
3317                mainSizer.Add(OriSizer)
3318                mainSizer.Add((5,5),0)
3319               
3320            else:
3321                topSizer = wx.BoxSizer(wx.HORIZONTAL)
3322                topSizer.Add(wx.StaticText(RigidBodies,-1,'Select rigid body model'),0,wx.ALIGN_CENTER_VERTICAL)
3323                rbSel = wx.ComboBox(RigidBodies,-1,value='',choices=rbNames.keys(),
3324                    style=wx.CB_READONLY|wx.CB_DROPDOWN)
3325                rbSel.Bind(wx.EVT_COMBOBOX, OnRBSel)
3326                topSizer.Add((5,5),0)
3327                topSizer.Add(rbSel,0,wx.ALIGN_CENTER_VERTICAL)
3328                mainSizer.Add(topSizer)
3329               
3330               
3331            OkBtn = wx.Button(RigidBodies,-1,"Ok")
3332            OkBtn.Bind(wx.EVT_BUTTON, OnOk)
3333            CancelBtn = wx.Button(RigidBodies,-1,'Cancel')
3334            CancelBtn.Bind(wx.EVT_BUTTON, OnCancel)
3335            btnSizer = wx.BoxSizer(wx.HORIZONTAL)
3336            btnSizer.Add((20,20),1)
3337            btnSizer.Add(OkBtn)
3338            btnSizer.Add(CancelBtn)
3339            btnSizer.Add((20,20),1)
3340            mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
3341            RigidBodies.SetSizer(mainSizer)
3342            mainSizer.FitInside(RigidBodies)
3343            Size = mainSizer.GetMinSize()
3344            Size[0] += 40
3345            Size[1] = max(Size[1],290) + 35
3346            RigidBodies.SetSize(Size)
3347            RigidBodies.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
3348            Size[1] = min(Size[1],450)
3349            G2frame.dataFrame.setSizePosLeft(Size)
3350           
3351        Draw()
3352       
3353    def OnAutoFindResRB(event):
3354        RBData = G2frame.PatternTree.GetItemPyData(   
3355            G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Rigid bodies'))['Residue']
3356        rbKeys = RBData.keys()
3357        rbKeys.remove('AtInfo')
3358        if not len(rbKeys):
3359            print '**** ERROR - no residue rigid bodies are defined ****'
3360            return
3361        RBNames = [RBData[k]['RBname'] for k in rbKeys]
3362        RBIds = dict(zip(RBNames,rbKeys))
3363        general = data['General']
3364        Amat,Bmat = G2lat.cell2AB(general['Cell'][1:7])
3365        Atoms = data['Atoms']
3366        AtLookUp = G2mth.FillAtomLookUp(Atoms)
3367        if 'macro' not in general['Type']:
3368            print '**** ERROR - this phase is not a macromolecule ****'
3369            return
3370        if not len(Atoms):
3371            print '**** ERROR - this phase has no atoms ****'
3372            return
3373        RBObjs = []
3374        cx,ct = general['AtomPtrs'][:2]
3375        iatm = 0
3376        wx.BeginBusyCursor()
3377        try:
3378            while iatm < len(Atoms):
3379                atom = Atoms[iatm]
3380                res = atom[1].strip()
3381                numChain = ' %s %s'%(atom[0],atom[2])
3382                if res not in RBIds or atom[ct-1] == 'OXT':
3383                    iatm += 1
3384                    continue        #skip for OXT, water molecules, etc.
3385                rbRes = RBData[RBIds[res]]
3386                rbRef = rbRes['rbRef']
3387                VAR = rbRes['rbXYZ'][rbRef[1]]-rbRes['rbXYZ'][rbRef[0]]
3388                VBR = rbRes['rbXYZ'][rbRef[2]]-rbRes['rbXYZ'][rbRef[0]]
3389                rbObj = {'RBname':rbRes['RBname'],'numChain':numChain}
3390                rbAtoms = []
3391                rbIds = []
3392                for iratm in range(len(rbRes['atNames'])):
3393                    rbAtoms.append(np.array(Atoms[iatm][cx:cx+3]))
3394                    rbIds.append(Atoms[iatm][20])
3395                    iatm += 1    #puts this at beginning of next residue?
3396                Orig = rbAtoms[rbRef[0]]
3397                rbObj['RBId'] = RBIds[res]
3398                rbObj['Ids'] = rbIds
3399                rbObj['Orig'] = [Orig,False]
3400#                print ' residue '+rbRes['RBname']+str(atom[0]).strip()+ \
3401#                    ' origin at: ','%.5f %.5f %.5f'%(Orig[0],Orig[1],Orig[2])
3402                VAC = np.inner(Amat,rbAtoms[rbRef[1]]-Orig)
3403                VBC = np.inner(Amat,rbAtoms[rbRef[2]]-Orig)
3404                VCC = np.cross(VAR,VAC)
3405                QuatA = G2mth.makeQuat(VAR,VAC,VCC)[0]
3406                VAR = G2mth.prodQVQ(QuatA,VAR)
3407                VBR = G2mth.prodQVQ(QuatA,VBR)
3408                QuatB = G2mth.makeQuat(VBR,VBC,VAR)[0]
3409                QuatC = G2mth.prodQQ(QuatB,QuatA)
3410                rbObj['Orient'] = [QuatC,' ']
3411                SXYZ = []
3412                TXYZ = []
3413                rbObj['Torsions'] = []
3414                for i,xyz in enumerate(rbRes['rbXYZ']):
3415                    SXYZ.append(G2mth.prodQVQ(QuatC,xyz))               
3416                    TXYZ.append(np.inner(Amat,rbAtoms[i]-Orig))
3417                for Oatm,Patm,x,Riders in rbRes['rbSeq']:
3418                    VBR = SXYZ[Oatm]-SXYZ[Patm]
3419                    VAR = SXYZ[Riders[0]]-SXYZ[Patm]
3420                    VAC = TXYZ[Riders[0]]-TXYZ[Patm]
3421                    QuatA,D = G2mth.makeQuat(VAR,VAC,VBR)
3422                    ang = 180.*D/np.pi
3423                    rbObj['Torsions'].append([ang,False])
3424                    for ride in Riders:
3425                        SXYZ[ride] = G2mth.prodQVQ(QuatA,SXYZ[ride]-SXYZ[Patm])+SXYZ[Patm]
3426                RBData[RBIds[res]]['useCount'] += 1
3427                RBObjs.append(rbObj)
3428            data['RBModels']['Residue'] = RBObjs
3429            for RBObj in RBObjs:
3430                newXYZ = G2mth.UpdateResRBAtoms(Bmat,RBObj,RBData)
3431                for i,id in enumerate(RBObj['Ids']):
3432                    data['Atoms'][AtLookUp[id]][cx:cx+3] = newXYZ[i]
3433        finally:
3434            wx.EndBusyCursor()
3435        wx.CallAfter(FillRigidBodyGrid,True)
3436       
3437    def OnRBRemoveAll(event):
3438        data['RBModels']['Residue'] = []
3439        data['RBModels']['Vector'] = []
3440        FillRigidBodyGrid(True)
3441       
3442    def OnGlobalResRBRef(event):
3443        RBObjs = data['RBModels']['Residue']
3444        names = ['Origin','Orientation',]
3445        nTor = 0
3446        for rbObj in RBObjs:
3447            nTor = max(nTor,len(rbObj['Torsions']))
3448        names += ['Torsion '+str(i) for i in range(nTor)]
3449        dlg = wx.MultiChoiceDialog(G2frame,'Select','Refinement controls',names)
3450        if dlg.ShowModal() == wx.ID_OK:
3451            sel = dlg.GetSelections()
3452            parms = []
3453            for x in sel:
3454                parms.append(names[x])
3455            wx.BeginBusyCursor()
3456            try:
3457                for rbObj in RBObjs:
3458                    if 'Origin' in parms:
3459                        rbObj['Orig'][1] = True
3460                    else:
3461                        rbObj['Orig'][1] = False
3462                    if 'Orientation' in parms:
3463                        rbObj['Orient'][1] = 'Q'
3464                    else:
3465                        rbObj['Orient'][1] = ' '
3466                    for i in range(len(rbObj['Torsions'])):
3467                        if 'Torsion '+str(i) in parms:
3468                            rbObj['Torsions'][i][1] = True
3469                        else:
3470                            rbObj['Torsions'][i][1] = False           
3471            finally:
3472                wx.EndBusyCursor()
3473            FillRigidBodyGrid()
3474                       
3475
3476################################################################################
3477##### Pawley routines
3478################################################################################
3479
3480    def FillPawleyReflectionsGrid():
3481        G2frame.dataFrame.SetStatusText('')
3482                       
3483        def KeyEditPawleyGrid(event):
3484            colList = G2frame.PawleyRefl.GetSelectedCols()
3485            PawleyPeaks = data['Pawley ref']
3486            if event.GetKeyCode() == wx.WXK_RETURN:
3487                event.Skip(True)
3488            elif event.GetKeyCode() == wx.WXK_CONTROL:
3489                event.Skip(True)
3490            elif event.GetKeyCode() == wx.WXK_SHIFT:
3491                event.Skip(True)
3492            elif colList:
3493                G2frame.PawleyRefl.ClearSelection()
3494                key = event.GetKeyCode()
3495                for col in colList:
3496                    if PawleyTable.GetTypeName(0,col) == wg.GRID_VALUE_BOOL:
3497                        if key == 89: #'Y'
3498                            for row in range(PawleyTable.GetNumberRows()): PawleyPeaks[row][col]=True
3499                        elif key == 78:  #'N'
3500                            for row in range(PawleyTable.GetNumberRows()): PawleyPeaks[row][col]=False
3501                        FillPawleyReflectionsGrid()
3502           
3503        if 'Pawley ref' in data:
3504            PawleyPeaks = data['Pawley ref']                       
3505            rowLabels = []
3506            for i in range(len(PawleyPeaks)): rowLabels.append(str(i))
3507            colLabels = ['h','k','l','mul','d','refine','Fsq(hkl)','sig(Fsq)']
3508            Types = 4*[wg.GRID_VALUE_LONG,]+[wg.GRID_VALUE_FLOAT+':10,4',wg.GRID_VALUE_BOOL,]+ \
3509                2*[wg.GRID_VALUE_FLOAT+':10,2',]
3510            PawleyTable = G2gd.Table(PawleyPeaks,rowLabels=rowLabels,colLabels=colLabels,types=Types)
3511            G2frame.PawleyRefl.SetTable(PawleyTable, True)
3512            G2frame.PawleyRefl.Bind(wx.EVT_KEY_DOWN, KeyEditPawleyGrid)                 
3513            for r in range(G2frame.PawleyRefl.GetNumberRows()):
3514                for c in range(G2frame.PawleyRefl.GetNumberCols()):
3515                    if c in [5,6]:
3516                        G2frame.PawleyRefl.SetReadOnly(r,c,isReadOnly=False)
3517                    else:
3518                        G2frame.PawleyRefl.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
3519            G2frame.PawleyRefl.SetMargins(0,0)
3520            G2frame.PawleyRefl.AutoSizeColumns(False)
3521            G2frame.dataFrame.setSizePosLeft([500,300])
3522                   
3523    def OnPawleyLoad(event):
3524        generalData = data['General']
3525        dmin = generalData['Pawley dmin']
3526        cell = generalData['Cell'][1:7]
3527        A = G2lat.cell2A(cell)
3528        SGData = generalData['SGData']
3529        HKLd = np.array(G2lat.GenHLaue(dmin,SGData,A))
3530        PawleyPeaks = []
3531        wx.BeginBusyCursor()
3532        try:
3533            for h,k,l,d in HKLd:
3534                ext,mul = G2spc.GenHKLf([h,k,l],SGData)[:2]
3535                if not ext:
3536                    mul *= 2        #for powder multiplicity
3537                    PawleyPeaks.append([h,k,l,mul,d,False,100.0,1.0])
3538        finally:
3539            wx.EndBusyCursor()
3540        data['Pawley ref'] = PawleyPeaks
3541        FillPawleyReflectionsGrid()
3542       
3543    def OnPawleyEstimate(event):
3544        try:
3545            Refs = data['Pawley ref']
3546            Histograms = data['Histograms']
3547        except KeyError:
3548            print '**** Error - no histograms defined for this phase ****'
3549            return
3550        HistoNames = Histograms.keys()
3551        PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,HistoNames[0])
3552        xdata = G2frame.PatternTree.GetItemPyData(PatternId)[1]
3553        Inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Instrument Parameters'))[0]
3554        Sample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Sample Parameters'))
3555        wave = G2mth.getWave(Inst)
3556        posCorr = Inst['Zero'][1]
3557        const = 9.e-2/(np.pi*Sample['Gonio. radius'])                  #shifts in microns
3558       
3559        wx.BeginBusyCursor()
3560        try:
3561            for ref in Refs:
3562                pos = 2.0*asind(wave/(2.0*ref[4]))
3563                if 'Bragg' in Sample['Type']:
3564                    pos -= const*(4.*Sample['Shift'][0]*cosd(pos/2.0)+ \
3565                        Sample['Transparency'][0]*sind(pos)*100.0)            #trans(=1/mueff) in cm
3566                else:               #Debye-Scherrer - simple but maybe not right
3567                    pos -= const*(Sample['DisplaceX'][0]*cosd(pos)+Sample['DisplaceY'][0]*sind(pos))
3568                indx = np.searchsorted(xdata[0],pos)
3569                try:
3570                    FWHM = max(0.001,G2pwd.getFWHM(pos,Inst))/2.
3571                    dx = xdata[0][indx+1]-xdata[0][indx]
3572                    ref[6] = FWHM*(xdata[1][indx]-xdata[4][indx])*cosd(pos/2.)**3/dx
3573                    Lorenz = 1./(2.*sind(xdata[0][indx]/2.)**2*cosd(xdata[0][indx]/2.))           #Lorentz correction
3574                    pola,dIdPola = G2pwd.Polarization(Inst['Polariz.'][1],xdata[0][indx],Inst['Azimuth'][1])
3575                    ref[6] /= (Lorenz*pola*ref[3])
3576                except IndexError:
3577                    pass
3578        finally:
3579            wx.EndBusyCursor()
3580        FillPawleyReflectionsGrid()
3581
3582    def OnPawleyUpdate(event):
3583        try:
3584            Refs = data['Pawley ref']
3585            Histograms = data['Histograms']
3586        except KeyError:
3587            print '**** Error - no histograms defined for this phase ****'
3588            return
3589        HistoNames = Histograms.keys()
3590        PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,HistoNames[0])
3591        refData = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Reflection Lists'))[PhaseName]
3592
3593        wx.BeginBusyCursor()
3594        try:
3595            for iref,ref in enumerate(Refs):
3596                try:
3597                    if refData[iref][9] < 0.:
3598                        ref[6] = abs(refData[iref][9])
3599                        ref[7] = 1.0
3600                except IndexError:
3601                    pass
3602        finally:
3603            wx.EndBusyCursor()
3604        FillPawleyReflectionsGrid()
3605                           
3606    def OnPawleyDelete(event):          #doesn't work
3607        dlg = wx.MessageDialog(G2frame,'Do you really want to delete selected Pawley reflections?','Delete', 
3608            wx.YES_NO | wx.ICON_QUESTION)
3609        try:
3610            result = dlg.ShowModal()
3611            if result == wx.ID_YES: 
3612                Refs = data['Pawley ref']
3613                Ind = G2frame.PawleyRefl.GetSelectedRows()
3614                Ind.sort()
3615                Ind.reverse()
3616                for ind in Ind:
3617                    Refs = np.delete(Refs,ind,0)
3618                data['Pawley ref'] = Refs
3619                FillPawleyReflectionsGrid()
3620        finally:
3621            dlg.Destroy()
3622
3623################################################################################
3624##### Fourier routines
3625################################################################################
3626
3627    def FillMapPeaksGrid():
3628                       
3629        def RowSelect(event):
3630            r,c =  event.GetRow(),event.GetCol()
3631            if r < 0 and c < 0:
3632                if MapPeaks.IsSelection():
3633                    MapPeaks.ClearSelection()
3634                else:
3635                    for row in range(MapPeaks.GetNumberRows()):
3636                        MapPeaks.SelectRow(row,True)
3637                   
3638            elif c < 0:                   #only row clicks
3639                if event.ControlDown():                   
3640                    if r in MapPeaks.GetSelectedRows():
3641                        MapPeaks.DeselectRow(r)
3642                    else:
3643                        MapPeaks.SelectRow(r,True)
3644                elif event.ShiftDown():
3645                    indxs = MapPeaks.GetSelectedRows()
3646                    MapPeaks.ClearSelection()
3647                    ibeg = 0
3648                    if indxs:
3649                        ibeg = indxs[-1]
3650                    for row in range(ibeg,r+1):
3651                        MapPeaks.SelectRow(row,True)
3652                else:
3653                    MapPeaks.ClearSelection()
3654                    MapPeaks.SelectRow(r,True)
3655            elif r < 0:                 #a column pick
3656                mapPeaks = data['Map Peaks']
3657                c =  event.GetCol()
3658                if colLabels[c] == 'mag':
3659                    mapPeaks = G2mth.sortArray(mapPeaks,c,reverse=True)
3660                elif colLabels[c] in ['x','y','z','dzero']:
3661                    mapPeaks = G2mth.sortArray(mapPeaks,c)
3662                else:
3663                    return
3664                data['Map Peaks'] = mapPeaks
3665                wx.CallAfter(FillMapPeaksGrid)
3666            G2plt.PlotStructure(G2frame,data)                   
3667           
3668        G2frame.dataFrame.setSizePosLeft([450,300])
3669        G2frame.dataFrame.SetStatusText('')
3670        if 'Map Peaks' in data:
3671            G2frame.dataFrame.SetStatusText('Select mag or dzero columns to sort')
3672            mapPeaks = data['Map Peaks']                       
3673            rowLabels = []
3674            for i in range(len(mapPeaks)): rowLabels.append(str(i))
3675            colLabels = ['mag','x','y','z','dzero']
3676            Types = 5*[wg.GRID_VALUE_FLOAT+':10,4',]
3677            G2frame.MapPeaksTable = G2gd.Table(mapPeaks,rowLabels=rowLabels,colLabels=colLabels,types=Types)
3678            MapPeaks.SetTable(G2frame.MapPeaksTable, True)
3679            MapPeaks.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK, RowSelect)
3680            for r in range(MapPeaks.GetNumberRows()):
3681                for c in range(MapPeaks.GetNumberCols()):
3682                    MapPeaks.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
3683            MapPeaks.SetMargins(0,0)
3684            MapPeaks.AutoSizeColumns(False)
3685                   
3686    def OnPeaksMove(event):
3687        if 'Map Peaks' in data:
3688            mapPeaks = np.array(data['Map Peaks'])
3689            peakMax = np.max(mapPeaks.T[0])
3690            Ind = MapPeaks.GetSelectedRows()
3691            for ind in Ind:
3692                mag,x,y,z,d = mapPeaks[ind]
3693                AtomAdd(x,y,z,'H',Name='M '+'%d'%(int(100*mag/peakMax)))
3694   
3695    def OnPeaksClear(event):
3696        data['Map Peaks'] = []
3697        FillMapPeaksGrid()
3698        G2plt.PlotStructure(G2frame,data)
3699       
3700    def OnPeaksDelete(event):
3701        if 'Map Peaks' in data:
3702            mapPeaks = data['Map Peaks']
3703            Ind = MapPeaks.GetSelectedRows()
3704            Ind.sort()
3705            Ind.reverse()
3706            for ind in Ind:
3707                mapPeaks = np.delete(mapPeaks,ind,0)
3708            data['Map Peaks'] = mapPeaks
3709        FillMapPeaksGrid()
3710        G2plt.PlotStructure(G2frame,data)
3711       
3712    def OnPeaksEquiv(event):
3713        if 'Map Peaks' in data:
3714            mapPeaks = data['Map Peaks']
3715            Ind = MapPeaks.GetSelectedRows()
3716            if Ind:
3717                wx.BeginBusyCursor()
3718                try:
3719                    Ind = G2mth.PeaksEquiv(data,Ind)
3720                    for r in range(MapPeaks.GetNumberRows()):
3721                        if r in Ind:
3722                            MapPeaks.SelectRow(r,addToSelected=True)
3723                        else:
3724                            MapPeaks.DeselectRow(r)
3725                finally:
3726                    wx.EndBusyCursor()
3727                G2plt.PlotStructure(G2frame,data)
3728
3729    def OnShowBonds(event):
3730        generalData = data['General']
3731        if generalData['Map']['Show bonds']:
3732            generalData['Map']['Show bonds'] = False
3733            G2frame.dataFrame.MapPeaksEdit.SetLabel(G2gd.wxID_SHOWBONDS,'Show bonds')
3734        else:
3735            generalData['Map']['Show bonds'] = True
3736            G2frame.dataFrame.MapPeaksEdit.SetLabel(G2gd.wxID_SHOWBONDS,'Hide bonds')
3737        FillMapPeaksGrid()
3738        G2plt.PlotStructure(G2frame,data)
3739               
3740    def OnPeaksUnique(event):
3741        if 'Map Peaks' in data:
3742            mapPeaks = data['Map Peaks']
3743            Ind = MapPeaks.GetSelectedRows()
3744            if Ind:
3745                wx.BeginBusyCursor()
3746                try:
3747                    Ind = G2mth.PeaksUnique(data,Ind)
3748                    for r in range(MapPeaks.GetNumberRows()):
3749                        if r in Ind:
3750                            MapPeaks.SelectRow(r,addToSelected=True)
3751                        else:
3752                            MapPeaks.DeselectRow(r)
3753                finally:
3754                    wx.EndBusyCursor()
3755                G2plt.PlotStructure(G2frame,data)
3756               
3757    def OnPeaksViewPoint(event):
3758        # set view point
3759        indx = MapPeaks.GetSelectedRows()
3760        if not indx:
3761            print '***** ERROR - no peaks selected'
3762            return
3763        mapPeaks = data['Map Peaks']
3764        drawingData = data['Drawing']
3765        drawingData['viewPoint'][0] = mapPeaks[indx[0]][1:4]
3766        G2plt.PlotStructure(G2frame,data)
3767   
3768    def OnPeaksDistVP(event):
3769        # distance to view point
3770        indx = MapPeaks.GetSelectedRows()
3771        if not indx:
3772            print '***** ERROR - no peaks selected'
3773            return
3774        generalData = data['General']
3775        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])           
3776        mapPeaks = data['Map Peaks']
3777        drawingData = data['Drawing']
3778        viewPt = np.array(drawingData['viewPoint'][0])
3779        print ' Distance from view point at %.3f %.3f %.3f to:'%(viewPt[0],viewPt[1],viewPt[2])
3780        colLabels = [MapPeaks.GetColLabelValue(c) for c in range(MapPeaks.GetNumberCols())]
3781        cx = colLabels.index('x')
3782        cm = colLabels.index('mag')
3783        for i in indx:
3784            peak = mapPeaks[i]
3785            Dx = np.array(peak[cx:cx+3])-viewPt
3786            dist = np.sqrt(np.sum(np.inner(Amat,Dx)**2,axis=0))
3787            print 'Peak: %5d mag= %8.2f distance = %.3f'%(i,peak[cm],dist)
3788
3789    def OnPeaksDA(event):
3790        #distance, angle
3791        indx = MapPeaks.GetSelectedRows()
3792        if len(indx) not in [2,3]:
3793            print '**** ERROR - wrong number of atoms for distance or angle calculation'
3794            return
3795        generalData = data['General']
3796        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])           
3797        mapPeaks = data['Map Peaks']
3798        xyz = []
3799        for i in indx:
3800            xyz.append(mapPeaks[i][1:4])
3801        if len(indx) == 2:
3802            print ' distance for atoms %s = %.3f'%(str(indx),G2mth.getRestDist(xyz,Amat))
3803        else:
3804            print ' angle for atoms %s = %.2f'%(str(indx),G2mth.getRestAngle(xyz,Amat))
3805                                   
3806    def OnFourierMaps(event):
3807        generalData = data['General']
3808        mapData = generalData['Map']
3809        reflName = mapData['RefList']
3810        phaseName = generalData['Name']
3811        if 'PWDR' in reflName:
3812            PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, reflName)
3813            reflSets = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Reflection Lists'))
3814            reflData = reflSets[phaseName]
3815        elif 'HKLF' in reflName:
3816            PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, reflName)
3817            reflData = G2frame.PatternTree.GetItemPyData(PatternId)[1]
3818        mapData.update(G2mth.FourierMap(data,reflData))
3819        mapData['Flip'] = False
3820        mapSig = np.std(mapData['rho'])
3821        if not data['Drawing']:                 #if new drawing - no drawing data!
3822            SetupDrawingData()
3823        data['Drawing']['contourLevel'] = 1.
3824        data['Drawing']['mapSize'] = 10.
3825        print mapData['MapType']+' computed: rhomax = %.3f rhomin = %.3f sigma = %.3f'%(np.max(mapData['rho']),np.min(mapData['rho']),mapSig)
3826        UpdateDrawAtoms()
3827        G2plt.PlotStructure(G2frame,data)
3828       
3829    def OnFourClear(event):
3830        generalData = data['General']
3831        generalData['Map'] = mapDefault
3832        G2plt.PlotStructure(G2frame,data)
3833       
3834    def printRho(SGLaue,rho,rhoMax):                         
3835# map printing for testing purposes
3836        dim = len(rho.shape)
3837        if dim == 2:
3838            ix,jy = rho.shape
3839            for j in range(jy):
3840                line = ''
3841                if SGLaue in ['3','3m1','31m','6/m','6/mmm']:
3842                    line += (jy-j)*'  '
3843                for i in range(ix):
3844                    r = int(100*rho[i,j]/rhoMax)
3845                    line += '%4d'%(r)
3846                print line+'\n'
3847        else:
3848            ix,jy,kz = rho.shape
3849            for k in range(kz):
3850                print 'k = ',k
3851                for j in range(jy):
3852                    line = ''
3853                    if SGLaue in ['3','3m1','31m','6/m','6/mmm']:
3854                        line += (jy-j)*'  '
3855                    for i in range(ix):
3856                        r = int(100*rho[i,j,k]/rhoMax)
3857                        line += '%4d'%(r)
3858                    print line+'\n'
3859## keep this               
3860   
3861    def OnSearchMaps(event):
3862                                   
3863        peaks = []
3864        mags = []
3865        print ' Begin fourier map search - can take some time'
3866        time0 = time.time()
3867        generalData = data['General']
3868        mapData = generalData['Map']
3869        if len(mapData['rho']):
3870            wx.BeginBusyCursor()
3871            try:
3872                peaks,mags,dzeros = G2mth.SearchMap(data)
3873            finally:
3874                wx.EndBusyCursor()
3875            if len(peaks):
3876                mapPeaks = np.concatenate((mags,peaks,dzeros),axis=1)
3877                data['Map Peaks'] = G2mth.sortArray(mapPeaks,0,reverse=True)           
3878            print ' Map search finished, time = %.2fs'%(time.time()-time0)
3879            print ' No.peaks found:',len(peaks)   
3880            Page = G2frame.dataDisplay.FindPage('Map peaks')
3881            G2frame.dataDisplay.ChangeSelection(Page)
3882            G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.MapPeaksMenu)
3883            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksMove, id=G2gd.wxID_PEAKSMOVE)
3884            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksDA, id=G2gd.wxID_PEAKSDA)
3885            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksUnique, id=G2gd.wxID_PEAKSUNIQUE)
3886            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksDelete, id=G2gd.wxID_PEAKSDELETE)
3887            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksClear, id=G2gd.wxID_PEAKSCLEAR)
3888            UpdateDrawAtoms()
3889            FillMapPeaksGrid()
3890        else:
3891            print 'No map available'
3892       
3893    def OnChargeFlip(event):
3894        generalData = data['General']
3895        mapData = generalData['Map']
3896        flipData = generalData['Flip']
3897        reflName = flipData['RefList']
3898        phaseName = generalData['Name']
3899        if 'PWDR' in reflName:
3900            PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, reflName)
3901            reflSets = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Reflection Lists'))
3902            reflData = reflSets[phaseName]
3903        elif 'HKLF' in reflName:
3904            PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, reflName)
3905            reflData = G2frame.PatternTree.GetItemPyData(PatternId)[1]
3906        else:
3907            print '**** ERROR - No data defined for charge flipping'
3908            return
3909        pgbar = wx.ProgressDialog('Charge flipping','Residual Rcf =',101.0, 
3910            style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_CAN_ABORT)
3911        screenSize = wx.ClientDisplayRect()
3912        Size = pgbar.GetSize()
3913        Size = (int(Size[0]*1.2),Size[1]) # increase size a bit along x
3914        pgbar.SetPosition(wx.Point(screenSize[2]-Size[0]-305,screenSize[1]+5))
3915        pgbar.SetSize(Size)
3916        try:
3917            mapData.update(G2mth.ChargeFlip(data,reflData,pgbar))
3918        finally:
3919            pgbar.Destroy()
3920        mapData['Flip'] = True       
3921        mapSig = np.std(mapData['rho'])
3922        if not data['Drawing']:                 #if new drawing - no drawing data!
3923            SetupDrawingData()
3924        data['Drawing']['contourLevel'] = 1.
3925        data['Drawing']['mapSize'] = 10.
3926        print ' Charge flip map computed: rhomax = %.3f rhomin = %.3f sigma = %.3f'%(np.max(mapData['rho']),np.min(mapData['rho']),mapSig)
3927        if mapData['Rcf'] < 99.:
3928            OnSearchMaps(event)             #does a plot structure at end
3929        else:
3930            print 'Bad charge flip map - no peak search done'
3931               
3932    def OnTextureRefine(event):
3933        print 'refine texture?'
3934        event.Skip()       
3935           
3936    def OnTextureClear(event):
3937        print 'clear texture?'
3938        event.Skip()
3939
3940    def OnPageChanged(event):
3941        page = event.GetSelection()
3942        text = G2frame.dataDisplay.GetPageText(page)
3943        if text == 'Atoms':
3944            G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.AtomsMenu)
3945            G2frame.dataFrame.Bind(wx.EVT_MENU, OnAtomAdd, id=G2gd.wxID_ATOMSEDITADD)
3946            G2frame.dataFrame.Bind(wx.EVT_MENU, OnAtomViewAdd, id=G2gd.wxID_ATOMSVIEWADD)
3947            G2frame.dataFrame.Bind(wx.EVT_MENU, OnRBAppend, id=G2gd.wxID_RBAPPEND)
3948            G2frame.dataFrame.Bind(wx.EVT_MENU, OnAtomInsert, id=G2gd.wxID_ATOMSEDITINSERT)
3949            G2frame.dataFrame.Bind(wx.EVT_MENU, OnAtomViewInsert, id=G2gd.wxID_ATOMVIEWINSERT)
3950            G2frame.dataFrame.Bind(wx.EVT_MENU, OnAtomMove, id=G2gd.wxID_ATOMMOVE)
3951            G2frame.dataFrame.Bind(wx.EVT_MENU, AtomDelete, id=G2gd.wxID_ATOMSEDITDELETE)
3952            G2frame.dataFrame.Bind(wx.EVT_MENU, AtomRefine, id=G2gd.wxID_ATOMSREFINE)
3953            G2frame.dataFrame.Bind(wx.EVT_MENU, AtomModify, id=G2gd.wxID_ATOMSMODIFY)
3954            G2frame.dataFrame.Bind(wx.EVT_MENU, AtomTransform, id=G2gd.wxID_ATOMSTRANSFORM)
3955            G2frame.dataFrame.Bind(wx.EVT_MENU, OnReloadDrawAtoms, id=G2gd.wxID_RELOADDRAWATOMS)
3956            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDistAngle, id=G2gd.wxID_ATOMSDISAGL)
3957            FillAtomsGrid(Atoms)
3958        elif text == 'General':
3959            G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.DataGeneral)
3960            G2frame.dataFrame.Bind(wx.EVT_MENU, OnFourierMaps, id=G2gd.wxID_FOURCALC)
3961            G2frame.dataFrame.Bind(wx.EVT_MENU, OnSearchMaps, id=G2gd.wxID_FOURSEARCH)
3962            G2frame.dataFrame.Bind(wx.EVT_MENU, OnChargeFlip, id=G2gd.wxID_CHARGEFLIP)
3963            G2frame.dataFrame.Bind(wx.EVT_MENU, OnFourClear, id=G2gd.wxID_FOURCLEAR)
3964            UpdateGeneral()
3965        elif text == 'Data':
3966            G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.DataMenu)
3967            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPwdrAdd, id=G2gd.wxID_PWDRADD)
3968            G2frame.dataFrame.Bind(wx.EVT_MENU, OnHklfAdd, id=G2gd.wxID_HKLFADD)
3969            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDataDelete, id=G2gd.wxID_DATADELETE)
3970            G2ddG.UpdateDData(G2frame,DData,data)
3971            G2plt.PlotSizeStrainPO(G2frame,data,Start=True)
3972        elif text == 'Draw Options':
3973            G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.DataDrawOptions)
3974            UpdateDrawOptions()
3975            G2plt.PlotStructure(G2frame,data)
3976        elif text == 'Draw Atoms':
3977            G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.DrawAtomsMenu)
3978            G2frame.dataFrame.Bind(wx.EVT_MENU, DrawAtomStyle, id=G2gd.wxID_DRAWATOMSTYLE)
3979            G2frame.dataFrame.Bind(wx.EVT_MENU, DrawAtomLabel, id=G2gd.wxID_DRAWATOMLABEL)
3980            G2frame.dataFrame.Bind(wx.EVT_MENU, DrawAtomColor, id=G2gd.wxID_DRAWATOMCOLOR)
3981            G2frame.dataFrame.Bind(wx.EVT_MENU, ResetAtomColors, id=G2gd.wxID_DRAWATOMRESETCOLOR)
3982            G2frame.dataFrame.Bind(wx.EVT_MENU, SetViewPoint, id=G2gd.wxID_DRAWVIEWPOINT)
3983            G2frame.dataFrame.Bind(wx.EVT_MENU, AddSymEquiv, id=G2gd.wxID_DRAWADDEQUIV)
3984            G2frame.dataFrame.Bind(wx.EVT_MENU, TransformSymEquiv, id=G2gd.wxID_DRAWTRANSFORM)
3985            G2frame.dataFrame.Bind(wx.EVT_MENU, FillCoordSphere, id=G2gd.wxID_DRAWFILLCOORD)           
3986            G2frame.dataFrame.Bind(wx.EVT_MENU, FillUnitCell, id=G2gd.wxID_DRAWFILLCELL)
3987            G2frame.dataFrame.Bind(wx.EVT_MENU, DrawAtomsDelete, id=G2gd.wxID_DRAWDELETE)
3988            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDrawDistVP, id=G2gd.wxID_DRAWDISTVP)
3989            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDrawDAT, id=G2gd.wxID_DRAWDISAGLTOR)
3990            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDrawPlane, id=G2gd.wxID_DRAWPLANE)
3991            G2frame.dataFrame.Bind(wx.EVT_MENU, OnRestraint, id=G2gd.wxID_DRAWRESTRBOND)
3992            G2frame.dataFrame.Bind(wx.EVT_MENU, OnRestraint, id=G2gd.wxID_DRAWRESTRANGLE)
3993            G2frame.dataFrame.Bind(wx.EVT_MENU, OnRestraint, id=G2gd.wxID_DRAWRESTRPLANE)
3994            G2frame.dataFrame.Bind(wx.EVT_MENU, OnRestraint, id=G2gd.wxID_DRAWRESTRCHIRAL)
3995            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDefineRB, id=G2gd.wxID_DRAWDEFINERB)
3996            UpdateDrawAtoms()
3997            G2plt.PlotStructure(G2frame,data)
3998        elif text == 'RB Models':
3999            G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.RigidBodiesMenu)
4000            G2frame.dataFrame.Bind(wx.EVT_MENU, OnAutoFindResRB, id=G2gd.wxID_AUTOFINDRESRB)
4001            G2frame.dataFrame.Bind(wx.EVT_MENU, OnRBAssign, id=G2gd.wxID_ASSIGNATMS2RB)
4002            G2frame.dataFrame.Bind(wx.EVT_MENU, OnGlobalResRBRef, id=G2gd.wxID_GLOBALRESREFINE)
4003            G2frame.dataFrame.Bind(wx.EVT_MENU, OnRBRemoveAll, id=G2gd.wxID_RBREMOVEALL)
4004            FillRigidBodyGrid()
4005        elif text == 'Pawley reflections':
4006            G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.PawleyMenu)
4007            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPawleyLoad, id=G2gd.wxID_PAWLEYLOAD)
4008            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPawleyEstimate, id=G2gd.wxID_PAWLEYESTIMATE)
4009            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPawleyUpdate, id=G2gd.wxID_PAWLEYUPDATE)
4010            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPawleyDelete, id=G2gd.wxID_PAWLEYDELETE)           
4011            FillPawleyReflectionsGrid()
4012        elif text == 'Map peaks':
4013            G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.MapPeaksMenu)
4014            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksMove, id=G2gd.wxID_PEAKSMOVE)
4015            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksViewPoint, id=G2gd.wxID_PEAKSVIEWPT)
4016            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksDistVP, id=G2gd.wxID_PEAKSDISTVP)
4017            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksDA, id=G2gd.wxID_PEAKSDA)
4018            G2frame.dataFrame.Bind(wx.EVT_MENU, OnShowBonds, id=G2gd.wxID_SHOWBONDS)
4019            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksEquiv, id=G2gd.wxID_FINDEQVPEAKS)
4020            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksUnique, id=G2gd.wxID_PEAKSUNIQUE)
4021            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksDelete, id=G2gd.wxID_PEAKSDELETE)
4022            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksClear, id=G2gd.wxID_PEAKSCLEAR)
4023            FillMapPeaksGrid()
4024            G2plt.PlotStructure(G2frame,data)
4025        elif text == 'Texture':
4026            G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.TextureMenu)
4027            G2frame.dataFrame.Bind(wx.EVT_MENU, OnTextureRefine, id=G2gd.wxID_REFINETEXTURE)
4028            G2frame.dataFrame.Bind(wx.EVT_MENU, OnTextureClear, id=G2gd.wxID_CLEARTEXTURE)
4029            UpdateTexture()                       
4030            G2plt.PlotTexture(G2frame,data,Start=True)
4031           
4032        else:
4033            G2gd.SetDataMenuBar(G2frame)
4034        event.Skip()
4035       
4036    General = wx.Window(G2frame.dataDisplay)
4037    G2frame.dataDisplay.AddPage(General,'General')
4038    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.DataGeneral)
4039    G2frame.dataFrame.Bind(wx.EVT_MENU, OnFourierMaps, id=G2gd.wxID_FOURCALC)
4040    G2frame.dataFrame.Bind(wx.EVT_MENU, OnSearchMaps, id=G2gd.wxID_FOURSEARCH)
4041    G2frame.dataFrame.Bind(wx.EVT_MENU, OnChargeFlip, id=G2gd.wxID_CHARGEFLIP)
4042    G2frame.dataFrame.Bind(wx.EVT_MENU, OnFourClear, id=G2gd.wxID_FOURCLEAR)
4043    SetupGeneral()
4044    GeneralData = data['General']
4045    UpdateGeneral()
4046
4047    DData = wx.ScrolledWindow(G2frame.dataDisplay)
4048    G2frame.dataDisplay.AddPage(DData,'Data')
4049    Atoms = G2gd.GSGrid(G2frame.dataDisplay)
4050    G2frame.dataDisplay.AddPage(Atoms,'Atoms')
4051    drawOptions = wx.Window(G2frame.dataDisplay)
4052    G2frame.dataDisplay.AddPage(drawOptions,'Draw Options')
4053    drawAtoms = G2gd.GSGrid(G2frame.dataDisplay)
4054    G2frame.dataDisplay.AddPage(drawAtoms,'Draw Atoms')
4055    RigidBodies = wx.ScrolledWindow(G2frame.dataDisplay)
4056    G2frame.dataDisplay.AddPage(RigidBodies,'RB Models')
4057    MapPeaks = G2gd.GSGrid(G2frame.dataDisplay)
4058    G2frame.dataDisplay.AddPage(MapPeaks,'Map peaks')
4059    Texture = wx.ScrolledWindow(G2frame.dataDisplay)
4060    G2frame.dataDisplay.AddPage(Texture,'Texture')
4061    G2frame.PawleyRefl = G2gd.GSGrid(G2frame.dataDisplay)
4062    G2frame.dataDisplay.AddPage(G2frame.PawleyRefl,'Pawley reflections')
4063           
4064    G2frame.dataDisplay.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, OnPageChanged)
4065    G2frame.dataDisplay.SetSelection(oldPage)
4066
Note: See TracBrowser for help on using the repository browser.