source: trunk/GSASIIphsGUI.py @ 527

Last change on this file since 527 was 527, checked in by vondreele, 11 years ago

more on map peak fitting
add a global for htmlFirstUse
fix periodic table display in unix/linux
fix setting of atom type in linux

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