source: trunk/GSASIIphsGUI.py @ 520

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

separate getHKLmax

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