source: trunk/GSASIIphsGUI.py @ 701

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

change Hessian progress bar dialog
fix crash in General cell & isotope editing
avoid error in reflection list

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