source: trunk/GSASIIphsGUI.py @ 573

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

add 'None' as one of the phase data plot options
trap failed charge flipping errors
add atom modify commands
add a new class - SingleFloatDialog? to GSASIIphsGUI.py
can now roll in place charge flip maps with u,d,l,r keys

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