source: trunk/GSASIIphsGUI.py @ 521

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

fourier maps & contouring - limiting sphere

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