source: trunk/GSASIIphsGUI.py @ 519

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

fixes to ViewParmDialog? try to get size right
add copy of refinement flags to various parameters
put some comment section breaks in
fix to eA derivative & wRp in seq refinement
add to help/gsasII.html

  • Property svn:keywords set to Date Author Revision URL Id
File size: 164.9 KB
Line 
1#GSASII - phase data display routines
2########### SVN repository information ###################
3# $Date: 2012-03-11 17:50:03 +0000 (Sun, 11 Mar 2012) $
4# $Author: vondreele $
5# $Revision: 519 $
6# $URL: trunk/GSASIIphsGUI.py $
7# $Id: GSASIIphsGUI.py 519 2012-03-11 17:50:03Z 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 OnCopyFlags(event):
2516            Obj = event.GetEventObject()
2517            hist = Indx[Obj.GetId()]
2518            sourceDict = UseList[hist]
2519            copyDict = {}
2520            copyNames = ['Scale','Pref.Ori.','Size','Mustrain','HStrain','Extinction']
2521            for name in copyNames:
2522                if name in ['Scale','Extinction','HStrain']:
2523                    copyDict[name] = sourceDict[name][1]
2524                elif name in ['Size','Mustrain']:
2525                    copyDict[name] = [sourceDict[name][0],sourceDict[name][2],sourceDict[name][4]]
2526                elif name == 'Pref.Ori.':
2527                    copyDict[name] = [sourceDict[name][0],sourceDict[name][2]]
2528                    if sourceDict[name][0] == 'SH':
2529                        SHterms = sourceDict[name][5]
2530                        SHflags = {}
2531                        for item in SHterms:
2532                            SHflags[item] = SHterms[item][1]
2533                        copyDict[name].append(SHflags)                       
2534            keyList = ['All',]+UseList.keys()
2535            if UseList:
2536                copyList = []
2537                dlg = wx.MultiChoiceDialog(G2frame, 
2538                    'Copy parameters to which histograms?', 'Copy parameters', 
2539                    keyList, wx.CHOICEDLG_STYLE)
2540                try:
2541                    if dlg.ShowModal() == wx.ID_OK:
2542                        result = dlg.GetSelections()
2543                        for i in result: 
2544                            copyList.append(keyList[i])
2545                        if 'All' in copyList: 
2546                            copyList = keyList[1:]
2547                        for item in copyList:
2548                            UseList[item]                           
2549                            for name in copyNames:
2550                                if name in ['Scale','Extinction','HStrain']:
2551                                    UseList[item][name][1] = copy.copy(copyDict[name])
2552                                elif name in ['Size','Mustrain']:
2553                                    UseList[item][name][0] = copy.copy(copyDict[name][0])
2554                                    UseList[item][name][2] = copy.copy(copyDict[name][1])
2555                                    UseList[item][name][4] = copy.copy(copyDict[name][2])
2556                                elif name == 'Pref.Ori.':
2557                                    UseList[item][name][0] = copy.copy(copyDict[name][0])
2558                                    UseList[item][name][2] = copy.copy(copyDict[name][1])
2559                                    if sourceDict[name][0] == 'SH':
2560                                        SHflags = copy.copy(copyDict[name][2])
2561                                        SHterms = copy.copy(sourceDict[name][5])
2562                                        for item in SHflags:
2563                                            SHterms[item][1] = copy.copy(SHflags[item])                                             
2564                        wx.CallAfter(UpdateDData)
2565                finally:
2566                    dlg.Destroy()
2567           
2568           
2569        def OnLGmixRef(event):
2570            Obj = event.GetEventObject()
2571            hist,name = Indx[Obj.GetId()]
2572            UseList[hist][name][2][2] = Obj.GetValue()
2573           
2574        def OnLGmixVal(event):
2575            Obj = event.GetEventObject()
2576            hist,name = Indx[Obj.GetId()]
2577            try:
2578                value = float(Obj.GetValue())
2579                if 0.1 <= value <= 1:
2580                    UseList[hist][name][1][2] = value
2581                else:
2582                    raise ValueError
2583            except ValueError:
2584                pass
2585            Obj.SetValue("%.4f"%(UseList[hist][name][1][2]))          #reset in case of error
2586
2587        def OnSizeType(event):
2588            Obj = event.GetEventObject()
2589            hist = Indx[Obj.GetId()]
2590            UseList[hist]['Size'][0] = Obj.GetValue()
2591            G2plt.PlotSizeStrainPO(G2frame,data)
2592            wx.CallAfter(UpdateDData)
2593           
2594        def OnSizeRef(event):
2595            Obj = event.GetEventObject()
2596            hist,pid = Indx[Obj.GetId()]
2597            if UseList[hist]['Size'][0] == 'ellipsoidal':
2598                UseList[hist]['Size'][5][pid] = Obj.GetValue()               
2599            else:
2600                UseList[hist]['Size'][2][pid] = Obj.GetValue()
2601           
2602        def OnSizeVal(event):
2603            Obj = event.GetEventObject()
2604            hist,pid = Indx[Obj.GetId()]
2605            if UseList[hist]['Size'][0] == 'ellipsoidal':
2606                try:
2607                    size = float(Obj.GetValue())
2608                    if pid < 3 and size <= 0.001:            #10A lower limit!
2609                        raise ValueError
2610                    UseList[hist]['Size'][4][pid] = size                   
2611                except ValueError:
2612                    pass
2613                Obj.SetValue("%.3f"%(UseList[hist]['Size'][4][pid]))          #reset in case of error
2614            else:
2615                try:
2616                    size = float(Obj.GetValue())
2617                    if size <= 0.001:            #10A lower limit!
2618                        raise ValueError
2619                    UseList[hist]['Size'][1][pid] = size
2620                except ValueError:
2621                    pass
2622                Obj.SetValue("%.3f"%(UseList[hist]['Size'][1][pid]))          #reset in case of error
2623            G2plt.PlotSizeStrainPO(G2frame,data)
2624           
2625        def OnSizeAxis(event):           
2626            Obj = event.GetEventObject()
2627            hist = Indx[Obj.GetId()]
2628            Saxis = Obj.GetValue().split()
2629            try:
2630                hkl = [int(Saxis[i]) for i in range(3)]
2631            except (ValueError,IndexError):
2632                hkl = UseList[hist]['Size'][3]
2633            if not np.any(np.array(hkl)):
2634                hkl = UseList[hist]['Size'][3]
2635            UseList[hist]['Size'][3] = hkl
2636            h,k,l = hkl
2637            Obj.SetValue('%3d %3d %3d'%(h,k,l)) 
2638                       
2639        def OnStrainType(event):
2640            Obj = event.GetEventObject()
2641            hist = Indx[Obj.GetId()]
2642            UseList[hist]['Mustrain'][0] = Obj.GetValue()
2643            wx.CallAfter(UpdateDData)
2644            G2plt.PlotSizeStrainPO(G2frame,data)
2645           
2646        def OnStrainRef(event):
2647            Obj = event.GetEventObject()
2648            hist,pid = Indx[Obj.GetId()]
2649            if UseList[hist]['Mustrain'][0] == 'generalized':
2650                UseList[hist]['Mustrain'][5][pid] = Obj.GetValue()
2651            else:
2652                UseList[hist]['Mustrain'][2][pid] = Obj.GetValue()
2653           
2654        def OnStrainVal(event):
2655            Snames = G2spc.MustrainNames(SGData)
2656            Obj = event.GetEventObject()
2657            hist,pid = Indx[Obj.GetId()]
2658            try:
2659                strain = float(Obj.GetValue())
2660                if UseList[hist]['Mustrain'][0] == 'generalized':
2661                    if '4' in Snames[pid] and strain < 0:
2662                        raise ValueError
2663                    UseList[hist]['Mustrain'][4][pid] = strain
2664                else:
2665                    if strain <= 0:
2666                        raise ValueError
2667                    UseList[hist]['Mustrain'][1][pid] = strain
2668            except ValueError:
2669                pass
2670            if UseList[hist]['Mustrain'][0] == 'generalized':
2671                Obj.SetValue("%.3f"%(UseList[hist]['Mustrain'][4][pid]))          #reset in case of error
2672            else:
2673                Obj.SetValue("%.1f"%(UseList[hist]['Mustrain'][1][pid]))          #reset in case of error
2674            G2plt.PlotSizeStrainPO(G2frame,data)
2675           
2676        def OnStrainAxis(event):
2677            Obj = event.GetEventObject()
2678            hist = Indx[Obj.GetId()]
2679            Saxis = Obj.GetValue().split()
2680            try:
2681                hkl = [int(Saxis[i]) for i in range(3)]
2682            except (ValueError,IndexError):
2683                hkl = UseList[hist]['Mustrain'][3]
2684            if not np.any(np.array(hkl)):
2685                hkl = UseList[hist]['Mustrain'][3]
2686            UseList[hist]['Mustrain'][3] = hkl
2687            h,k,l = hkl
2688            Obj.SetValue('%3d %3d %3d'%(h,k,l)) 
2689            G2plt.PlotSizeStrainPO(G2frame,data)
2690           
2691        def OnHstrainRef(event):
2692            Obj = event.GetEventObject()
2693            hist,pid = Indx[Obj.GetId()]
2694            UseList[hist]['HStrain'][1][pid] = Obj.GetValue()
2695           
2696        def OnHstrainVal(event):
2697            Snames = G2spc.HStrainNames(SGData)
2698            Obj = event.GetEventObject()
2699            hist,pid = Indx[Obj.GetId()]
2700            try:
2701                strain = float(Obj.GetValue())
2702                UseList[hist]['HStrain'][0][pid] = strain
2703            except ValueError:
2704                pass
2705            Obj.SetValue("%.5f"%(UseList[hist]['HStrain'][0][pid]))          #reset in case of error
2706
2707        def OnPOType(event):
2708            Obj = event.GetEventObject()
2709            hist = Indx[Obj.GetId()]
2710            if 'March' in Obj.GetValue():
2711                UseList[hist]['Pref.Ori.'][0] = 'MD'
2712            else:
2713                UseList[hist]['Pref.Ori.'][0] = 'SH'
2714            wx.CallAfter(UpdateDData)           
2715
2716        def OnPORef(event):
2717            Obj = event.GetEventObject()
2718            hist = Indx[Obj.GetId()]
2719            UseList[hist]['Pref.Ori.'][2] = Obj.GetValue()
2720           
2721        def OnPOVal(event):
2722            Obj = event.GetEventObject()
2723            hist = Indx[Obj.GetId()]
2724            try:
2725                mdVal = float(Obj.GetValue())
2726                if mdVal > 0:
2727                    UseList[hist]['Pref.Ori.'][1] = mdVal
2728            except ValueError:
2729                pass
2730            Obj.SetValue("%.3f"%(UseList[hist]['Pref.Ori.'][1]))          #reset in case of error
2731           
2732        def OnPOAxis(event):
2733            Obj = event.GetEventObject()
2734            hist = Indx[Obj.GetId()]
2735            Saxis = Obj.GetValue().split()
2736            try:
2737                hkl = [int(Saxis[i]) for i in range(3)]
2738            except (ValueError,IndexError):
2739                hkl = UseList[hist]['Pref.Ori.'][3]
2740            if not np.any(np.array(hkl)):
2741                hkl = UseList[hist]['Pref.Ori.'][3]
2742            UseList[hist]['Pref.Ori.'][3] = hkl
2743            h,k,l = hkl
2744            Obj.SetValue('%3d %3d %3d'%(h,k,l)) 
2745           
2746        def OnPOOrder(event):
2747            Obj = event.GetEventObject()
2748            hist = Indx[Obj.GetId()]
2749            Order = int(Obj.GetValue())
2750            UseList[hist]['Pref.Ori.'][4] = Order
2751            UseList[hist]['Pref.Ori.'][5] = SetPOCoef(Order,hist)
2752            wx.CallAfter(UpdateDData)
2753
2754        def SetPOCoef(Order,hist):
2755            cofNames = G2lat.GenSHCoeff(SGData['SGLaue'],'0',Order,False)     #cylindrical & no M
2756            newPOCoef = dict(zip(cofNames,np.zeros(len(cofNames))))
2757            POCoeff = UseList[hist]['Pref.Ori.'][5]
2758            for cofName in POCoeff:
2759                if cofName in  cofNames:
2760                    newPOCoef[cofName] = POCoeff[cofName]
2761            return newPOCoef
2762       
2763        def OnExtRef(event):
2764            Obj = event.GetEventObject()
2765            UseList[Indx[Obj.GetId()]]['Extinction'][1] = Obj.GetValue()
2766           
2767        def OnExtVal(event):
2768            Obj = event.GetEventObject()
2769            try:
2770                ext = float(Obj.GetValue())
2771                if ext >= 0:
2772                    UseList[Indx[Obj.GetId()]]['Extinction'][0] = ext
2773            except ValueError:
2774                pass
2775            Obj.SetValue("%.2f"%(UseList[Indx[Obj.GetId()]]['Extinction'][0]))          #reset in case of error
2776           
2777        def checkAxis(axis):
2778            if not np.any(np.array(axis)):
2779                return False
2780            return axis
2781           
2782        def TopSizer(name,choices,parm,OnType):
2783            topSizer = wx.BoxSizer(wx.HORIZONTAL)
2784            topSizer.Add(wx.StaticText(DData,-1,name),0,wx.ALIGN_CENTER_VERTICAL)
2785            sizeType = wx.ComboBox(DData,wx.ID_ANY,value=UseList[item][parm][0],choices=choices,
2786                style=wx.CB_READONLY|wx.CB_DROPDOWN)
2787            sizeType.Bind(wx.EVT_COMBOBOX, OnType)
2788            Indx[sizeType.GetId()] = item
2789            topSizer.Add(sizeType)
2790            topSizer.Add((5,0),0)
2791            return topSizer
2792           
2793        def LGmixSizer(name,OnVal,OnRef):
2794            lgmixSizer = wx.BoxSizer(wx.HORIZONTAL)
2795            lgmixRef = wx.CheckBox(DData,-1,label='LGmix')
2796            lgmixRef.thisown = False
2797            lgmixRef.SetValue(UseList[item][name][2][2])
2798            Indx[lgmixRef.GetId()] = [item,name]
2799            lgmixRef.Bind(wx.EVT_CHECKBOX, OnRef)
2800            lgmixSizer.Add(lgmixRef,0,wx.ALIGN_CENTER_VERTICAL)
2801            lgmixVal = wx.TextCtrl(DData,wx.ID_ANY,
2802                '%.4f'%(UseList[item][name][1][2]),style=wx.TE_PROCESS_ENTER)
2803            Indx[lgmixVal.GetId()] = [item,name]
2804            lgmixVal.Bind(wx.EVT_TEXT_ENTER,OnVal)
2805            lgmixVal.Bind(wx.EVT_KILL_FOCUS,OnVal)
2806            lgmixSizer.Add(lgmixVal,0,wx.ALIGN_CENTER_VERTICAL)
2807            return lgmixSizer
2808                       
2809        def IsoSizer(name,parm,fmt,OnVal,OnRef):
2810            isoSizer = wx.BoxSizer(wx.HORIZONTAL)
2811            sizeRef = wx.CheckBox(DData,-1,label=name)
2812            sizeRef.thisown = False
2813            sizeRef.SetValue(UseList[item][parm][2][0])
2814            Indx[sizeRef.GetId()] = [item,0]
2815            sizeRef.Bind(wx.EVT_CHECKBOX, OnRef)
2816            isoSizer.Add(sizeRef,0,wx.ALIGN_CENTER_VERTICAL)
2817            sizeVal = wx.TextCtrl(DData,wx.ID_ANY,
2818                fmt%(UseList[item][parm][1][0]),style=wx.TE_PROCESS_ENTER)
2819            Indx[sizeVal.GetId()] = [item,0]
2820            sizeVal.Bind(wx.EVT_TEXT_ENTER,OnVal)
2821            sizeVal.Bind(wx.EVT_KILL_FOCUS,OnVal)
2822            isoSizer.Add(sizeVal,0,wx.ALIGN_CENTER_VERTICAL)
2823            return isoSizer
2824           
2825        def UniSizer(parm,OnAxis):
2826            uniSizer = wx.BoxSizer(wx.HORIZONTAL)
2827            uniSizer.Add(wx.StaticText(DData,-1,' Unique axis, H K L: '),0,wx.ALIGN_CENTER_VERTICAL)
2828            h,k,l = UseList[item][parm][3]
2829            Axis = wx.TextCtrl(DData,-1,'%3d %3d %3d'%(h,k,l),style=wx.TE_PROCESS_ENTER)
2830            Indx[Axis.GetId()] = item
2831            Axis.Bind(wx.EVT_TEXT_ENTER,OnAxis)
2832            Axis.Bind(wx.EVT_KILL_FOCUS,OnAxis)
2833            uniSizer.Add(Axis,0,wx.ALIGN_CENTER_VERTICAL)
2834            return uniSizer
2835           
2836        def UniDataSizer(parmName,parm,fmt,OnVal,OnRef):
2837            dataSizer = wx.BoxSizer(wx.HORIZONTAL)
2838            parms = zip([' Equatorial '+parmName,' Axial '+parmName],
2839                UseList[item][parm][1],UseList[item][parm][2],range(2))
2840            for Pa,val,ref,id in parms:
2841                sizeRef = wx.CheckBox(DData,-1,label=Pa)
2842                sizeRef.thisown = False
2843                sizeRef.SetValue(ref)
2844                Indx[sizeRef.GetId()] = [item,id]
2845                sizeRef.Bind(wx.EVT_CHECKBOX, OnRef)
2846                dataSizer.Add(sizeRef,0,wx.ALIGN_CENTER_VERTICAL)
2847                sizeVal = wx.TextCtrl(DData,wx.ID_ANY,fmt%(val),style=wx.TE_PROCESS_ENTER)
2848                Indx[sizeVal.GetId()] = [item,id]
2849                sizeVal.Bind(wx.EVT_TEXT_ENTER,OnVal)
2850                sizeVal.Bind(wx.EVT_KILL_FOCUS,OnVal)
2851                dataSizer.Add(sizeVal,0,wx.ALIGN_CENTER_VERTICAL)
2852                dataSizer.Add((5,0),0)
2853            return dataSizer
2854           
2855        def EllSizeDataSizer():
2856            parms = zip(['S11','S22','S33','S12','S13','S23'],UseList[item]['Size'][4],
2857                UseList[item]['Size'][5],range(6))
2858            dataSizer = wx.FlexGridSizer(1,6,5,5)
2859            for Pa,val,ref,id in parms:
2860                sizeRef = wx.CheckBox(DData,-1,label=Pa)
2861                sizeRef.thisown = False
2862                sizeRef.SetValue(ref)
2863                Indx[sizeRef.GetId()] = [item,id]
2864                sizeRef.Bind(wx.EVT_CHECKBOX, OnSizeRef)
2865                dataSizer.Add(sizeRef,0,wx.ALIGN_CENTER_VERTICAL)
2866                sizeVal = wx.TextCtrl(DData,wx.ID_ANY,'%.3f'%(val),style=wx.TE_PROCESS_ENTER)
2867                Indx[sizeVal.GetId()] = [item,id]
2868                sizeVal.Bind(wx.EVT_TEXT_ENTER,OnSizeVal)
2869                sizeVal.Bind(wx.EVT_KILL_FOCUS,OnSizeVal)
2870                dataSizer.Add(sizeVal,0,wx.ALIGN_CENTER_VERTICAL)
2871            return dataSizer
2872           
2873        def GenStrainDataSizer():
2874            Snames = G2spc.MustrainNames(SGData)
2875            numb = len(Snames)
2876            if len(UseList[item]['Mustrain'][4]) < numb:
2877                UseList[item]['Mustrain'][4] = numb*[0.0,]
2878                UseList[item]['Mustrain'][5] = numb*[False,]
2879            parms = zip(Snames,UseList[item]['Mustrain'][4],UseList[item]['Mustrain'][5],range(numb))
2880            dataSizer = wx.FlexGridSizer(1,6,5,5)
2881            for Pa,val,ref,id in parms:
2882                strainRef = wx.CheckBox(DData,-1,label=Pa)
2883                strainRef.thisown = False
2884                strainRef.SetValue(ref)
2885                Indx[strainRef.GetId()] = [item,id]
2886                strainRef.Bind(wx.EVT_CHECKBOX, OnStrainRef)
2887                dataSizer.Add(strainRef,0,wx.ALIGN_CENTER_VERTICAL)
2888                strainVal = wx.TextCtrl(DData,wx.ID_ANY,'%.5f'%(val),style=wx.TE_PROCESS_ENTER)
2889                Indx[strainVal.GetId()] = [item,id]
2890                strainVal.Bind(wx.EVT_TEXT_ENTER,OnStrainVal)
2891                strainVal.Bind(wx.EVT_KILL_FOCUS,OnStrainVal)
2892                dataSizer.Add(strainVal,0,wx.ALIGN_CENTER_VERTICAL)
2893            return dataSizer
2894           
2895        def HstrainSizer():
2896            hstrainSizer = wx.FlexGridSizer(1,6,5,5)
2897            Hsnames = G2spc.HStrainNames(SGData)
2898            parms = zip(Hsnames,UseList[item]['HStrain'][0],UseList[item]['HStrain'][1],range(len(Hsnames)))
2899            for Pa,val,ref,id in parms:
2900                hstrainRef = wx.CheckBox(DData,-1,label=Pa)
2901                hstrainRef.thisown = False
2902                hstrainRef.SetValue(ref)
2903                Indx[hstrainRef.GetId()] = [item,id]
2904                hstrainRef.Bind(wx.EVT_CHECKBOX, OnHstrainRef)
2905                hstrainSizer.Add(hstrainRef,0,wx.ALIGN_CENTER_VERTICAL)
2906                hstrainVal = wx.TextCtrl(DData,wx.ID_ANY,'%.5f'%(val),style=wx.TE_PROCESS_ENTER)
2907                Indx[hstrainVal.GetId()] = [item,id]
2908                hstrainVal.Bind(wx.EVT_TEXT_ENTER,OnHstrainVal)
2909                hstrainVal.Bind(wx.EVT_KILL_FOCUS,OnHstrainVal)
2910                hstrainSizer.Add(hstrainVal,0,wx.ALIGN_CENTER_VERTICAL)
2911            return hstrainSizer
2912           
2913        def PoTopSizer(POData):
2914            poSizer = wx.FlexGridSizer(1,6,5,5)
2915            choice = ['March-Dollase','Spherical harmonics']
2916            POtype = choice[['MD','SH'].index(POData[0])]
2917            poSizer.Add(wx.StaticText(DData,-1,' Preferred orientation model '),0,wx.ALIGN_CENTER_VERTICAL)
2918            POType = wx.ComboBox(DData,wx.ID_ANY,value=POtype,choices=choice,
2919                style=wx.CB_READONLY|wx.CB_DROPDOWN)
2920            Indx[POType.GetId()] = item
2921            POType.Bind(wx.EVT_COMBOBOX, OnPOType)
2922            poSizer.Add(POType)
2923            if POData[0] == 'SH':
2924                poSizer.Add(wx.StaticText(DData,-1,' Harmonic order: '),0,wx.ALIGN_CENTER_VERTICAL)
2925                poOrder = wx.ComboBox(DData,wx.ID_ANY,value=str(POData[4]),choices=[str(2*i) for i in range(18)],
2926                    style=wx.CB_READONLY|wx.CB_DROPDOWN)
2927                Indx[poOrder.GetId()] = item
2928                poOrder.Bind(wx.EVT_COMBOBOX,OnPOOrder)
2929                poSizer.Add(poOrder,0,wx.ALIGN_CENTER_VERTICAL)
2930                poRef = wx.CheckBox(DData,-1,label=' Refine? ')
2931                poRef.SetValue(POData[2])
2932                Indx[poRef.GetId()] = item
2933                poRef.Bind(wx.EVT_CHECKBOX,OnPORef)
2934                poSizer.Add(poRef,0,wx.ALIGN_CENTER_VERTICAL)
2935            return poSizer
2936           
2937        def MDDataSizer(POData):
2938            poSizer = wx.BoxSizer(wx.HORIZONTAL)
2939            poRef = wx.CheckBox(DData,-1,label=' March-Dollase ratio: ')
2940            poRef.SetValue(POData[2])
2941            Indx[poRef.GetId()] = item
2942            poRef.Bind(wx.EVT_CHECKBOX,OnPORef)
2943            poSizer.Add(poRef,0,wx.ALIGN_CENTER_VERTICAL)
2944            poVal = wx.TextCtrl(DData,wx.ID_ANY,
2945                '%.3f'%(POData[1]),style=wx.TE_PROCESS_ENTER)
2946            Indx[poVal.GetId()] = item
2947            poVal.Bind(wx.EVT_TEXT_ENTER,OnPOVal)
2948            poVal.Bind(wx.EVT_KILL_FOCUS,OnPOVal)
2949            poSizer.Add(poVal,0,wx.ALIGN_CENTER_VERTICAL)
2950            poSizer.Add(wx.StaticText(DData,-1,' Unique axis, H K L: '),0,wx.ALIGN_CENTER_VERTICAL)
2951            h,k,l =POData[3]
2952            poAxis = wx.TextCtrl(DData,-1,'%3d %3d %3d'%(h,k,l),style=wx.TE_PROCESS_ENTER)
2953            Indx[poAxis.GetId()] = item
2954            poAxis.Bind(wx.EVT_TEXT_ENTER,OnPOAxis)
2955            poAxis.Bind(wx.EVT_KILL_FOCUS,OnPOAxis)
2956            poSizer.Add(poAxis,0,wx.ALIGN_CENTER_VERTICAL)
2957            return poSizer
2958           
2959        def SHDataSizer(POData):
2960            textJ = G2lat.textureIndex(POData[5])
2961            mainSizer.Add(wx.StaticText(DData,-1,' Spherical harmonic coefficients: '+'Texture index: %.3f'%(textJ)),0,wx.ALIGN_CENTER_VERTICAL)
2962            mainSizer.Add((0,5),0)
2963            ODFSizer = wx.FlexGridSizer(2,8,2,2)
2964            ODFIndx = {}
2965            ODFkeys = POData[5].keys()
2966            ODFkeys.sort()
2967            for odf in ODFkeys:
2968                ODFSizer.Add(wx.StaticText(DData,-1,odf),0,wx.ALIGN_CENTER_VERTICAL)
2969                ODFval = wx.TextCtrl(DData,wx.ID_ANY,'%8.3f'%(POData[5][odf]),style=wx.TE_PROCESS_ENTER)
2970                ODFIndx[ODFval.GetId()] = odf
2971#                ODFval.Bind(wx.EVT_TEXT_ENTER,OnODFValue)
2972#                ODFval.Bind(wx.EVT_KILL_FOCUS,OnODFValue)
2973                ODFSizer.Add(ODFval,0,wx.ALIGN_CENTER_VERTICAL)
2974            return ODFSizer
2975           
2976        def ExtSizer():           
2977            extSizer = wx.BoxSizer(wx.HORIZONTAL)
2978            extRef = wx.CheckBox(DData,-1,label=' Extinction: ')
2979            extRef.SetValue(UseList[item]['Extinction'][1])
2980            Indx[extRef.GetId()] = item
2981            extRef.Bind(wx.EVT_CHECKBOX, OnExtRef)
2982            extSizer.Add(extRef,0,wx.ALIGN_CENTER_VERTICAL)
2983            extVal = wx.TextCtrl(DData,wx.ID_ANY,
2984                '%.2f'%(UseList[item]['Extinction'][0]),style=wx.TE_PROCESS_ENTER)
2985            Indx[extVal.GetId()] = item
2986            extVal.Bind(wx.EVT_TEXT_ENTER,OnExtVal)
2987            extVal.Bind(wx.EVT_KILL_FOCUS,OnExtVal)
2988            extSizer.Add(extVal,0,wx.ALIGN_CENTER_VERTICAL)
2989            return extSizer
2990           
2991        if DData.GetSizer():
2992            DData.GetSizer().Clear(True)
2993        mainSizer = wx.BoxSizer(wx.VERTICAL)
2994        mainSizer.Add(wx.StaticText(DData,-1,'Histogram data for '+PhaseName+':'),0,wx.ALIGN_CENTER_VERTICAL)
2995        mainSizer.Add(PlotSizer())           
2996           
2997        for item in keyList:
2998            histData = UseList[item]
2999###### Patch to add LGmix to Size & Mustrain
3000            if len(histData['Size'][1]) == 2:
3001                histData['Size'][1].append(0.6667)
3002                histData['Size'][2].append(False)
3003                histData['Mustrain'][1].append(0.6667)
3004                histData['Mustrain'][2].append(False)
3005                UseList[item] = histData
3006###### end patch
3007            showSizer = wx.BoxSizer(wx.HORIZONTAL)
3008            showData = wx.CheckBox(DData,-1,label=' Show '+item)
3009            showData.SetValue(UseList[item]['Show'])
3010            Indx[showData.GetId()] = item
3011            showData.Bind(wx.EVT_CHECKBOX, OnShowData)
3012            showSizer.Add(showData,0,wx.ALIGN_CENTER_VERTICAL)
3013            copyData = wx.Button(DData,-1,label=' Copy?')
3014            Indx[copyData.GetId()] = item
3015            copyData.Bind(wx.EVT_BUTTON,OnCopyData)
3016            showSizer.Add(copyData,wx.ALIGN_CENTER_VERTICAL)
3017            copyFlags = wx.Button(DData,-1,label=' Copy flags?')
3018            Indx[copyFlags.GetId()] = item
3019            copyFlags.Bind(wx.EVT_BUTTON,OnCopyFlags)
3020            showSizer.Add(copyFlags,wx.ALIGN_CENTER_VERTICAL)
3021            mainSizer.Add((5,5),0)
3022            mainSizer.Add(showSizer,0,wx.ALIGN_CENTER_VERTICAL)
3023            mainSizer.Add((0,5),0)
3024           
3025            if UseList[item]['Show']:
3026                mainSizer.Add(ScaleSizer())
3027                mainSizer.Add((0,5),0)
3028               
3029            if item[:4] == 'PWDR' and UseList[item]['Show']:
3030                if UseList[item]['Size'][0] == 'isotropic':
3031                    isoSizer = wx.BoxSizer(wx.HORIZONTAL)
3032                    isoSizer.Add(TopSizer(' Size model: ',['isotropic','uniaxial','ellipsoidal'],
3033                        'Size',OnSizeType),0,wx.ALIGN_CENTER_VERTICAL)
3034                    isoSizer.Add(LGmixSizer('Size',OnLGmixVal,OnLGmixRef))
3035                    mainSizer.Add(isoSizer)
3036                    mainSizer.Add(IsoSizer(u' Cryst. size(\xb5m): ','Size','%.3f',
3037                        OnSizeVal,OnSizeRef),0,wx.ALIGN_CENTER_VERTICAL)
3038                elif UseList[item]['Size'][0] == 'uniaxial':
3039                    uniSizer = wx.BoxSizer(wx.HORIZONTAL)
3040                    uniSizer.Add(TopSizer(' Size model: ',['isotropic','uniaxial','ellipsoidal'],
3041                        'Size',OnSizeType),0,wx.ALIGN_CENTER_VERTICAL)
3042                    uniSizer.Add(LGmixSizer('Size',OnLGmixVal,OnLGmixRef))
3043                    uniSizer.Add(UniSizer('Size',OnSizeAxis),0,wx.ALIGN_CENTER_VERTICAL)
3044                    mainSizer.Add(uniSizer)
3045                    mainSizer.Add(UniDataSizer(u'size(\xb5m): ','Size','%.3f',OnSizeVal,OnSizeRef))
3046                elif UseList[item]['Size'][0] == 'ellipsoidal':
3047                    ellSizer = wx.BoxSizer(wx.HORIZONTAL)
3048                    ellSizer.Add(TopSizer(' Size model: ',['isotropic','uniaxial','ellipsoidal'],
3049                        'Size',OnSizeType),0,wx.ALIGN_CENTER_VERTICAL)
3050                    ellSizer.Add(LGmixSizer('Size',OnLGmixVal,OnLGmixRef))
3051                    mainSizer.Add(ellSizer)
3052                    mainSizer.Add(EllSizeDataSizer())
3053                mainSizer.Add((0,5),0)                   
3054               
3055                if UseList[item]['Mustrain'][0] == 'isotropic':
3056                    isoSizer = wx.BoxSizer(wx.HORIZONTAL)
3057                    isoSizer.Add(TopSizer(' Mustrain model: ',['isotropic','uniaxial','generalized',],
3058                        'Mustrain',OnStrainType),0,wx.ALIGN_CENTER_VERTICAL)
3059                    isoSizer.Add(LGmixSizer('Mustrain',OnLGmixVal,OnLGmixRef))
3060                    mainSizer.Add(isoSizer)
3061                    mainSizer.Add(IsoSizer(' microstrain: ','Mustrain','%.1f',
3062                        OnStrainVal,OnStrainRef),0,wx.ALIGN_CENTER_VERTICAL)                   
3063                    mainSizer.Add((0,5),0)
3064                elif UseList[item]['Mustrain'][0] == 'uniaxial':
3065                    uniSizer = wx.BoxSizer(wx.HORIZONTAL)
3066                    uniSizer.Add(TopSizer(' Mustrain model: ',['isotropic','uniaxial','generalized',],
3067                        'Mustrain',OnStrainType),0,wx.ALIGN_CENTER_VERTICAL)
3068                    uniSizer.Add(LGmixSizer('Mustrain',OnLGmixVal,OnLGmixRef))
3069                    uniSizer.Add(UniSizer('Mustrain',OnStrainAxis),0,wx.ALIGN_CENTER_VERTICAL)
3070                    mainSizer.Add(uniSizer)
3071                    mainSizer.Add(UniDataSizer('mustrain: ','Mustrain','%.1f',OnStrainVal,OnStrainRef))
3072                elif UseList[item]['Mustrain'][0] == 'generalized':
3073                    genSizer = wx.BoxSizer(wx.HORIZONTAL)
3074                    genSizer.Add(TopSizer(' Mustrain model: ',['isotropic','uniaxial','generalized',],
3075                        'Mustrain',OnStrainType),0,wx.ALIGN_CENTER_VERTICAL)
3076                    genSizer.Add(LGmixSizer('Mustrain',OnLGmixVal,OnLGmixRef))
3077                    mainSizer.Add(genSizer)
3078                    mainSizer.Add(GenStrainDataSizer())                       
3079                mainSizer.Add((0,5),0)
3080               
3081                mainSizer.Add(wx.StaticText(DData,-1,' Hydrostatic/elastic strain:'))
3082                mainSizer.Add(HstrainSizer())
3083                   
3084                #texture  'Pref. Ori.':['MD',1.0,False,[0,0,1],0,[]] last two for 'SH' are SHorder & coeff
3085                poSizer = wx.BoxSizer(wx.VERTICAL)
3086                POData = UseList[item]['Pref.Ori.']
3087                poSizer.Add(PoTopSizer(POData))
3088                if POData[0] == 'MD':
3089                    poSizer.Add(MDDataSizer(POData))
3090                else:           #'SH'
3091                    if POData[4]:       #SH order > 0
3092                        poSizer.Add(SHDataSizer(POData))
3093                       
3094                mainSizer.Add(poSizer)
3095                mainSizer.Add((0,5),0)               
3096                #Extinction  'Extinction':[0.0,False]
3097                mainSizer.Add(ExtSizer())
3098                mainSizer.Add((0,5),0)
3099            elif item[:4] == 'HKLF' and UseList[item]['Show']:
3100                pass
3101        mainSizer.Add((5,5),0)
3102
3103        DData.SetSizer(mainSizer,True)
3104        mainSizer.FitInside(G2frame.dataFrame)
3105        Size = mainSizer.GetMinSize()
3106        Size[0] += 40
3107        Size[1] = max(Size[1],250) + 20
3108        DData.SetSize(Size)
3109        DData.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
3110        Size[1] = min(Size[1],450)
3111        G2frame.dataFrame.setSizePosLeft(Size)
3112       
3113    def OnHklfAdd(event):
3114        UseList = data['Histograms']
3115        keyList = UseList.keys()
3116        TextList = []
3117        if G2frame.PatternTree.GetCount():
3118            item, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
3119            while item:
3120                name = G2frame.PatternTree.GetItemText(item)
3121                if name not in keyList and 'HKLF' in name:
3122                    TextList.append(name)
3123                item, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)                       
3124            dlg = wx.MultiChoiceDialog(G2frame, 'Which new data to use?', 'Use data', TextList, wx.CHOICEDLG_STYLE)
3125            try:
3126                if dlg.ShowModal() == wx.ID_OK:
3127                    result = dlg.GetSelections()
3128                    for i in result:
3129                        histoName = TextList[i]
3130                        UseList[histoName] = {'Histogram':histoName,'Show':False,'Scale':[1.0,True],
3131                            'Extinction':['Lorentzian','Secondary Type I',{'Eg':[0.0,False]},]}                       
3132                    data['Histograms'] = UseList
3133                    wx.CallAfter(UpdateDData)
3134            finally:
3135                dlg.Destroy()
3136       
3137    def OnPwdrAdd(event):
3138        generalData = data['General']
3139        SGData = generalData['SGData']
3140        UseList = data['Histograms']
3141        newList = []
3142        NShkl = len(G2spc.MustrainNames(SGData))
3143        NDij = len(G2spc.HStrainNames(SGData))
3144        keyList = UseList.keys()
3145        TextList = ['All PWDR']
3146        if G2frame.PatternTree.GetCount():
3147            item, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
3148            while item:
3149                name = G2frame.PatternTree.GetItemText(item)
3150                if name not in keyList and 'PWDR' in name:
3151                    TextList.append(name)
3152                item, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
3153            dlg = wx.MultiChoiceDialog(G2frame, 'Which new data to use?', 'Use data', TextList, wx.CHOICEDLG_STYLE)
3154            try:
3155                if dlg.ShowModal() == wx.ID_OK:
3156                    result = dlg.GetSelections()
3157                    for i in result: newList.append(TextList[i])
3158                    if 'All PWDR' in newList:
3159                        newList = TextList[1:]
3160                    for histoName in newList:
3161                        pId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,histoName)
3162                        UseList[histoName] = {'Histogram':histoName,'Show':False,
3163                            'Scale':[1.0,False],'Pref.Ori.':['MD',1.0,False,[0,0,1],0,{}],
3164                            'Size':['isotropic',[4.,4.,0.66667],[False,False,False],[0,0,1],
3165                                [4.,4.,4.,0.,0.,0.],6*[False,]],
3166                            'Mustrain':['isotropic',[1000.0,1000.0,0.666667],[False,False,False],[0,0,1],
3167                                NShkl*[0.01,],NShkl*[False,]],
3168                            'HStrain':[NDij*[0.0,],NDij*[False,]],                         
3169                            'Extinction':[0.0,False]}
3170                        refList = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,pId,'Reflection Lists'))
3171                        refList[generalData['Name']] = []                       
3172                    data['Histograms'] = UseList
3173                    wx.CallAfter(UpdateDData)
3174            finally:
3175                dlg.Destroy()
3176       
3177    def OnDataDelete(event):
3178        UseList = data['Histograms']
3179        keyList = ['All',]+UseList.keys()
3180        keyList.sort()
3181        DelList = []
3182        if UseList:
3183            DelList = []
3184            dlg = wx.MultiChoiceDialog(G2frame, 
3185                'Which histogram to delete from this phase?', 'Delete histogram', 
3186                keyList, wx.CHOICEDLG_STYLE)
3187            try:
3188                if dlg.ShowModal() == wx.ID_OK:
3189                    result = dlg.GetSelections()
3190                    for i in result: 
3191                        DelList.append(keyList[i])
3192                    if 'All' in DelList:
3193                        DelList = keyList[1:]
3194                    for i in DelList:
3195                        del UseList[i]
3196                    wx.CallAfter(UpdateDData)
3197            finally:
3198                dlg.Destroy()
3199
3200################################################################################
3201##### Pawley routines
3202################################################################################
3203
3204    def FillPawleyReflectionsGrid():
3205                       
3206        def KeyEditPawleyGrid(event):
3207            colList = G2frame.PawleyRefl.GetSelectedCols()
3208            PawleyPeaks = data['Pawley ref']
3209            if event.GetKeyCode() == wx.WXK_RETURN:
3210                event.Skip(True)
3211            elif event.GetKeyCode() == wx.WXK_CONTROL:
3212                event.Skip(True)
3213            elif event.GetKeyCode() == wx.WXK_SHIFT:
3214                event.Skip(True)
3215            elif colList:
3216                G2frame.PawleyRefl.ClearSelection()
3217                key = event.GetKeyCode()
3218                for col in colList:
3219                    if PawleyTable.GetTypeName(0,col) == wg.GRID_VALUE_BOOL:
3220                        if key == 89: #'Y'
3221                            for row in range(PawleyTable.GetNumberRows()): PawleyPeaks[row][col]=True
3222                        elif key == 78:  #'N'
3223                            for row in range(PawleyTable.GetNumberRows()): PawleyPeaks[row][col]=False
3224                        FillPawleyReflectionsGrid()
3225           
3226        if 'Pawley ref' in data:
3227            PawleyPeaks = data['Pawley ref']                       
3228            rowLabels = []
3229            for i in range(len(PawleyPeaks)): rowLabels.append(str(i))
3230            colLabels = ['h','k','l','mul','d','refine','Fsq(hkl)','sig(Fsq)']
3231            Types = 4*[wg.GRID_VALUE_LONG,]+[wg.GRID_VALUE_FLOAT+':10,4',wg.GRID_VALUE_BOOL,]+ \
3232                2*[wg.GRID_VALUE_FLOAT+':10,2',]
3233            PawleyTable = G2gd.Table(PawleyPeaks,rowLabels=rowLabels,colLabels=colLabels,types=Types)
3234            G2frame.PawleyRefl.SetTable(PawleyTable, True)
3235            G2frame.PawleyRefl.Bind(wx.EVT_KEY_DOWN, KeyEditPawleyGrid)                 
3236            for r in range(G2frame.PawleyRefl.GetNumberRows()):
3237                for c in range(G2frame.PawleyRefl.GetNumberCols()):
3238                    if c in [5,6]:
3239                        G2frame.PawleyRefl.SetReadOnly(r,c,isReadOnly=False)
3240                    else:
3241                        G2frame.PawleyRefl.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
3242            G2frame.PawleyRefl.SetMargins(0,0)
3243            G2frame.PawleyRefl.AutoSizeColumns(False)
3244            G2frame.dataFrame.setSizePosLeft([500,300])
3245                   
3246    def OnPawleyLoad(event):
3247        generalData = data['General']
3248        dmin = generalData['Pawley dmin']
3249        cell = generalData['Cell'][1:7]
3250        A = G2lat.cell2A(cell)
3251        SGData = generalData['SGData']
3252        HKLd = np.array(G2lat.GenHLaue(dmin,SGData,A))
3253        PawleyPeaks = []
3254        wx.BeginBusyCursor()
3255        try:
3256            for h,k,l,d in HKLd:
3257                ext,mul = G2spc.GenHKLf([h,k,l],SGData)[:2]
3258                if not ext:
3259                    PawleyPeaks.append([h,k,l,mul,d,False,100.0,1.0])
3260        finally:
3261            wx.EndBusyCursor()
3262        data['Pawley ref'] = PawleyPeaks
3263        FillPawleyReflectionsGrid()
3264       
3265    def OnPawleyEstimate(event):
3266        try:
3267            Refs = data['Pawley ref']
3268            Histograms = data['Histograms']
3269        except KeyError:
3270            print '**** Error - no histograms defined for this phase ****'
3271            return
3272        HistoNames = Histograms.keys()
3273        PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,HistoNames[0])
3274        xdata = G2frame.PatternTree.GetItemPyData(PatternId)[1]
3275        Inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Instrument Parameters'))
3276        Inst = dict(zip(Inst[3],Inst[1]))
3277        Sample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Sample Parameters'))
3278        if 'Lam' in Inst:
3279            wave = Inst['Lam']
3280        else:
3281            wave = Inst['Lam1']
3282       
3283        posCorr = Inst['Zero']
3284        const = 9.e-2/(np.pi*Sample['Gonio. radius'])                  #shifts in microns
3285       
3286        for ref in Refs:
3287            pos = 2.0*asind(wave/(2.0*ref[4]))
3288            if 'Bragg' in Sample['Type']:
3289                pos -= const*(4.*Sample['Shift'][0]*cosd(pos/2.0)+ \
3290                    Sample['Transparency'][0]*sind(pos)*100.0)            #trans(=1/mueff) in cm
3291            else:               #Debye-Scherrer - simple but maybe not right
3292                pos -= const*(Sample['DisplaceX'][0]*cosd(pos)+Sample['DisplaceY'][0]*sind(pos))
3293            indx = np.searchsorted(xdata[0],pos)
3294            try:
3295                ref[6] = xdata[1][indx]
3296            except IndexError:
3297                pass
3298        FillPawleyReflectionsGrid()
3299                           
3300    def OnPawleyDelete(event):
3301        dlg = wx.MessageDialog(G2frame,'Do you really want to delete Pawley reflections?','Delete', 
3302            wx.YES_NO | wx.ICON_QUESTION)
3303        try:
3304            result = dlg.ShowModal()
3305        finally:
3306            dlg.Destroy()
3307        if result == wx.ID_YES: 
3308            data['Pawley ref'] = []
3309            FillPawleyReflectionsGrid()
3310
3311################################################################################
3312##### End of main routines
3313################################################################################
3314   
3315    def OnFourierMaps(event):
3316        generalData = data['General']
3317        if not generalData['Map']['MapType']:
3318            print '**** ERROR - Fourier map not defined'
3319            return
3320        print 'Calculate Fourier maps'
3321        print generalData['Map']
3322       
3323    def OnTextureRefine(event):
3324        print 'refine texture?'
3325        event.Skip()       
3326           
3327    def OnTextureClear(event):
3328        print 'clear texture?'
3329        event.Skip()
3330
3331    def OnPageChanged(event):
3332        page = event.GetSelection()
3333        text = G2frame.dataDisplay.GetPageText(page)
3334        if text == 'Atoms':
3335            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.AtomsMenu)
3336            G2frame.dataFrame.Bind(wx.EVT_MENU, OnAtomAdd, id=G2gd.wxID_ATOMSEDITADD)
3337            G2frame.dataFrame.Bind(wx.EVT_MENU, OnAtomTestAdd, id=G2gd.wxID_ATOMSTESTADD)
3338            G2frame.dataFrame.Bind(wx.EVT_MENU, OnAtomInsert, id=G2gd.wxID_ATOMSEDITINSERT)
3339            G2frame.dataFrame.Bind(wx.EVT_MENU, OnAtomTestInsert, id=G2gd.wxID_ATONTESTINSERT)
3340            G2frame.dataFrame.Bind(wx.EVT_MENU, AtomDelete, id=G2gd.wxID_ATOMSEDITDELETE)
3341            G2frame.dataFrame.Bind(wx.EVT_MENU, AtomRefine, id=G2gd.wxID_ATOMSREFINE)
3342            G2frame.dataFrame.Bind(wx.EVT_MENU, AtomModify, id=G2gd.wxID_ATOMSMODIFY)
3343            G2frame.dataFrame.Bind(wx.EVT_MENU, AtomTransform, id=G2gd.wxID_ATOMSTRANSFORM)
3344            G2frame.dataFrame.Bind(wx.EVT_MENU, OnReloadDrawAtoms, id=G2gd.wxID_RELOADDRAWATOMS)
3345            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDistAngle, id=G2gd.wxID_ATOMSDISAGL)
3346            FillAtomsGrid()
3347        elif text == 'General':
3348            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.DataGeneral)
3349            G2frame.dataFrame.Bind(wx.EVT_MENU, OnFourierMaps, id=G2gd.wxID_FOURCALC)
3350            UpdateGeneral()
3351        elif text == 'Data':
3352            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.DataMenu)
3353            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPwdrAdd, id=G2gd.wxID_PWDRADD)
3354            G2frame.dataFrame.Bind(wx.EVT_MENU, OnHklfAdd, id=G2gd.wxID_HKLFADD)
3355            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDataDelete, id=G2gd.wxID_DATADELETE)
3356            UpdateDData()
3357            G2plt.PlotSizeStrainPO(G2frame,data,Start=True)
3358        elif text == 'Draw Options':
3359            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.DataDrawOptions)
3360            UpdateDrawOptions()
3361            G2plt.PlotStructure(G2frame,data)
3362        elif text == 'Draw Atoms':
3363            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.DrawAtomsMenu)
3364            G2frame.dataFrame.Bind(wx.EVT_MENU, DrawAtomStyle, id=G2gd.wxID_DRAWATOMSTYLE)
3365            G2frame.dataFrame.Bind(wx.EVT_MENU, DrawAtomLabel, id=G2gd.wxID_DRAWATOMLABEL)
3366            G2frame.dataFrame.Bind(wx.EVT_MENU, DrawAtomColor, id=G2gd.wxID_DRAWATOMCOLOR)
3367            G2frame.dataFrame.Bind(wx.EVT_MENU, ResetAtomColors, id=G2gd.wxID_DRAWATOMRESETCOLOR)
3368            G2frame.dataFrame.Bind(wx.EVT_MENU, SetViewPoint, id=G2gd.wxID_DRAWVIEWPOINT)
3369            G2frame.dataFrame.Bind(wx.EVT_MENU, AddSymEquiv, id=G2gd.wxID_DRAWADDEQUIV)
3370            G2frame.dataFrame.Bind(wx.EVT_MENU, TransformSymEquiv, id=G2gd.wxID_DRAWTRANSFORM)
3371            G2frame.dataFrame.Bind(wx.EVT_MENU, FillCoordSphere, id=G2gd.wxID_DRAWFILLCOORD)           
3372            G2frame.dataFrame.Bind(wx.EVT_MENU, FillUnitCell, id=G2gd.wxID_DRAWFILLCELL)
3373            G2frame.dataFrame.Bind(wx.EVT_MENU, DrawAtomsDelete, id=G2gd.wxID_DRAWDELETE)
3374            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDrawDAT, id=G2gd.wxID_DRAWDISAGLTOR)
3375            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDrawPlane, id=G2gd.wxID_DRAWPLANE)
3376            UpdateDrawAtoms()
3377            G2plt.PlotStructure(G2frame,data)
3378        elif text == 'Pawley reflections':
3379            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.PawleyMenu)
3380            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPawleyLoad, id=G2gd.wxID_PAWLEYLOAD)
3381            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPawleyEstimate, id=G2gd.wxID_PAWLEYESTIMATE)
3382            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPawleyDelete, id=G2gd.wxID_PAWLEYDELETE)           
3383            FillPawleyReflectionsGrid()
3384        elif text == 'Texture':
3385            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.TextureMenu)
3386            G2frame.dataFrame.Bind(wx.EVT_MENU, OnTextureRefine, id=G2gd.wxID_REFINETEXTURE)
3387            G2frame.dataFrame.Bind(wx.EVT_MENU, OnTextureClear, id=G2gd.wxID_CLEARTEXTURE)
3388            UpdateTexture()                       
3389            G2plt.PlotTexture(G2frame,data,Start=True)
3390        else:
3391            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.BlankMenu)
3392        event.Skip()
3393       
3394    General = wx.Window(G2frame.dataDisplay)
3395    G2frame.dataDisplay.AddPage(General,'General')
3396    G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.DataGeneral)
3397    G2frame.dataFrame.Bind(wx.EVT_MENU, OnFourierMaps, id=G2gd.wxID_FOURCALC)
3398    SetupGeneral()
3399    GeneralData = data['General']
3400    UpdateGeneral()
3401
3402    if GeneralData['Type'] == 'Pawley':
3403        DData = wx.ScrolledWindow(G2frame.dataDisplay)
3404        G2frame.dataDisplay.AddPage(DData,'Data')
3405        G2frame.PawleyRefl = G2gd.GSGrid(G2frame.dataDisplay)
3406        G2frame.dataDisplay.AddPage(G2frame.PawleyRefl,'Pawley reflections')
3407#        Texture = wx.ScrolledWindow(G2frame.dataDisplay)
3408#        G2frame.dataDisplay.AddPage(Texture,'Texture')
3409    else:
3410        DData = wx.ScrolledWindow(G2frame.dataDisplay)
3411        G2frame.dataDisplay.AddPage(DData,'Data')
3412        Atoms = G2gd.GSGrid(G2frame.dataDisplay)
3413        G2frame.dataDisplay.AddPage(Atoms,'Atoms')
3414        drawOptions = wx.Window(G2frame.dataDisplay)
3415        G2frame.dataDisplay.AddPage(drawOptions,'Draw Options')
3416        drawAtoms = G2gd.GSGrid(G2frame.dataDisplay)
3417        G2frame.dataDisplay.AddPage(drawAtoms,'Draw Atoms')
3418        Texture = wx.ScrolledWindow(G2frame.dataDisplay)
3419        G2frame.dataDisplay.AddPage(Texture,'Texture')
3420
3421    G2frame.dataDisplay.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, OnPageChanged)
3422    G2frame.dataDisplay.SetSelection(oldPage)
3423   
3424           
Note: See TracBrowser for help on using the repository browser.