source: trunk/GSASIIphsGUI.py @ 702

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

fix up the drawing options window

  • Property svn:keywords set to Date Author Revision URL Id
File size: 199.5 KB
Line 
1# -*- coding: utf-8 -*-
2#GSASII - phase data display routines
3########### SVN repository information ###################
4# $Date: 2012-08-09 15:26:38 +0000 (Thu, 09 Aug 2012) $
5# $Author: vondreele $
6# $Revision: 702 $
7# $URL: trunk/GSASIIphsGUI.py $
8# $Id: GSASIIphsGUI.py 702 2012-08-09 15:26:38Z 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: 702 $")
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.BoxSizer(wx.VERTICAL)           
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           
2503            lineSizer.Add(wx.StaticText(dataDisplay,-1,' View Point:'),0,wx.ALIGN_CENTER_VERTICAL)
2504            VP = drawingData['viewPoint'][0]
2505            viewPoint = wx.TextCtrl(dataDisplay,value='%.3f, %.3f, %.3f'%(VP[0],VP[1],VP[2]),
2506                style=wx.TE_READONLY,size=wx.Size(140,20),name='viewPoint')
2507            viewPoint.SetBackgroundColour(VERY_LIGHT_GREY)
2508            lineSizer.Add(viewPoint,0,wx.ALIGN_CENTER_VERTICAL)
2509            showSizer.Add(lineSizer)
2510            showSizer.Add((0,5),0)
2511           
2512            line2Sizer = wx.BoxSizer(wx.HORIZONTAL)
2513            showABC = wx.CheckBox(dataDisplay,-1,label=' Show test point?')
2514            showABC.Bind(wx.EVT_CHECKBOX, OnShowABC)
2515            showABC.SetValue(drawingData['showABC'])
2516            line2Sizer.Add(showABC,0,wx.ALIGN_CENTER_VERTICAL)
2517   
2518            unitCellBox = wx.CheckBox(dataDisplay,-1,label=' Show unit cell?')
2519            unitCellBox.Bind(wx.EVT_CHECKBOX, OnShowUnitCell)
2520            unitCellBox.SetValue(drawingData['unitCellBox'])
2521            line2Sizer.Add(unitCellBox,0,wx.ALIGN_CENTER_VERTICAL)
2522   
2523            showHydrogen = wx.CheckBox(dataDisplay,-1,label=' Show hydrogens?')
2524            showHydrogen.Bind(wx.EVT_CHECKBOX, OnShowHyd)
2525            showHydrogen.SetValue(drawingData['showHydrogen'])
2526            line2Sizer.Add(showHydrogen,0,wx.ALIGN_CENTER_VERTICAL)
2527            showSizer.Add(line2Sizer)
2528            return showSizer
2529           
2530        def RadSizer():
2531           
2532            def OnSizeHatoms(event):
2533                try:
2534                    value = max(0.1,min(1.2,float(sizeH.GetValue())))
2535                except ValueError:
2536                    value = 0.5
2537                drawingData['sizeH'] = value
2538                sizeH.SetValue("%.2f"%(value))
2539                G2plt.PlotStructure(G2frame,data)
2540               
2541            def OnRadFactor(event):
2542                try:
2543                    value = max(0.1,min(1.2,float(radFactor.GetValue())))
2544                except ValueError:
2545                    value = 0.85
2546                drawingData['radiusFactor'] = value
2547                radFactor.SetValue("%.2f"%(value))
2548                FindBondsDraw()
2549                G2plt.PlotStructure(G2frame,data)
2550           
2551            radSizer = wx.BoxSizer(wx.HORIZONTAL)
2552            radSizer.Add(wx.StaticText(dataDisplay,-1,' Hydrogen radius, A:  '),0,wx.ALIGN_CENTER_VERTICAL)
2553            sizeH = wx.TextCtrl(dataDisplay,-1,value='%.2f'%(drawingData['sizeH']),size=wx.Size(60,20),style=wx.TE_PROCESS_ENTER)
2554            sizeH.Bind(wx.EVT_TEXT_ENTER,OnSizeHatoms)
2555            sizeH.Bind(wx.EVT_KILL_FOCUS,OnSizeHatoms)
2556            radSizer.Add(sizeH,0,wx.ALIGN_CENTER_VERTICAL)
2557   
2558            radSizer.Add(wx.StaticText(dataDisplay,-1,' Bond search factor:  '),0,wx.ALIGN_CENTER_VERTICAL)
2559            radFactor = wx.TextCtrl(dataDisplay,value='%.2f'%(drawingData['radiusFactor']),size=wx.Size(60,20),style=wx.TE_PROCESS_ENTER)
2560            radFactor.Bind(wx.EVT_TEXT_ENTER,OnRadFactor)
2561            radFactor.Bind(wx.EVT_KILL_FOCUS,OnRadFactor)
2562            radSizer.Add(radFactor,0,wx.ALIGN_CENTER_VERTICAL)
2563            return radSizer
2564
2565        drawOptions.DestroyChildren()
2566        dataDisplay = wx.Panel(drawOptions)
2567        mainSizer = wx.BoxSizer(wx.VERTICAL)
2568        mainSizer.Add((5,5),0)
2569        mainSizer.Add(wx.StaticText(dataDisplay,-1,' Drawing controls:'),0,wx.ALIGN_CENTER_VERTICAL)
2570        mainSizer.Add((5,5),0)       
2571        mainSizer.Add(SlopSizer(),0)
2572        mainSizer.Add((5,5),0)
2573        mainSizer.Add(ShowSizer(),0,)
2574        mainSizer.Add((5,5),0)
2575        mainSizer.Add(RadSizer(),0,)
2576
2577        dataDisplay.SetSizer(mainSizer)
2578        Size = mainSizer.Fit(G2frame.dataFrame)
2579        Size[1] += 30                           #compensate for status bar
2580        dataDisplay.SetSize(Size)
2581        G2frame.dataFrame.setSizePosLeft(Size)
2582
2583################################################################################
2584####  Texture routines
2585################################################################################
2586       
2587    def UpdateTexture():
2588        generalData = data['General']       
2589        SGData = generalData['SGData']
2590        try:
2591            textureData = generalData['SH Texture']
2592        except KeyError:            #fix old files!
2593            textureData = generalData['SH Texture'] = {'Order':0,'Model':'cylindrical',
2594                'Sample omega':[False,0.0],'Sample chi':[False,0.0],'Sample phi':[False,0.0],
2595                'SH Coeff':[False,{}],'SHShow':False,'PFhkl':[0,0,1],
2596                'PFxyz':[0,0,1.],'PlotType':'Pole figure'}
2597        if 'SHShow' not in textureData:     #another fix
2598            textureData.update({'SHShow':False,'PFhkl':[0,0,1],'PFxyz':[0,0,1.],'PlotType':'Pole figure'})
2599        try:                        #another fix!
2600            x = textureData['PlotType']
2601        except KeyError:
2602            textureData.update({'PFxyz':[0,0,1.],'PlotType':'Pole figure'})
2603        shModels = ['cylindrical','none','shear - 2/m','rolling - mmm']
2604        SamSym = dict(zip(shModels,['0','-1','2/m','mmm']))
2605        if generalData['doPawley'] and G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Sequental results'):
2606            G2frame.dataFrame.RefineTexture.Enable(True)
2607        shAngles = ['omega','chi','phi']
2608       
2609        def SetSHCoef():
2610            cofNames = G2lat.GenSHCoeff(SGData['SGLaue'],SamSym[textureData['Model']],textureData['Order'])
2611            newSHCoef = dict(zip(cofNames,np.zeros(len(cofNames))))
2612            SHCoeff = textureData['SH Coeff'][1]
2613            for cofName in SHCoeff:
2614                if cofName in  cofNames:
2615                    newSHCoef[cofName] = SHCoeff[cofName]
2616            return newSHCoef
2617       
2618        def OnShOrder(event):
2619            Obj = event.GetEventObject()
2620            textureData['Order'] = int(Obj.GetValue())
2621            textureData['SH Coeff'][1] = SetSHCoef()
2622            wx.CallAfter(UpdateTexture)
2623            G2plt.PlotTexture(G2frame,data)
2624                       
2625        def OnShModel(event):
2626            Obj = event.GetEventObject()
2627            textureData['Model'] = Obj.GetValue()
2628            textureData['SH Coeff'][1] = SetSHCoef()
2629            wx.CallAfter(UpdateTexture)
2630            G2plt.PlotTexture(G2frame,data)
2631           
2632        def OnSHRefine(event):
2633            Obj = event.GetEventObject()
2634            textureData['SH Coeff'][0] = Obj.GetValue()
2635           
2636        def OnSHShow(event):
2637            Obj = event.GetEventObject()
2638            textureData['SHShow'] = Obj.GetValue()
2639            wx.CallAfter(UpdateTexture)
2640           
2641        def OnProjSel(event):
2642            Obj = event.GetEventObject()
2643            G2frame.Projection = Obj.GetValue()
2644            G2plt.PlotTexture(G2frame,data)
2645           
2646        def OnColorSel(event):
2647            Obj = event.GetEventObject()
2648            G2frame.ContourColor = Obj.GetValue()
2649            G2plt.PlotTexture(G2frame,data)
2650           
2651        def OnAngRef(event):
2652            Obj = event.GetEventObject()
2653            textureData[angIndx[Obj.GetId()]][0] = Obj.GetValue()
2654           
2655        def OnAngValue(event):
2656            Obj = event.GetEventObject()
2657            try:
2658                value =  float(Obj.GetValue())
2659            except ValueError:
2660                value = textureData[valIndx[Obj.GetId()]][1]
2661            Obj.SetValue('%8.2f'%(value))
2662            textureData[valIndx[Obj.GetId()]][1] = value
2663           
2664        def OnODFValue(event): 
2665            Obj = event.GetEventObject()
2666            try:
2667                value =  float(Obj.GetValue())
2668            except ValueError:
2669                value = textureData['SH Coeff'][1][ODFIndx[Obj.GetId()]]
2670            Obj.SetValue('%8.3f'%(value))
2671            textureData['SH Coeff'][1][ODFIndx[Obj.GetId()]] = value
2672            G2plt.PlotTexture(G2frame,data)
2673           
2674        def OnPfType(event):
2675            Obj = event.GetEventObject()
2676            textureData['PlotType'] = Obj.GetValue()
2677            wx.CallAfter(UpdateTexture)
2678            G2plt.PlotTexture(G2frame,data)
2679           
2680        def OnPFValue(event):
2681            Obj = event.GetEventObject()
2682            Saxis = Obj.GetValue().split()
2683            if textureData['PlotType'] in ['Pole figure','Axial pole distribution']:               
2684                try:
2685                    hkl = [int(Saxis[i]) for i in range(3)]
2686                except (ValueError,IndexError):
2687                    hkl = textureData['PFhkl']
2688                if not np.any(np.array(hkl)):       #can't be all zeros!
2689                    hkl = textureData['PFhkl']
2690                Obj.SetValue('%d %d %d'%(hkl[0],hkl[1],hkl[2]))
2691                textureData['PFhkl'] = hkl
2692            else:
2693                try:
2694                    xyz = [float(Saxis[i]) for i in range(3)]
2695                except (ValueError,IndexError):
2696                    xyz = textureData['PFxyz']
2697                if not np.any(np.array(xyz)):       #can't be all zeros!
2698                    xyz = textureData['PFxyz']
2699                Obj.SetValue('%3.1f %3.1f %3.1f'%(xyz[0],xyz[1],xyz[2]))
2700                textureData['PFxyz'] = xyz
2701            G2plt.PlotTexture(G2frame,data)
2702
2703        if Texture.GetSizer():
2704            Texture.GetSizer().Clear(True)
2705        mainSizer = wx.BoxSizer(wx.VERTICAL)
2706        titleSizer = wx.BoxSizer(wx.HORIZONTAL)
2707        titleSizer.Add(wx.StaticText(Texture,-1,'Spherical harmonics texture data for '+PhaseName+':'),0,wx.ALIGN_CENTER_VERTICAL)
2708        titleSizer.Add(wx.StaticText(Texture,-1,
2709            ' Texture Index J = %7.3f'%(G2lat.textureIndex(textureData['SH Coeff'][1]))),
2710            0,wx.ALIGN_CENTER_VERTICAL)
2711        mainSizer.Add(titleSizer,0)
2712        mainSizer.Add((0,5),0)
2713        shSizer = wx.FlexGridSizer(1,6,5,5)
2714        shSizer.Add(wx.StaticText(Texture,-1,'Texture model: '),0,wx.ALIGN_CENTER_VERTICAL)
2715        shModel = wx.ComboBox(Texture,-1,value=textureData['Model'],choices=shModels,
2716            style=wx.CB_READONLY|wx.CB_DROPDOWN)
2717        shModel.Bind(wx.EVT_COMBOBOX,OnShModel)
2718        shSizer.Add(shModel,0,wx.ALIGN_CENTER_VERTICAL)
2719        shSizer.Add(wx.StaticText(Texture,-1,'  Harmonic order: '),0,wx.ALIGN_CENTER_VERTICAL)
2720        shOrder = wx.ComboBox(Texture,-1,value=str(textureData['Order']),choices=[str(2*i) for i in range(18)],
2721            style=wx.CB_READONLY|wx.CB_DROPDOWN)
2722        shOrder.Bind(wx.EVT_COMBOBOX,OnShOrder)
2723        shSizer.Add(shOrder,0,wx.ALIGN_CENTER_VERTICAL)
2724        shRef = wx.CheckBox(Texture,-1,label=' Refine texture?')
2725        shRef.SetValue(textureData['SH Coeff'][0])
2726        shRef.Bind(wx.EVT_CHECKBOX, OnSHRefine)
2727        shSizer.Add(shRef,0,wx.ALIGN_CENTER_VERTICAL)
2728        shShow = wx.CheckBox(Texture,-1,label=' Show coeff.?')
2729        shShow.SetValue(textureData['SHShow'])
2730        shShow.Bind(wx.EVT_CHECKBOX, OnSHShow)
2731        shSizer.Add(shShow,0,wx.ALIGN_CENTER_VERTICAL)
2732        mainSizer.Add(shSizer,0,0)
2733        mainSizer.Add((0,5),0)
2734        PTSizer = wx.FlexGridSizer(2,4,5,5)
2735        PTSizer.Add(wx.StaticText(Texture,-1,' Texture plot type: '),0,wx.ALIGN_CENTER_VERTICAL)
2736        choices = ['Axial pole distribution','Pole figure','Inverse pole figure']           
2737        pfType = wx.ComboBox(Texture,-1,value=str(textureData['PlotType']),choices=choices,
2738            style=wx.CB_READONLY|wx.CB_DROPDOWN)
2739        pfType.Bind(wx.EVT_COMBOBOX,OnPfType)
2740        PTSizer.Add(pfType,0,wx.ALIGN_CENTER_VERTICAL)
2741        if 'Axial' not in textureData['PlotType']:
2742            PTSizer.Add(wx.StaticText(Texture,-1,' Projection type: '),0,wx.ALIGN_CENTER_VERTICAL)
2743            projSel = wx.ComboBox(Texture,-1,value=G2frame.Projection,choices=['equal area','stereographic','3D display'],
2744                style=wx.CB_READONLY|wx.CB_DROPDOWN)
2745            projSel.Bind(wx.EVT_COMBOBOX,OnProjSel)
2746            PTSizer.Add(projSel,0,wx.ALIGN_CENTER_VERTICAL)
2747        if textureData['PlotType'] in ['Pole figure','Axial pole distribution']:
2748            PTSizer.Add(wx.StaticText(Texture,-1,' Pole figure HKL: '),0,wx.ALIGN_CENTER_VERTICAL)
2749            PH = textureData['PFhkl']
2750            pfVal = wx.TextCtrl(Texture,-1,'%d %d %d'%(PH[0],PH[1],PH[2]),style=wx.TE_PROCESS_ENTER)
2751        else:
2752            PTSizer.Add(wx.StaticText(Texture,-1,' Inverse pole figure XYZ: '),0,wx.ALIGN_CENTER_VERTICAL)
2753            PX = textureData['PFxyz']
2754            pfVal = wx.TextCtrl(Texture,-1,'%3.1f %3.1f %3.1f'%(PX[0],PX[1],PX[2]),style=wx.TE_PROCESS_ENTER)
2755        pfVal.Bind(wx.EVT_TEXT_ENTER,OnPFValue)
2756        pfVal.Bind(wx.EVT_KILL_FOCUS,OnPFValue)
2757        PTSizer.Add(pfVal,0,wx.ALIGN_CENTER_VERTICAL)
2758        if 'Axial' not in textureData['PlotType']:
2759            PTSizer.Add(wx.StaticText(Texture,-1,' Color scheme'),0,wx.ALIGN_CENTER_VERTICAL)
2760            choice = [m for m in mpl.cm.datad.keys() if not m.endswith("_r")]
2761            choice.sort()
2762            colorSel = wx.ComboBox(Texture,-1,value=G2frame.ContourColor,choices=choice,
2763                style=wx.CB_READONLY|wx.CB_DROPDOWN)
2764            colorSel.Bind(wx.EVT_COMBOBOX,OnColorSel)
2765            PTSizer.Add(colorSel,0,wx.ALIGN_CENTER_VERTICAL)       
2766        mainSizer.Add(PTSizer,0,wx.ALIGN_CENTER_VERTICAL)
2767        mainSizer.Add((0,5),0)
2768        if textureData['SHShow']:
2769            mainSizer.Add(wx.StaticText(Texture,-1,'Spherical harmonic coefficients: '),0,wx.ALIGN_CENTER_VERTICAL)
2770            mainSizer.Add((0,5),0)
2771            ODFSizer = wx.FlexGridSizer(2,8,2,2)
2772            ODFIndx = {}
2773            ODFkeys = textureData['SH Coeff'][1].keys()
2774            ODFkeys.sort()
2775            for item in ODFkeys:
2776                ODFSizer.Add(wx.StaticText(Texture,-1,item),0,wx.ALIGN_CENTER_VERTICAL)
2777                ODFval = wx.TextCtrl(Texture,wx.ID_ANY,'%8.3f'%(textureData['SH Coeff'][1][item]),style=wx.TE_PROCESS_ENTER)
2778                ODFIndx[ODFval.GetId()] = item
2779                ODFval.Bind(wx.EVT_TEXT_ENTER,OnODFValue)
2780                ODFval.Bind(wx.EVT_KILL_FOCUS,OnODFValue)
2781                ODFSizer.Add(ODFval,0,wx.ALIGN_CENTER_VERTICAL)
2782            mainSizer.Add(ODFSizer,0,wx.ALIGN_CENTER_VERTICAL)
2783            mainSizer.Add((0,5),0)
2784        mainSizer.Add((0,5),0)
2785        mainSizer.Add(wx.StaticText(Texture,-1,'Sample orientation angles: '),0,wx.ALIGN_CENTER_VERTICAL)
2786        mainSizer.Add((0,5),0)
2787        angSizer = wx.BoxSizer(wx.HORIZONTAL)
2788        angIndx = {}
2789        valIndx = {}
2790        for item in ['Sample omega','Sample chi','Sample phi']:
2791            angRef = wx.CheckBox(Texture,-1,label=item+': ')
2792            angRef.SetValue(textureData[item][0])
2793            angIndx[angRef.GetId()] = item
2794            angRef.Bind(wx.EVT_CHECKBOX, OnAngRef)
2795            angSizer.Add(angRef,0,wx.ALIGN_CENTER_VERTICAL)
2796            angVal = wx.TextCtrl(Texture,wx.ID_ANY,'%8.2f'%(textureData[item][1]),style=wx.TE_PROCESS_ENTER)
2797            valIndx[angVal.GetId()] = item
2798            angVal.Bind(wx.EVT_TEXT_ENTER,OnAngValue)
2799            angVal.Bind(wx.EVT_KILL_FOCUS,OnAngValue)
2800            angSizer.Add(angVal,0,wx.ALIGN_CENTER_VERTICAL)
2801            angSizer.Add((5,0),0)
2802        mainSizer.Add(angSizer,0,wx.ALIGN_CENTER_VERTICAL)
2803        Texture.SetSizer(mainSizer,True)
2804        mainSizer.Fit(G2frame.dataFrame)
2805        Size = mainSizer.GetMinSize()
2806        Size[0] += 40
2807        Size[1] = max(Size[1],250) + 20
2808        Texture.SetSize(Size)
2809        Texture.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
2810        Size[1] = min(Size[1],450)
2811        G2frame.dataFrame.setSizePosLeft(Size)
2812
2813################################################################################
2814##### DData routines
2815################################################################################
2816       
2817    def UpdateDData():
2818        UseList = data['Histograms']
2819        if UseList:
2820            G2frame.dataFrame.DataMenu.Enable(G2gd.wxID_DATADELETE,True)
2821            G2frame.Refine.Enable(True)
2822        else:
2823            G2frame.dataFrame.DataMenu.Enable(G2gd.wxID_DATADELETE,False)
2824            G2frame.Refine.Enable(False)           
2825        generalData = data['General']       
2826        SGData = generalData['SGData']
2827        keyList = UseList.keys()
2828        keyList.sort()
2829        PWDR = any(['PWDR' in item for item in keyList])
2830        Indx = {}
2831       
2832        def PlotSizer():
2833
2834            def OnPlotSel(event):
2835                Obj = event.GetEventObject()
2836                generalData['Data plot type'] = Obj.GetStringSelection()
2837                wx.CallAfter(UpdateDData)
2838                G2plt.PlotSizeStrainPO(G2frame,data)
2839               
2840            def OnPOhkl(event):
2841                Obj = event.GetEventObject()
2842                Saxis = Obj.GetValue().split()
2843                try:
2844                    hkl = [int(Saxis[i]) for i in range(3)]
2845                except (ValueError,IndexError):
2846                    hkl = generalData['POhkl']
2847                if not np.any(np.array(hkl)):
2848                    hkl = generalData['POhkl']
2849                generalData['POhkl'] = hkl
2850                h,k,l = hkl
2851                Obj.SetValue('%3d %3d %3d'%(h,k,l)) 
2852                G2plt.PlotSizeStrainPO(G2frame,data)
2853           
2854            plotSizer = wx.BoxSizer(wx.VERTICAL)
2855            choice = ['None','Mustrain','Size','Preferred orientation']
2856            plotSel = wx.RadioBox(DData,-1,'Select plot type:',choices=choice,
2857                majorDimension=2,style=wx.RA_SPECIFY_COLS)
2858            plotSel.SetStringSelection(generalData['Data plot type'])
2859            plotSel.Bind(wx.EVT_RADIOBOX,OnPlotSel)   
2860            plotSizer.Add(plotSel)
2861            if generalData['Data plot type'] == 'Preferred orientation':
2862                POhklSizer = wx.BoxSizer(wx.HORIZONTAL)
2863                POhklSizer.Add(wx.StaticText(DData,-1,' Plot preferred orientation for H K L: '),0,wx.ALIGN_CENTER_VERTICAL)
2864                h,k,l = generalData['POhkl']
2865                poAxis = wx.TextCtrl(DData,-1,'%3d %3d %3d'%(h,k,l),style=wx.TE_PROCESS_ENTER)
2866                poAxis.Bind(wx.EVT_TEXT_ENTER,OnPOhkl)
2867                poAxis.Bind(wx.EVT_KILL_FOCUS,OnPOhkl)
2868                POhklSizer.Add(poAxis,0,wx.ALIGN_CENTER_VERTICAL)
2869                plotSizer.Add(POhklSizer)           
2870            return plotSizer
2871           
2872        def ScaleSizer():
2873           
2874            def OnScaleRef(event):
2875                Obj = event.GetEventObject()
2876                UseList[Indx[Obj.GetId()]]['Scale'][1] = Obj.GetValue()
2877               
2878            def OnScaleVal(event):
2879                Obj = event.GetEventObject()
2880                try:
2881                    scale = float(Obj.GetValue())
2882                    if scale > 0:
2883                        UseList[Indx[Obj.GetId()]]['Scale'][0] = scale
2884                except ValueError:
2885                    pass
2886                Obj.SetValue("%.4f"%(UseList[Indx[Obj.GetId()]]['Scale'][0]))          #reset in case of error
2887                           
2888            scaleSizer = wx.BoxSizer(wx.HORIZONTAL)
2889            if 'PWDR' in item:
2890                scaleRef = wx.CheckBox(DData,-1,label=' Phase fraction: ')
2891            elif 'HKLF' in item:
2892                scaleRef = wx.CheckBox(DData,-1,label=' Scale factor: ')               
2893            scaleRef.SetValue(UseList[item]['Scale'][1])
2894            Indx[scaleRef.GetId()] = item
2895            scaleRef.Bind(wx.EVT_CHECKBOX, OnScaleRef)
2896            scaleSizer.Add(scaleRef,0,wx.ALIGN_CENTER_VERTICAL)
2897            scaleVal = wx.TextCtrl(DData,wx.ID_ANY,
2898                '%.4f'%(UseList[item]['Scale'][0]),style=wx.TE_PROCESS_ENTER)
2899            Indx[scaleVal.GetId()] = item
2900            scaleVal.Bind(wx.EVT_TEXT_ENTER,OnScaleVal)
2901            scaleVal.Bind(wx.EVT_KILL_FOCUS,OnScaleVal)
2902            scaleSizer.Add(scaleVal,0,wx.ALIGN_CENTER_VERTICAL)
2903            return scaleSizer
2904           
2905        def OnUseData(event):
2906            Obj = event.GetEventObject()
2907            hist = Indx[Obj.GetId()]
2908            UseList[hist]['Use'] = Obj.GetValue()
2909           
2910        def OnShowData(event):
2911            Obj = event.GetEventObject()
2912            hist = Indx[Obj.GetId()]
2913            UseList[hist]['Show'] = Obj.GetValue()
2914            wx.CallAfter(UpdateDData)
2915            G2plt.PlotSizeStrainPO(G2frame,data)
2916           
2917        def OnCopyData(event):
2918            #how about HKLF data? This is only for PWDR data
2919            Obj = event.GetEventObject()
2920            hist = Indx[Obj.GetId()]
2921            sourceDict = UseList[hist]
2922            copyNames = ['Scale','Pref.Ori.','Size','Mustrain','HStrain','Extinction']
2923            copyDict = {}
2924            for name in copyNames: 
2925                copyDict[name] = copy.deepcopy(sourceDict[name])        #force copy
2926            keyList = ['All',]+UseList.keys()
2927            if UseList:
2928                copyList = []
2929                dlg = wx.MultiChoiceDialog(G2frame, 
2930                    'Copy parameters to which histograms?', 'Copy parameters', 
2931                    keyList, wx.CHOICEDLG_STYLE)
2932                try:
2933                    if dlg.ShowModal() == wx.ID_OK:
2934                        result = dlg.GetSelections()
2935                        for i in result: 
2936                            copyList.append(keyList[i])
2937                        if 'All' in copyList: 
2938                            copyList = keyList[1:]
2939                        for item in copyList:
2940                            UseList[item].update(copy.deepcopy(copyDict))
2941                        wx.CallAfter(UpdateDData)
2942                finally:
2943                    dlg.Destroy()
2944                   
2945        def OnCopyFlags(event):
2946            Obj = event.GetEventObject()
2947            hist = Indx[Obj.GetId()]
2948            sourceDict = UseList[hist]
2949            copyDict = {}
2950            copyNames = ['Scale','Pref.Ori.','Size','Mustrain','HStrain','Extinction']
2951            for name in copyNames:
2952                if name in ['Scale','Extinction','HStrain']:
2953                    copyDict[name] = sourceDict[name][1]
2954                elif name in ['Size','Mustrain']:
2955                    copyDict[name] = [sourceDict[name][0],sourceDict[name][2],sourceDict[name][4]]
2956                elif name == 'Pref.Ori.':
2957                    copyDict[name] = [sourceDict[name][0],sourceDict[name][2]]
2958                    if sourceDict[name][0] == 'SH':
2959                        SHterms = sourceDict[name][5]
2960                        SHflags = {}
2961                        for item in SHterms:
2962                            SHflags[item] = SHterms[item][1]
2963                        copyDict[name].append(SHflags)                       
2964            keyList = ['All',]+UseList.keys()
2965            if UseList:
2966                copyList = []
2967                dlg = wx.MultiChoiceDialog(G2frame, 
2968                    'Copy parameters to which histograms?', 'Copy parameters', 
2969                    keyList, wx.CHOICEDLG_STYLE)
2970                try:
2971                    if dlg.ShowModal() == wx.ID_OK:
2972                        result = dlg.GetSelections()
2973                        for i in result: 
2974                            copyList.append(keyList[i])
2975                        if 'All' in copyList: 
2976                            copyList = keyList[1:]
2977                        for item in copyList:
2978                            UseList[item]                           
2979                            for name in copyNames:
2980                                if name in ['Scale','Extinction','HStrain']:
2981                                    UseList[item][name][1] = copy.copy(copyDict[name])
2982                                elif name in ['Size','Mustrain']:
2983                                    UseList[item][name][0] = copy.copy(copyDict[name][0])
2984                                    UseList[item][name][2] = copy.copy(copyDict[name][1])
2985                                    UseList[item][name][4] = copy.copy(copyDict[name][2])
2986                                elif name == 'Pref.Ori.':
2987                                    UseList[item][name][0] = copy.copy(copyDict[name][0])
2988                                    UseList[item][name][2] = copy.copy(copyDict[name][1])
2989                                    if sourceDict[name][0] == 'SH':
2990                                        SHflags = copy.copy(copyDict[name][2])
2991                                        SHterms = copy.copy(sourceDict[name][5])
2992                                        for item in SHflags:
2993                                            SHterms[item][1] = copy.copy(SHflags[item])                                             
2994                        wx.CallAfter(UpdateDData)
2995                finally:
2996                    dlg.Destroy()
2997           
2998           
2999        def OnLGmixRef(event):
3000            Obj = event.GetEventObject()
3001            hist,name = Indx[Obj.GetId()]
3002            UseList[hist][name][2][2] = Obj.GetValue()
3003           
3004        def OnLGmixVal(event):
3005            Obj = event.GetEventObject()
3006            hist,name = Indx[Obj.GetId()]
3007            try:
3008                value = float(Obj.GetValue())
3009                if 0.1 <= value <= 1:
3010                    UseList[hist][name][1][2] = value
3011                else:
3012                    raise ValueError
3013            except ValueError:
3014                pass
3015            Obj.SetValue("%.4f"%(UseList[hist][name][1][2]))          #reset in case of error
3016
3017        def OnSizeType(event):
3018            Obj = event.GetEventObject()
3019            hist = Indx[Obj.GetId()]
3020            UseList[hist]['Size'][0] = Obj.GetValue()
3021            G2plt.PlotSizeStrainPO(G2frame,data)
3022            wx.CallAfter(UpdateDData)
3023           
3024        def OnSizeRef(event):
3025            Obj = event.GetEventObject()
3026            hist,pid = Indx[Obj.GetId()]
3027            if UseList[hist]['Size'][0] == 'ellipsoidal':
3028                UseList[hist]['Size'][5][pid] = Obj.GetValue()               
3029            else:
3030                UseList[hist]['Size'][2][pid] = Obj.GetValue()
3031           
3032        def OnSizeVal(event):
3033            Obj = event.GetEventObject()
3034            hist,pid = Indx[Obj.GetId()]
3035            if UseList[hist]['Size'][0] == 'ellipsoidal':
3036                try:
3037                    size = float(Obj.GetValue())
3038                    if pid < 3 and size <= 0.001:            #10A lower limit!
3039                        raise ValueError
3040                    UseList[hist]['Size'][4][pid] = size                   
3041                except ValueError:
3042                    pass
3043                Obj.SetValue("%.3f"%(UseList[hist]['Size'][4][pid]))          #reset in case of error
3044            else:
3045                try:
3046                    size = float(Obj.GetValue())
3047                    if size <= 0.001:            #10A lower limit!
3048                        raise ValueError
3049                    UseList[hist]['Size'][1][pid] = size
3050                except ValueError:
3051                    pass
3052                Obj.SetValue("%.3f"%(UseList[hist]['Size'][1][pid]))          #reset in case of error
3053            G2plt.PlotSizeStrainPO(G2frame,data)
3054           
3055        def OnSizeAxis(event):           
3056            Obj = event.GetEventObject()
3057            hist = Indx[Obj.GetId()]
3058            Saxis = Obj.GetValue().split()
3059            try:
3060                hkl = [int(Saxis[i]) for i in range(3)]
3061            except (ValueError,IndexError):
3062                hkl = UseList[hist]['Size'][3]
3063            if not np.any(np.array(hkl)):
3064                hkl = UseList[hist]['Size'][3]
3065            UseList[hist]['Size'][3] = hkl
3066            h,k,l = hkl
3067            Obj.SetValue('%3d %3d %3d'%(h,k,l)) 
3068                       
3069        def OnStrainType(event):
3070            Obj = event.GetEventObject()
3071            hist = Indx[Obj.GetId()]
3072            UseList[hist]['Mustrain'][0] = Obj.GetValue()
3073            wx.CallAfter(UpdateDData)
3074            G2plt.PlotSizeStrainPO(G2frame,data)
3075           
3076        def OnStrainRef(event):
3077            Obj = event.GetEventObject()
3078            hist,pid = Indx[Obj.GetId()]
3079            if UseList[hist]['Mustrain'][0] == 'generalized':
3080                UseList[hist]['Mustrain'][5][pid] = Obj.GetValue()
3081            else:
3082                UseList[hist]['Mustrain'][2][pid] = Obj.GetValue()
3083           
3084        def OnStrainVal(event):
3085            Snames = G2spc.MustrainNames(SGData)
3086            Obj = event.GetEventObject()
3087            hist,pid = Indx[Obj.GetId()]
3088            try:
3089                strain = float(Obj.GetValue())
3090                if UseList[hist]['Mustrain'][0] == 'generalized':
3091                    if '4' in Snames[pid] and strain < 0:
3092                        raise ValueError
3093                    UseList[hist]['Mustrain'][4][pid] = strain
3094                else:
3095                    if strain <= 0:
3096                        raise ValueError
3097                    UseList[hist]['Mustrain'][1][pid] = strain
3098            except ValueError:
3099                pass
3100            if UseList[hist]['Mustrain'][0] == 'generalized':
3101                Obj.SetValue("%.3f"%(UseList[hist]['Mustrain'][4][pid]))          #reset in case of error
3102            else:
3103                Obj.SetValue("%.1f"%(UseList[hist]['Mustrain'][1][pid]))          #reset in case of error
3104            G2plt.PlotSizeStrainPO(G2frame,data)
3105           
3106        def OnStrainAxis(event):
3107            Obj = event.GetEventObject()
3108            hist = Indx[Obj.GetId()]
3109            Saxis = Obj.GetValue().split()
3110            try:
3111                hkl = [int(Saxis[i]) for i in range(3)]
3112            except (ValueError,IndexError):
3113                hkl = UseList[hist]['Mustrain'][3]
3114            if not np.any(np.array(hkl)):
3115                hkl = UseList[hist]['Mustrain'][3]
3116            UseList[hist]['Mustrain'][3] = hkl
3117            h,k,l = hkl
3118            Obj.SetValue('%3d %3d %3d'%(h,k,l)) 
3119            G2plt.PlotSizeStrainPO(G2frame,data)
3120           
3121        def OnHstrainRef(event):
3122            Obj = event.GetEventObject()
3123            hist,pid = Indx[Obj.GetId()]
3124            UseList[hist]['HStrain'][1][pid] = Obj.GetValue()
3125           
3126        def OnHstrainVal(event):
3127            Snames = G2spc.HStrainNames(SGData)
3128            Obj = event.GetEventObject()
3129            hist,pid = Indx[Obj.GetId()]
3130            try:
3131                strain = float(Obj.GetValue())
3132                UseList[hist]['HStrain'][0][pid] = strain
3133            except ValueError:
3134                pass
3135            Obj.SetValue("%.5f"%(UseList[hist]['HStrain'][0][pid]))          #reset in case of error
3136
3137        def OnPOVal(event):
3138            Obj = event.GetEventObject()
3139            hist = Indx[Obj.GetId()]
3140            try:
3141                mdVal = float(Obj.GetValue())
3142                if mdVal > 0:
3143                    UseList[hist]['Pref.Ori.'][1] = mdVal
3144            except ValueError:
3145                pass
3146            Obj.SetValue("%.3f"%(UseList[hist]['Pref.Ori.'][1]))          #reset in case of error
3147           
3148        def OnPOAxis(event):
3149            Obj = event.GetEventObject()
3150            hist = Indx[Obj.GetId()]
3151            Saxis = Obj.GetValue().split()
3152            try:
3153                hkl = [int(Saxis[i]) for i in range(3)]
3154            except (ValueError,IndexError):
3155                hkl = UseList[hist]['Pref.Ori.'][3]
3156            if not np.any(np.array(hkl)):
3157                hkl = UseList[hist]['Pref.Ori.'][3]
3158            UseList[hist]['Pref.Ori.'][3] = hkl
3159            h,k,l = hkl
3160            Obj.SetValue('%3d %3d %3d'%(h,k,l)) 
3161           
3162        def OnPOOrder(event):
3163            Obj = event.GetEventObject()
3164            hist = Indx[Obj.GetId()]
3165            Order = int(Obj.GetValue())
3166            UseList[hist]['Pref.Ori.'][4] = Order
3167            UseList[hist]['Pref.Ori.'][5] = SetPOCoef(Order,hist)
3168            wx.CallAfter(UpdateDData)
3169
3170        def OnPOType(event):
3171            Obj = event.GetEventObject()
3172            hist = Indx[Obj.GetId()]
3173            if 'March' in Obj.GetValue():
3174                UseList[hist]['Pref.Ori.'][0] = 'MD'
3175            else:
3176                UseList[hist]['Pref.Ori.'][0] = 'SH'
3177            wx.CallAfter(UpdateDData)           
3178   
3179        def OnPORef(event):
3180            Obj = event.GetEventObject()
3181            hist = Indx[Obj.GetId()]
3182            UseList[hist]['Pref.Ori.'][2] = Obj.GetValue()
3183               
3184        def SetPOCoef(Order,hist):
3185            cofNames = G2lat.GenSHCoeff(SGData['SGLaue'],'0',Order,False)     #cylindrical & no M
3186            newPOCoef = dict(zip(cofNames,np.zeros(len(cofNames))))
3187            POCoeff = UseList[hist]['Pref.Ori.'][5]
3188            for cofName in POCoeff:
3189                if cofName in  cofNames:
3190                    newPOCoef[cofName] = POCoeff[cofName]
3191            return newPOCoef
3192       
3193        def OnExtRef(event):
3194            Obj = event.GetEventObject()
3195            UseList[Indx[Obj.GetId()]]['Extinction'][1] = Obj.GetValue()
3196           
3197        def OnExtVal(event):
3198            Obj = event.GetEventObject()
3199            try:
3200                ext = float(Obj.GetValue())
3201                if ext >= 0:
3202                    UseList[Indx[Obj.GetId()]]['Extinction'][0] = ext
3203            except ValueError:
3204                pass
3205            Obj.SetValue("%.2f"%(UseList[Indx[Obj.GetId()]]['Extinction'][0]))
3206           
3207        def OnTbarVal(event):
3208            Obj = event.GetEventObject()
3209            try:
3210                tbar = float(Obj.GetValue())
3211                if tbar >= 0:
3212                    UseList[Indx[Obj.GetId()]]['Extinction'][2]['Tbar'] = tbar
3213            except ValueError:
3214                pass
3215            Obj.SetValue("%.2f"%(UseList[Indx[Obj.GetId()]]['Extinction'][2]['Tbar']))
3216           
3217        def OnEval(event):
3218            Obj = event.GetEventObject()
3219            item = Indx[Obj.GetId()]
3220            try:
3221                val = float(Obj.GetValue())
3222                if val >= 0:
3223                    UseList[item[0]]['Extinction'][2][item[1]][0] = val
3224            except ValueError:
3225                pass
3226            Obj.SetValue("%9.3g"%(UseList[item[0]]['Extinction'][2][item[1]][0]))
3227           
3228        def OnEref(event):
3229            Obj = event.GetEventObject()
3230            item = Indx[Obj.GetId()]
3231            UseList[item[0]]['Extinction'][2][item[1]][1] = Obj.GetValue()
3232
3233        def OnSCExtType(event):
3234            Obj = event.GetEventObject()
3235            item = Indx[Obj.GetId()]
3236            UseList[item[0]]['Extinction'][item[1]] = Obj.GetValue()
3237            wx.CallAfter(UpdateDData)
3238               
3239        def checkAxis(axis):
3240            if not np.any(np.array(axis)):
3241                return False
3242            return axis
3243           
3244        def TopSizer(name,choices,parm,OnType):
3245            topSizer = wx.BoxSizer(wx.HORIZONTAL)
3246            topSizer.Add(wx.StaticText(DData,-1,name),0,wx.ALIGN_CENTER_VERTICAL)
3247            sizeType = wx.ComboBox(DData,wx.ID_ANY,value=UseList[item][parm][0],choices=choices,
3248                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3249            sizeType.Bind(wx.EVT_COMBOBOX, OnType)
3250            Indx[sizeType.GetId()] = item
3251            topSizer.Add(sizeType)
3252            topSizer.Add((5,0),0)
3253            return topSizer
3254           
3255        def LGmixSizer(name,OnVal,OnRef):
3256            lgmixSizer = wx.BoxSizer(wx.HORIZONTAL)
3257            lgmixRef = wx.CheckBox(DData,-1,label='LGmix')
3258            lgmixRef.thisown = False
3259            lgmixRef.SetValue(UseList[item][name][2][2])
3260            Indx[lgmixRef.GetId()] = [item,name]
3261            lgmixRef.Bind(wx.EVT_CHECKBOX, OnRef)
3262            lgmixSizer.Add(lgmixRef,0,wx.ALIGN_CENTER_VERTICAL)
3263            lgmixVal = wx.TextCtrl(DData,wx.ID_ANY,
3264                '%.4f'%(UseList[item][name][1][2]),style=wx.TE_PROCESS_ENTER)
3265            Indx[lgmixVal.GetId()] = [item,name]
3266            lgmixVal.Bind(wx.EVT_TEXT_ENTER,OnVal)
3267            lgmixVal.Bind(wx.EVT_KILL_FOCUS,OnVal)
3268            lgmixSizer.Add(lgmixVal,0,wx.ALIGN_CENTER_VERTICAL)
3269            return lgmixSizer
3270                       
3271        def IsoSizer(name,parm,fmt,OnVal,OnRef):
3272            isoSizer = wx.BoxSizer(wx.HORIZONTAL)
3273            sizeRef = wx.CheckBox(DData,-1,label=name)
3274            sizeRef.thisown = False
3275            sizeRef.SetValue(UseList[item][parm][2][0])
3276            Indx[sizeRef.GetId()] = [item,0]
3277            sizeRef.Bind(wx.EVT_CHECKBOX, OnRef)
3278            isoSizer.Add(sizeRef,0,wx.ALIGN_CENTER_VERTICAL)
3279            sizeVal = wx.TextCtrl(DData,wx.ID_ANY,
3280                fmt%(UseList[item][parm][1][0]),style=wx.TE_PROCESS_ENTER)
3281            Indx[sizeVal.GetId()] = [item,0]
3282            sizeVal.Bind(wx.EVT_TEXT_ENTER,OnVal)
3283            sizeVal.Bind(wx.EVT_KILL_FOCUS,OnVal)
3284            isoSizer.Add(sizeVal,0,wx.ALIGN_CENTER_VERTICAL)
3285            return isoSizer
3286           
3287        def UniSizer(parm,OnAxis):
3288            uniSizer = wx.BoxSizer(wx.HORIZONTAL)
3289            uniSizer.Add(wx.StaticText(DData,-1,' Unique axis, H K L: '),0,wx.ALIGN_CENTER_VERTICAL)
3290            h,k,l = UseList[item][parm][3]
3291            Axis = wx.TextCtrl(DData,-1,'%3d %3d %3d'%(h,k,l),style=wx.TE_PROCESS_ENTER)
3292            Indx[Axis.GetId()] = item
3293            Axis.Bind(wx.EVT_TEXT_ENTER,OnAxis)
3294            Axis.Bind(wx.EVT_KILL_FOCUS,OnAxis)
3295            uniSizer.Add(Axis,0,wx.ALIGN_CENTER_VERTICAL)
3296            return uniSizer
3297           
3298        def UniDataSizer(parmName,parm,fmt,OnVal,OnRef):
3299            dataSizer = wx.BoxSizer(wx.HORIZONTAL)
3300            parms = zip([' Equatorial '+parmName,' Axial '+parmName],
3301                UseList[item][parm][1],UseList[item][parm][2],range(2))
3302            for Pa,val,ref,id in parms:
3303                sizeRef = wx.CheckBox(DData,-1,label=Pa)
3304                sizeRef.thisown = False
3305                sizeRef.SetValue(ref)
3306                Indx[sizeRef.GetId()] = [item,id]
3307                sizeRef.Bind(wx.EVT_CHECKBOX, OnRef)
3308                dataSizer.Add(sizeRef,0,wx.ALIGN_CENTER_VERTICAL)
3309                sizeVal = wx.TextCtrl(DData,wx.ID_ANY,fmt%(val),style=wx.TE_PROCESS_ENTER)
3310                Indx[sizeVal.GetId()] = [item,id]
3311                sizeVal.Bind(wx.EVT_TEXT_ENTER,OnVal)
3312                sizeVal.Bind(wx.EVT_KILL_FOCUS,OnVal)
3313                dataSizer.Add(sizeVal,0,wx.ALIGN_CENTER_VERTICAL)
3314                dataSizer.Add((5,0),0)
3315            return dataSizer
3316           
3317        def EllSizeDataSizer():
3318            parms = zip(['S11','S22','S33','S12','S13','S23'],UseList[item]['Size'][4],
3319                UseList[item]['Size'][5],range(6))
3320            dataSizer = wx.FlexGridSizer(1,6,5,5)
3321            for Pa,val,ref,id in parms:
3322                sizeRef = wx.CheckBox(DData,-1,label=Pa)
3323                sizeRef.thisown = False
3324                sizeRef.SetValue(ref)
3325                Indx[sizeRef.GetId()] = [item,id]
3326                sizeRef.Bind(wx.EVT_CHECKBOX, OnSizeRef)
3327                dataSizer.Add(sizeRef,0,wx.ALIGN_CENTER_VERTICAL)
3328                sizeVal = wx.TextCtrl(DData,wx.ID_ANY,'%.3f'%(val),style=wx.TE_PROCESS_ENTER)
3329                Indx[sizeVal.GetId()] = [item,id]
3330                sizeVal.Bind(wx.EVT_TEXT_ENTER,OnSizeVal)
3331                sizeVal.Bind(wx.EVT_KILL_FOCUS,OnSizeVal)
3332                dataSizer.Add(sizeVal,0,wx.ALIGN_CENTER_VERTICAL)
3333            return dataSizer
3334           
3335        def GenStrainDataSizer():
3336            Snames = G2spc.MustrainNames(SGData)
3337            numb = len(Snames)
3338            if len(UseList[item]['Mustrain'][4]) < numb:
3339                UseList[item]['Mustrain'][4] = numb*[0.0,]
3340                UseList[item]['Mustrain'][5] = numb*[False,]
3341            parms = zip(Snames,UseList[item]['Mustrain'][4],UseList[item]['Mustrain'][5],range(numb))
3342            dataSizer = wx.FlexGridSizer(1,6,5,5)
3343            for Pa,val,ref,id in parms:
3344                strainRef = wx.CheckBox(DData,-1,label=Pa)
3345                strainRef.thisown = False
3346                strainRef.SetValue(ref)
3347                Indx[strainRef.GetId()] = [item,id]
3348                strainRef.Bind(wx.EVT_CHECKBOX, OnStrainRef)
3349                dataSizer.Add(strainRef,0,wx.ALIGN_CENTER_VERTICAL)
3350                strainVal = wx.TextCtrl(DData,wx.ID_ANY,'%.5f'%(val),style=wx.TE_PROCESS_ENTER)
3351                Indx[strainVal.GetId()] = [item,id]
3352                strainVal.Bind(wx.EVT_TEXT_ENTER,OnStrainVal)
3353                strainVal.Bind(wx.EVT_KILL_FOCUS,OnStrainVal)
3354                dataSizer.Add(strainVal,0,wx.ALIGN_CENTER_VERTICAL)
3355            return dataSizer
3356           
3357        def HstrainSizer():
3358            hstrainSizer = wx.FlexGridSizer(1,6,5,5)
3359            Hsnames = G2spc.HStrainNames(SGData)
3360            parms = zip(Hsnames,UseList[item]['HStrain'][0],UseList[item]['HStrain'][1],range(len(Hsnames)))
3361            for Pa,val,ref,id in parms:
3362                hstrainRef = wx.CheckBox(DData,-1,label=Pa)
3363                hstrainRef.thisown = False
3364                hstrainRef.SetValue(ref)
3365                Indx[hstrainRef.GetId()] = [item,id]
3366                hstrainRef.Bind(wx.EVT_CHECKBOX, OnHstrainRef)
3367                hstrainSizer.Add(hstrainRef,0,wx.ALIGN_CENTER_VERTICAL)
3368                hstrainVal = wx.TextCtrl(DData,wx.ID_ANY,'%.5f'%(val),style=wx.TE_PROCESS_ENTER)
3369                Indx[hstrainVal.GetId()] = [item,id]
3370                hstrainVal.Bind(wx.EVT_TEXT_ENTER,OnHstrainVal)
3371                hstrainVal.Bind(wx.EVT_KILL_FOCUS,OnHstrainVal)
3372                hstrainSizer.Add(hstrainVal,0,wx.ALIGN_CENTER_VERTICAL)
3373            return hstrainSizer
3374           
3375        def PoTopSizer(POData):
3376            poSizer = wx.FlexGridSizer(1,6,5,5)
3377            choice = ['March-Dollase','Spherical harmonics']
3378            POtype = choice[['MD','SH'].index(POData[0])]
3379            poSizer.Add(wx.StaticText(DData,-1,' Preferred orientation model '),0,wx.ALIGN_CENTER_VERTICAL)
3380            POType = wx.ComboBox(DData,wx.ID_ANY,value=POtype,choices=choice,
3381                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3382            Indx[POType.GetId()] = item
3383            POType.Bind(wx.EVT_COMBOBOX, OnPOType)
3384            poSizer.Add(POType)
3385            if POData[0] == 'SH':
3386                poSizer.Add(wx.StaticText(DData,-1,' Harmonic order: '),0,wx.ALIGN_CENTER_VERTICAL)
3387                poOrder = wx.ComboBox(DData,wx.ID_ANY,value=str(POData[4]),choices=[str(2*i) for i in range(18)],
3388                    style=wx.CB_READONLY|wx.CB_DROPDOWN)
3389                Indx[poOrder.GetId()] = item
3390                poOrder.Bind(wx.EVT_COMBOBOX,OnPOOrder)
3391                poSizer.Add(poOrder,0,wx.ALIGN_CENTER_VERTICAL)
3392                poRef = wx.CheckBox(DData,-1,label=' Refine? ')
3393                poRef.SetValue(POData[2])
3394                Indx[poRef.GetId()] = item
3395                poRef.Bind(wx.EVT_CHECKBOX,OnPORef)
3396                poSizer.Add(poRef,0,wx.ALIGN_CENTER_VERTICAL)
3397            return poSizer
3398           
3399        def MDDataSizer(POData):
3400            poSizer = wx.BoxSizer(wx.HORIZONTAL)
3401            poRef = wx.CheckBox(DData,-1,label=' March-Dollase ratio: ')
3402            poRef.SetValue(POData[2])
3403            Indx[poRef.GetId()] = item
3404            poRef.Bind(wx.EVT_CHECKBOX,OnPORef)
3405            poSizer.Add(poRef,0,wx.ALIGN_CENTER_VERTICAL)
3406            poVal = wx.TextCtrl(DData,wx.ID_ANY,
3407                '%.3f'%(POData[1]),style=wx.TE_PROCESS_ENTER)
3408            Indx[poVal.GetId()] = item
3409            poVal.Bind(wx.EVT_TEXT_ENTER,OnPOVal)
3410            poVal.Bind(wx.EVT_KILL_FOCUS,OnPOVal)
3411            poSizer.Add(poVal,0,wx.ALIGN_CENTER_VERTICAL)
3412            poSizer.Add(wx.StaticText(DData,-1,' Unique axis, H K L: '),0,wx.ALIGN_CENTER_VERTICAL)
3413            h,k,l =POData[3]
3414            poAxis = wx.TextCtrl(DData,-1,'%3d %3d %3d'%(h,k,l),style=wx.TE_PROCESS_ENTER)
3415            Indx[poAxis.GetId()] = item
3416            poAxis.Bind(wx.EVT_TEXT_ENTER,OnPOAxis)
3417            poAxis.Bind(wx.EVT_KILL_FOCUS,OnPOAxis)
3418            poSizer.Add(poAxis,0,wx.ALIGN_CENTER_VERTICAL)
3419            return poSizer
3420           
3421        def SHDataSizer(POData):
3422            textJ = G2lat.textureIndex(POData[5])
3423            mainSizer.Add(wx.StaticText(DData,-1,' Spherical harmonic coefficients: '+'Texture index: %.3f'%(textJ)),0,wx.ALIGN_CENTER_VERTICAL)
3424            mainSizer.Add((0,5),0)
3425            ODFSizer = wx.FlexGridSizer(2,8,2,2)
3426            ODFIndx = {}
3427            ODFkeys = POData[5].keys()
3428            ODFkeys.sort()
3429            for odf in ODFkeys:
3430                ODFSizer.Add(wx.StaticText(DData,-1,odf),0,wx.ALIGN_CENTER_VERTICAL)
3431                ODFval = wx.TextCtrl(DData,wx.ID_ANY,'%8.3f'%(POData[5][odf]),style=wx.TE_PROCESS_ENTER)
3432                ODFIndx[ODFval.GetId()] = odf
3433#                ODFval.Bind(wx.EVT_TEXT_ENTER,OnODFValue)
3434#                ODFval.Bind(wx.EVT_KILL_FOCUS,OnODFValue)
3435                ODFSizer.Add(ODFval,0,wx.ALIGN_CENTER_VERTICAL)
3436            return ODFSizer
3437           
3438        def ExtSizer():           
3439            extSizer = wx.BoxSizer(wx.HORIZONTAL)
3440            extRef = wx.CheckBox(DData,-1,label=' Extinction: ')
3441            extRef.SetValue(UseList[item]['Extinction'][1])
3442            Indx[extRef.GetId()] = item
3443            extRef.Bind(wx.EVT_CHECKBOX, OnExtRef)
3444            extSizer.Add(extRef,0,wx.ALIGN_CENTER_VERTICAL)
3445            extVal = wx.TextCtrl(DData,wx.ID_ANY,
3446                '%.2f'%(UseList[item]['Extinction'][0]),style=wx.TE_PROCESS_ENTER)
3447            Indx[extVal.GetId()] = item
3448            extVal.Bind(wx.EVT_TEXT_ENTER,OnExtVal)
3449            extVal.Bind(wx.EVT_KILL_FOCUS,OnExtVal)
3450            extSizer.Add(extVal,0,wx.ALIGN_CENTER_VERTICAL)
3451            return extSizer
3452       
3453        def SCExtSizer():
3454            extSizer = wx.BoxSizer(wx.VERTICAL)
3455            typeSizer = wx.BoxSizer(wx.HORIZONTAL)           
3456            typeSizer.Add(wx.StaticText(DData,-1,' Extinction type: '),0,wx.ALIGN_CENTER_VERTICAL)
3457            Choices = ['Primary','Secondary Type I','Secondary Type II','Secondary Type I & II']
3458            typeTxt = wx.ComboBox(DData,-1,choices=Choices,value=UseList[item]['Extinction'][1],
3459                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3460            Indx[typeTxt.GetId()] = [item,1]
3461            typeTxt.Bind(wx.EVT_COMBOBOX,OnSCExtType)
3462            typeSizer.Add(typeTxt)
3463            typeSizer.Add(wx.StaticText(DData,-1,' Approx: '),0,wx.ALIGN_CENTER_VERTICAL)
3464            Choices=['Lorentzian','Gaussian']
3465            approxTxT = wx.ComboBox(DData,-1,choices=Choices,value=UseList[item]['Extinction'][0],
3466                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3467            Indx[approxTxT.GetId()] = [item,0]
3468            approxTxT.Bind(wx.EVT_COMBOBOX,OnSCExtType)
3469            typeSizer.Add(approxTxT)
3470            extSizer.Add(typeSizer,0,wx.ALIGN_CENTER_VERTICAL)
3471            extSizer.Add((0,5),)
3472            valSizer =wx.BoxSizer(wx.HORIZONTAL)
3473            valSizer.Add(wx.StaticText(DData,-1,' Tbar(mm):'),0,wx.ALIGN_CENTER_VERTICAL)
3474            tbarVal = wx.TextCtrl(DData,wx.ID_ANY,
3475                '%.3f'%(UseList[item]['Extinction'][2]['Tbar']),style=wx.TE_PROCESS_ENTER)
3476            Indx[tbarVal.GetId()] = item
3477            tbarVal.Bind(wx.EVT_TEXT_ENTER,OnTbarVal)
3478            tbarVal.Bind(wx.EVT_KILL_FOCUS,OnTbarVal)
3479            valSizer.Add(tbarVal,0,wx.ALIGN_CENTER_VERTICAL)
3480            if 'Primary' in UseList[item]['Extinction'][1]:
3481                Ekey = ['Ep',]
3482            elif 'Secondary Type II' == UseList[item]['Extinction'][1]:
3483                Ekey = ['Es',]
3484            elif 'Secondary Type I' == UseList[item]['Extinction'][1]:
3485                Ekey = ['Eg',]
3486            else:
3487                Ekey = ['Eg','Es']
3488            for ekey in Ekey:
3489                Eref = wx.CheckBox(DData,-1,label=ekey+' : ')
3490                Eref.SetValue(UseList[item]['Extinction'][2][ekey][1])
3491                Indx[Eref.GetId()] = [item,ekey]
3492                Eref.Bind(wx.EVT_CHECKBOX, OnEref)
3493                valSizer.Add(Eref,0,wx.ALIGN_CENTER_VERTICAL)
3494                Eval = wx.TextCtrl(DData,wx.ID_ANY,
3495                    '%9.3g'%(UseList[item]['Extinction'][2][ekey][0]),style=wx.TE_PROCESS_ENTER)
3496                Indx[Eval.GetId()] = [item,ekey]
3497                Eval.Bind(wx.EVT_TEXT_ENTER,OnEval)
3498                Eval.Bind(wx.EVT_KILL_FOCUS,OnEval)
3499                valSizer.Add(Eval,0,wx.ALIGN_CENTER_VERTICAL)
3500
3501            extSizer.Add(valSizer,0,wx.ALIGN_CENTER_VERTICAL)
3502            return extSizer
3503           
3504        if DData.GetSizer():
3505            DData.GetSizer().Clear(True)
3506        mainSizer = wx.BoxSizer(wx.VERTICAL)
3507        mainSizer.Add(wx.StaticText(DData,-1,'Histogram data for '+PhaseName+':'),0,wx.ALIGN_CENTER_VERTICAL)
3508        if PWDR:
3509            mainSizer.Add(PlotSizer())           
3510           
3511        for item in keyList:
3512            histData = UseList[item]
3513            if 'Use' not in UseList[item]:      #patch
3514                UseList[item]['Use'] = True
3515            showSizer = wx.BoxSizer(wx.HORIZONTAL)
3516            showData = wx.CheckBox(DData,-1,label=' Show '+item)
3517            showData.SetValue(UseList[item]['Show'])
3518            Indx[showData.GetId()] = item
3519            showData.Bind(wx.EVT_CHECKBOX, OnShowData)
3520            showSizer.Add(showData,0,wx.ALIGN_CENTER_VERTICAL)
3521            useData = wx.CheckBox(DData,-1,label='Use?')
3522            Indx[useData.GetId()] = item
3523            showSizer.Add(useData,0,wx.ALIGN_CENTER_VERTICAL)
3524            useData.Bind(wx.EVT_CHECKBOX, OnUseData)
3525            useData.SetValue(UseList[item]['Use'])
3526            copyData = wx.Button(DData,-1,label=' Copy?')
3527            Indx[copyData.GetId()] = item
3528            copyData.Bind(wx.EVT_BUTTON,OnCopyData)
3529            showSizer.Add(copyData,wx.ALIGN_CENTER_VERTICAL)
3530            copyFlags = wx.Button(DData,-1,label=' Copy flags?')
3531            Indx[copyFlags.GetId()] = item
3532            copyFlags.Bind(wx.EVT_BUTTON,OnCopyFlags)
3533            showSizer.Add(copyFlags,wx.ALIGN_CENTER_VERTICAL)
3534            mainSizer.Add((5,5),0)
3535            mainSizer.Add(showSizer,0,wx.ALIGN_CENTER_VERTICAL)
3536            mainSizer.Add((0,5),0)
3537           
3538            if UseList[item]['Show']:
3539                mainSizer.Add(ScaleSizer())
3540                mainSizer.Add((0,5),0)
3541               
3542            if item[:4] == 'PWDR' and UseList[item]['Show']:
3543                if UseList[item]['Size'][0] == 'isotropic':
3544                    isoSizer = wx.BoxSizer(wx.HORIZONTAL)
3545                    isoSizer.Add(TopSizer(' Size model: ',['isotropic','uniaxial','ellipsoidal'],
3546                        'Size',OnSizeType),0,wx.ALIGN_CENTER_VERTICAL)
3547                    isoSizer.Add(LGmixSizer('Size',OnLGmixVal,OnLGmixRef))
3548                    mainSizer.Add(isoSizer)
3549                    mainSizer.Add(IsoSizer(u' Cryst. size(\xb5m): ','Size','%.3f',
3550                        OnSizeVal,OnSizeRef),0,wx.ALIGN_CENTER_VERTICAL)
3551                elif UseList[item]['Size'][0] == 'uniaxial':
3552                    uniSizer = wx.BoxSizer(wx.HORIZONTAL)
3553                    uniSizer.Add(TopSizer(' Size model: ',['isotropic','uniaxial','ellipsoidal'],
3554                        'Size',OnSizeType),0,wx.ALIGN_CENTER_VERTICAL)
3555                    uniSizer.Add(LGmixSizer('Size',OnLGmixVal,OnLGmixRef))
3556                    uniSizer.Add(UniSizer('Size',OnSizeAxis),0,wx.ALIGN_CENTER_VERTICAL)
3557                    mainSizer.Add(uniSizer)
3558                    mainSizer.Add(UniDataSizer(u'size(\xb5m): ','Size','%.3f',OnSizeVal,OnSizeRef))
3559                elif UseList[item]['Size'][0] == 'ellipsoidal':
3560                    ellSizer = wx.BoxSizer(wx.HORIZONTAL)
3561                    ellSizer.Add(TopSizer(' Size model: ',['isotropic','uniaxial','ellipsoidal'],
3562                        'Size',OnSizeType),0,wx.ALIGN_CENTER_VERTICAL)
3563                    ellSizer.Add(LGmixSizer('Size',OnLGmixVal,OnLGmixRef))
3564                    mainSizer.Add(ellSizer)
3565                    mainSizer.Add(EllSizeDataSizer())
3566                mainSizer.Add((0,5),0)                   
3567               
3568                if UseList[item]['Mustrain'][0] == 'isotropic':
3569                    isoSizer = wx.BoxSizer(wx.HORIZONTAL)
3570                    isoSizer.Add(TopSizer(' Mustrain model: ',['isotropic','uniaxial','generalized',],
3571                        'Mustrain',OnStrainType),0,wx.ALIGN_CENTER_VERTICAL)
3572                    isoSizer.Add(LGmixSizer('Mustrain',OnLGmixVal,OnLGmixRef))
3573                    mainSizer.Add(isoSizer)
3574                    mainSizer.Add(IsoSizer(' microstrain: ','Mustrain','%.1f',
3575                        OnStrainVal,OnStrainRef),0,wx.ALIGN_CENTER_VERTICAL)                   
3576                    mainSizer.Add((0,5),0)
3577                elif UseList[item]['Mustrain'][0] == 'uniaxial':
3578                    uniSizer = wx.BoxSizer(wx.HORIZONTAL)
3579                    uniSizer.Add(TopSizer(' Mustrain model: ',['isotropic','uniaxial','generalized',],
3580                        'Mustrain',OnStrainType),0,wx.ALIGN_CENTER_VERTICAL)
3581                    uniSizer.Add(LGmixSizer('Mustrain',OnLGmixVal,OnLGmixRef))
3582                    uniSizer.Add(UniSizer('Mustrain',OnStrainAxis),0,wx.ALIGN_CENTER_VERTICAL)
3583                    mainSizer.Add(uniSizer)
3584                    mainSizer.Add(UniDataSizer('mustrain: ','Mustrain','%.1f',OnStrainVal,OnStrainRef))
3585                elif UseList[item]['Mustrain'][0] == 'generalized':
3586                    genSizer = wx.BoxSizer(wx.HORIZONTAL)
3587                    genSizer.Add(TopSizer(' Mustrain model: ',['isotropic','uniaxial','generalized',],
3588                        'Mustrain',OnStrainType),0,wx.ALIGN_CENTER_VERTICAL)
3589                    genSizer.Add(LGmixSizer('Mustrain',OnLGmixVal,OnLGmixRef))
3590                    mainSizer.Add(genSizer)
3591                    mainSizer.Add(GenStrainDataSizer())                       
3592                mainSizer.Add((0,5),0)
3593               
3594                mainSizer.Add(wx.StaticText(DData,-1,' Hydrostatic/elastic strain:'))
3595                mainSizer.Add(HstrainSizer())
3596                   
3597                #texture  'Pref. Ori.':['MD',1.0,False,[0,0,1],0,[]] last two for 'SH' are SHorder & coeff
3598                poSizer = wx.BoxSizer(wx.VERTICAL)
3599                POData = UseList[item]['Pref.Ori.']
3600                poSizer.Add(PoTopSizer(POData))
3601                if POData[0] == 'MD':
3602                    poSizer.Add(MDDataSizer(POData))
3603                else:           #'SH'
3604                    if POData[4]:       #SH order > 0
3605                        poSizer.Add(SHDataSizer(POData))
3606                       
3607                mainSizer.Add(poSizer)
3608                mainSizer.Add((0,5),0)               
3609                #Extinction  'Extinction':[0.0,False]
3610                mainSizer.Add(ExtSizer())
3611                mainSizer.Add((0,5),0)
3612            elif item[:4] == 'HKLF' and UseList[item]['Show']:
3613                mainSizer.Add((0,5),0)               
3614                mainSizer.Add(SCExtSizer())
3615                mainSizer.Add((0,5),0)
3616                pass
3617        mainSizer.Add((5,5),0)
3618
3619        DData.SetSizer(mainSizer,True)
3620        mainSizer.FitInside(G2frame.dataFrame)
3621        Size = mainSizer.GetMinSize()
3622        Size[0] += 40
3623        Size[1] = max(Size[1],290) + 20
3624        DData.SetSize(Size)
3625        DData.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
3626        Size[1] = min(Size[1],450)
3627        G2frame.dataFrame.setSizePosLeft(Size)
3628       
3629    def OnHklfAdd(event):
3630        UseList = data['Histograms']
3631        keyList = UseList.keys()
3632        TextList = []
3633        if G2frame.PatternTree.GetCount():
3634            item, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
3635            while item:
3636                name = G2frame.PatternTree.GetItemText(item)
3637                if name not in keyList and 'HKLF' in name:
3638                    TextList.append(name)
3639                item, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)                       
3640            dlg = wx.MultiChoiceDialog(G2frame, 'Which new data to use?', 'Use data', TextList, wx.CHOICEDLG_STYLE)
3641            try:
3642                if dlg.ShowModal() == wx.ID_OK:
3643                    result = dlg.GetSelections()
3644                    for i in result:
3645                        histoName = TextList[i]
3646                        UseList[histoName] = {'Histogram':histoName,'Show':False,'Scale':[1.0,True],
3647                            'Extinction':['Lorentzian','Secondary Type I',
3648                            {'Tbar':0.0,'Eg':[0.0,False],'Es':[0.0,False],'Ep':[0.0,False]},]}                       
3649                    data['Histograms'] = UseList
3650                    wx.BeginBusyCursor()
3651                    UpdateHKLFdata(histoName)
3652                    wx.EndBusyCursor()
3653                    wx.CallAfter(UpdateDData)
3654            finally:
3655                dlg.Destroy()
3656               
3657    def UpdateHKLFdata(histoName):
3658        generalData = data['General']
3659        Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,histoName)
3660        reflData = G2frame.PatternTree.GetItemPyData(Id)[1]
3661        SGData = generalData['SGData']
3662        Cell = generalData['Cell'][1:7]
3663        G,g = G2lat.cell2Gmat(Cell)
3664        for ref in reflData:
3665            H = ref[:3]
3666            ref[4] = np.sqrt(1./G2lat.calc_rDsq2(H,G))
3667            iabsnt,ref[3],ref[11],ref[12] = G2spc.GenHKLf(H,SGData)
3668        G2frame.PatternTree.SetItemPyData(Id,[histoName,reflData])
3669       
3670    def OnPwdrAdd(event):
3671        generalData = data['General']
3672        SGData = generalData['SGData']
3673        UseList = data['Histograms']
3674        newList = []
3675        NShkl = len(G2spc.MustrainNames(SGData))
3676        NDij = len(G2spc.HStrainNames(SGData))
3677        keyList = UseList.keys()
3678        TextList = ['All PWDR']
3679        if G2frame.PatternTree.GetCount():
3680            item, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
3681            while item:
3682                name = G2frame.PatternTree.GetItemText(item)
3683                if name not in keyList and 'PWDR' in name:
3684                    TextList.append(name)
3685                item, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
3686            dlg = wx.MultiChoiceDialog(G2frame, 'Which new data to use?', 'Use data', TextList, wx.CHOICEDLG_STYLE)
3687            try:
3688                if dlg.ShowModal() == wx.ID_OK:
3689                    result = dlg.GetSelections()
3690                    for i in result: newList.append(TextList[i])
3691                    if 'All PWDR' in newList:
3692                        newList = TextList[1:]
3693                    for histoName in newList:
3694                        pId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,histoName)
3695                        UseList[histoName] = {'Histogram':histoName,'Show':False,
3696                            'Scale':[1.0,False],'Pref.Ori.':['MD',1.0,False,[0,0,1],0,{}],
3697                            'Size':['isotropic',[4.,4.,1.0],[False,False,False],[0,0,1],
3698                                [4.,4.,4.,0.,0.,0.],6*[False,]],
3699                            'Mustrain':['isotropic',[1000.0,1000.0,1.0],[False,False,False],[0,0,1],
3700                                NShkl*[0.01,],NShkl*[False,]],
3701                            'HStrain':[NDij*[0.0,],NDij*[False,]],                         
3702                            'Extinction':[0.0,False]}
3703                        refList = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,pId,'Reflection Lists'))
3704                        refList[generalData['Name']] = []                       
3705                    data['Histograms'] = UseList
3706                    wx.CallAfter(UpdateDData)
3707            finally:
3708                dlg.Destroy()
3709       
3710    def OnDataDelete(event):
3711        UseList = data['Histograms']
3712        keyList = ['All',]+UseList.keys()
3713        keyList.sort()
3714        DelList = []
3715        if UseList:
3716            DelList = []
3717            dlg = wx.MultiChoiceDialog(G2frame, 
3718                'Which histogram to delete from this phase?', 'Delete histogram', 
3719                keyList, wx.CHOICEDLG_STYLE)
3720            try:
3721                if dlg.ShowModal() == wx.ID_OK:
3722                    result = dlg.GetSelections()
3723                    for i in result: 
3724                        DelList.append(keyList[i])
3725                    if 'All' in DelList:
3726                        DelList = keyList[1:]
3727                    for i in DelList:
3728                        del UseList[i]
3729                    wx.CallAfter(UpdateDData)
3730            finally:
3731                dlg.Destroy()
3732
3733################################################################################
3734##### Pawley routines
3735################################################################################
3736
3737    def FillPawleyReflectionsGrid():
3738                       
3739        def KeyEditPawleyGrid(event):
3740            colList = G2frame.PawleyRefl.GetSelectedCols()
3741            PawleyPeaks = data['Pawley ref']
3742            if event.GetKeyCode() == wx.WXK_RETURN:
3743                event.Skip(True)
3744            elif event.GetKeyCode() == wx.WXK_CONTROL:
3745                event.Skip(True)
3746            elif event.GetKeyCode() == wx.WXK_SHIFT:
3747                event.Skip(True)
3748            elif colList:
3749                G2frame.PawleyRefl.ClearSelection()
3750                key = event.GetKeyCode()
3751                for col in colList:
3752                    if PawleyTable.GetTypeName(0,col) == wg.GRID_VALUE_BOOL:
3753                        if key == 89: #'Y'
3754                            for row in range(PawleyTable.GetNumberRows()): PawleyPeaks[row][col]=True
3755                        elif key == 78:  #'N'
3756                            for row in range(PawleyTable.GetNumberRows()): PawleyPeaks[row][col]=False
3757                        FillPawleyReflectionsGrid()
3758           
3759        if 'Pawley ref' in data:
3760            PawleyPeaks = data['Pawley ref']                       
3761            rowLabels = []
3762            for i in range(len(PawleyPeaks)): rowLabels.append(str(i))
3763            colLabels = ['h','k','l','mul','d','refine','Fsq(hkl)','sig(Fsq)']
3764            Types = 4*[wg.GRID_VALUE_LONG,]+[wg.GRID_VALUE_FLOAT+':10,4',wg.GRID_VALUE_BOOL,]+ \
3765                2*[wg.GRID_VALUE_FLOAT+':10,2',]
3766            PawleyTable = G2gd.Table(PawleyPeaks,rowLabels=rowLabels,colLabels=colLabels,types=Types)
3767            G2frame.PawleyRefl.SetTable(PawleyTable, True)
3768            G2frame.PawleyRefl.Bind(wx.EVT_KEY_DOWN, KeyEditPawleyGrid)                 
3769            for r in range(G2frame.PawleyRefl.GetNumberRows()):
3770                for c in range(G2frame.PawleyRefl.GetNumberCols()):
3771                    if c in [5,6]:
3772                        G2frame.PawleyRefl.SetReadOnly(r,c,isReadOnly=False)
3773                    else:
3774                        G2frame.PawleyRefl.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
3775            G2frame.PawleyRefl.SetMargins(0,0)
3776            G2frame.PawleyRefl.AutoSizeColumns(False)
3777            G2frame.dataFrame.setSizePosLeft([500,300])
3778                   
3779    def OnPawleyLoad(event):
3780        generalData = data['General']
3781        dmin = generalData['Pawley dmin']
3782        cell = generalData['Cell'][1:7]
3783        A = G2lat.cell2A(cell)
3784        SGData = generalData['SGData']
3785        HKLd = np.array(G2lat.GenHLaue(dmin,SGData,A))
3786        PawleyPeaks = []
3787        wx.BeginBusyCursor()
3788        try:
3789            for h,k,l,d in HKLd:
3790                ext,mul = G2spc.GenHKLf([h,k,l],SGData)[:2]
3791                if not ext:
3792                    mul *= 2        #for powder multiplicity
3793                    PawleyPeaks.append([h,k,l,mul,d,False,100.0,1.0])
3794        finally:
3795            wx.EndBusyCursor()
3796        data['Pawley ref'] = PawleyPeaks
3797        FillPawleyReflectionsGrid()
3798       
3799    def OnPawleyEstimate(event):
3800        try:
3801            Refs = data['Pawley ref']
3802            Histograms = data['Histograms']
3803        except KeyError:
3804            print '**** Error - no histograms defined for this phase ****'
3805            return
3806        HistoNames = Histograms.keys()
3807        PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,HistoNames[0])
3808        xdata = G2frame.PatternTree.GetItemPyData(PatternId)[1]
3809        Inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Instrument Parameters'))
3810        Inst = dict(zip(Inst[3],Inst[1]))
3811        Sample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Sample Parameters'))
3812        if 'Lam' in Inst:
3813            wave = Inst['Lam']
3814        else:
3815            wave = Inst['Lam1']
3816        posCorr = Inst['Zero']
3817        const = 9.e-2/(np.pi*Sample['Gonio. radius'])                  #shifts in microns
3818       
3819        for ref in Refs:
3820            pos = 2.0*asind(wave/(2.0*ref[4]))
3821            if 'Bragg' in Sample['Type']:
3822                pos -= const*(4.*Sample['Shift'][0]*cosd(pos/2.0)+ \
3823                    Sample['Transparency'][0]*sind(pos)*100.0)            #trans(=1/mueff) in cm
3824            else:               #Debye-Scherrer - simple but maybe not right
3825                pos -= const*(Sample['DisplaceX'][0]*cosd(pos)+Sample['DisplaceY'][0]*sind(pos))
3826            indx = np.searchsorted(xdata[0],pos)
3827            try:
3828                FWHM = max(0.001,G2pwd.getFWHM(pos,Inst))/2.
3829                dx = xdata[0][indx+1]-xdata[0][indx]
3830                ref[6] = FWHM*xdata[1][indx]/dx
3831                Lorenz = 1./(2.*sind(xdata[0][indx]/2.)**2*cosd(xdata[0][indx]/2.))           #Lorentz correction
3832                pola,dIdPola = G2pwd.Polarization(Inst['Polariz.'],xdata[0][indx],Inst['Azimuth'])
3833                ref[6] /= (Lorenz*pola*ref[3])
3834            except IndexError:
3835                pass
3836        FillPawleyReflectionsGrid()
3837
3838    def OnPawleyUpdate(event):
3839        try:
3840            Refs = data['Pawley ref']
3841            Histograms = data['Histograms']
3842        except KeyError:
3843            print '**** Error - no histograms defined for this phase ****'
3844            return
3845        HistoNames = Histograms.keys()
3846        PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,HistoNames[0])
3847        refData = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Reflection Lists'))[PhaseName]
3848        for iref,ref in enumerate(Refs):
3849            try:
3850                ref[6] = refData[iref][9]
3851                ref[7] = 1.0
3852            except IndexError:
3853                pass
3854        FillPawleyReflectionsGrid()
3855                           
3856    def OnPawleyDelete(event):
3857        dlg = wx.MessageDialog(G2frame,'Do you really want to delete Pawley reflections?','Delete', 
3858            wx.YES_NO | wx.ICON_QUESTION)
3859        try:
3860            result = dlg.ShowModal()
3861        finally:
3862            dlg.Destroy()
3863        if result == wx.ID_YES: 
3864            data['Pawley ref'] = []
3865            FillPawleyReflectionsGrid()
3866
3867################################################################################
3868##### Fourier routines
3869################################################################################
3870
3871    def FillMapPeaksGrid():
3872                       
3873        def RowSelect(event):
3874            r,c =  event.GetRow(),event.GetCol()
3875            if r < 0 and c < 0:
3876                if MapPeaks.IsSelection():
3877                    MapPeaks.ClearSelection()
3878                else:
3879                    for row in range(MapPeaks.GetNumberRows()):
3880                        MapPeaks.SelectRow(row,True)
3881                   
3882            elif c < 0:                   #only row clicks
3883                if event.ControlDown():                   
3884                    if r in MapPeaks.GetSelectedRows():
3885                        MapPeaks.DeselectRow(r)
3886                    else:
3887                        MapPeaks.SelectRow(r,True)
3888                elif event.ShiftDown():
3889                    for row in range(r+1):
3890                        MapPeaks.SelectRow(row,True)
3891                else:
3892                    MapPeaks.ClearSelection()
3893                    MapPeaks.SelectRow(r,True)               
3894            G2plt.PlotStructure(G2frame,data)                   
3895           
3896        G2frame.dataFrame.setSizePosLeft([450,300])
3897        if 'Map Peaks' in data:
3898            mapPeaks = data['Map Peaks']                       
3899            rowLabels = []
3900            for i in range(len(mapPeaks)): rowLabels.append(str(i))
3901            colLabels = ['mag','x','y','z']
3902            Types = 4*[wg.GRID_VALUE_FLOAT+':10,4',]
3903            MapPeaksTable = G2gd.Table(mapPeaks,rowLabels=rowLabels,colLabels=colLabels,types=Types)
3904            MapPeaks.SetTable(MapPeaksTable, True)
3905            MapPeaks.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK, RowSelect)
3906            for r in range(MapPeaks.GetNumberRows()):
3907                for c in range(MapPeaks.GetNumberCols()):
3908                    MapPeaks.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
3909            MapPeaks.SetMargins(0,0)
3910            MapPeaks.AutoSizeColumns(False)
3911                   
3912    def OnPeaksMove(event):
3913        if 'Map Peaks' in data:
3914            mapPeaks = data['Map Peaks']                       
3915            Ind = MapPeaks.GetSelectedRows()
3916            for ind in Ind:
3917                x,y,z = mapPeaks[ind][1:]
3918                AtomAdd(x,y,z,'C')
3919   
3920    def OnPeaksClear(event):
3921        data['Map Peaks'] = []
3922        FillMapPeaksGrid()
3923        G2plt.PlotStructure(G2frame,data)
3924       
3925    def OnPeaksDelete(event):
3926        if 'Map Peaks' in data:
3927            mapPeaks = data['Map Peaks']
3928            Ind = MapPeaks.GetSelectedRows()
3929            Ind.sort()
3930            Ind.reverse()
3931            for ind in Ind:
3932                mapPeaks = np.delete(mapPeaks,ind,0)
3933            data['Map Peaks'] = mapPeaks
3934        FillMapPeaksGrid()
3935        G2plt.PlotStructure(G2frame,data)
3936               
3937    def OnPeaksUnique(event):
3938        if 'Map Peaks' in data:
3939            mapPeaks = data['Map Peaks']
3940            Ind = MapPeaks.GetSelectedRows()
3941            if Ind:
3942                G2mth.PeaksUnique(data,Ind)
3943                FillMapPeaksGrid()
3944                G2plt.PlotStructure(G2frame,data)
3945   
3946    def OnFourierMaps(event):
3947        generalData = data['General']
3948        mapData = generalData['Map']
3949        reflName = mapData['RefList']
3950        phaseName = generalData['Name']
3951        if 'PWDR' in reflName:
3952            PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, reflName)
3953            reflSets = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Reflection Lists'))
3954            reflData = reflSets[phaseName]
3955        elif 'HKLF' in reflName:
3956            PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, reflName)
3957            reflData = G2frame.PatternTree.GetItemPyData(PatternId)[1]
3958        mapData.update(G2mth.FourierMap(data,reflData))
3959        mapData['Flip'] = False
3960        mapSig = np.std(mapData['rho'])
3961        if not data['Drawing']:                 #if new drawing - no drawing data!
3962            SetupDrawingData()
3963        data['Drawing']['contourLevel'] = 1.
3964        data['Drawing']['mapSize'] = 10.
3965        print mapData['MapType']+' computed: rhomax = %.3f rhomin = %.3f sigma = %.3f'%(np.max(mapData['rho']),np.min(mapData['rho']),mapSig)
3966        UpdateDrawAtoms()
3967        G2plt.PlotStructure(G2frame,data)
3968       
3969    def OnFourClear(event):
3970        generalData = data['General']
3971        generalData['Map'] = mapDefault
3972        G2plt.PlotStructure(G2frame,data)
3973       
3974    def printRho(SGLaue,rho,rhoMax):                         
3975# map printing for testing purposes
3976        dim = len(rho.shape)
3977        if dim == 2:
3978            ix,jy = rho.shape
3979            for j in range(jy):
3980                line = ''
3981                if SGLaue in ['3','3m1','31m','6/m','6/mmm']:
3982                    line += (jy-j)*'  '
3983                for i in range(ix):
3984                    r = int(100*rho[i,j]/rhoMax)
3985                    line += '%4d'%(r)
3986                print line+'\n'
3987        else:
3988            ix,jy,kz = rho.shape
3989            for k in range(kz):
3990                print 'k = ',k
3991                for j in range(jy):
3992                    line = ''
3993                    if SGLaue in ['3','3m1','31m','6/m','6/mmm']:
3994                        line += (jy-j)*'  '
3995                    for i in range(ix):
3996                        r = int(100*rho[i,j,k]/rhoMax)
3997                        line += '%4d'%(r)
3998                    print line+'\n'
3999## keep this               
4000   
4001    def OnSearchMaps(event):
4002       
4003        peaks = []
4004        mags = []
4005        print ' Begin fourier map search - can take some time'
4006        time0 = time.time()
4007        generalData = data['General']
4008        mapData = generalData['Map']
4009        if len(mapData['rho']):
4010            pgbar = wx.ProgressDialog('Map search','No. Peaks found =',301.0, 
4011                style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_CAN_ABORT)
4012            screenSize = wx.ClientDisplayRect()
4013            Size = pgbar.GetSize()
4014            Size = (int(Size[0]*1.2),Size[1]) # increase size a bit along x
4015            pgbar.SetPosition(wx.Point(screenSize[2]-Size[0]-305,screenSize[1]+5))
4016            pgbar.SetSize(Size)
4017            try:
4018                peaks,mags = G2mth.SearchMap(data,keepDup=True,Pgbar=pgbar)
4019            finally:
4020                pgbar.Destroy()
4021            sortIdx = np.argsort(mags.flatten())
4022            if len(peaks):
4023                data['Map Peaks'] = np.concatenate((mags,peaks),axis=1)           
4024                print ' Map search finished, time = %.2fs'%(time.time()-time0)
4025            Page = G2frame.dataDisplay.FindPage('Map peaks')
4026            G2frame.dataDisplay.ChangeSelection(Page)
4027            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.MapPeaksMenu)
4028            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksMove, id=G2gd.wxID_PEAKSMOVE)
4029            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksUnique, id=G2gd.wxID_PEAKSUNIQUE)
4030            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksDelete, id=G2gd.wxID_PEAKSDELETE)
4031            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksClear, id=G2gd.wxID_PEAKSCLEAR)
4032            UpdateDrawAtoms()
4033            FillMapPeaksGrid()
4034        else:
4035            print 'No map available'
4036       
4037    def OnChargeFlip(event):
4038        generalData = data['General']
4039        mapData = generalData['Map']
4040        flipData = generalData['Flip']
4041        reflName = flipData['RefList']
4042        phaseName = generalData['Name']
4043        if 'PWDR' in reflName:
4044            PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, reflName)
4045            reflSets = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Reflection Lists'))
4046            reflData = reflSets[phaseName]
4047        elif 'HKLF' in reflName:
4048            PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, reflName)
4049            reflData = G2frame.PatternTree.GetItemPyData(PatternId)[1]
4050        else:
4051            print '**** ERROR - No data defined for charge flipping'
4052            return
4053        pgbar = wx.ProgressDialog('Charge flipping','Residual Rcf =',101.0, 
4054            style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_CAN_ABORT)
4055        screenSize = wx.ClientDisplayRect()
4056        Size = pgbar.GetSize()
4057        Size = (int(Size[0]*1.2),Size[1]) # increase size a bit along x
4058        pgbar.SetPosition(wx.Point(screenSize[2]-Size[0]-305,screenSize[1]+5))
4059        pgbar.SetSize(Size)
4060        try:
4061            mapData.update(G2mth.ChargeFlip(data,reflData,pgbar))
4062        finally:
4063            pgbar.Destroy()
4064        mapData['Flip'] = True       
4065        mapSig = np.std(mapData['rho'])
4066        if not data['Drawing']:                 #if new drawing - no drawing data!
4067            SetupDrawingData()
4068        data['Drawing']['contourLevel'] = 1.
4069        data['Drawing']['mapSize'] = 10.
4070        print ' Charge flip map computed: rhomax = %.3f rhomin = %.3f sigma = %.3f'%(np.max(mapData['rho']),np.min(mapData['rho']),mapSig)
4071        if mapData['Rcf'] < 99.:
4072            OnSearchMaps(event)             #does a plot structure at end
4073        else:
4074            print 'Bad charge flip map - no peak search done'
4075               
4076    def OnTextureRefine(event):
4077        print 'refine texture?'
4078        event.Skip()       
4079           
4080    def OnTextureClear(event):
4081        print 'clear texture?'
4082        event.Skip()
4083
4084    def OnPageChanged(event):
4085        page = event.GetSelection()
4086        text = G2frame.dataDisplay.GetPageText(page)
4087        if text == 'Atoms':
4088            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.AtomsMenu)
4089            G2frame.dataFrame.Bind(wx.EVT_MENU, OnAtomAdd, id=G2gd.wxID_ATOMSEDITADD)
4090            G2frame.dataFrame.Bind(wx.EVT_MENU, OnAtomTestAdd, id=G2gd.wxID_ATOMSTESTADD)
4091            G2frame.dataFrame.Bind(wx.EVT_MENU, OnAtomInsert, id=G2gd.wxID_ATOMSEDITINSERT)
4092            G2frame.dataFrame.Bind(wx.EVT_MENU, OnAtomTestInsert, id=G2gd.wxID_ATONTESTINSERT)
4093            G2frame.dataFrame.Bind(wx.EVT_MENU, AtomDelete, id=G2gd.wxID_ATOMSEDITDELETE)
4094            G2frame.dataFrame.Bind(wx.EVT_MENU, AtomRefine, id=G2gd.wxID_ATOMSREFINE)
4095            G2frame.dataFrame.Bind(wx.EVT_MENU, AtomModify, id=G2gd.wxID_ATOMSMODIFY)
4096            G2frame.dataFrame.Bind(wx.EVT_MENU, AtomTransform, id=G2gd.wxID_ATOMSTRANSFORM)
4097            G2frame.dataFrame.Bind(wx.EVT_MENU, OnReloadDrawAtoms, id=G2gd.wxID_RELOADDRAWATOMS)
4098            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDistAngle, id=G2gd.wxID_ATOMSDISAGL)
4099            FillAtomsGrid()
4100        elif text == 'General':
4101            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.DataGeneral)
4102            G2frame.dataFrame.Bind(wx.EVT_MENU, OnFourierMaps, id=G2gd.wxID_FOURCALC)
4103            G2frame.dataFrame.Bind(wx.EVT_MENU, OnSearchMaps, id=G2gd.wxID_FOURSEARCH)
4104            G2frame.dataFrame.Bind(wx.EVT_MENU, OnChargeFlip, id=G2gd.wxID_CHARGEFLIP)
4105            G2frame.dataFrame.Bind(wx.EVT_MENU, OnFourClear, id=G2gd.wxID_FOURCLEAR)
4106            UpdateGeneral()
4107        elif text == 'Data':
4108            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.DataMenu)
4109            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPwdrAdd, id=G2gd.wxID_PWDRADD)
4110            G2frame.dataFrame.Bind(wx.EVT_MENU, OnHklfAdd, id=G2gd.wxID_HKLFADD)
4111            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDataDelete, id=G2gd.wxID_DATADELETE)
4112            UpdateDData()
4113            G2plt.PlotSizeStrainPO(G2frame,data,Start=True)
4114        elif text == 'Draw Options':
4115            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.DataDrawOptions)
4116            UpdateDrawOptions()
4117            G2plt.PlotStructure(G2frame,data)
4118        elif text == 'Draw Atoms':
4119            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.DrawAtomsMenu)
4120            G2frame.dataFrame.Bind(wx.EVT_MENU, DrawAtomStyle, id=G2gd.wxID_DRAWATOMSTYLE)
4121            G2frame.dataFrame.Bind(wx.EVT_MENU, DrawAtomLabel, id=G2gd.wxID_DRAWATOMLABEL)
4122            G2frame.dataFrame.Bind(wx.EVT_MENU, DrawAtomColor, id=G2gd.wxID_DRAWATOMCOLOR)
4123            G2frame.dataFrame.Bind(wx.EVT_MENU, ResetAtomColors, id=G2gd.wxID_DRAWATOMRESETCOLOR)
4124            G2frame.dataFrame.Bind(wx.EVT_MENU, SetViewPoint, id=G2gd.wxID_DRAWVIEWPOINT)
4125            G2frame.dataFrame.Bind(wx.EVT_MENU, AddSymEquiv, id=G2gd.wxID_DRAWADDEQUIV)
4126            G2frame.dataFrame.Bind(wx.EVT_MENU, TransformSymEquiv, id=G2gd.wxID_DRAWTRANSFORM)
4127            G2frame.dataFrame.Bind(wx.EVT_MENU, FillCoordSphere, id=G2gd.wxID_DRAWFILLCOORD)           
4128            G2frame.dataFrame.Bind(wx.EVT_MENU, FillUnitCell, id=G2gd.wxID_DRAWFILLCELL)
4129            G2frame.dataFrame.Bind(wx.EVT_MENU, DrawAtomsDelete, id=G2gd.wxID_DRAWDELETE)
4130            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDrawDAT, id=G2gd.wxID_DRAWDISAGLTOR)
4131            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDrawPlane, id=G2gd.wxID_DRAWPLANE)
4132            G2frame.dataFrame.Bind(wx.EVT_MENU, OnRestraint, id=G2gd.wxID_DRAWRESTRBOND)
4133            G2frame.dataFrame.Bind(wx.EVT_MENU, OnRestraint, id=G2gd.wxID_DRAWRESTRANGLE)
4134            G2frame.dataFrame.Bind(wx.EVT_MENU, OnRestraint, id=G2gd.wxID_DRAWRESTRPLANE)
4135            G2frame.dataFrame.Bind(wx.EVT_MENU, OnRestraint, id=G2gd.wxID_DRAWRESTRCHIRAL)
4136            UpdateDrawAtoms()
4137            G2plt.PlotStructure(G2frame,data)
4138        elif text == 'Pawley reflections':
4139            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.PawleyMenu)
4140            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPawleyLoad, id=G2gd.wxID_PAWLEYLOAD)
4141            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPawleyEstimate, id=G2gd.wxID_PAWLEYESTIMATE)
4142            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPawleyUpdate, id=G2gd.wxID_PAWLEYUPDATE)
4143            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPawleyDelete, id=G2gd.wxID_PAWLEYDELETE)           
4144            FillPawleyReflectionsGrid()
4145        elif text == 'Texture':
4146            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.TextureMenu)
4147            G2frame.dataFrame.Bind(wx.EVT_MENU, OnTextureRefine, id=G2gd.wxID_REFINETEXTURE)
4148            G2frame.dataFrame.Bind(wx.EVT_MENU, OnTextureClear, id=G2gd.wxID_CLEARTEXTURE)
4149            UpdateTexture()                       
4150            G2plt.PlotTexture(G2frame,data,Start=True)
4151        elif text == 'Map peaks':
4152            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.MapPeaksMenu)
4153            G2frame.dataFrame.</