source: trunk/GSASIIphsGUI.py @ 508

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

some refactoring in GSASIIphsGUI.py
implement LG mixing coeff for size & mustrain
remove MP stuff (it'll go in later)

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