source: trunk/GSASIIphsGUI.py @ 853

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

more rigid body stuff

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 193.7 KB
Line 
1# -*- coding: utf-8 -*-
2#GSASII - phase data display routines
3########### SVN repository information ###################
4# $Date: 2013-02-19 16:27:54 +0000 (Tue, 19 Feb 2013) $
5# $Author: vondreele $
6# $Revision: 853 $
7# $URL: trunk/GSASIIphsGUI.py $
8# $Id: GSASIIphsGUI.py 853 2013-02-19 16:27:54Z 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: 853 $")
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                rbRef = rbData[rbType][rbId]['rbRef']
3181                data['testRBObj']['rbRef'] = rbRef
3182                refType = []
3183                refName = []
3184                for ref in rbRef[:3]:
3185                    reftype = data['testRBObj']['rbAtTypes'][ref]
3186                    refType.append(reftype)
3187                    refName.append(reftype+' '+str(rbRef[0]))
3188                atNames = [{},{},{}]
3189                for iatm,atom in enumerate(atomData):
3190                    for i,reftype in enumerate(refType):
3191                        if atom[ct] == reftype:
3192                            atNames[i][atom[ct-1]] = iatm
3193                data['testRBObj']['atNames'] = atNames
3194                data['testRBObj']['rbObj'] = {'Orig':[[0,0,0],False],'Orient':[[0,0,0,1.],' '],
3195                    'RBId':rbId,'Torsions':[],'numChain':'','RBname':rbData[rbType][rbId]['RBname']}               
3196                for item in rbData[rbType][rbId].get('rbSeq',[]):
3197                    data['testRBObj']['rbObj']['Torsions'].append([0.0,False])
3198                Draw()
3199               
3200            def OnOrigX(event):
3201                Obj = event.GetEventObject()
3202                item = Indx[Obj.GetId()]
3203                try:
3204                    val = float(Obj.GetValue())
3205                    data['testRBObj']['rbObj']['Orig'][0][item] = val
3206                except ValueError:
3207                    pass
3208                Draw()
3209               
3210            def OnOrien(event):
3211                Obj = event.GetEventObject()
3212                item = Indx[Obj.GetId()]
3213                Q = data['testRBObj']['rbObj']['Orient'][0]
3214                try:
3215                    val = float(Obj.GetValue())
3216                    Q[item] = val
3217                    if not any(Q):
3218                        raise ValueError
3219                    Q = G2mth.normQ(Q)
3220                    data['testRBObj']['rbObj']['Orient'][0] = Q
3221                except ValueError:
3222                    pass
3223                Draw()               
3224               
3225            def OnAtOrigPick(event):
3226                Obj = event.GetEventObject()
3227                item = Indx[Obj.GetId()]
3228                atName = Obj.GetValue()
3229                rbType = data['testRBObj']['rbType']
3230                atInd[0] = atNames[item][atName]
3231                if 'Vector' in rbType:
3232                    rbObj = data['testRBObj']['rbObj']
3233                    rbId = rbObj['RBId']
3234                    rbRef = data['testRBObj']['rbRef']
3235                    rbXYZ = -rbData[rbType][rbId]['rbXYZ']
3236                    nref = atNames[item][atName]
3237                    Oxyz = np.inner(Bmat,np.array(rbXYZ[rbRef[0]]))
3238                    Nxyz = np.array(atomData[nref][cx:cx+3])
3239                    data['testRBObj']['rbObj']['Orig'][0] = Nxyz-Oxyz   
3240                else:           
3241                    data['testRBObj']['rbObj']['Orig'][0] = atomData[atNames[item][atName]][cx:cx+3]
3242                Draw()
3243               
3244            def OnAtQPick(event):
3245                Obj = event.GetEventObject()
3246                item = Indx[Obj.GetId()]
3247                atName = Obj.GetValue()
3248                atInd[item] = atNames[item][atName]
3249                rbType = data['testRBObj']['rbType']
3250                rbObj = data['testRBObj']['rbObj']
3251                rbId = rbObj['RBId']
3252                rbRef = data['testRBObj']['rbRef']
3253                rbXYZ = rbData[rbType][rbId]['rbXYZ']
3254                rbOrig = rbXYZ[rbRef[0]]
3255                VAR = rbXYZ[rbRef[1]]-rbOrig
3256                VBR = rbXYZ[rbRef[2]]-rbOrig
3257                if rbType == 'Vector':
3258                    Orig = np.array(atomData[atInd[0]][cx:cx+3])
3259                else:
3260                    Orig = np.array(data['testRBObj']['rbObj']['Orig'][0])               
3261                VAC = np.inner(Amat,np.array(atomData[atInd[1]][cx:cx+3])-Orig)
3262                VBC = np.inner(Amat,np.array(atomData[atInd[2]][cx:cx+3])-Orig)
3263                VCC = np.cross(VAR,VAC)
3264                QuatA = G2mth.makeQuat(VAR,VAC,VCC)[0]
3265                VAR = G2mth.prodQVQ(QuatA,VAR)
3266                VBR = G2mth.prodQVQ(QuatA,VBR)
3267                QuatB = G2mth.makeQuat(VBR,VBC,VAR)[0]
3268                QuatC = G2mth.prodQQ(QuatB,QuatA)
3269                data['testRBObj']['rbObj']['Orient'] = [QuatC,' ']
3270                if rbType == 'Vector':
3271                    Oxyz = np.inner(Bmat,G2mth.prodQVQ(QuatC,rbOrig))
3272                    Nxyz = np.array(atomData[atInd[0]][cx:cx+3])
3273                    data['testRBObj']['rbObj']['Orig'][0] = Nxyz-Oxyz
3274                Draw()
3275
3276            if len(data['testRBObj']):
3277                G2plt.PlotStructure(G2frame,data)
3278                   
3279            RigidBodies.DestroyChildren()
3280            mainSizer = wx.BoxSizer(wx.VERTICAL)
3281            mainSizer.Add((5,5),0)
3282            mainSizer.Add(wx.StaticText(RigidBodies,-1,'Assign rigid body:'),0,wx.ALIGN_CENTER_VERTICAL)
3283            mainSizer.Add((5,5),0)
3284            if data['testRBObj']:
3285                Xsizers = []
3286                Osizers = []
3287                OriSizer = wx.FlexGridSizer(1,6,5,5)
3288                Orig = data['testRBObj']['rbObj']['Orig'][0]
3289                Orien = data['testRBObj']['rbObj']['Orient'][0]
3290                rbRef = data['testRBObj']['rbRef']
3291                refName = []
3292                for ref in rbRef:
3293                    refName.append(data['testRBObj']['rbAtTypes'][ref]+str(ref))
3294                atNames = data['testRBObj']['atNames']
3295                OriSizer.Add(wx.StaticText(RigidBodies,-1,'Origin x,y,z: '),0,wx.ALIGN_CENTER_VERTICAL)
3296                for ix,x in enumerate(Orig):
3297                    origX = wx.TextCtrl(RigidBodies,-1,value='%10.5f'%(x),style=wx.TE_PROCESS_ENTER)
3298                    origX.Bind(wx.EVT_TEXT_ENTER,OnOrigX)
3299                    origX.Bind(wx.EVT_KILL_FOCUS,OnOrigX)
3300                    Indx[origX.GetId()] = ix
3301                    OriSizer.Add(origX,0,wx.ALIGN_CENTER_VERTICAL)
3302                    Xsizers.append(origX)
3303                if len(atomData):
3304                    OriSizer.Add(wx.StaticText(RigidBodies,-1,'Select match to '+refName[0]+': '),0,wx.ALIGN_CENTER_VERTICAL)               
3305                    atPick = wx.ComboBox(RigidBodies,-1,value=atomData[atInd[0]][ct-1],
3306                        choices=atNames[0].keys(),style=wx.CB_READONLY|wx.CB_DROPDOWN)
3307                    atPick.Bind(wx.EVT_COMBOBOX, OnAtOrigPick)
3308                    Indx[atPick.GetId()] = 0
3309                    OriSizer.Add(atPick,0,wx.ALIGN_CENTER_VERTICAL)
3310                    data['testRBObj']['Sizers']['Xsizers'] = Xsizers
3311                else:
3312                    OriSizer.Add((5,0),)
3313                    OriSizer.Add((5,0),)                   
3314                OriSizer.Add(wx.StaticText(RigidBodies,-1,'Orientation quaternion: '),0,wx.ALIGN_CENTER_VERTICAL)
3315                for ix,x in enumerate(Orien):
3316                    orien = wx.TextCtrl(RigidBodies,-1,value='%8.4f'%(x),style=wx.TE_PROCESS_ENTER)
3317                    orien.Bind(wx.EVT_TEXT_ENTER,OnOrien)
3318                    orien.Bind(wx.EVT_KILL_FOCUS,OnOrien)
3319                    Indx[orien.GetId()] = ix
3320                    OriSizer.Add(orien,0,wx.ALIGN_CENTER_VERTICAL)
3321                    Osizers.append(orien)
3322                data['testRBObj']['Sizers']['Osizers'] = Osizers
3323                OriSizer.Add((5,0),)
3324                if len(atomData):
3325                    OriSizer.Add(wx.StaticText(RigidBodies,-1,'Orientation setting: '),0,wx.ALIGN_CENTER_VERTICAL)
3326                    for i in [1,2]:
3327                        OriSizer.Add(wx.StaticText(RigidBodies,-1,'Select match to '+refName[i]+': '),0,wx.ALIGN_CENTER_VERTICAL)
3328                        atPick = wx.ComboBox(RigidBodies,-1,value=atomData[atInd[i]][ct-1],
3329                            choices=atNames[i].keys(),style=wx.CB_READONLY|wx.CB_DROPDOWN)
3330                        atPick.Bind(wx.EVT_COMBOBOX, OnAtQPick)
3331                        Indx[atPick.GetId()] = i
3332                        OriSizer.Add(atPick,0,wx.ALIGN_CENTER_VERTICAL)
3333                mainSizer.Add(OriSizer)
3334                mainSizer.Add((5,5),0)
3335               
3336            else:
3337                topSizer = wx.BoxSizer(wx.HORIZONTAL)
3338                topSizer.Add(wx.StaticText(RigidBodies,-1,'Select rigid body model'),0,wx.ALIGN_CENTER_VERTICAL)
3339                rbSel = wx.ComboBox(RigidBodies,-1,value='',choices=rbNames.keys(),
3340                    style=wx.CB_READONLY|wx.CB_DROPDOWN)
3341                rbSel.Bind(wx.EVT_COMBOBOX, OnRBSel)
3342                topSizer.Add((5,5),0)
3343                topSizer.Add(rbSel,0,wx.ALIGN_CENTER_VERTICAL)
3344                mainSizer.Add(topSizer)               
3345               
3346            OkBtn = wx.Button(RigidBodies,-1,"Ok")
3347            OkBtn.Bind(wx.EVT_BUTTON, OnOk)
3348            CancelBtn = wx.Button(RigidBodies,-1,'Cancel')
3349            CancelBtn.Bind(wx.EVT_BUTTON, OnCancel)
3350            btnSizer = wx.BoxSizer(wx.HORIZONTAL)
3351            btnSizer.Add((20,20),1)
3352            btnSizer.Add(OkBtn)
3353            btnSizer.Add(CancelBtn)
3354            btnSizer.Add((20,20),1)
3355            mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
3356            RigidBodies.SetSizer(mainSizer)
3357            mainSizer.FitInside(RigidBodies)
3358            Size = mainSizer.GetMinSize()
3359            Size[0] += 40
3360            Size[1] = max(Size[1],290) + 35
3361            RigidBodies.SetSize(Size)
3362            RigidBodies.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
3363            Size[1] = min(Size[1],450)
3364            G2frame.dataFrame.setSizePosLeft(Size)
3365           
3366        Draw()
3367       
3368    def OnAutoFindResRB(event):
3369        RBData = G2frame.PatternTree.GetItemPyData(   
3370            G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Rigid bodies'))['Residue']
3371        rbKeys = RBData.keys()
3372        rbKeys.remove('AtInfo')
3373        if not len(rbKeys):
3374            print '**** ERROR - no residue rigid bodies are defined ****'
3375            return
3376        RBNames = [RBData[k]['RBname'] for k in rbKeys]
3377        RBIds = dict(zip(RBNames,rbKeys))
3378        general = data['General']
3379        Amat,Bmat = G2lat.cell2AB(general['Cell'][1:7])
3380        Atoms = data['Atoms']
3381        AtLookUp = G2mth.FillAtomLookUp(Atoms)
3382        if 'macro' not in general['Type']:
3383            print '**** ERROR - this phase is not a macromolecule ****'
3384            return
3385        if not len(Atoms):
3386            print '**** ERROR - this phase has no atoms ****'
3387            return
3388        RBObjs = []
3389        cx,ct = general['AtomPtrs'][:2]
3390        iatm = 0
3391        wx.BeginBusyCursor()
3392        try:
3393            while iatm < len(Atoms):
3394                atom = Atoms[iatm]
3395                res = atom[1].strip()
3396                numChain = ' %s %s'%(atom[0],atom[2])
3397                if res not in RBIds or atom[ct-1] == 'OXT':
3398                    iatm += 1
3399                    continue        #skip for OXT, water molecules, etc.
3400                rbRes = RBData[RBIds[res]]
3401                rbRef = rbRes['rbRef']
3402                VAR = rbRes['rbXYZ'][rbRef[1]]-rbRes['rbXYZ'][rbRef[0]]
3403                VBR = rbRes['rbXYZ'][rbRef[2]]-rbRes['rbXYZ'][rbRef[0]]
3404                rbObj = {'RBname':rbRes['RBname'],'numChain':numChain}
3405                rbAtoms = []
3406                rbIds = []
3407                for iratm in range(len(rbRes['atNames'])):
3408                    rbAtoms.append(np.array(Atoms[iatm][cx:cx+3]))
3409                    rbIds.append(Atoms[iatm][20])
3410                    iatm += 1    #puts this at beginning of next residue?
3411                Orig = rbAtoms[rbRef[0]]
3412                rbObj['RBId'] = RBIds[res]
3413                rbObj['Ids'] = rbIds
3414                rbObj['Orig'] = [Orig,False]
3415#                print ' residue '+rbRes['RBname']+str(atom[0]).strip()+ \
3416#                    ' origin at: ','%.5f %.5f %.5f'%(Orig[0],Orig[1],Orig[2])
3417                VAC = np.inner(Amat,rbAtoms[rbRef[1]]-Orig)
3418                VBC = np.inner(Amat,rbAtoms[rbRef[2]]-Orig)
3419                VCC = np.cross(VAR,VAC)
3420                QuatA = G2mth.makeQuat(VAR,VAC,VCC)[0]
3421                VAR = G2mth.prodQVQ(QuatA,VAR)
3422                VBR = G2mth.prodQVQ(QuatA,VBR)
3423                QuatB = G2mth.makeQuat(VBR,VBC,VAR)[0]
3424                QuatC = G2mth.prodQQ(QuatB,QuatA)
3425                rbObj['Orient'] = [QuatC,' ']
3426                SXYZ = []
3427                TXYZ = []
3428                rbObj['Torsions'] = []
3429                for i,xyz in enumerate(rbRes['rbXYZ']):
3430                    SXYZ.append(G2mth.prodQVQ(QuatC,xyz))               
3431                    TXYZ.append(np.inner(Amat,rbAtoms[i]-Orig))
3432                for Oatm,Patm,x,Riders in rbRes['rbSeq']:
3433                    VBR = SXYZ[Oatm]-SXYZ[Patm]
3434                    VAR = SXYZ[Riders[0]]-SXYZ[Patm]
3435                    VAC = TXYZ[Riders[0]]-TXYZ[Patm]
3436                    QuatA,D = G2mth.makeQuat(VAR,VAC,VBR)
3437                    ang = 180.*D/np.pi
3438                    rbObj['Torsions'].append([ang,False])
3439                    for ride in Riders:
3440                        SXYZ[ride] = G2mth.prodQVQ(QuatA,SXYZ[ride]-SXYZ[Patm])+SXYZ[Patm]
3441                RBData[RBIds[res]]['useCount'] += 1
3442                RBObjs.append(rbObj)
3443            data['RBModels']['Residue'] = RBObjs
3444            for RBObj in RBObjs:
3445                newXYZ = G2mth.UpdateResRBAtoms(Bmat,RBObj,RBData)
3446                for i,id in enumerate(RBObj['Ids']):
3447                    data['Atoms'][AtLookUp[id]][cx:cx+3] = newXYZ[i]
3448        finally:
3449            wx.EndBusyCursor()
3450        wx.CallAfter(FillRigidBodyGrid,True)
3451       
3452    def OnRBRemoveAll(event):
3453        data['RBModels']['Residue'] = []
3454        data['RBModels']['Vector'] = []
3455        FillRigidBodyGrid(True)
3456       
3457    def OnGlobalResRBRef(event):
3458        RBObjs = data['RBModels']['Residue']
3459        names = ['Origin','Orientation',]
3460        nTor = 0
3461        for rbObj in RBObjs:
3462            nTor = max(nTor,len(rbObj['Torsions']))
3463        names += ['Torsion '+str(i) for i in range(nTor)]
3464        dlg = wx.MultiChoiceDialog(G2frame,'Select','Refinement controls',names)
3465        if dlg.ShowModal() == wx.ID_OK:
3466            sel = dlg.GetSelections()
3467            parms = []
3468            for x in sel:
3469                parms.append(names[x])
3470            wx.BeginBusyCursor()
3471            try:
3472                for rbObj in RBObjs:
3473                    if 'Origin' in parms:
3474                        rbObj['Orig'][1] = True
3475                    else:
3476                        rbObj['Orig'][1] = False
3477                    if 'Orientation' in parms:
3478                        rbObj['Orient'][1] = 'Q'
3479                    else:
3480                        rbObj['Orient'][1] = ' '
3481                    for i in range(len(rbObj['Torsions'])):
3482                        if 'Torsion '+str(i) in parms:
3483                            rbObj['Torsions'][i][1] = True
3484                        else:
3485                            rbObj['Torsions'][i][1] = False           
3486            finally:
3487                wx.EndBusyCursor()
3488            FillRigidBodyGrid()
3489                       
3490
3491################################################################################
3492##### Pawley routines
3493################################################################################
3494
3495    def FillPawleyReflectionsGrid():
3496        G2frame.dataFrame.SetStatusText('')
3497                       
3498        def KeyEditPawleyGrid(event):
3499            colList = G2frame.PawleyRefl.GetSelectedCols()
3500            PawleyPeaks = data['Pawley ref']
3501            if event.GetKeyCode() == wx.WXK_RETURN:
3502                event.Skip(True)
3503            elif event.GetKeyCode() == wx.WXK_CONTROL:
3504                event.Skip(True)
3505            elif event.GetKeyCode() == wx.WXK_SHIFT:
3506                event.Skip(True)
3507            elif colList:
3508                G2frame.PawleyRefl.ClearSelection()
3509                key = event.GetKeyCode()
3510                for col in colList:
3511                    if PawleyTable.GetTypeName(0,col) == wg.GRID_VALUE_BOOL:
3512                        if key == 89: #'Y'
3513                            for row in range(PawleyTable.GetNumberRows()): PawleyPeaks[row][col]=True
3514                        elif key == 78:  #'N'
3515                            for row in range(PawleyTable.GetNumberRows()): PawleyPeaks[row][col]=False
3516                        FillPawleyReflectionsGrid()
3517           
3518        if 'Pawley ref' in data:
3519            PawleyPeaks = data['Pawley ref']                       
3520            rowLabels = []
3521            for i in range(len(PawleyPeaks)): rowLabels.append(str(i))
3522            colLabels = ['h','k','l','mul','d','refine','Fsq(hkl)','sig(Fsq)']
3523            Types = 4*[wg.GRID_VALUE_LONG,]+[wg.GRID_VALUE_FLOAT+':10,4',wg.GRID_VALUE_BOOL,]+ \
3524                2*[wg.GRID_VALUE_FLOAT+':10,2',]
3525            PawleyTable = G2gd.Table(PawleyPeaks,rowLabels=rowLabels,colLabels=colLabels,types=Types)
3526            G2frame.PawleyRefl.SetTable(PawleyTable, True)
3527            G2frame.PawleyRefl.Bind(wx.EVT_KEY_DOWN, KeyEditPawleyGrid)                 
3528            for r in range(G2frame.PawleyRefl.GetNumberRows()):
3529                for c in range(G2frame.PawleyRefl.GetNumberCols()):
3530                    if c in [5,6]:
3531                        G2frame.PawleyRefl.SetReadOnly(r,c,isReadOnly=False)
3532                    else:
3533                        G2frame.PawleyRefl.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
3534            G2frame.PawleyRefl.SetMargins(0,0)
3535            G2frame.PawleyRefl.AutoSizeColumns(False)
3536            G2frame.dataFrame.setSizePosLeft([500,300])
3537                   
3538    def OnPawleyLoad(event):
3539        generalData = data['General']
3540        dmin = generalData['Pawley dmin']
3541        cell = generalData['Cell'][1:7]
3542        A = G2lat.cell2A(cell)
3543        SGData = generalData['SGData']
3544        HKLd = np.array(G2lat.GenHLaue(dmin,SGData,A))
3545        PawleyPeaks = []
3546        wx.BeginBusyCursor()
3547        try:
3548            for h,k,l,d in HKLd:
3549                ext,mul = G2spc.GenHKLf([h,k,l],SGData)[:2]
3550                if not ext:
3551                    mul *= 2        #for powder multiplicity
3552                    PawleyPeaks.append([h,k,l,mul,d,False,100.0,1.0])
3553        finally:
3554            wx.EndBusyCursor()
3555        data['Pawley ref'] = PawleyPeaks
3556        FillPawleyReflectionsGrid()
3557       
3558    def OnPawleyEstimate(event):
3559        try:
3560            Refs = data['Pawley ref']
3561            Histograms = data['Histograms']
3562        except KeyError:
3563            print '**** Error - no histograms defined for this phase ****'
3564            return
3565        HistoNames = Histograms.keys()
3566        PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,HistoNames[0])
3567        xdata = G2frame.PatternTree.GetItemPyData(PatternId)[1]
3568        Inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Instrument Parameters'))[0]
3569        Sample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Sample Parameters'))
3570        wave = G2mth.getWave(Inst)
3571        posCorr = Inst['Zero'][1]
3572        const = 9.e-2/(np.pi*Sample['Gonio. radius'])                  #shifts in microns
3573       
3574        wx.BeginBusyCursor()
3575        try:
3576            for ref in Refs:
3577                pos = 2.0*asind(wave/(2.0*ref[4]))
3578                if 'Bragg' in Sample['Type']:
3579                    pos -= const*(4.*Sample['Shift'][0]*cosd(pos/2.0)+ \
3580                        Sample['Transparency'][0]*sind(pos)*100.0)            #trans(=1/mueff) in cm
3581                else:               #Debye-Scherrer - simple but maybe not right
3582                    pos -= const*(Sample['DisplaceX'][0]*cosd(pos)+Sample['DisplaceY'][0]*sind(pos))
3583                indx = np.searchsorted(xdata[0],pos)
3584                try:
3585                    FWHM = max(0.001,G2pwd.getFWHM(pos,Inst))/2.
3586                    dx = xdata[0][indx+1]-xdata[0][indx]
3587                    ref[6] = FWHM*(xdata[1][indx]-xdata[4][indx])*cosd(pos/2.)**3/dx
3588                    Lorenz = 1./(2.*sind(xdata[0][indx]/2.)**2*cosd(xdata[0][indx]/2.))           #Lorentz correction
3589                    pola,dIdPola = G2pwd.Polarization(Inst['Polariz.'][1],xdata[0][indx],Inst['Azimuth'][1])
3590                    ref[6] /= (Lorenz*pola*ref[3])
3591                except IndexError:
3592                    pass
3593        finally:
3594            wx.EndBusyCursor()
3595        FillPawleyReflectionsGrid()
3596
3597    def OnPawleyUpdate(event):
3598        try:
3599            Refs = data['Pawley ref']
3600            Histograms = data['Histograms']
3601        except KeyError:
3602            print '**** Error - no histograms defined for this phase ****'
3603            return
3604        HistoNames = Histograms.keys()
3605        PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,HistoNames[0])
3606        refData = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Reflection Lists'))[PhaseName]
3607
3608        wx.BeginBusyCursor()
3609        try:
3610            for iref,ref in enumerate(Refs):
3611                try:
3612                    if refData[iref][9] < 0.:
3613                        ref[6] = abs(refData[iref][9])
3614                        ref[7] = 1.0
3615                except IndexError:
3616                    pass
3617        finally:
3618            wx.EndBusyCursor()
3619        FillPawleyReflectionsGrid()
3620                           
3621    def OnPawleyDelete(event):          #doesn't work
3622        dlg = wx.MessageDialog(G2frame,'Do you really want to delete selected Pawley reflections?','Delete', 
3623            wx.YES_NO | wx.ICON_QUESTION)
3624        try:
3625            result = dlg.ShowModal()
3626            if result == wx.ID_YES: 
3627                Refs = data['Pawley ref']
3628                Ind = G2frame.PawleyRefl.GetSelectedRows()
3629                Ind.sort()
3630                Ind.reverse()
3631                for ind in Ind:
3632                    Refs = np.delete(Refs,ind,0)
3633                data['Pawley ref'] = Refs
3634                FillPawleyReflectionsGrid()
3635        finally:
3636            dlg.Destroy()
3637
3638################################################################################
3639##### Fourier routines
3640################################################################################
3641
3642    def FillMapPeaksGrid():
3643                       
3644        def RowSelect(event):
3645            r,c =  event.GetRow(),event.GetCol()
3646            if r < 0 and c < 0:
3647                if MapPeaks.IsSelection():
3648                    MapPeaks.ClearSelection()
3649                else:
3650                    for row in range(MapPeaks.GetNumberRows()):
3651                        MapPeaks.SelectRow(row,True)
3652                   
3653            elif c < 0:                   #only row clicks
3654                if event.ControlDown():                   
3655                    if r in MapPeaks.GetSelectedRows():
3656                        MapPeaks.DeselectRow(r)
3657                    else:
3658                        MapPeaks.SelectRow(r,True)
3659                elif event.ShiftDown():
3660                    indxs = MapPeaks.GetSelectedRows()
3661                    MapPeaks.ClearSelection()
3662                    ibeg = 0
3663                    if indxs:
3664                        ibeg = indxs[-1]
3665                    for row in range(ibeg,r+1):
3666                        MapPeaks.SelectRow(row,True)
3667                else:
3668                    MapPeaks.ClearSelection()
3669                    MapPeaks.SelectRow(r,True)
3670            elif r < 0:                 #a column pick
3671                mapPeaks = data['Map Peaks']
3672                c =  event.GetCol()
3673                if colLabels[c] == 'mag':
3674                    mapPeaks = G2mth.sortArray(mapPeaks,c,reverse=True)
3675                elif colLabels[c] in ['x','y','z','dzero']:
3676                    mapPeaks = G2mth.sortArray(mapPeaks,c)
3677                else:
3678                    return
3679                data['Map Peaks'] = mapPeaks
3680                wx.CallAfter(FillMapPeaksGrid)
3681            G2plt.PlotStructure(G2frame,data)                   
3682           
3683        G2frame.dataFrame.setSizePosLeft([450,300])
3684        G2frame.dataFrame.SetStatusText('')
3685        if 'Map Peaks' in data:
3686            G2frame.dataFrame.SetStatusText('Select mag or dzero columns to sort')
3687            mapPeaks = data['Map Peaks']                       
3688            rowLabels = []
3689            for i in range(len(mapPeaks)): rowLabels.append(str(i))
3690            colLabels = ['mag','x','y','z','dzero']
3691            Types = 5*[wg.GRID_VALUE_FLOAT+':10,4',]
3692            G2frame.MapPeaksTable = G2gd.Table(mapPeaks,rowLabels=rowLabels,colLabels=colLabels,types=Types)
3693            MapPeaks.SetTable(G2frame.MapPeaksTable, True)
3694            MapPeaks.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK, RowSelect)
3695            for r in range(MapPeaks.GetNumberRows()):
3696                for c in range(MapPeaks.GetNumberCols()):
3697                    MapPeaks.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
3698            MapPeaks.SetMargins(0,0)
3699            MapPeaks.AutoSizeColumns(False)
3700                   
3701    def OnPeaksMove(event):
3702        if 'Map Peaks' in data:
3703            mapPeaks = np.array(data['Map Peaks'])
3704            peakMax = np.max(mapPeaks.T[0])
3705            Ind = MapPeaks.GetSelectedRows()
3706            for ind in Ind:
3707                mag,x,y,z,d = mapPeaks[ind]
3708                AtomAdd(x,y,z,'H',Name='M '+'%d'%(int(100*mag/peakMax)))
3709   
3710    def OnPeaksClear(event):
3711        data['Map Peaks'] = []
3712        FillMapPeaksGrid()
3713        G2plt.PlotStructure(G2frame,data)
3714       
3715    def OnPeaksDelete(event):
3716        if 'Map Peaks' in data:
3717            mapPeaks = data['Map Peaks']
3718            Ind = MapPeaks.GetSelectedRows()
3719            Ind.sort()
3720            Ind.reverse()
3721            for ind in Ind:
3722                mapPeaks = np.delete(mapPeaks,ind,0)
3723            data['Map Peaks'] = mapPeaks
3724        FillMapPeaksGrid()
3725        G2plt.PlotStructure(G2frame,data)
3726       
3727    def OnPeaksEquiv(event):
3728        if 'Map Peaks' in data:
3729            mapPeaks = data['Map Peaks']
3730            Ind = MapPeaks.GetSelectedRows()
3731            if Ind:
3732                wx.BeginBusyCursor()
3733                try:
3734                    Ind = G2mth.PeaksEquiv(data,Ind)
3735                    for r in range(MapPeaks.GetNumberRows()):
3736                        if r in Ind:
3737                            MapPeaks.SelectRow(r,addToSelected=True)
3738                        else:
3739                            MapPeaks.DeselectRow(r)
3740                finally:
3741                    wx.EndBusyCursor()
3742                G2plt.PlotStructure(G2frame,data)
3743
3744    def OnShowBonds(event):
3745        generalData = data['General']
3746        if generalData['Map']['Show bonds']:
3747            generalData['Map']['Show bonds'] = False
3748            G2frame.dataFrame.MapPeaksEdit.SetLabel(G2gd.wxID_SHOWBONDS,'Show bonds')
3749        else:
3750            generalData['Map']['Show bonds'] = True
3751            G2frame.dataFrame.MapPeaksEdit.SetLabel(G2gd.wxID_SHOWBONDS,'Hide bonds')
3752        FillMapPeaksGrid()
3753        G2plt.PlotStructure(G2frame,data)
3754               
3755    def OnPeaksUnique(event):
3756        if 'Map Peaks' in data:
3757            mapPeaks = data['Map Peaks']
3758            Ind = MapPeaks.GetSelectedRows()
3759            if Ind:
3760                wx.BeginBusyCursor()
3761                try:
3762                    Ind = G2mth.PeaksUnique(data,Ind)
3763                    for r in range(MapPeaks.GetNumberRows()):
3764                        if r in Ind:
3765                            MapPeaks.SelectRow(r,addToSelected=True)
3766                        else:
3767                            MapPeaks.DeselectRow(r)
3768                finally:
3769                    wx.EndBusyCursor()
3770                G2plt.PlotStructure(G2frame,data)
3771               
3772    def OnPeaksViewPoint(event):
3773        # set view point
3774        indx = MapPeaks.GetSelectedRows()
3775        if not indx:
3776            print '***** ERROR - no peaks selected'
3777            return
3778        mapPeaks = data['Map Peaks']
3779        drawingData = data['Drawing']
3780        drawingData['viewPoint'][0] = mapPeaks[indx[0]][1:4]
3781        G2plt.PlotStructure(G2frame,data)
3782   
3783    def OnPeaksDistVP(event):
3784        # distance to view point
3785        indx = MapPeaks.GetSelectedRows()
3786        if not indx:
3787            print '***** ERROR - no peaks selected'
3788            return
3789        generalData = data['General']
3790        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])           
3791        mapPeaks = data['Map Peaks']
3792        drawingData = data['Drawing']
3793        viewPt = np.array(drawingData['viewPoint'][0])
3794        print ' Distance from view point at %.3f %.3f %.3f to:'%(viewPt[0],viewPt[1],viewPt[2])
3795        colLabels = [MapPeaks.GetColLabelValue(c) for c in range(MapPeaks.GetNumberCols())]
3796        cx = colLabels.index('x')
3797        cm = colLabels.index('mag')
3798        for i in indx:
3799            peak = mapPeaks[i]
3800            Dx = np.array(peak[cx:cx+3])-viewPt
3801            dist = np.sqrt(np.sum(np.inner(Amat,Dx)**2,axis=0))
3802            print 'Peak: %5d mag= %8.2f distance = %.3f'%(i,peak[cm],dist)
3803
3804    def OnPeaksDA(event):
3805        #distance, angle
3806        indx = MapPeaks.GetSelectedRows()
3807        if len(indx) not in [2,3]:
3808            print '**** ERROR - wrong number of atoms for distance or angle calculation'
3809            return
3810        generalData = data['General']
3811        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])           
3812        mapPeaks = data['Map Peaks']
3813        xyz = []
3814        for i in indx:
3815            xyz.append(mapPeaks[i][1:4])
3816        if len(indx) == 2:
3817            print ' distance for atoms %s = %.3f'%(str(indx),G2mth.getRestDist(xyz,Amat))
3818        else:
3819            print ' angle for atoms %s = %.2f'%(str(indx),G2mth.getRestAngle(xyz,Amat))
3820                                   
3821    def OnFourierMaps(event):
3822        generalData = data['General']
3823        mapData = generalData['Map']
3824        reflName = mapData['RefList']
3825        phaseName = generalData['Name']
3826        if 'PWDR' in reflName:
3827            PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, reflName)
3828            reflSets = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Reflection Lists'))
3829            reflData = reflSets[phaseName]
3830        elif 'HKLF' in reflName:
3831            PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, reflName)
3832            reflData = G2frame.PatternTree.GetItemPyData(PatternId)[1]
3833        mapData.update(G2mth.FourierMap(data,reflData))
3834        mapData['Flip'] = False
3835        mapSig = np.std(mapData['rho'])
3836        if not data['Drawing']:                 #if new drawing - no drawing data!
3837            SetupDrawingData()
3838        data['Drawing']['contourLevel'] = 1.
3839        data['Drawing']['mapSize'] = 10.
3840        print mapData['MapType']+' computed: rhomax = %.3f rhomin = %.3f sigma = %.3f'%(np.max(mapData['rho']),np.min(mapData['rho']),mapSig)
3841        UpdateDrawAtoms()
3842        G2plt.PlotStructure(G2frame,data)
3843       
3844    def OnFourClear(event):
3845        generalData = data['General']
3846        generalData['Map'] = mapDefault
3847        G2plt.PlotStructure(G2frame,data)
3848       
3849    def printRho(SGLaue,rho,rhoMax):                         
3850# map printing for testing purposes
3851        dim = len(rho.shape)
3852        if dim == 2:
3853            ix,jy = rho.shape
3854            for j in range(jy):
3855                line = ''
3856                if SGLaue in ['3','3m1','31m','6/m','6/mmm']:
3857                    line += (jy-j)*'  '
3858                for i in range(ix):
3859                    r = int(100*rho[i,j]/rhoMax)
3860                    line += '%4d'%(r)
3861                print line+'\n'
3862        else:
3863            ix,jy,kz = rho.shape
3864            for k in range(kz):
3865                print 'k = ',k
3866                for j in range(jy):
3867                    line = ''
3868                    if SGLaue in ['3','3m1','31m','6/m','6/mmm']:
3869                        line += (jy-j)*'  '
3870                    for i in range(ix):
3871                        r = int(100*rho[i,j,k]/rhoMax)
3872                        line += '%4d'%(r)
3873                    print line+'\n'
3874## keep this               
3875   
3876    def OnSearchMaps(event):
3877                                   
3878        peaks = []
3879        mags = []
3880        print ' Begin fourier map search - can take some time'
3881        time0 = time.time()
3882        generalData = data['General']
3883        mapData = generalData['Map']
3884        if len(mapData['rho']):
3885            wx.BeginBusyCursor()
3886            try:
3887                peaks,mags,dzeros = G2mth.SearchMap(data)
3888            finally:
3889                wx.EndBusyCursor()
3890            if len(peaks):
3891                mapPeaks = np.concatenate((mags,peaks,dzeros),axis=1)
3892                data['Map Peaks'] = G2mth.sortArray(mapPeaks,0,reverse=True)           
3893            print ' Map search finished, time = %.2fs'%(time.time()-time0)
3894            print ' No.peaks found:',len(peaks)   
3895            Page = G2frame.dataDisplay.FindPage('Map peaks')
3896            G2frame.dataDisplay.ChangeSelection(Page)
3897            G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.MapPeaksMenu)
3898            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksMove, id=G2gd.wxID_PEAKSMOVE)
3899            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksDA, id=G2gd.wxID_PEAKSDA)
3900            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksUnique, id=G2gd.wxID_PEAKSUNIQUE)
3901            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksDelete, id=G2gd.wxID_PEAKSDELETE)
3902            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksClear, id=G2gd.wxID_PEAKSCLEAR)
3903            UpdateDrawAtoms()
3904            FillMapPeaksGrid()
3905        else:
3906            print 'No map available'
3907       
3908    def OnChargeFlip(event):
3909        generalData = data['General']
3910        mapData = generalData['Map']
3911        flipData = generalData['Flip']
3912        reflName = flipData['RefList']
3913        phaseName = generalData['Name']
3914        if 'PWDR' in reflName:
3915            PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, reflName)
3916            reflSets = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Reflection Lists'))
3917            reflData = reflSets[phaseName]
3918        elif 'HKLF' in reflName:
3919            PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, reflName)
3920            reflData = G2frame.PatternTree.GetItemPyData(PatternId)[1]
3921        else:
3922            print '**** ERROR - No data defined for charge flipping'
3923            return
3924        pgbar = wx.ProgressDialog('Charge flipping','Residual Rcf =',101.0, 
3925            style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_CAN_ABORT)
3926        screenSize = wx.ClientDisplayRect()
3927        Size = pgbar.GetSize()
3928        Size = (int(Size[0]*1.2),Size[1]) # increase size a bit along x
3929        pgbar.SetPosition(wx.Point(screenSize[2]-Size[0]-305,screenSize[1]+5))
3930        pgbar.SetSize(Size)
3931        try:
3932            mapData.update(G2mth.ChargeFlip(data,reflData,pgbar))
3933        finally:
3934            pgbar.Destroy()
3935        mapData['Flip'] = True       
3936        mapSig = np.std(mapData['rho'])
3937        if not data['Drawing']:                 #if new drawing - no drawing data!
3938            SetupDrawingData()
3939        data['Drawing']['contourLevel'] = 1.
3940        data['Drawing']['mapSize'] = 10.
3941        print ' Charge flip map computed: rhomax = %.3f rhomin = %.3f sigma = %.3f'%(np.max(mapData['rho']),np.min(mapData['rho']),mapSig)
3942        if mapData['Rcf'] < 99.:
3943            OnSearchMaps(event)             #does a plot structure at end
3944        else:
3945            print 'Bad charge flip map - no peak search done'
3946               
3947    def OnTextureRefine(event):
3948        print 'refine texture?'
3949        event.Skip()       
3950           
3951    def OnTextureClear(event):
3952        print 'clear texture?'
3953        event.Skip()
3954
3955    def OnPageChanged(event):
3956        page = event.GetSelection()
3957        text = G2frame.dataDisplay.GetPageText(page)
3958        if text == 'Atoms':
3959            G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.AtomsMenu)
3960            G2frame.dataFrame.Bind(wx.EVT_MENU, OnAtomAdd, id=G2gd.wxID_ATOMSEDITADD)
3961            G2frame.dataFrame.Bind(wx.EVT_MENU, OnAtomViewAdd, id=G2gd.wxID_ATOMSVIEWADD)
3962            G2frame.dataFrame.Bind(wx.EVT_MENU, OnRBAppend, id=G2gd.wxID_RBAPPEND)
3963            G2frame.dataFrame.Bind(wx.EVT_MENU, OnAtomInsert, id=G2gd.wxID_ATOMSEDITINSERT)
3964            G2frame.dataFrame.Bind(wx.EVT_MENU, OnAtomViewInsert, id=G2gd.wxID_ATOMVIEWINSERT)
3965            G2frame.dataFrame.Bind(wx.EVT_MENU, OnAtomMove, id=G2gd.wxID_ATOMMOVE)
3966            G2frame.dataFrame.Bind(wx.EVT_MENU, AtomDelete, id=G2gd.wxID_ATOMSEDITDELETE)
3967            G2frame.dataFrame.Bind(wx.EVT_MENU, AtomRefine, id=G2gd.wxID_ATOMSREFINE)
3968            G2frame.dataFrame.Bind(wx.EVT_MENU, AtomModify, id=G2gd.wxID_ATOMSMODIFY)
3969            G2frame.dataFrame.Bind(wx.EVT_MENU, AtomTransform, id=G2gd.wxID_ATOMSTRANSFORM)
3970            G2frame.dataFrame.Bind(wx.EVT_MENU, OnReloadDrawAtoms, id=G2gd.wxID_RELOADDRAWATOMS)
3971            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDistAngle, id=G2gd.wxID_ATOMSDISAGL)
3972            FillAtomsGrid(Atoms)
3973        elif text == 'General':
3974            G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.DataGeneral)
3975            G2frame.dataFrame.Bind(wx.EVT_MENU, OnFourierMaps, id=G2gd.wxID_FOURCALC)
3976            G2frame.dataFrame.Bind(wx.EVT_MENU, OnSearchMaps, id=G2gd.wxID_FOURSEARCH)
3977            G2frame.dataFrame.Bind(wx.EVT_MENU, OnChargeFlip, id=G2gd.wxID_CHARGEFLIP)
3978            G2frame.dataFrame.Bind(wx.EVT_MENU, OnFourClear, id=G2gd.wxID_FOURCLEAR)
3979            UpdateGeneral()
3980        elif text == 'Data':
3981            G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.DataMenu)
3982            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPwdrAdd, id=G2gd.wxID_PWDRADD)
3983            G2frame.dataFrame.Bind(wx.EVT_MENU, OnHklfAdd, id=G2gd.wxID_HKLFADD)
3984            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDataDelete, id=G2gd.wxID_DATADELETE)
3985            G2ddG.UpdateDData(G2frame,DData,data)
3986            G2plt.PlotSizeStrainPO(G2frame,data,Start=True)
3987        elif text == 'Draw Options':
3988            G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.DataDrawOptions)
3989            UpdateDrawOptions()
3990            G2plt.PlotStructure(G2frame,data)
3991        elif text == 'Draw Atoms':
3992            G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.DrawAtomsMenu)
3993            G2frame.dataFrame.Bind(wx.EVT_MENU, DrawAtomStyle, id=G2gd.wxID_DRAWATOMSTYLE)
3994            G2frame.dataFrame.Bind(wx.EVT_MENU, DrawAtomLabel, id=G2gd.wxID_DRAWATOMLABEL)
3995            G2frame.dataFrame.Bind(wx.EVT_MENU, DrawAtomColor, id=G2gd.wxID_DRAWATOMCOLOR)
3996            G2frame.dataFrame.Bind(wx.EVT_MENU, ResetAtomColors, id=G2gd.wxID_DRAWATOMRESETCOLOR)
3997            G2frame.dataFrame.Bind(wx.EVT_MENU, SetViewPoint, id=G2gd.wxID_DRAWVIEWPOINT)
3998            G2frame.dataFrame.Bind(wx.EVT_MENU, AddSymEquiv, id=G2gd.wxID_DRAWADDEQUIV)
3999            G2frame.dataFrame.Bind(wx.EVT_MENU, TransformSymEquiv, id=G2gd.wxID_DRAWTRANSFORM)
4000            G2frame.dataFrame.Bind(wx.EVT_MENU, FillCoordSphere, id=G2gd.wxID_DRAWFILLCOORD)           
4001            G2frame.dataFrame.Bind(wx.EVT_MENU, FillUnitCell, id=G2gd.wxID_DRAWFILLCELL)
4002            G2frame.dataFrame.Bind(wx.EVT_MENU, DrawAtomsDelete, id=G2gd.wxID_DRAWDELETE)
4003            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDrawDistVP, id=G2gd.wxID_DRAWDISTVP)
4004            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDrawDAT, id=G2gd.wxID_DRAWDISAGLTOR)
4005            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDrawPlane, id=G2gd.wxID_DRAWPLANE)
4006            G2frame.dataFrame.Bind(wx.EVT_MENU, OnRestraint, id=G2gd.wxID_DRAWRESTRBOND)
4007            G2frame.dataFrame.Bind(wx.EVT_MENU, OnRestraint, id=G2gd.wxID_DRAWRESTRANGLE)
4008            G2frame.dataFrame.Bind(wx.EVT_MENU, OnRestraint, id=G2gd.wxID_DRAWRESTRPLANE)
4009            G2frame.dataFrame.Bind(wx.EVT_MENU, OnRestraint, id=G2gd.wxID_DRAWRESTRCHIRAL)
4010            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDefineRB, id=G2gd.wxID_DRAWDEFINERB)
4011            UpdateDrawAtoms()
4012            G2plt.PlotStructure(G2frame,data)
4013        elif text == 'RB Models':
4014            G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.RigidBodiesMenu)
4015            G2frame.dataFrame.Bind(wx.EVT_MENU, OnAutoFindResRB, id=G2gd.wxID_AUTOFINDRESRB)
4016            G2frame.dataFrame.Bind(wx.EVT_MENU, OnRBAssign, id=G2gd.wxID_ASSIGNATMS2RB)
4017            G2frame.dataFrame.Bind(wx.EVT_MENU, OnGlobalResRBRef, id=G2gd.wxID_GLOBALRESREFINE)
4018            G2frame.dataFrame.Bind(wx.EVT_MENU, OnRBRemoveAll, id=G2gd.wxID_RBREMOVEALL)
4019            FillRigidBodyGrid()
4020        elif text == 'Pawley reflections':
4021            G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.PawleyMenu)
4022            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPawleyLoad, id=G2gd.wxID_PAWLEYLOAD)
4023            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPawleyEstimate, id=G2gd.wxID_PAWLEYESTIMATE)
4024            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPawleyUpdate, id=G2gd.wxID_PAWLEYUPDATE)
4025            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPawleyDelete, id=G2gd.wxID_PAWLEYDELETE)           
4026            FillPawleyReflectionsGrid()
4027        elif text == 'Map peaks':
4028            G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.MapPeaksMenu)
4029            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksMove, id=G2gd.wxID_PEAKSMOVE)
4030            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksViewPoint, id=G2gd.wxID_PEAKSVIEWPT)
4031            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksDistVP, id=G2gd.wxID_PEAKSDISTVP)
4032            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksDA, id=G2gd.wxID_PEAKSDA)
4033            G2frame.dataFrame.Bind(wx.EVT_MENU, OnShowBonds, id=G2gd.wxID_SHOWBONDS)
4034            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksEquiv, id=G2gd.wxID_FINDEQVPEAKS)
4035            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksUnique, id=G2gd.wxID_PEAKSUNIQUE)
4036            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksDelete, id=G2gd.wxID_PEAKSDELETE)
4037            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksClear, id=G2gd.wxID_PEAKSCLEAR)
4038            FillMapPeaksGrid()
4039            G2plt.PlotStructure(G2frame,data)
4040        elif text == 'Texture':
4041            G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.TextureMenu)
4042            G2frame.dataFrame.Bind(wx.EVT_MENU, OnTextureRefine, id=G2gd.wxID_REFINETEXTURE)
4043            G2frame.dataFrame.Bind(wx.EVT_MENU, OnTextureClear, id=G2gd.wxID_CLEARTEXTURE)
4044            UpdateTexture()                       
4045            G2plt.PlotTexture(G2frame,data,Start=True)
4046           
4047        else:
4048            G2gd.SetDataMenuBar(G2frame)
4049        event.Skip()
4050       
4051    General = wx.Window(G2frame.dataDisplay)
4052    G2frame.dataDisplay.AddPage(General,'General')
4053    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.DataGeneral)
4054    G2frame.dataFrame.Bind(wx.EVT_MENU, OnFourierMaps, id=G2gd.wxID_FOURCALC)
4055    G2frame.dataFrame.Bind(wx.EVT_MENU, OnSearchMaps, id=G2gd.wxID_FOURSEARCH)
4056    G2frame.dataFrame.Bind(wx.EVT_MENU, OnChargeFlip, id=G2gd.wxID_CHARGEFLIP)
4057    G2frame.dataFrame.Bind(wx.EVT_MENU, OnFourClear, id=G2gd.wxID_FOURCLEAR)
4058    SetupGeneral()
4059    GeneralData = data['General']
4060    UpdateGeneral()
4061
4062    DData = wx.ScrolledWindow(G2frame.dataDisplay)
4063    G2frame.dataDisplay.AddPage(DData,'Data')
4064    Atoms = G2gd.GSGrid(G2frame.dataDisplay)
4065    G2frame.dataDisplay.AddPage(Atoms,'Atoms')
4066    drawOptions = wx.Window(G2frame.dataDisplay)
4067    G2frame.dataDisplay.AddPage(drawOptions,'Draw Options')
4068    drawAtoms = G2gd.GSGrid(G2frame.dataDisplay)
4069    G2frame.dataDisplay.AddPage(drawAtoms,'Draw Atoms')
4070    RigidBodies = wx.ScrolledWindow(G2frame.dataDisplay)
4071    G2frame.dataDisplay.AddPage(RigidBodies,'RB Models')
4072    MapPeaks = G2gd.GSGrid(G2frame.dataDisplay)
4073    G2frame.dataDisplay.AddPage(MapPeaks,'Map peaks')
4074    Texture = wx.ScrolledWindow(G2frame.dataDisplay)
4075    G2frame.dataDisplay.AddPage(Texture,'Texture')
4076    G2frame.PawleyRefl = G2gd.GSGrid(G2frame.dataDisplay)
4077    G2frame.dataDisplay.AddPage(G2frame.PawleyRefl,'Pawley reflections')
4078           
4079    G2frame.dataDisplay.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, OnPageChanged)
4080    G2frame.dataDisplay.SetSelection(oldPage)
4081
Note: See TracBrowser for help on using the repository browser.