source: MPbranch/GSASIIphsGUI.py @ 516

Last change on this file since 516 was 486, checked in by vondreele, 13 years ago

edit help & fix references to it
begin implementation of Fourier calcs.

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