source: trunk/GSASIIphsGUI.py @ 530

Last change on this file since 530 was 530, checked in by vondreele, 11 years ago

small fix to HessianLSQ about # of cycles
finish map peak search (no GUI/plot output yet)

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