source: trunk/GSASIIphsGUI.py @ 758

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

fix in sph. harm. for hex/rhom/trig
fix for view dir in plots
remove a few extra Draw() in structure plotting

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