source: trunk/GSASIIphsGUI.py @ 756

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

change display of density maps - now faster
implement a view direction command (not succcessfuly so far)

  • Property svn:keywords set to Date Author Revision URL Id
File size: 211.0 KB
Line 
1# -*- coding: utf-8 -*-
2#GSASII - phase data display routines
3########### SVN repository information ###################
4# $Date: 2012-09-11 19:28:29 +0000 (Tue, 11 Sep 2012) $
5# $Author: vondreele $
6# $Revision: 756 $
7# $URL: trunk/GSASIIphsGUI.py $
8# $Id: GSASIIphsGUI.py 756 2012-09-11 19:28:29Z 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: 756 $")
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        atomData = data['Atoms']
1558        AA3letter = ['ALA','ARG','ASN','ASP','CYS','GLN','GLU','GLY','HIS','ILE',
1559            'LEU','LYS','MET','PHE','PRO','SER','THR','TRP','TYR','VAL','MSE','HOH','WAT','UNK']
1560        AA1letter = ['A','R','N','D','C','Q','E','G','H','I',
1561            'L','K','M','F','P','S','T','W','Y','V','M',' ',' ',' ']
1562        defaultDrawing = {'Atoms':[],'viewPoint':[[0.5,0.5,0.5],[]],'showHydrogen':True,
1563            'backColor':[0,0,0],'depthFog':False,'Zclip':50.0,'cameraPos':50.,
1564            'radiusFactor':0.85,'contourLevel':1.,'bondRadius':0.1,'ballScale':0.33,
1565            'vdwScale':0.67,'ellipseProb':50,'sizeH':0.50,'unitCellBox':False,
1566            'showABC':True,'selectedAtoms':[],'Atoms':[],'oldxy':[],
1567            'Quaternion':[1.0,0.0,0.0,0.0],'bondList':{},'viewDir':[0,0,1]}
1568        try:
1569            drawingData = data['Drawing']
1570        except KeyError:
1571            data['Drawing'] = {}
1572            drawingData = data['Drawing']
1573        if not drawingData:                 #fill with defaults if empty
1574            drawingData.update(defaultDrawing)
1575        if 'contourLevel' not in drawingData:
1576            drawingData['contourLevel'] = 1.
1577        if 'viewDir' not in drawingData:
1578            drawingData['viewDir'] = [0,0,1]
1579        if 'Quaternion' not in drawingData:
1580            drawingData['Quaternion'] = [1.0,0.0,0.0,0.0]
1581        cx,ct,cs,ci = [0,0,0,0]
1582        if generalData['Type'] == 'nuclear':
1583            cx,ct,cs,ci = [2,1,6,17]         #x, type, style & index
1584        elif generalData['Type'] == 'macromolecular':
1585            cx,ct,cs,ci = [5,4,9,20]         #x, type, style & index
1586        elif generalData['Type'] == 'magnetic':
1587            cx,ct,cs,ci = [2,1,6,20]         #x, type, style & index
1588#        elif generalData['Type'] == 'modulated':
1589#           ?????   for future
1590        drawingData['atomPtrs'] = [cx,ct,cs,ci]
1591        if not drawingData.get('Atoms'):
1592            for atom in atomData:
1593                DrawAtomAdd(drawingData,atom)
1594            data['Drawing'] = drawingData
1595           
1596    def MakeDrawAtom(atom,oldatom=None):
1597        AA3letter = ['ALA','ARG','ASN','ASP','CYS','GLN','GLU','GLY','HIS','ILE',
1598            'LEU','LYS','MET','PHE','PRO','SER','THR','TRP','TYR','VAL','MSE','HOH','WAT','UNK']
1599        AA1letter = ['A','R','N','D','C','Q','E','G','H','I',
1600            'L','K','M','F','P','S','T','W','Y','V','M',' ',' ',' ']
1601        generalData = data['General']
1602        SGData = generalData['SGData']
1603        if generalData['Type'] == 'nuclear':
1604            if oldatom:
1605                opr = oldatom[5]
1606                if atom[9] == 'A':                   
1607                    X,U = G2spc.ApplyStringOps(opr,SGData,atom[3:6],atom[11:17])
1608                    atomInfo = [atom[:2]+list(X)+oldatom[5:9]+atom[9:11]+list(U)+oldatom[17:]][0]
1609                else:
1610                    X = G2spc.ApplyStringOps(opr,SGData,atom[3:6])
1611                    atomInfo = [atom[:2]+list(X)+oldatom[5:9]+atom[9:]+[oldatom[-1]]][0]
1612            else:
1613                atomInfo = [atom[:2]+atom[3:6]+['1',]+['vdW balls',]+
1614                    ['',]+[[255,255,255],]+atom[9:]+[[],[]]][0]
1615            ct,cs = [1,8]         #type & color
1616        elif generalData['Type'] == 'macromolecular':
1617            try:
1618                oneLetter = AA3letter.index(atom[1])
1619            except ValueError:
1620                oneLetter = -1
1621            atomInfo = [[atom[1].strip()+atom[0],]+
1622                [AA1letter[oneLetter]+atom[0],]+atom[2:5]+
1623                atom[6:9]+['1',]+['sticks',]+['',]+[[255,255,255],]+atom[12:]+[[],[]]][0]
1624            ct,cs = [4,11]         #type & color
1625        elif generalData['Type'] == 'magnetic':
1626            if oldatom:
1627                atomInfo = [atom[:2]+oldatom[3:]][0]
1628            else:
1629                atomInfo = [atom[:2]+atom[3:6]+['vdW balls',]+['',]+atom[9:]+[[],[]]][0]
1630            ct,cs = [1,8]         #type & color
1631#        elif generalData['Type'] == 'modulated':
1632#           ?????   for future
1633        atNum = generalData['AtomTypes'].index(atom[ct])
1634        atomInfo[cs] = list(generalData['Color'][atNum])
1635        return atomInfo
1636           
1637    def DrawAtomAdd(drawingData,atom):
1638        drawingData['Atoms'].append(MakeDrawAtom(atom))
1639       
1640    def DrawAtomsReplaceByID(drawingData,atom,ID):
1641        IDs = [ID,]
1642        atomData = drawingData['Atoms']
1643        indx = FindAtomIndexByIDs(atomData,IDs)
1644        for ind in indx:
1645            atomData[ind] = MakeDrawAtom(atom,atomData[ind])
1646           
1647    def OnRestraint(event):       
1648        indx = drawAtoms.GetSelectedRows()
1649        restData = G2frame.PatternTree.GetItemPyData(   
1650            G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Restraints'))
1651        drawingData = data['Drawing']
1652        generalData = data['General']
1653        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])           
1654        cx,ct,cs,ci = drawingData['atomPtrs']
1655        atomData = drawingData['Atoms']
1656        atNames = []
1657        atXYZ = []
1658        atSymOp = []
1659        atIndx = []
1660        for item in indx:
1661            atNames.append(atomData[item][ct-1])
1662            atXYZ.append(np.array(atomData[item][cx:cx+3]))
1663            atSymOp.append(atomData[item][cs-1])
1664            atIndx.append(atomData[item][ci])
1665        if event.GetId() == G2gd.wxID_DRAWRESTRBOND and len(indx) == 2:
1666            try:
1667                bondData = restData[PhaseName]['Bond']
1668            except KeyError:
1669                bondData = {'wtFactor':1.0,'Bonds':[]}
1670                restData[PhaseName] = {}
1671                restData[PhaseName]['Bond'] = bondData
1672            dist = G2mth.getRestDist(atXYZ,Amat)
1673            bondData['Bonds'].append([atNames,atSymOp,atIndx,dist,1.54,0.01])
1674        elif event.GetId() == G2gd.wxID_DRAWRESTRANGLE and len(indx) == 3:
1675            try:
1676                angleData = restData[PhaseName]['Angle']
1677            except KeyError:
1678                angleData = {'wtFactor':1.0,'Angles':[]}
1679                restData[PhaseName] = {}
1680                restData[PhaseName]['Angle'] = angleData
1681            angle = G2mth.getRestAngle(atXYZ,Amat)
1682            angleData['Angles'].append([atNames,atSymOp,atIndx,angle,109.5,1.0])           
1683        elif event.GetId() == G2gd.wxID_DRAWRESTRPLANE and len(indx) > 3:
1684            try:
1685                planeData = restData[PhaseName]['Plane']
1686            except KeyError:
1687                planeData = {'wtFactor':1.0,'Planes':[]}
1688                restData[PhaseName] = {}
1689                restData[PhaseName]['Plane'] = planeData
1690            plane = G2mth.getRestPlane(atXYZ,Amat)
1691            planeData['Planes'].append([atNames,atSymOp,atIndx,plane,0.0,0.01])           
1692        elif event.GetId() == G2gd.wxID_DRAWRESTRCHIRAL and len(indx) == 4:
1693            try:
1694                chiralData = restData[PhaseName]['Chiral']
1695            except KeyError:
1696                chiralData = {'wtFactor':1.0,'Volumes':[]}
1697                restData[PhaseName] = {}
1698                restData[PhaseName]['Chiral'] = chiralData
1699            volume = G2mth.getRestChiral(atXYZ,Amat)
1700            chiralData['Volumes'].append([atNames,atSymOp,atIndx,volume,2.5,0.1])           
1701        else:
1702            print '**** ERROR wrong number of atoms selected for this restraint'
1703            return
1704        G2frame.PatternTree.SetItemPyData(   
1705            G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Restraints'),restData)
1706
1707################################################################################
1708##### Atom draw routines
1709################################################################################
1710           
1711    def UpdateDrawAtoms():
1712        G2frame.dataFrame.SetStatusText('')
1713        generalData = data['General']
1714        SetupDrawingData()
1715        drawingData = data['Drawing']
1716        cx,ct,cs,ci = drawingData['atomPtrs']
1717        atomData = drawingData['Atoms']
1718        Types = [wg.GRID_VALUE_STRING,wg.GRID_VALUE_STRING,]+3*[wg.GRID_VALUE_FLOAT+':10,5',]+ \
1719            [wg.GRID_VALUE_STRING,wg.GRID_VALUE_CHOICE+": ,lines,vdW balls,sticks,balls & sticks,ellipsoids,polyhedra",
1720            wg.GRID_VALUE_CHOICE+": ,type,name,number",wg.GRID_VALUE_STRING,wg.GRID_VALUE_STRING,]
1721        styleChoice = [' ','lines','vdW balls','sticks','balls & sticks','ellipsoids','polyhedra']
1722        labelChoice = [' ','type','name','number']
1723        colLabels = ['Name','Type','x','y','z','Sym Op','Style','Label','Color','I/A']
1724        if generalData['Type'] == 'macromolecular':
1725            colLabels = ['Residue','1-letter','Chain'] + colLabels
1726            Types = 3*[wg.GRID_VALUE_STRING,]+Types
1727            Types[8] = wg.GRID_VALUE_CHOICE+": ,lines,vdW balls,sticks,balls & sticks,ellipsoids,backbone,ribbons,schematic"
1728            styleChoice = [' ','lines','vdW balls','sticks','balls & sticks','ellipsoids','backbone','ribbons','schematic']
1729            labelChoice = [' ','type','name','number','residue','1-letter','chain']
1730            Types[9] = wg.GRID_VALUE_CHOICE+": ,type,name,number,residue,1-letter,chain"
1731#        elif generalData['Type'] == 'modulated':
1732#            Types += []
1733#            colLabels += []
1734
1735        def RefreshAtomGrid(event):
1736
1737            def SetChoice(name,c,n=0):
1738                choice = []
1739                for r in range(len(atomData)):
1740                    if n:
1741                        srchStr = str(atomData[r][c][:n])
1742                    else:
1743                        srchStr = str(atomData[r][c])
1744                    if srchStr not in choice:
1745                        if n:
1746                            choice.append(str(atomData[r][c][:n]))
1747                        else:
1748                            choice.append(str(atomData[r][c]))
1749                choice.sort()
1750
1751                dlg = wx.MultiChoiceDialog(G2frame,'Select',name,choice)
1752                if dlg.ShowModal() == wx.ID_OK:
1753                    sel = dlg.GetSelections()
1754                    parms = []
1755                    for x in sel:
1756                        parms.append(choice[x])
1757                    noSkip = False
1758                    drawAtoms.ClearSelection()
1759                    drawingData['selectedAtoms'] = []
1760                    for row in range(len(atomData)):
1761                        test = atomData[row][c]
1762                        if n:
1763                            test = test[:n]
1764                        if  test in parms:
1765                            drawAtoms.SelectRow(row,True)
1766                            drawingData['selectedAtoms'].append(row)
1767                    G2plt.PlotStructure(G2frame,data)                   
1768                dlg.Destroy()
1769               
1770            r,c =  event.GetRow(),event.GetCol()
1771            if r < 0 and c < 0:
1772                for row in range(drawAtoms.GetNumberRows()):
1773                    drawingData['selectedAtoms'].append(row)
1774                    drawAtoms.SelectRow(row,True)                   
1775            elif r < 0:                          #dclick on col label
1776                sel = -1
1777                Parms = False
1778                noSkip = True
1779                if drawAtoms.GetColLabelValue(c) == 'Style':
1780                    dlg = wx.SingleChoiceDialog(G2frame,'Select','Atom drawing style',styleChoice)
1781                    if dlg.ShowModal() == wx.ID_OK:
1782                        sel = dlg.GetSelection()
1783                        parms = styleChoice[sel]
1784                        for r in range(len(atomData)):
1785                            atomData[r][c] = parms
1786                            drawAtoms.SetCellValue(r,c,parms)
1787                        FindBondsDraw()
1788                        G2plt.PlotStructure(G2frame,data)
1789                    dlg.Destroy()
1790                elif drawAtoms.GetColLabelValue(c) == 'Label':
1791                    dlg = wx.SingleChoiceDialog(G2frame,'Select','Atom labelling style',labelChoice)
1792                    if dlg.ShowModal() == wx.ID_OK:
1793                        sel = dlg.GetSelection()
1794                        parms = labelChoice[sel]
1795                        for r in range(len(atomData)):
1796                            atomData[r][c] = parms
1797                            drawAtoms.SetCellValue(r,c,parms)
1798                    dlg.Destroy()                   
1799                elif drawAtoms.GetColLabelValue(c) == 'Color':
1800                    dlg = wx.ColourDialog(G2frame)
1801                    if dlg.ShowModal() == wx.ID_OK:
1802                        color = dlg.GetColourData().GetColour()
1803                        attr = wg.GridCellAttr()                #needs to be here - gets lost if outside loop!
1804                        attr.SetReadOnly(True)
1805                        attr.SetBackgroundColour(color)
1806                        for r in range(len(atomData)):
1807                            atomData[r][c] = color
1808                            drawingData['Atoms'][r][c] = color
1809                            drawAtoms.SetAttr(r,c,attr)
1810                        UpdateDrawAtoms()
1811                    dlg.Destroy()
1812                elif drawAtoms.GetColLabelValue(c) == 'Residue':
1813                    SetChoice('Residue',c,3)
1814                elif drawAtoms.GetColLabelValue(c) == '1-letter':
1815                    SetChoice('1-letter',c,1)
1816                elif drawAtoms.GetColLabelValue(c) == 'Chain':
1817                    SetChoice('Chain',c)
1818                elif drawAtoms.GetColLabelValue(c) == 'Name':
1819                    SetChoice('Name',c)
1820                elif drawAtoms.GetColLabelValue(c) == 'Sym Op':
1821                    SetChoice('Name',c)
1822                elif drawAtoms.GetColLabelValue(c) == 'Type':
1823                    SetChoice('Type',c)
1824                elif drawAtoms.GetColLabelValue(c) in ['x','y','z','I/A']:
1825                    drawAtoms.ClearSelection()
1826            else:
1827                if drawAtoms.GetColLabelValue(c) in ['Style','Label']:
1828                    atomData[r][c] = drawAtoms.GetCellValue(r,c)
1829                    FindBondsDraw()
1830                elif drawAtoms.GetColLabelValue(c) == 'Color':
1831                    dlg = wx.ColourDialog(G2frame)
1832                    if dlg.ShowModal() == wx.ID_OK:
1833                        color = dlg.GetColourData().GetColour()
1834                        attr = wg.GridCellAttr()                #needs to be here - gets lost if outside loop!
1835                        attr.SetReadOnly(True)
1836                        attr.SetBackgroundColour(color)
1837                        atomData[r][c] = color
1838                        drawingData['Atoms'][r][c] = color
1839                        drawAtoms.SetAttr(i,cs+2,attr)
1840                    dlg.Destroy()
1841#                    event.StopPropagation()
1842                    UpdateDrawAtoms()
1843            G2plt.PlotStructure(G2frame,data)
1844                   
1845        def RowSelect(event):
1846            r,c =  event.GetRow(),event.GetCol()
1847            if r < 0 and c < 0:
1848                if drawAtoms.IsSelection():
1849                    drawAtoms.ClearSelection()
1850            elif c < 0:                   #only row clicks
1851                if event.ControlDown():                   
1852                    if r in drawAtoms.GetSelectedRows():
1853                        drawAtoms.DeselectRow(r)
1854                    else:
1855                        drawAtoms.SelectRow(r,True)
1856                elif event.ShiftDown():
1857                    for row in range(r+1):
1858                        drawAtoms.SelectRow(row,True)
1859                else:
1860                    drawAtoms.ClearSelection()
1861                    drawAtoms.SelectRow(r,True)               
1862            drawingData['selectedAtoms'] = []
1863            drawingData['selectedAtoms'] = drawAtoms.GetSelectedRows()
1864            G2plt.PlotStructure(G2frame,data)                   
1865               
1866        table = []
1867        rowLabels = []
1868        for i,atom in enumerate(drawingData['Atoms']):
1869            table.append(atom[:colLabels.index('I/A')+1])
1870            rowLabels.append(str(i))
1871
1872        atomTable = G2gd.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
1873        drawAtoms.SetTable(atomTable, True)
1874        drawAtoms.SetMargins(0,0)
1875        drawAtoms.AutoSizeColumns(True)
1876        drawAtoms.SetColSize(colLabels.index('Style'),80)
1877        drawAtoms.SetColSize(colLabels.index('Color'),50)
1878        drawAtoms.Bind(wg.EVT_GRID_CELL_CHANGE, RefreshAtomGrid)
1879        drawAtoms.Bind(wg.EVT_GRID_LABEL_LEFT_DCLICK, RefreshAtomGrid)
1880        drawAtoms.Bind(wg.EVT_GRID_CELL_LEFT_DCLICK, RefreshAtomGrid)
1881        drawAtoms.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK, RowSelect)
1882        for i,atom in enumerate(drawingData['Atoms']):
1883            attr = wg.GridCellAttr()                #needs to be here - gets lost if outside loop!
1884            attr.SetReadOnly(True)
1885            attr.SetBackgroundColour(atom[cs+2])
1886            drawAtoms.SetAttr(i,cs+2,attr)
1887            drawAtoms.SetCellValue(i,cs+2,'')
1888        indx = drawingData['selectedAtoms']
1889        if indx:
1890            for r in range(len(atomData)):
1891                if r in indx:
1892                    drawAtoms.SelectRow(r)
1893        for c in range(len(colLabels)):
1894           attr = wg.GridCellAttr()                #needs to be here - gets lost if outside loop!
1895           attr.SetReadOnly(True)
1896           attr.SetBackgroundColour(VERY_LIGHT_GREY)
1897           if colLabels[c] not in ['Style','Label','Color']:
1898                drawAtoms.SetColAttr(c,attr)
1899        G2frame.dataFrame.setSizePosLeft([600,300])
1900       
1901        FindBondsDraw()
1902        drawAtoms.ClearSelection()
1903        G2plt.PlotStructure(G2frame,data)
1904
1905    def DrawAtomStyle(event):
1906        indx = drawAtoms.GetSelectedRows()
1907        if indx:
1908            generalData = data['General']
1909            atomData = data['Drawing']['Atoms']
1910            cx,ct,cs,ci = data['Drawing']['atomPtrs']
1911            styleChoice = [' ','lines','vdW balls','sticks','balls & sticks','ellipsoids','polyhedra']
1912            if generalData['Type'] == 'macromolecular':
1913                styleChoice = [' ','lines','vdW balls','sticks','balls & sticks','ellipsoids',
1914                'backbone','ribbons','schematic']
1915            dlg = wx.SingleChoiceDialog(G2frame,'Select','Atom drawing style',styleChoice)
1916            if dlg.ShowModal() == wx.ID_OK:
1917                sel = dlg.GetSelection()
1918                parms = styleChoice[sel]
1919                for r in indx:
1920                    atomData[r][cs] = parms
1921                    drawAtoms.SetCellValue(r,cs,parms)
1922            dlg.Destroy()
1923            FindBondsDraw()
1924            drawAtoms.ClearSelection()
1925            G2plt.PlotStructure(G2frame,data)
1926
1927    def DrawAtomLabel(event):
1928        indx = drawAtoms.GetSelectedRows()
1929        if indx:
1930            generalData = data['General']
1931            atomData = data['Drawing']['Atoms']
1932            cx,ct,cs,ci = data['Drawing']['atomPtrs']
1933            styleChoice = [' ','type','name','number']
1934            if generalData['Type'] == 'macromolecular':
1935                styleChoice = [' ','type','name','number','residue','1-letter','chain']
1936            dlg = wx.SingleChoiceDialog(G2frame,'Select','Atom label style',styleChoice)
1937            if dlg.ShowModal() == wx.ID_OK:
1938                sel = dlg.GetSelection()
1939                parms = styleChoice[sel]
1940                for r in indx:
1941                    atomData[r][cs+1] = parms
1942                    drawAtoms.SetCellValue(r,cs+1,parms)
1943            dlg.Destroy()
1944            drawAtoms.ClearSelection()
1945            G2plt.PlotStructure(G2frame,data)
1946           
1947    def DrawAtomColor(event):
1948
1949        indx = drawAtoms.GetSelectedRows()
1950        if indx:
1951            if len(indx) > 1:
1952                G2frame.dataFrame.SetStatusText('Select Custom Color, change color, Add to Custom Colors, then OK')
1953            else:
1954                G2frame.dataFrame.SetStatusText('Change color, Add to Custom Colors, then OK')
1955            generalData = data['General']
1956            atomData = data['Drawing']['Atoms']
1957            cx,ct,cs,ci = data['Drawing']['atomPtrs']
1958            atmColors = []
1959            atmTypes = []
1960            for r in indx:
1961                if atomData[r][cs+2] not in atmColors:
1962                    atmColors.append(atomData[r][cs+2])
1963                    atmTypes.append(atomData[r][ct])
1964                    if len(atmColors) > 16:
1965                        break
1966            colors = wx.ColourData()
1967            colors.SetChooseFull(True)
1968            dlg = wx.ColourDialog(G2frame)
1969            if dlg.ShowModal() == wx.ID_OK:
1970                for i in range(len(atmColors)):                   
1971                    atmColors[i] = dlg.GetColourData().GetColour()
1972                colorDict = dict(zip(atmTypes,atmColors))
1973                for r in indx:
1974                    color = colorDict[atomData[r][ct]]
1975                    atomData[r][cs+2] = color
1976                    attr = wg.GridCellAttr()                #needs to be here - gets lost if outside loop!
1977                    attr.SetBackgroundColour(color)
1978                    drawAtoms.SetAttr(r,cs+2,attr)
1979                    data['Drawing']['Atoms'][r][cs+2] = color
1980            drawAtoms.ClearSelection()
1981            dlg.Destroy()
1982            G2frame.dataFrame.SetStatusText('')
1983            G2plt.PlotStructure(G2frame,data)
1984           
1985    def ResetAtomColors(event):
1986        generalData = data['General']
1987        atomData = data['Drawing']['Atoms']
1988        cx,ct,cs,ci = data['Drawing']['atomPtrs']
1989        for atom in atomData:           
1990            atNum = generalData['AtomTypes'].index(atom[ct])
1991            atom[cs+2] = list(generalData['Color'][atNum])
1992        UpdateDrawAtoms()
1993        drawAtoms.ClearSelection()
1994        G2plt.PlotStructure(G2frame,data)       
1995       
1996    def SetViewPoint(event):
1997        indx = drawAtoms.GetSelectedRows()
1998        if indx:
1999            atomData = data['Drawing']['Atoms']
2000            cx = data['Drawing']['atomPtrs'][0]
2001            data['Drawing']['viewPoint'] = [atomData[indx[0]][cx:cx+3],[indx[0],0]]
2002            drawAtoms.ClearSelection()                                  #do I really want to do this?
2003            G2plt.PlotStructure(G2frame,data)
2004           
2005    def noDuplicate(xyz,atomData):                  #be careful where this is used - it's slow
2006        cx = data['Drawing']['atomPtrs'][0]
2007        if True in [np.allclose(np.array(xyz),np.array(atom[cx:cx+3]),atol=0.0002) for atom in atomData]:
2008            return False
2009        else:
2010            return True
2011               
2012    def AddSymEquiv(event):
2013        indx = drawAtoms.GetSelectedRows()
2014        indx.sort()
2015        if indx:
2016            colLabels = [drawAtoms.GetColLabelValue(c) for c in range(drawAtoms.GetNumberCols())]
2017            cx = colLabels.index('x')
2018            cuia = colLabels.index('I/A')
2019            cuij = cuia+2
2020            atomData = data['Drawing']['Atoms']
2021            generalData = data['General']
2022            SGData = generalData['SGData']
2023            dlg = SymOpDialog(G2frame,SGData,False,True)
2024            try:
2025                if dlg.ShowModal() == wx.ID_OK:
2026                    Inv,Cent,Opr,Cell,New,Force = dlg.GetSelection()
2027                    Cell = np.array(Cell)
2028                    cent = SGData['SGCen'][Cent]
2029                    M,T = SGData['SGOps'][Opr]
2030                    for ind in indx:
2031                        XYZ = np.array(atomData[ind][cx:cx+3])
2032                        XYZ = np.inner(M,XYZ)+T
2033                        if Inv:
2034                            XYZ = -XYZ
2035                        XYZ = XYZ+cent+Cell
2036                        if Force:
2037                            XYZ = G2spc.MoveToUnitCell(XYZ)
2038                        if noDuplicate(XYZ,atomData):
2039                            atom = copy.copy(atomData[ind])
2040                            atom[cx:cx+3] = XYZ
2041                            atomOp = atom[cx+3]
2042                            newOp = str(((Opr+1)+100*Cent)*(1-2*Inv))+'+'+ \
2043                                str(int(Cell[0]))+','+str(int(Cell[1]))+','+str(int(Cell[2]))                           
2044                            atom[cx+3] = G2spc.StringOpsProd(atomOp,newOp,SGData)
2045                            if atom[cuia] == 'A':
2046                                Uij = atom[cuij:cuij+6]
2047                                U = G2spc.Uij2U(Uij)
2048                                U = np.inner(np.inner(M,U),M)
2049                                Uij = G2spc.U2Uij(U)
2050                                atom[cuij:cuij+6] = Uij
2051                            atomData.append(atom)
2052            finally:
2053                dlg.Destroy()
2054            UpdateDrawAtoms()
2055            drawAtoms.ClearSelection()
2056            G2plt.PlotStructure(G2frame,data)
2057           
2058    def TransformSymEquiv(event):
2059        indx = drawAtoms.GetSelectedRows()
2060        indx.sort()
2061        if indx:
2062            atomData = data['Drawing']['Atoms']
2063            colLabels = [drawAtoms.GetColLabelValue(c) for c in range(drawAtoms.GetNumberCols())]
2064            cx = colLabels.index('x')
2065            cuia = colLabels.index('I/A')
2066            cuij = cuia+2
2067            atomData = data['Drawing']['Atoms']
2068            generalData = data['General']
2069            SGData = generalData['SGData']
2070            dlg = SymOpDialog(G2frame,SGData,False,True)
2071            try:
2072                if dlg.ShowModal() == wx.ID_OK:
2073                    Inv,Cent,Opr,Cell,New,Force = dlg.GetSelection()
2074                    Cell = np.array(Cell)
2075                    cent = SGData['SGCen'][Cent]
2076                    M,T = SGData['SGOps'][Opr]
2077                    for ind in indx:
2078                        XYZ = np.array(atomData[ind][cx:cx+3])
2079                        XYZ = np.inner(M,XYZ)+T
2080                        if Inv:
2081                            XYZ = -XYZ
2082                        XYZ = XYZ+cent+Cell
2083                        if Force:
2084                            XYZ = G2spc.MoveToUnitCell(XYZ)
2085                        atom = atomData[ind]
2086                        atom[cx:cx+3] = XYZ
2087                        atomOp = atom[cx+3]
2088                        newOp = str(((Opr+1)+100*Cent)*(1-2*Inv))+'+'+ \
2089                            str(int(Cell[0]))+','+str(int(Cell[1]))+','+str(int(Cell[2]))
2090                        atom[cx+3] = G2spc.StringOpsProd(atomOp,newOp,SGData)
2091                        if atom[cuia] == 'A':
2092                            Uij = atom[cuij:cuij+6]
2093                            U = G2spc.Uij2U(Uij)
2094                            U = np.inner(np.inner(M,U),M)
2095                            Uij = G2spc.U2Uij(U)
2096                            atom[cuij:cuij+6] = Uij
2097                    data['Drawing']['Atoms'] = atomData
2098            finally:
2099                dlg.Destroy()
2100            UpdateDrawAtoms()
2101            drawAtoms.ClearSelection()
2102            G2plt.PlotStructure(G2frame,data)
2103           
2104    def FillCoordSphere(event):
2105        generalData = data['General']
2106        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])
2107        radii = generalData['BondRadii']
2108        atomTypes = generalData['AtomTypes']
2109        try:
2110            indH = atomTypes.index('H')
2111            radii[indH] = 0.5
2112        except:
2113            pass           
2114        indx = drawAtoms.GetSelectedRows()
2115        if indx:
2116            indx.sort()
2117            atomData = data['Drawing']['Atoms']
2118            numAtoms = len(atomData)
2119            cx,ct,cs,ci = data['Drawing']['atomPtrs']
2120            generalData = data['General']
2121            SGData = generalData['SGData']
2122            cellArray = G2lat.CellBlock(1)
2123            wx.BeginBusyCursor()
2124            try:
2125                for ind in indx:
2126                    atomA = atomData[ind]
2127                    xyzA = np.array(atomA[cx:cx+3])
2128                    indA = atomTypes.index(atomA[ct])
2129                    for atomB in atomData[:numAtoms]:
2130                        indB = atomTypes.index(atomB[ct])
2131                        sumR = radii[indA]+radii[indB]
2132                        xyzB = np.array(atomB[cx:cx+3])
2133                        for xyz in cellArray+xyzB:
2134                            dist = np.sqrt(np.sum(np.inner(Amat,xyz-xyzA)**2))
2135                            if 0 < dist <= data['Drawing']['radiusFactor']*sumR:
2136                                if noDuplicate(xyz,atomData):
2137                                    oprB = atomB[cx+3]
2138                                    C = xyz-xyzB
2139                                    newOp = '1+'+str(int(round(C[0])))+','+str(int(round(C[1])))+','+str(int(round(C[2])))
2140                                    newAtom = atomB[:]
2141                                    newAtom[cx:cx+3] = xyz
2142                                    newAtom[cx+3] = G2spc.StringOpsProd(oprB,newOp,SGData)
2143                                    atomData.append(newAtom)
2144            finally:
2145                wx.EndBusyCursor()
2146            data['Drawing']['Atoms'] = atomData
2147            UpdateDrawAtoms()
2148            drawAtoms.ClearSelection()
2149            G2plt.PlotStructure(G2frame,data)
2150           
2151    def FillUnitCell(event):
2152        indx = drawAtoms.GetSelectedRows()
2153        indx.sort()
2154        if indx:
2155            atomData = data['Drawing']['Atoms']
2156            colLabels = [drawAtoms.GetColLabelValue(c) for c in range(drawAtoms.GetNumberCols())]
2157            cx = colLabels.index('x')
2158            cuia = colLabels.index('I/A')
2159            cuij = cuia+2
2160            generalData = data['General']
2161            SGData = generalData['SGData']
2162            wx.BeginBusyCursor()
2163            try:
2164                for ind in indx:
2165                    atom = atomData[ind]
2166                    XYZ = np.array(atom[cx:cx+3])
2167                    if atom[cuia] == 'A':
2168                        Uij = atom[cuij:cuij+6]
2169                        result = G2spc.GenAtom(XYZ,SGData,False,Uij,False)
2170                        for item in result:
2171                            atom = copy.copy(atomData[ind])
2172                            atom[cx:cx+3] = item[0]
2173                            atom[cx+3] = str(item[2])+'+' \
2174                                +str(item[3][0])+','+str(item[3][1])+','+str(item[3][2])
2175                            atom[cuij:cuij+6] = item[1]
2176                            Opp = G2spc.Opposite(item[0])
2177                            for xyz in Opp:
2178                                if noDuplicate(xyz,atomData):
2179                                    cell = np.asarray(np.rint(xyz-atom[cx:cx+3]),dtype=np.int32)
2180                                    cell = '1'+'+'+ \
2181                                        str(cell[0])+','+str(cell[1])+','+str(cell[2])
2182                                    atom[cx:cx+3] = xyz
2183                                    atom[cx+3] = G2spc.StringOpsProd(cell,atom[cx+3],SGData)
2184                                    atomData.append(atom[:])
2185                    else:
2186                        result = G2spc.GenAtom(XYZ,SGData,False,Move=False)
2187                        for item in result:
2188                            atom = copy.copy(atomData[ind])
2189                            atom[cx:cx+3] = item[0]
2190                            atom[cx+3] = str(item[1])+'+' \
2191                                +str(item[2][0])+','+str(item[2][1])+','+str(item[2][2])
2192                            Opp = G2spc.Opposite(item[0])
2193                            for xyz in Opp:
2194                                if noDuplicate(xyz,atomData):
2195                                    cell = np.asarray(np.rint(xyz-atom[cx:cx+3]),dtype=np.int32)
2196                                    cell = '1'+'+'+ \
2197                                        str(cell[0])+','+str(cell[1])+','+str(cell[2])
2198                                    atom[cx:cx+3] = xyz
2199                                    atom[cx+3] = G2spc.StringOpsProd(cell,atom[cx+3],SGData)
2200                                    atomData.append(atom[:])               
2201                    data['Drawing']['Atoms'] = atomData
2202            finally:
2203                wx.EndBusyCursor()
2204            UpdateDrawAtoms()
2205            drawAtoms.ClearSelection()
2206            G2plt.PlotStructure(G2frame,data)
2207           
2208    def FindBondsToo():                         #works but slow for large structures - keep as reference
2209        cx,ct,cs,ci = data['Drawing']['atomPtrs']
2210        atomData = data['Drawing']['Atoms']
2211        generalData = data['General']
2212        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])
2213        radii = generalData['BondRadii']
2214        atomTypes = generalData['AtomTypes']
2215        try:
2216            indH = atomTypes.index('H')
2217            radii[indH] = 0.5
2218        except:
2219            pass           
2220        for atom in atomData:
2221            atom[-1] = []
2222        Atoms = []
2223        for i,atom in enumerate(atomData):
2224            Atoms.append([i,np.array(atom[cx:cx+3]),atom[cs],radii[atomTypes.index(atom[ct])]])
2225        for atomA in Atoms:
2226            if atomA[2] in ['lines','sticks','ellipsoids','balls & sticks','polyhedra']:
2227                for atomB in Atoms:                   
2228                    Dx = atomB[1]-atomA[1]
2229                    DX = np.inner(Amat,Dx)
2230                    dist = np.sqrt(np.sum(DX**2))
2231                    sumR = atomA[3]+atomB[3]
2232                    if 0.5 < dist <= 0.85*sumR:
2233                        i = atomA[0]
2234                        if atomA[2] == 'polyhedra':
2235                            atomData[i][-1].append(DX)
2236                        elif atomB[1] != 'polyhedra':
2237                            j = atomB[0]
2238                            atomData[i][-1].append(Dx*atomA[3]/sumR)
2239                            atomData[j][-1].append(-Dx*atomB[3]/sumR)
2240                   
2241    def FindBondsDraw():                    #uses numpy & masks - very fast even for proteins!
2242        import numpy.ma as ma
2243        cx,ct,cs,ci = data['Drawing']['atomPtrs']
2244        hydro = data['Drawing']['showHydrogen']
2245        atomData = data['Drawing']['Atoms']
2246        generalData = data['General']
2247        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])
2248        radii = generalData['BondRadii']
2249        atomTypes = generalData['AtomTypes']
2250        try:
2251            indH = atomTypes.index('H')
2252            radii[indH] = 0.5
2253        except:
2254            pass           
2255        for atom in atomData:
2256            atom[-2] = []               #clear out old bonds/polyhedra
2257            atom[-1] = []
2258        Indx = range(len(atomData))
2259        Atoms = []
2260        Styles = []
2261        Radii = []
2262        for atom in atomData:
2263            Atoms.append(np.array(atom[cx:cx+3]))
2264            Styles.append(atom[cs])
2265            try:
2266                if not hydro and atom[ct] == 'H':
2267                    Radii.append(0.0)
2268                else:
2269                    Radii.append(radii[atomTypes.index(atom[ct])])
2270            except ValueError:          #changed atom type!
2271                Radii.append(0.20)
2272        Atoms = np.array(Atoms)
2273        Radii = np.array(Radii)
2274        IASR = zip(Indx,Atoms,Styles,Radii)
2275        for atomA in IASR:
2276            if atomA[2] in ['lines','sticks','ellipsoids','balls & sticks','polyhedra']:
2277                Dx = Atoms-atomA[1]
2278                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
2279                sumR = atomA[3]+Radii
2280                IndB = ma.nonzero(ma.masked_greater(dist-data['Drawing']['radiusFactor']*sumR,0.))                 #get indices of bonded atoms
2281                i = atomA[0]
2282                for j in IndB[0]:
2283                    if Styles[i] == 'polyhedra':
2284                        atomData[i][-2].append(np.inner(Amat,Dx[j]))
2285                    elif Styles[j] != 'polyhedra' and j > i:
2286                        atomData[i][-2].append(Dx[j]*Radii[i]/sumR[j])
2287                        atomData[j][-2].append(-Dx[j]*Radii[j]/sumR[j])
2288                if Styles[i] == 'polyhedra':
2289                    Bonds = atomData[i][-2]
2290                    Faces = []
2291                    if len(Bonds) > 2:
2292                        FaceGen = G2lat.uniqueCombinations(Bonds,3)     #N.B. this is a generator
2293                        for face in FaceGen:
2294                            vol = nl.det(face)
2295                            if abs(vol) > 1. or len(Bonds) == 3:
2296                                if vol < 0.:
2297                                    face = [face[0],face[2],face[1]]
2298                                face = np.array(face)
2299                                if not np.array([np.array(nl.det(face-bond))+0.0001 < 0 for bond in Bonds]).any():
2300                                    norm = np.cross(face[1]-face[0],face[2]-face[0])
2301                                    norm /= np.sqrt(np.sum(norm**2))
2302                                    Faces.append([face,norm])
2303                        atomData[i][-1] = Faces
2304                       
2305    def DrawAtomsDelete(event):   
2306        indx = drawAtoms.GetSelectedRows()
2307        indx.sort()
2308        if indx:
2309            atomData = data['Drawing']['Atoms']
2310            indx.reverse()
2311            for ind in indx:
2312                del atomData[ind]
2313            UpdateDrawAtoms()
2314            drawAtoms.ClearSelection()
2315            G2plt.PlotStructure(G2frame,data)
2316        event.StopPropagation()
2317       
2318    def OnReloadDrawAtoms(event):
2319        data['Drawing']['Atoms'] = []
2320        UpdateDrawAtoms()
2321        drawAtoms.ClearSelection()
2322        G2plt.PlotStructure(G2frame,data)
2323        event.StopPropagation()
2324       
2325    def FindAtomIndexByIDs(atomData,IDs,Draw=True):
2326        indx = []
2327        for i,atom in enumerate(atomData):
2328            if Draw and atom[-3] in IDs:
2329                indx.append(i)
2330            elif atom[-1] in IDs:
2331                indx.append(i)
2332        return indx
2333       
2334    def DrawAtomsDeleteByIDs(IDs):
2335        atomData = data['Drawing']['Atoms']
2336        indx = FindAtomIndexByIDs(atomData,IDs)
2337        indx.reverse()
2338        for ind in indx:
2339            del atomData[ind]
2340           
2341    def ChangeDrawAtomsByIDs(colName,IDs,value):
2342        atomData = data['Drawing']['Atoms']
2343        cx,ct,cs,ci = data['Drawing']['atomPtrs']
2344        if colName == 'Name':
2345            col = ct-1
2346        elif colName == 'Type':
2347            col = ct
2348        elif colName == 'I/A':
2349            col = cs
2350        indx = FindAtomIndexByIDs(atomData,IDs)
2351        for ind in indx:
2352            atomData[ind][col] = value
2353               
2354    def OnDrawPlane(event):
2355        indx = drawAtoms.GetSelectedRows()
2356        if len(indx) < 4:
2357            print '**** ERROR - need 4+ atoms for plane calculation'
2358            return
2359        PlaneData = {}
2360        drawingData = data['Drawing']
2361        atomData = drawingData['Atoms']
2362        colLabels = [drawAtoms.GetColLabelValue(c) for c in range(drawAtoms.GetNumberCols())]
2363        cx = colLabels.index('x')
2364        cn = colLabels.index('Name')
2365        xyz = []
2366        for i,atom in enumerate(atomData):
2367            if i in indx:
2368                xyz.append([i,]+atom[cn:cn+2]+atom[cx:cx+3])
2369        generalData = data['General']
2370        PlaneData['Name'] = generalData['Name']
2371        PlaneData['Atoms'] = xyz
2372        PlaneData['Cell'] = generalData['Cell'][1:] #+ volume
2373        G2str.BestPlane(PlaneData)
2374       
2375    def OnDrawDistVP(event):
2376        # distance to view point
2377        indx = drawAtoms.GetSelectedRows()
2378        if not indx:
2379            print '***** ERROR - no atoms selected'
2380            return
2381        generalData = data['General']
2382        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])           
2383        drawingData = data['Drawing']
2384        viewPt = np.array(drawingData['viewPoint'][0])
2385        print ' Distance from view point at %.3f %.3f %.3f to:'%(viewPt[0],viewPt[1],viewPt[2])
2386        atomDData = drawingData['Atoms']
2387        colLabels = [drawAtoms.GetColLabelValue(c) for c in range(drawAtoms.GetNumberCols())]
2388        cx = colLabels.index('x')
2389        cn = colLabels.index('Name')
2390        for i in indx:
2391            atom = atomDData[i]
2392            Dx = np.array(atom[cx:cx+3])-viewPt
2393            dist = np.sqrt(np.sum(np.inner(Amat,Dx)**2,axis=0))
2394            print 'Atom: %8s (%12s) distance = %.3f'%(atom[cn],atom[cx+3],dist)
2395   
2396    def OnDrawDAT(event):
2397        #distance, angle, torsion
2398        indx = drawAtoms.GetSelectedRows()
2399        if len(indx) not in [2,3,4]:
2400            print '**** ERROR - wrong number of atoms for distance, angle or torsion calculation'
2401            return
2402        DATData = {}
2403        ocx,oct,ocs,cia = data['General']['AtomPtrs']
2404        drawingData = data['Drawing']
2405        atomData = data['Atoms']
2406        atomDData = drawingData['Atoms']
2407        colLabels = [drawAtoms.GetColLabelValue(c) for c in range(drawAtoms.GetNumberCols())]
2408        cx = colLabels.index('x')
2409        cn = colLabels.index('Name')
2410        cid = colLabels.index('I/A')+8
2411        xyz = []
2412        Oxyz = []
2413        DATData['Natoms'] = len(indx)
2414        for i in indx:
2415            atom = atomDData[i]
2416            xyz.append([i,]+atom[cn:cn+2]+atom[cx:cx+4]) #also gets Sym Op
2417            id = FindAtomIndexByIDs(atomData,[atom[cid],],False)[0]
2418            Oxyz.append([id,]+atomData[id][cx+1:cx+4])
2419        DATData['Datoms'] = xyz
2420        DATData['Oatoms'] = Oxyz
2421        generalData = data['General']
2422        DATData['Name'] = generalData['Name']
2423        DATData['SGData'] = generalData['SGData']
2424        DATData['Cell'] = generalData['Cell'][1:] #+ volume
2425        if 'pId' in data:
2426            DATData['pId'] = data['pId']
2427            DATData['covData'] = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.root, 'Covariance'))
2428        G2str.DisAglTor(DATData)
2429               
2430################################################################################
2431#### Draw Options page
2432################################################################################
2433
2434    def UpdateDrawOptions():
2435        import copy
2436        import wx.lib.colourselect as wcs
2437        generalData = data['General']
2438        SetupDrawingData()
2439        drawingData = data['Drawing']
2440        if generalData['Type'] == 'nuclear':
2441            pickChoice = ['Atoms','Bonds','Torsions','Planes']
2442        elif generalData['Type'] == 'macromolecular':
2443            pickChoice = ['Atoms','Residues','Chains','Bonds','Torsions','Planes','phi/psi']
2444
2445        def SlopSizer():
2446           
2447            def OnCameraPos(event):
2448                drawingData['cameraPos'] = cameraPos.GetValue()
2449                cameraPosTxt.SetLabel(' Camera Distance: '+'%.2f'%(drawingData['cameraPos']))
2450                ZclipTxt.SetLabel(' Z clipping: '+'%.2fA'%(drawingData['Zclip']*drawingData['cameraPos']/100.))
2451                G2plt.PlotStructure(G2frame,data)
2452
2453            def OnZclip(event):
2454                drawingData['Zclip'] = Zclip.GetValue()
2455                ZclipTxt.SetLabel(' Z clipping: '+'%.2fA'%(drawingData['Zclip']*drawingData['cameraPos']/100.))
2456                G2plt.PlotStructure(G2frame,data)
2457               
2458            def OnVdWScale(event):
2459                drawingData['vdwScale'] = vdwScale.GetValue()/100.
2460                vdwScaleTxt.SetLabel(' van der Waals scale: '+'%.2f'%(drawingData['vdwScale']))
2461                G2plt.PlotStructure(G2frame,data)
2462   
2463            def OnEllipseProb(event):
2464                drawingData['ellipseProb'] = ellipseProb.GetValue()
2465                ellipseProbTxt.SetLabel(' Ellipsoid probability: '+'%d%%'%(drawingData['ellipseProb']))
2466                G2plt.PlotStructure(G2frame,data)
2467   
2468            def OnBallScale(event):
2469                drawingData['ballScale'] = ballScale.GetValue()/100.
2470                ballScaleTxt.SetLabel(' Ball scale: '+'%.2f'%(drawingData['ballScale']))
2471                G2plt.PlotStructure(G2frame,data)
2472
2473            def OnBondRadius(event):
2474                drawingData['bondRadius'] = bondRadius.GetValue()/100.
2475                bondRadiusTxt.SetLabel(' Bond radius, A: '+'%.2f'%(drawingData['bondRadius']))
2476                G2plt.PlotStructure(G2frame,data)
2477               
2478            def OnContourLevel(event):
2479                drawingData['contourLevel'] = contourLevel.GetValue()/100.
2480                contourLevelTxt.SetLabel(' Contour level: '+'%.2f'%(drawingData['contourLevel']*generalData['Map']['rhoMax']))
2481                G2plt.PlotStructure(G2frame,data)
2482
2483            def OnMapSize(event):
2484                drawingData['mapSize'] = mapSize.GetValue()/10.
2485                mapSizeTxt.SetLabel(' Map radius, A: '+'%.1f'%(drawingData['mapSize']))
2486                G2plt.PlotStructure(G2frame,data)
2487
2488           
2489            slopSizer = wx.BoxSizer(wx.HORIZONTAL)
2490            slideSizer = wx.FlexGridSizer(7,2)
2491            slideSizer.AddGrowableCol(1,1)
2492   
2493            cameraPosTxt = wx.StaticText(dataDisplay,-1,
2494                ' Camera Distance: '+'%.2f'%(drawingData['cameraPos']),name='cameraPos')
2495            slideSizer.Add(cameraPosTxt,0,wx.ALIGN_CENTER_VERTICAL)
2496            cameraPos = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=drawingData['cameraPos'],name='cameraSlider')
2497            cameraPos.SetRange(10,500)
2498            cameraPos.Bind(wx.EVT_SLIDER, OnCameraPos)
2499            slideSizer.Add(cameraPos,1,wx.EXPAND|wx.RIGHT)
2500           
2501            ZclipTxt = wx.StaticText(dataDisplay,-1,' Z clipping: '+'%.2fA'%(drawingData['Zclip']*drawingData['cameraPos']/100.))
2502            slideSizer.Add(ZclipTxt,0,wx.ALIGN_CENTER_VERTICAL)
2503            Zclip = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=drawingData['Zclip'])
2504            Zclip.SetRange(1,99)
2505            Zclip.Bind(wx.EVT_SLIDER, OnZclip)
2506            slideSizer.Add(Zclip,1,wx.EXPAND|wx.RIGHT)
2507           
2508            vdwScaleTxt = wx.StaticText(dataDisplay,-1,' van der Waals scale: '+'%.2f'%(drawingData['vdwScale']))
2509            slideSizer.Add(vdwScaleTxt,0,wx.ALIGN_CENTER_VERTICAL)
2510            vdwScale = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=int(100*drawingData['vdwScale']))
2511            vdwScale.Bind(wx.EVT_SLIDER, OnVdWScale)
2512            slideSizer.Add(vdwScale,1,wx.EXPAND|wx.RIGHT)
2513   
2514            ellipseProbTxt = wx.StaticText(dataDisplay,-1,' Ellipsoid probability: '+'%d%%'%(drawingData['ellipseProb']))
2515            slideSizer.Add(ellipseProbTxt,0,wx.ALIGN_CENTER_VERTICAL)
2516            ellipseProb = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=drawingData['ellipseProb'])
2517            ellipseProb.SetRange(1,99)
2518            ellipseProb.Bind(wx.EVT_SLIDER, OnEllipseProb)
2519            slideSizer.Add(ellipseProb,1,wx.EXPAND|wx.RIGHT)
2520   
2521            ballScaleTxt = wx.StaticText(dataDisplay,-1,' Ball scale: '+'%.2f'%(drawingData['ballScale']))
2522            slideSizer.Add(ballScaleTxt,0,wx.ALIGN_CENTER_VERTICAL)
2523            ballScale = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=int(100*drawingData['ballScale']))
2524            ballScale.Bind(wx.EVT_SLIDER, OnBallScale)
2525            slideSizer.Add(ballScale,1,wx.EXPAND|wx.RIGHT)
2526   
2527            bondRadiusTxt = wx.StaticText(dataDisplay,-1,' Bond radius, A: '+'%.2f'%(drawingData['bondRadius']))
2528            slideSizer.Add(bondRadiusTxt,0,wx.ALIGN_CENTER_VERTICAL)
2529            bondRadius = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=int(100*drawingData['bondRadius']))
2530            bondRadius.SetRange(1,25)
2531            bondRadius.Bind(wx.EVT_SLIDER, OnBondRadius)
2532            slideSizer.Add(bondRadius,1,wx.EXPAND|wx.RIGHT)
2533           
2534            if generalData['Map']['rhoMax']:
2535                contourLevelTxt = wx.StaticText(dataDisplay,-1,' Contour level: '+'%.2f'%(drawingData['contourLevel']*generalData['Map']['rhoMax']))
2536                slideSizer.Add(contourLevelTxt,0,wx.ALIGN_CENTER_VERTICAL)
2537                contourLevel = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=int(100*drawingData['contourLevel']))
2538                contourLevel.SetRange(1,100)
2539                contourLevel.Bind(wx.EVT_SLIDER, OnContourLevel)
2540                slideSizer.Add(contourLevel,1,wx.EXPAND|wx.RIGHT)
2541                mapSizeTxt = wx.StaticText(dataDisplay,-1,' Map radius, A: '+'%.1f'%(drawingData['mapSize']))
2542                slideSizer.Add(mapSizeTxt,0,wx.ALIGN_CENTER_VERTICAL)
2543                mapSize = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=int(10*drawingData['mapSize']))
2544                mapSize.SetRange(1,100)
2545                mapSize.Bind(wx.EVT_SLIDER, OnMapSize)
2546                slideSizer.Add(mapSize,1,wx.EXPAND|wx.RIGHT)
2547           
2548            slopSizer.Add(slideSizer,1,wx.EXPAND|wx.RIGHT)
2549            slopSizer.Add((10,5),0)
2550            slopSizer.SetMinSize(wx.Size(350,10))
2551            return slopSizer
2552           
2553        def ShowSizer():
2554           
2555            def OnBackColor(event):
2556                drawingData['backColor'] = event.GetValue()
2557                G2plt.PlotStructure(G2frame,data)
2558   
2559            def OnShowABC(event):
2560                drawingData['showABC'] = showABC.GetValue()
2561                G2plt.PlotStructure(G2frame,data)
2562   
2563            def OnShowUnitCell(event):
2564                drawingData['unitCellBox'] = unitCellBox.GetValue()
2565                G2plt.PlotStructure(G2frame,data)
2566   
2567            def OnShowHyd(event):
2568                drawingData['showHydrogen'] = showHydrogen.GetValue()
2569                FindBondsDraw()
2570                G2plt.PlotStructure(G2frame,data)
2571               
2572            def OnViewPoint(event):
2573                Obj = event.GetEventObject()
2574                viewPt = Obj.GetValue().split()
2575                try:
2576                    VP = [float(viewPt[i]) for i in range(3)]
2577                except (ValueError,IndexError):
2578                    VP = drawingData['viewPoint'][0]
2579                Obj.SetValue('%.3f %.3f %.3f'%(VP[0],VP[1],VP[2]))
2580                drawingData['viewPoint'][0] = VP
2581                G2plt.PlotStructure(G2frame,data)
2582               
2583            def OnViewDir(event):
2584                event.Skip()
2585                Obj = event.GetEventObject()
2586                viewDir = Obj.GetValue().split()
2587                try:
2588                    Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])
2589                    VD = np.array([float(viewDir[i]) for i in range(3)])
2590#                    VD = np.inner(Amat,VD)
2591                    VD /= np.sqrt(np.sum(VD**2))
2592                    V = np.array(drawingData['viewDir'])
2593#                    V = np.inner(Amat,V)
2594                    V /= np.sqrt(np.sum(V**2))
2595                    A = acosd(np.sum(V*VD))
2596                    VX = np.cross(V,VD)
2597                    QV = G2mth.AVdeg2Q(A,VX)
2598                    Q = drawingData['Quaternion']
2599                    drawingData['Quaternion'] = G2mth.prodQQ(Q,QV)
2600                except (ValueError,IndexError):
2601                    VD = drawingData['viewDir']
2602                Obj.SetValue('%.3f %.3f %.3f'%(VD[0],VD[1],VD[2]))
2603                drawingData['viewDir'] = VD
2604                G2plt.PlotStructure(G2frame,data)
2605                               
2606            showSizer = wx.BoxSizer(wx.VERTICAL)           
2607            lineSizer = wx.BoxSizer(wx.HORIZONTAL)
2608            lineSizer.Add(wx.StaticText(dataDisplay,-1,' Background color:'),0,wx.ALIGN_CENTER_VERTICAL)
2609            backColor = wcs.ColourSelect(dataDisplay, -1,colour=drawingData['backColor'],size=wx.Size(25,25))
2610            backColor.Bind(wcs.EVT_COLOURSELECT, OnBackColor)
2611            lineSizer.Add(backColor,0,wx.ALIGN_CENTER_VERTICAL)
2612            lineSizer.Add(wx.StaticText(dataDisplay,-1,' View Dir.:'),0,wx.ALIGN_CENTER_VERTICAL)
2613            VD = drawingData['viewDir']
2614            viewDir = wx.TextCtrl(dataDisplay,value='%.3f %.3f %.3f'%(VD[0],VD[1],VD[2]),
2615                style=wx.TE_PROCESS_ENTER,size=wx.Size(140,20),name='viewDir')
2616            viewDir.Bind(wx.EVT_TEXT_ENTER,OnViewDir)
2617            viewDir.Bind(wx.EVT_KILL_FOCUS,OnViewDir)
2618            lineSizer.Add(viewDir,0,wx.ALIGN_CENTER_VERTICAL)
2619            showSizer.Add(lineSizer)
2620            showSizer.Add((0,5),0)
2621           
2622            lineSizer = wx.BoxSizer(wx.HORIZONTAL)
2623            showABC = wx.CheckBox(dataDisplay,-1,label=' Show view point?')
2624            showABC.Bind(wx.EVT_CHECKBOX, OnShowABC)
2625            showABC.SetValue(drawingData['showABC'])
2626            lineSizer.Add(showABC,0,wx.ALIGN_CENTER_VERTICAL)
2627            lineSizer.Add(wx.StaticText(dataDisplay,-1,' View Point:'),0,wx.ALIGN_CENTER_VERTICAL)
2628            VP = drawingData['viewPoint'][0]
2629            viewPoint = wx.TextCtrl(dataDisplay,value='%.3f %.3f %.3f'%(VP[0],VP[1],VP[2]),
2630                style=wx.TE_PROCESS_ENTER,size=wx.Size(140,20),name='viewPoint')
2631            viewPoint.Bind(wx.EVT_TEXT_ENTER,OnViewPoint)
2632            viewPoint.Bind(wx.EVT_KILL_FOCUS,OnViewPoint)
2633            lineSizer.Add(viewPoint,0,wx.ALIGN_CENTER_VERTICAL)
2634            showSizer.Add(lineSizer)
2635            showSizer.Add((0,5),0)
2636           
2637            line2Sizer = wx.BoxSizer(wx.HORIZONTAL)
2638   
2639            unitCellBox = wx.CheckBox(dataDisplay,-1,label=' Show unit cell?')
2640            unitCellBox.Bind(wx.EVT_CHECKBOX, OnShowUnitCell)
2641            unitCellBox.SetValue(drawingData['unitCellBox'])
2642            line2Sizer.Add(unitCellBox,0,wx.ALIGN_CENTER_VERTICAL)
2643   
2644            showHydrogen = wx.CheckBox(dataDisplay,-1,label=' Show hydrogens?')
2645            showHydrogen.Bind(wx.EVT_CHECKBOX, OnShowHyd)
2646            showHydrogen.SetValue(drawingData['showHydrogen'])
2647            line2Sizer.Add(showHydrogen,0,wx.ALIGN_CENTER_VERTICAL)
2648            showSizer.Add(line2Sizer)
2649            return showSizer
2650           
2651        def RadSizer():
2652           
2653            def OnSizeHatoms(event):
2654                try:
2655                    value = max(0.1,min(1.2,float(sizeH.GetValue())))
2656                except ValueError:
2657                    value = 0.5
2658                drawingData['sizeH'] = value
2659                sizeH.SetValue("%.2f"%(value))
2660                G2plt.PlotStructure(G2frame,data)
2661               
2662            def OnRadFactor(event):
2663                try:
2664                    value = max(0.1,min(1.2,float(radFactor.GetValue())))
2665                except ValueError:
2666                    value = 0.85
2667                drawingData['radiusFactor'] = value
2668                radFactor.SetValue("%.2f"%(value))
2669                FindBondsDraw()
2670                G2plt.PlotStructure(G2frame,data)
2671           
2672            radSizer = wx.BoxSizer(wx.HORIZONTAL)
2673            radSizer.Add(wx.StaticText(dataDisplay,-1,' Hydrogen radius, A:  '),0,wx.ALIGN_CENTER_VERTICAL)
2674            sizeH = wx.TextCtrl(dataDisplay,-1,value='%.2f'%(drawingData['sizeH']),size=wx.Size(60,20),style=wx.TE_PROCESS_ENTER)
2675            sizeH.Bind(wx.EVT_TEXT_ENTER,OnSizeHatoms)
2676            sizeH.Bind(wx.EVT_KILL_FOCUS,OnSizeHatoms)
2677            radSizer.Add(sizeH,0,wx.ALIGN_CENTER_VERTICAL)
2678   
2679            radSizer.Add(wx.StaticText(dataDisplay,-1,' Bond search factor:  '),0,wx.ALIGN_CENTER_VERTICAL)
2680            radFactor = wx.TextCtrl(dataDisplay,value='%.2f'%(drawingData['radiusFactor']),size=wx.Size(60,20),style=wx.TE_PROCESS_ENTER)
2681            radFactor.Bind(wx.EVT_TEXT_ENTER,OnRadFactor)
2682            radFactor.Bind(wx.EVT_KILL_FOCUS,OnRadFactor)
2683            radSizer.Add(radFactor,0,wx.ALIGN_CENTER_VERTICAL)
2684            return radSizer
2685
2686        G2frame.dataFrame.SetStatusText('')
2687        drawOptions.DestroyChildren()
2688        dataDisplay = wx.Panel(drawOptions)
2689        mainSizer = wx.BoxSizer(wx.VERTICAL)
2690        mainSizer.Add((5,5),0)
2691        mainSizer.Add(wx.StaticText(dataDisplay,-1,' Drawing controls:'),0,wx.ALIGN_CENTER_VERTICAL)
2692        mainSizer.Add((5,5),0)       
2693        mainSizer.Add(SlopSizer(),0)
2694        mainSizer.Add((5,5),0)
2695        mainSizer.Add(ShowSizer(),0,)
2696        mainSizer.Add((5,5),0)
2697        mainSizer.Add(RadSizer(),0,)
2698
2699        dataDisplay.SetSizer(mainSizer)
2700        Size = mainSizer.Fit(G2frame.dataFrame)
2701        Size[1] += 35                           #compensate for status bar
2702        dataDisplay.SetSize(Size)
2703        G2frame.dataFrame.setSizePosLeft(Size)
2704
2705################################################################################
2706####  Texture routines
2707################################################################################
2708       
2709    def UpdateTexture():
2710        G2frame.dataFrame.SetStatusText('')
2711        generalData = data['General']       
2712        SGData = generalData['SGData']
2713        try:
2714            textureData = generalData['SH Texture']
2715        except KeyError:            #fix old files!
2716            textureData = generalData['SH Texture'] = {'Order':0,'Model':'cylindrical',
2717                'Sample omega':[False,0.0],'Sample chi':[False,0.0],'Sample phi':[False,0.0],
2718                'SH Coeff':[False,{}],'SHShow':False,'PFhkl':[0,0,1],
2719                'PFxyz':[0,0,1.],'PlotType':'Pole figure'}
2720        if 'SHShow' not in textureData:     #another fix
2721            textureData.update({'SHShow':False,'PFhkl':[0,0,1],'PFxyz':[0,0,1.],'PlotType':'Pole figure'})
2722        try:                        #another fix!
2723            x = textureData['PlotType']
2724        except KeyError:
2725            textureData.update({'PFxyz':[0,0,1.],'PlotType':'Pole figure'})
2726        shModels = ['cylindrical','none','shear - 2/m','rolling - mmm']
2727        SamSym = dict(zip(shModels,['0','-1','2/m','mmm']))
2728        if generalData['doPawley'] and G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Sequental results'):
2729            G2frame.dataFrame.RefineTexture.Enable(True)
2730        shAngles = ['omega','chi','phi']
2731       
2732        def SetSHCoef():
2733            cofNames = G2lat.GenSHCoeff(SGData['SGLaue'],SamSym[textureData['Model']],textureData['Order'])
2734            newSHCoef = dict(zip(cofNames,np.zeros(len(cofNames))))
2735            SHCoeff = textureData['SH Coeff'][1]
2736            for cofName in SHCoeff:
2737                if cofName in  cofNames:
2738                    newSHCoef[cofName] = SHCoeff[cofName]
2739            return newSHCoef
2740       
2741        def OnShOrder(event):
2742            Obj = event.GetEventObject()
2743            textureData['Order'] = int(Obj.GetValue())
2744            textureData['SH Coeff'][1] = SetSHCoef()
2745            wx.CallAfter(UpdateTexture)
2746            G2plt.PlotTexture(G2frame,data)
2747                       
2748        def OnShModel(event):
2749            Obj = event.GetEventObject()
2750            textureData['Model'] = Obj.GetValue()
2751            textureData['SH Coeff'][1] = SetSHCoef()
2752            wx.CallAfter(UpdateTexture)
2753            G2plt.PlotTexture(G2frame,data)
2754           
2755        def OnSHRefine(event):
2756            Obj = event.GetEventObject()
2757            textureData['SH Coeff'][0] = Obj.GetValue()
2758           
2759        def OnSHShow(event):
2760            Obj = event.GetEventObject()
2761            textureData['SHShow'] = Obj.GetValue()
2762            wx.CallAfter(UpdateTexture)
2763           
2764        def OnProjSel(event):
2765            Obj = event.GetEventObject()
2766            G2frame.Projection = Obj.GetValue()
2767            G2plt.PlotTexture(G2frame,data)
2768           
2769        def OnColorSel(event):
2770            Obj = event.GetEventObject()
2771            G2frame.ContourColor = Obj.GetValue()
2772            G2plt.PlotTexture(G2frame,data)
2773           
2774        def OnAngRef(event):
2775            Obj = event.GetEventObject()
2776            textureData[angIndx[Obj.GetId()]][0] = Obj.GetValue()
2777           
2778        def OnAngValue(event):
2779            Obj = event.GetEventObject()
2780            try:
2781                value =  float(Obj.GetValue())
2782            except ValueError:
2783                value = textureData[valIndx[Obj.GetId()]][1]
2784            Obj.SetValue('%8.2f'%(value))
2785            textureData[valIndx[Obj.GetId()]][1] = value
2786           
2787        def OnODFValue(event): 
2788            Obj = event.GetEventObject()
2789            try:
2790                value =  float(Obj.GetValue())
2791            except ValueError:
2792                value = textureData['SH Coeff'][1][ODFIndx[Obj.GetId()]]
2793            Obj.SetValue('%8.3f'%(value))
2794            textureData['SH Coeff'][1][ODFIndx[Obj.GetId()]] = value
2795            G2plt.PlotTexture(G2frame,data)
2796           
2797        def OnPfType(event):
2798            Obj = event.GetEventObject()
2799            textureData['PlotType'] = Obj.GetValue()
2800            wx.CallAfter(UpdateTexture)
2801            G2plt.PlotTexture(G2frame,data)
2802           
2803        def OnPFValue(event):
2804            Obj = event.GetEventObject()
2805            Saxis = Obj.GetValue().split()
2806            if textureData['PlotType'] in ['Pole figure','Axial pole distribution']:               
2807                try:
2808                    hkl = [int(Saxis[i]) for i in range(3)]
2809                except (ValueError,IndexError):
2810                    hkl = textureData['PFhkl']
2811                if not np.any(np.array(hkl)):       #can't be all zeros!
2812                    hkl = textureData['PFhkl']
2813                Obj.SetValue('%d %d %d'%(hkl[0],hkl[1],hkl[2]))
2814                textureData['PFhkl'] = hkl
2815            else:
2816                try:
2817                    xyz = [float(Saxis[i]) for i in range(3)]
2818                except (ValueError,IndexError):
2819                    xyz = textureData['PFxyz']
2820                if not np.any(np.array(xyz)):       #can't be all zeros!
2821                    xyz = textureData['PFxyz']
2822                Obj.SetValue('%3.1f %3.1f %3.1f'%(xyz[0],xyz[1],xyz[2]))
2823                textureData['PFxyz'] = xyz
2824            G2plt.PlotTexture(G2frame,data)
2825
2826        if Texture.GetSizer():
2827            Texture.GetSizer().Clear(True)
2828        mainSizer = wx.BoxSizer(wx.VERTICAL)
2829        titleSizer = wx.BoxSizer(wx.HORIZONTAL)
2830        titleSizer.Add(wx.StaticText(Texture,-1,'Spherical harmonics texture data for '+PhaseName+':'),0,wx.ALIGN_CENTER_VERTICAL)
2831        titleSizer.Add(wx.StaticText(Texture,-1,
2832            ' Texture Index J = %7.3f'%(G2lat.textureIndex(textureData['SH Coeff'][1]))),
2833            0,wx.ALIGN_CENTER_VERTICAL)
2834        mainSizer.Add(titleSizer,0)
2835        mainSizer.Add((0,5),0)
2836        shSizer = wx.FlexGridSizer(1,6,5,5)
2837        shSizer.Add(wx.StaticText(Texture,-1,'Texture model: '),0,wx.ALIGN_CENTER_VERTICAL)
2838        shModel = wx.ComboBox(Texture,-1,value=textureData['Model'],choices=shModels,
2839            style=wx.CB_READONLY|wx.CB_DROPDOWN)
2840        shModel.Bind(wx.EVT_COMBOBOX,OnShModel)
2841        shSizer.Add(shModel,0,wx.ALIGN_CENTER_VERTICAL)
2842        shSizer.Add(wx.StaticText(Texture,-1,'  Harmonic order: '),0,wx.ALIGN_CENTER_VERTICAL)
2843        shOrder = wx.ComboBox(Texture,-1,value=str(textureData['Order']),choices=[str(2*i) for i in range(18)],
2844            style=wx.CB_READONLY|wx.CB_DROPDOWN)
2845        shOrder.Bind(wx.EVT_COMBOBOX,OnShOrder)
2846        shSizer.Add(shOrder,0,wx.ALIGN_CENTER_VERTICAL)
2847        shRef = wx.CheckBox(Texture,-1,label=' Refine texture?')
2848        shRef.SetValue(textureData['SH Coeff'][0])
2849        shRef.Bind(wx.EVT_CHECKBOX, OnSHRefine)
2850        shSizer.Add(shRef,0,wx.ALIGN_CENTER_VERTICAL)
2851        shShow = wx.CheckBox(Texture,-1,label=' Show coeff.?')
2852        shShow.SetValue(textureData['SHShow'])
2853        shShow.Bind(wx.EVT_CHECKBOX, OnSHShow)
2854        shSizer.Add(shShow,0,wx.ALIGN_CENTER_VERTICAL)
2855        mainSizer.Add(shSizer,0,0)
2856        mainSizer.Add((0,5),0)
2857        PTSizer = wx.FlexGridSizer(2,4,5,5)
2858        PTSizer.Add(wx.StaticText(Texture,-1,' Texture plot type: '),0,wx.ALIGN_CENTER_VERTICAL)
2859        choices = ['Axial pole distribution','Pole figure','Inverse pole figure']           
2860        pfType = wx.ComboBox(Texture,-1,value=str(textureData['PlotType']),choices=choices,
2861            style=wx.CB_READONLY|wx.CB_DROPDOWN)
2862        pfType.Bind(wx.EVT_COMBOBOX,OnPfType)
2863        PTSizer.Add(pfType,0,wx.ALIGN_CENTER_VERTICAL)
2864        if 'Axial' not in textureData['PlotType']:
2865            PTSizer.Add(wx.StaticText(Texture,-1,' Projection type: '),0,wx.ALIGN_CENTER_VERTICAL)
2866            projSel = wx.ComboBox(Texture,-1,value=G2frame.Projection,choices=['equal area','stereographic','3D display'],
2867                style=wx.CB_READONLY|wx.CB_DROPDOWN)
2868            projSel.Bind(wx.EVT_COMBOBOX,OnProjSel)
2869            PTSizer.Add(projSel,0,wx.ALIGN_CENTER_VERTICAL)
2870        if textureData['PlotType'] in ['Pole figure','Axial pole distribution']:
2871            PTSizer.Add(wx.StaticText(Texture,-1,' Pole figure HKL: '),0,wx.ALIGN_CENTER_VERTICAL)
2872            PH = textureData['PFhkl']
2873            pfVal = wx.TextCtrl(Texture,-1,'%d %d %d'%(PH[0],PH[1],PH[2]),style=wx.TE_PROCESS_ENTER)
2874        else:
2875            PTSizer.Add(wx.StaticText(Texture,-1,' Inverse pole figure XYZ: '),0,wx.ALIGN_CENTER_VERTICAL)
2876            PX = textureData['PFxyz']
2877            pfVal = wx.TextCtrl(Texture,-1,'%3.1f %3.1f %3.1f'%(PX[0],PX[1],PX[2]),style=wx.TE_PROCESS_ENTER)
2878        pfVal.Bind(wx.EVT_TEXT_ENTER,OnPFValue)
2879        pfVal.Bind(wx.EVT_KILL_FOCUS,OnPFValue)
2880        PTSizer.Add(pfVal,0,wx.ALIGN_CENTER_VERTICAL)
2881        if 'Axial' not in textureData['PlotType']:
2882            PTSizer.Add(wx.StaticText(Texture,-1,' Color scheme'),0,wx.ALIGN_CENTER_VERTICAL)
2883            choice = [m for m in mpl.cm.datad.keys() if not m.endswith("_r")]
2884            choice.sort()
2885            colorSel = wx.ComboBox(Texture,-1,value=G2frame.ContourColor,choices=choice,
2886                style=wx.CB_READONLY|wx.CB_DROPDOWN)
2887            colorSel.Bind(wx.EVT_COMBOBOX,OnColorSel)
2888            PTSizer.Add(colorSel,0,wx.ALIGN_CENTER_VERTICAL)       
2889        mainSizer.Add(PTSizer,0,wx.ALIGN_CENTER_VERTICAL)
2890        mainSizer.Add((0,5),0)
2891        if textureData['SHShow']:
2892            mainSizer.Add(wx.StaticText(Texture,-1,'Spherical harmonic coefficients: '),0,wx.ALIGN_CENTER_VERTICAL)
2893            mainSizer.Add((0,5),0)
2894            ODFSizer = wx.FlexGridSizer(2,8,2,2)
2895            ODFIndx = {}
2896            ODFkeys = textureData['SH Coeff'][1].keys()
2897            ODFkeys.sort()
2898            for item in ODFkeys:
2899                ODFSizer.Add(wx.StaticText(Texture,-1,item),0,wx.ALIGN_CENTER_VERTICAL)
2900                ODFval = wx.TextCtrl(Texture,wx.ID_ANY,'%8.3f'%(textureData['SH Coeff'][1][item]),style=wx.TE_PROCESS_ENTER)
2901                ODFIndx[ODFval.GetId()] = item
2902                ODFval.Bind(wx.EVT_TEXT_ENTER,OnODFValue)
2903                ODFval.Bind(wx.EVT_KILL_FOCUS,OnODFValue)
2904                ODFSizer.Add(ODFval,0,wx.ALIGN_CENTER_VERTICAL)
2905            mainSizer.Add(ODFSizer,0,wx.ALIGN_CENTER_VERTICAL)
2906            mainSizer.Add((0,5),0)
2907        mainSizer.Add((0,5),0)
2908        mainSizer.Add(wx.StaticText(Texture,-1,'Sample orientation angles: '),0,wx.ALIGN_CENTER_VERTICAL)
2909        mainSizer.Add((0,5),0)
2910        angSizer = wx.BoxSizer(wx.HORIZONTAL)
2911        angIndx = {}
2912        valIndx = {}
2913        for item in ['Sample omega','Sample chi','Sample phi']:
2914            angRef = wx.CheckBox(Texture,-1,label=item+': ')
2915            angRef.SetValue(textureData[item][0])
2916            angIndx[angRef.GetId()] = item
2917            angRef.Bind(wx.EVT_CHECKBOX, OnAngRef)
2918            angSizer.Add(angRef,0,wx.ALIGN_CENTER_VERTICAL)
2919            angVal = wx.TextCtrl(Texture,wx.ID_ANY,'%8.2f'%(textureData[item][1]),style=wx.TE_PROCESS_ENTER)
2920            valIndx[angVal.GetId()] = item
2921            angVal.Bind(wx.EVT_TEXT_ENTER,OnAngValue)
2922            angVal.Bind(wx.EVT_KILL_FOCUS,OnAngValue)
2923            angSizer.Add(angVal,0,wx.ALIGN_CENTER_VERTICAL)
2924            angSizer.Add((5,0),0)
2925        mainSizer.Add(angSizer,0,wx.ALIGN_CENTER_VERTICAL)
2926        Texture.SetSizer(mainSizer,True)
2927        mainSizer.Fit(G2frame.dataFrame)
2928        Size = mainSizer.GetMinSize()
2929        Size[0] += 40
2930        Size[1] = max(Size[1],250) + 35
2931        Texture.SetSize(Size)
2932        Texture.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
2933        Size[1] = min(Size[1],450)
2934        G2frame.dataFrame.setSizePosLeft(Size)
2935
2936################################################################################
2937##### DData routines
2938################################################################################
2939       
2940    def UpdateDData():
2941        G2frame.dataFrame.SetStatusText('')
2942        UseList = data['Histograms']
2943        if UseList:
2944            G2frame.dataFrame.DataMenu.Enable(G2gd.wxID_DATADELETE,True)
2945            G2frame.Refine.Enable(True)
2946        else:
2947            G2frame.dataFrame.DataMenu.Enable(G2gd.wxID_DATADELETE,False)
2948            G2frame.Refine.Enable(False)           
2949        generalData = data['General']       
2950        SGData = generalData['SGData']
2951        keyList = UseList.keys()
2952        keyList.sort()
2953        PWDR = any(['PWDR' in item for item in keyList])
2954        Indx = {}
2955       
2956        def PlotSizer():
2957
2958            def OnPlotSel(event):
2959                Obj = event.GetEventObject()
2960                generalData['Data plot type'] = Obj.GetStringSelection()
2961                wx.CallAfter(UpdateDData)
2962                G2plt.PlotSizeStrainPO(G2frame,data)
2963               
2964            def OnPOhkl(event):
2965                Obj = event.GetEventObject()
2966                Saxis = Obj.GetValue().split()
2967                try:
2968                    hkl = [int(Saxis[i]) for i in range(3)]
2969                except (ValueError,IndexError):
2970                    hkl = generalData['POhkl']
2971                if not np.any(np.array(hkl)):
2972                    hkl = generalData['POhkl']
2973                generalData['POhkl'] = hkl
2974                h,k,l = hkl
2975                Obj.SetValue('%3d %3d %3d'%(h,k,l)) 
2976                G2plt.PlotSizeStrainPO(G2frame,data)
2977           
2978            plotSizer = wx.BoxSizer(wx.VERTICAL)
2979            choice = ['None','Mustrain','Size','Preferred orientation']
2980            plotSel = wx.RadioBox(DData,-1,'Select plot type:',choices=choice,
2981                majorDimension=2,style=wx.RA_SPECIFY_COLS)
2982            plotSel.SetStringSelection(generalData['Data plot type'])
2983            plotSel.Bind(wx.EVT_RADIOBOX,OnPlotSel)   
2984            plotSizer.Add(plotSel)
2985            if generalData['Data plot type'] == 'Preferred orientation':
2986                POhklSizer = wx.BoxSizer(wx.HORIZONTAL)
2987                POhklSizer.Add(wx.StaticText(DData,-1,' Plot preferred orientation for H K L: '),0,wx.ALIGN_CENTER_VERTICAL)
2988                h,k,l = generalData['POhkl']
2989                poAxis = wx.TextCtrl(DData,-1,'%3d %3d %3d'%(h,k,l),style=wx.TE_PROCESS_ENTER)
2990                poAxis.Bind(wx.EVT_TEXT_ENTER,OnPOhkl)
2991                poAxis.Bind(wx.EVT_KILL_FOCUS,OnPOhkl)
2992                POhklSizer.Add(poAxis,0,wx.ALIGN_CENTER_VERTICAL)
2993                plotSizer.Add(POhklSizer)           
2994            return plotSizer
2995           
2996        def ScaleSizer():
2997           
2998            def OnScaleRef(event):
2999                Obj = event.GetEventObject()
3000                UseList[Indx[Obj.GetId()]]['Scale'][1] = Obj.GetValue()
3001               
3002            def OnScaleVal(event):
3003                Obj = event.GetEventObject()
3004                try:
3005                    scale = float(Obj.GetValue())
3006                    if scale > 0:
3007                        UseList[Indx[Obj.GetId()]]['Scale'][0] = scale
3008                except ValueError:
3009                    pass
3010                Obj.SetValue("%.4f"%(UseList[Indx[Obj.GetId()]]['Scale'][0]))          #reset in case of error
3011                           
3012            scaleSizer = wx.BoxSizer(wx.HORIZONTAL)
3013            if 'PWDR' in item:
3014                scaleRef = wx.CheckBox(DData,-1,label=' Phase fraction: ')
3015            elif 'HKLF' in item:
3016                scaleRef = wx.CheckBox(DData,-1,label=' Scale factor: ')               
3017            scaleRef.SetValue(UseList[item]['Scale'][1])
3018            Indx[scaleRef.GetId()] = item
3019            scaleRef.Bind(wx.EVT_CHECKBOX, OnScaleRef)
3020            scaleSizer.Add(scaleRef,0,wx.ALIGN_CENTER_VERTICAL)
3021            scaleVal = wx.TextCtrl(DData,wx.ID_ANY,
3022                '%.4f'%(UseList[item]['Scale'][0]),style=wx.TE_PROCESS_ENTER)
3023            Indx[scaleVal.GetId()] = item
3024            scaleVal.Bind(wx.EVT_TEXT_ENTER,OnScaleVal)
3025            scaleVal.Bind(wx.EVT_KILL_FOCUS,OnScaleVal)
3026            scaleSizer.Add(scaleVal,0,wx.ALIGN_CENTER_VERTICAL)
3027            return scaleSizer
3028           
3029        def OnUseData(event):
3030            Obj = event.GetEventObject()
3031            hist = Indx[Obj.GetId()]
3032            UseList[hist]['Use'] = Obj.GetValue()
3033           
3034        def OnShowData(event):
3035            Obj = event.GetEventObject()
3036            hist = Indx[Obj.GetId()]
3037            UseList[hist]['Show'] = Obj.GetValue()
3038            wx.CallAfter(UpdateDData)
3039            G2plt.PlotSizeStrainPO(G2frame,data)
3040           
3041        def OnCopyData(event):
3042            #how about HKLF data? This is only for PWDR data
3043            Obj = event.GetEventObject()
3044            hist = Indx[Obj.GetId()]
3045            sourceDict = UseList[hist]
3046            copyNames = ['Scale','Pref.Ori.','Size','Mustrain','HStrain','Extinction']
3047            copyDict = {}
3048            for name in copyNames: 
3049                copyDict[name] = copy.deepcopy(sourceDict[name])        #force copy
3050            keyList = ['All',]+UseList.keys()
3051            if UseList:
3052                copyList = []
3053                dlg = wx.MultiChoiceDialog(G2frame, 
3054                    'Copy parameters to which histograms?', 'Copy parameters', 
3055                    keyList, wx.CHOICEDLG_STYLE)
3056                try:
3057                    if dlg.ShowModal() == wx.ID_OK:
3058                        result = dlg.GetSelections()
3059                        for i in result: 
3060                            copyList.append(keyList[i])
3061                        if 'All' in copyList: 
3062                            copyList = keyList[1:]
3063                        for item in copyList:
3064                            UseList[item].update(copy.deepcopy(copyDict))
3065                        wx.CallAfter(UpdateDData)
3066                finally:
3067                    dlg.Destroy()
3068                   
3069        def OnCopyFlags(event):
3070            Obj = event.GetEventObject()
3071            hist = Indx[Obj.GetId()]
3072            sourceDict = UseList[hist]
3073            copyDict = {}
3074            copyNames = ['Scale','Pref.Ori.','Size','Mustrain','HStrain','Extinction']
3075            for name in copyNames:
3076                if name in ['Scale','Extinction','HStrain']:
3077                    copyDict[name] = sourceDict[name][1]
3078                elif name in ['Size','Mustrain']:
3079                    copyDict[name] = [sourceDict[name][0],sourceDict[name][2],sourceDict[name][4]]
3080                elif name == 'Pref.Ori.':
3081                    copyDict[name] = [sourceDict[name][0],sourceDict[name][2]]
3082                    if sourceDict[name][0] == 'SH':
3083                        SHterms = sourceDict[name][5]
3084                        SHflags = {}
3085                        for item in SHterms:
3086                            SHflags[item] = SHterms[item][1]
3087                        copyDict[name].append(SHflags)                       
3088            keyList = ['All',]+UseList.keys()
3089            if UseList:
3090                copyList = []
3091                dlg = wx.MultiChoiceDialog(G2frame, 
3092                    'Copy parameters to which histograms?', 'Copy parameters', 
3093                    keyList, wx.CHOICEDLG_STYLE)
3094                try:
3095                    if dlg.ShowModal() == wx.ID_OK:
3096                        result = dlg.GetSelections()
3097                        for i in result: 
3098                            copyList.append(keyList[i])
3099                        if 'All' in copyList: 
3100                            copyList = keyList[1:]
3101                        for item in copyList:
3102                            UseList[item]                           
3103                            for name in copyNames:
3104                                if name in ['Scale','Extinction','HStrain']:
3105                                    UseList[item][name][1] = copy.copy(copyDict[name])
3106                                elif name in ['Size','Mustrain']:
3107                                    UseList[item][name][0] = copy.copy(copyDict[name][0])
3108                                    UseList[item][name][2] = copy.copy(copyDict[name][1])
3109                                    UseList[item][name][4] = copy.copy(copyDict[name][2])
3110                                elif name == 'Pref.Ori.':
3111                                    UseList[item][name][0] = copy.copy(copyDict[name][0])
3112                                    UseList[item][name][2] = copy.copy(copyDict[name][1])
3113                                    if sourceDict[name][0] == 'SH':
3114                                        SHflags = copy.copy(copyDict[name][2])
3115                                        SHterms = copy.copy(sourceDict[name][5])
3116                                        for item in SHflags:
3117                                            SHterms[item][1] = copy.copy(SHflags[item])                                             
3118                        wx.CallAfter(UpdateDData)
3119                finally:
3120                    dlg.Destroy()
3121           
3122           
3123        def OnLGmixRef(event):
3124            Obj = event.GetEventObject()
3125            hist,name = Indx[Obj.GetId()]
3126            UseList[hist][name][2][2] = Obj.GetValue()
3127           
3128        def OnLGmixVal(event):
3129            Obj = event.GetEventObject()
3130            hist,name = Indx[Obj.GetId()]
3131            try:
3132                value = float(Obj.GetValue())
3133                if 0.1 <= value <= 1:
3134                    UseList[hist][name][1][2] = value
3135                else:
3136                    raise ValueError
3137            except ValueError:
3138                pass
3139            Obj.SetValue("%.4f"%(UseList[hist][name][1][2]))          #reset in case of error
3140
3141        def OnSizeType(event):
3142            Obj = event.GetEventObject()
3143            hist = Indx[Obj.GetId()]
3144            UseList[hist]['Size'][0] = Obj.GetValue()
3145            G2plt.PlotSizeStrainPO(G2frame,data)
3146            wx.CallAfter(UpdateDData)
3147           
3148        def OnSizeRef(event):
3149            Obj = event.GetEventObject()
3150            hist,pid = Indx[Obj.GetId()]
3151            if UseList[hist]['Size'][0] == 'ellipsoidal':
3152                UseList[hist]['Size'][5][pid] = Obj.GetValue()               
3153            else:
3154                UseList[hist]['Size'][2][pid] = Obj.GetValue()
3155           
3156        def OnSizeVal(event):
3157            Obj = event.GetEventObject()
3158            hist,pid = Indx[Obj.GetId()]
3159            if UseList[hist]['Size'][0] == 'ellipsoidal':
3160                try:
3161                    size = float(Obj.GetValue())
3162                    if pid < 3 and size <= 0.001:            #10A lower limit!
3163                        raise ValueError
3164                    UseList[hist]['Size'][4][pid] = size                   
3165                except ValueError:
3166                    pass
3167                Obj.SetValue("%.3f"%(UseList[hist]['Size'][4][pid]))          #reset in case of error
3168            else:
3169                try:
3170                    size = float(Obj.GetValue())
3171                    if size <= 0.001:            #10A lower limit!
3172                        raise ValueError
3173                    UseList[hist]['Size'][1][pid] = size
3174                except ValueError:
3175                    pass
3176                Obj.SetValue("%.3f"%(UseList[hist]['Size'][1][pid]))          #reset in case of error
3177            G2plt.PlotSizeStrainPO(G2frame,data)
3178           
3179        def OnSizeAxis(event):           
3180            Obj = event.GetEventObject()
3181            hist = Indx[Obj.GetId()]
3182            Saxis = Obj.GetValue().split()
3183            try:
3184                hkl = [int(Saxis[i]) for i in range(3)]
3185            except (ValueError,IndexError):
3186                hkl = UseList[hist]['Size'][3]
3187            if not np.any(np.array(hkl)):
3188                hkl = UseList[hist]['Size'][3]
3189            UseList[hist]['Size'][3] = hkl
3190            h,k,l = hkl
3191            Obj.SetValue('%3d %3d %3d'%(h,k,l)) 
3192                       
3193        def OnStrainType(event):
3194            Obj = event.GetEventObject()
3195            hist = Indx[Obj.GetId()]
3196            UseList[hist]['Mustrain'][0] = Obj.GetValue()
3197            wx.CallAfter(UpdateDData)
3198            G2plt.PlotSizeStrainPO(G2frame,data)
3199           
3200        def OnStrainRef(event):
3201            Obj = event.GetEventObject()
3202            hist,pid = Indx[Obj.GetId()]
3203            if UseList[hist]['Mustrain'][0] == 'generalized':
3204                UseList[hist]['Mustrain'][5][pid] = Obj.GetValue()
3205            else:
3206                UseList[hist]['Mustrain'][2][pid] = Obj.GetValue()
3207           
3208        def OnStrainVal(event):
3209            Snames = G2spc.MustrainNames(SGData)
3210            Obj = event.GetEventObject()
3211            hist,pid = Indx[Obj.GetId()]
3212            try:
3213                strain = float(Obj.GetValue())
3214                if UseList[hist]['Mustrain'][0] == 'generalized':
3215                    if '4' in Snames[pid] and strain < 0:
3216                        raise ValueError
3217                    UseList[hist]['Mustrain'][4][pid] = strain
3218                else:
3219                    if strain <= 0:
3220                        raise ValueError
3221                    UseList[hist]['Mustrain'][1][pid] = strain
3222            except ValueError:
3223                pass
3224            if UseList[hist]['Mustrain'][0] == 'generalized':
3225                Obj.SetValue("%.3f"%(UseList[hist]['Mustrain'][4][pid]))          #reset in case of error
3226            else:
3227                Obj.SetValue("%.1f"%(UseList[hist]['Mustrain'][1][pid]))          #reset in case of error
3228            G2plt.PlotSizeStrainPO(G2frame,data)
3229           
3230        def OnStrainAxis(event):
3231            Obj = event.GetEventObject()
3232            hist = Indx[Obj.GetId()]
3233            Saxis = Obj.GetValue().split()
3234            try:
3235                hkl = [int(Saxis[i]) for i in range(3)]
3236            except (ValueError,IndexError):
3237                hkl = UseList[hist]['Mustrain'][3]
3238            if not np.any(np.array(hkl)):
3239                hkl = UseList[hist]['Mustrain'][3]
3240            UseList[hist]['Mustrain'][3] = hkl
3241            h,k,l = hkl
3242            Obj.SetValue('%3d %3d %3d'%(h,k,l)) 
3243            G2plt.PlotSizeStrainPO(G2frame,data)
3244           
3245        def OnHstrainRef(event):
3246            Obj = event.GetEventObject()
3247            hist,pid = Indx[Obj.GetId()]
3248            UseList[hist]['HStrain'][1][pid] = Obj.GetValue()
3249           
3250        def OnHstrainVal(event):
3251            Snames = G2spc.HStrainNames(SGData)
3252            Obj = event.GetEventObject()
3253            hist,pid = Indx[Obj.GetId()]
3254            try:
3255                strain = float(Obj.GetValue())
3256                UseList[hist]['HStrain'][0][pid] = strain
3257            except ValueError:
3258                pass
3259            Obj.SetValue("%.5f"%(UseList[hist]['HStrain'][0][pid]))          #reset in case of error
3260
3261        def OnPOVal(event):
3262            Obj = event.GetEventObject()
3263            hist = Indx[Obj.GetId()]
3264            try:
3265                mdVal = float(Obj.GetValue())
3266                if mdVal > 0:
3267                    UseList[hist]['Pref.Ori.'][1] = mdVal
3268            except ValueError:
3269                pass
3270            Obj.SetValue("%.3f"%(UseList[hist]['Pref.Ori.'][1]))          #reset in case of error
3271           
3272        def OnPOAxis(event):
3273            Obj = event.GetEventObject()
3274            hist = Indx[Obj.GetId()]
3275            Saxis = Obj.GetValue().split()
3276            try:
3277                hkl = [int(Saxis[i]) for i in range(3)]
3278            except (ValueError,IndexError):
3279                hkl = UseList[hist]['Pref.Ori.'][3]
3280            if not np.any(np.array(hkl)):
3281                hkl = UseList[hist]['Pref.Ori.'][3]
3282            UseList[hist]['Pref.Ori.'][3] = hkl
3283            h,k,l = hkl
3284            Obj.SetValue('%3d %3d %3d'%(h,k,l)) 
3285           
3286        def OnPOOrder(event):
3287            Obj = event.GetEventObject()
3288            hist = Indx[Obj.GetId()]
3289            Order = int(Obj.GetValue())
3290            UseList[hist]['Pref.Ori.'][4] = Order
3291            UseList[hist]['Pref.Ori.'][5] = SetPOCoef(Order,hist)
3292            wx.CallAfter(UpdateDData)
3293
3294        def OnPOType(event):
3295            Obj = event.GetEventObject()
3296            hist = Indx[Obj.GetId()]
3297            if 'March' in Obj.GetValue():
3298                UseList[hist]['Pref.Ori.'][0] = 'MD'
3299            else:
3300                UseList[hist]['Pref.Ori.'][0] = 'SH'
3301            wx.CallAfter(UpdateDData)           
3302   
3303        def OnPORef(event):
3304            Obj = event.GetEventObject()
3305            hist = Indx[Obj.GetId()]
3306            UseList[hist]['Pref.Ori.'][2] = Obj.GetValue()
3307               
3308        def SetPOCoef(Order,hist):
3309            cofNames = G2lat.GenSHCoeff(SGData['SGLaue'],'0',Order,False)     #cylindrical & no M
3310            newPOCoef = dict(zip(cofNames,np.zeros(len(cofNames))))
3311            POCoeff = UseList[hist]['Pref.Ori.'][5]
3312            for cofName in POCoeff:
3313                if cofName in  cofNames:
3314                    newPOCoef[cofName] = POCoeff[cofName]
3315            return newPOCoef
3316       
3317        def OnExtRef(event):
3318            Obj = event.GetEventObject()
3319            UseList[Indx[Obj.GetId()]]['Extinction'][1] = Obj.GetValue()
3320           
3321        def OnExtVal(event):
3322            Obj = event.GetEventObject()
3323            try:
3324                ext = float(Obj.GetValue())
3325                if ext >= 0:
3326                    UseList[Indx[Obj.GetId()]]['Extinction'][0] = ext
3327            except ValueError:
3328                pass
3329            Obj.SetValue("%.2f"%(UseList[Indx[Obj.GetId()]]['Extinction'][0]))
3330           
3331        def OnTbarVal(event):
3332            Obj = event.GetEventObject()
3333            try:
3334                tbar = float(Obj.GetValue())
3335                if tbar >= 0:
3336                    UseList[Indx[Obj.GetId()]]['Extinction'][2]['Tbar'] = tbar
3337            except ValueError:
3338                pass
3339            Obj.SetValue("%.2f"%(UseList[Indx[Obj.GetId()]]['Extinction'][2]['Tbar']))
3340           
3341        def OnEval(event):
3342            Obj = event.GetEventObject()
3343            item = Indx[Obj.GetId()]
3344            try:
3345                val = float(Obj.GetValue())
3346                if val >= 0:
3347                    UseList[item[0]]['Extinction'][2][item[1]][0] = val
3348            except ValueError:
3349                pass
3350            Obj.SetValue("%9.3g"%(UseList[item[0]]['Extinction'][2][item[1]][0]))
3351           
3352        def OnEref(event):
3353            Obj = event.GetEventObject()
3354            item = Indx[Obj.GetId()]
3355            UseList[item[0]]['Extinction'][2][item[1]][1] = Obj.GetValue()
3356
3357        def OnSCExtType(event):
3358            Obj = event.GetEventObject()
3359            item = Indx[Obj.GetId()]
3360            UseList[item[0]]['Extinction'][item[1]] = Obj.GetValue()
3361            wx.CallAfter(UpdateDData)
3362               
3363        def checkAxis(axis):
3364            if not np.any(np.array(axis)):
3365                return False
3366            return axis
3367           
3368        def TopSizer(name,choices,parm,OnType):
3369            topSizer = wx.BoxSizer(wx.HORIZONTAL)
3370            topSizer.Add(wx.StaticText(DData,-1,name),0,wx.ALIGN_CENTER_VERTICAL)
3371            sizeType = wx.ComboBox(DData,wx.ID_ANY,value=UseList[item][parm][0],choices=choices,
3372                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3373            sizeType.Bind(wx.EVT_COMBOBOX, OnType)
3374            Indx[sizeType.GetId()] = item
3375            topSizer.Add(sizeType)
3376            topSizer.Add((5,0),0)
3377            return topSizer
3378           
3379        def LGmixSizer(name,OnVal,OnRef):
3380            lgmixSizer = wx.BoxSizer(wx.HORIZONTAL)
3381            lgmixRef = wx.CheckBox(DData,-1,label='LGmix')
3382            lgmixRef.thisown = False
3383            lgmixRef.SetValue(UseList[item][name][2][2])
3384            Indx[lgmixRef.GetId()] = [item,name]
3385            lgmixRef.Bind(wx.EVT_CHECKBOX, OnRef)
3386            lgmixSizer.Add(lgmixRef,0,wx.ALIGN_CENTER_VERTICAL)
3387            lgmixVal = wx.TextCtrl(DData,wx.ID_ANY,
3388                '%.4f'%(UseList[item][name][1][2]),style=wx.TE_PROCESS_ENTER)
3389            Indx[lgmixVal.GetId()] = [item,name]
3390            lgmixVal.Bind(wx.EVT_TEXT_ENTER,OnVal)
3391            lgmixVal.Bind(wx.EVT_KILL_FOCUS,OnVal)
3392            lgmixSizer.Add(lgmixVal,0,wx.ALIGN_CENTER_VERTICAL)
3393            return lgmixSizer
3394                       
3395        def IsoSizer(name,parm,fmt,OnVal,OnRef):
3396            isoSizer = wx.BoxSizer(wx.HORIZONTAL)
3397            sizeRef = wx.CheckBox(DData,-1,label=name)
3398            sizeRef.thisown = False
3399            sizeRef.SetValue(UseList[item][parm][2][0])
3400            Indx[sizeRef.GetId()] = [item,0]
3401            sizeRef.Bind(wx.EVT_CHECKBOX, OnRef)
3402            isoSizer.Add(sizeRef,0,wx.ALIGN_CENTER_VERTICAL)
3403            sizeVal = wx.TextCtrl(DData,wx.ID_ANY,
3404                fmt%(UseList[item][parm][1][0]),style=wx.TE_PROCESS_ENTER)
3405            Indx[sizeVal.GetId()] = [item,0]
3406            sizeVal.Bind(wx.EVT_TEXT_ENTER,OnVal)
3407            sizeVal.Bind(wx.EVT_KILL_FOCUS,OnVal)
3408            isoSizer.Add(sizeVal,0,wx.ALIGN_CENTER_VERTICAL)
3409            return isoSizer
3410           
3411        def UniSizer(parm,OnAxis):
3412            uniSizer = wx.BoxSizer(wx.HORIZONTAL)
3413            uniSizer.Add(wx.StaticText(DData,-1,' Unique axis, H K L: '),0,wx.ALIGN_CENTER_VERTICAL)
3414            h,k,l = UseList[item][parm][3]
3415            Axis = wx.TextCtrl(DData,-1,'%3d %3d %3d'%(h,k,l),style=wx.TE_PROCESS_ENTER)
3416            Indx[Axis.GetId()] = item
3417            Axis.Bind(wx.EVT_TEXT_ENTER,OnAxis)
3418            Axis.Bind(wx.EVT_KILL_FOCUS,OnAxis)
3419            uniSizer.Add(Axis,0,wx.ALIGN_CENTER_VERTICAL)
3420            return uniSizer
3421           
3422        def UniDataSizer(parmName,parm,fmt,OnVal,OnRef):
3423            dataSizer = wx.BoxSizer(wx.HORIZONTAL)
3424            parms = zip([' Equatorial '+parmName,' Axial '+parmName],
3425                UseList[item][parm][1],UseList[item][parm][2],range(2))
3426            for Pa,val,ref,id in parms:
3427                sizeRef = wx.CheckBox(DData,-1,label=Pa)
3428                sizeRef.thisown = False
3429                sizeRef.SetValue(ref)
3430                Indx[sizeRef.GetId()] = [item,id]
3431                sizeRef.Bind(wx.EVT_CHECKBOX, OnRef)
3432                dataSizer.Add(sizeRef,0,wx.ALIGN_CENTER_VERTICAL)
3433                sizeVal = wx.TextCtrl(DData,wx.ID_ANY,fmt%(val),style=wx.TE_PROCESS_ENTER)
3434                Indx[sizeVal.GetId()] = [item,id]
3435                sizeVal.Bind(wx.EVT_TEXT_ENTER,OnVal)
3436                sizeVal.Bind(wx.EVT_KILL_FOCUS,OnVal)
3437                dataSizer.Add(sizeVal,0,wx.ALIGN_CENTER_VERTICAL)
3438                dataSizer.Add((5,0),0)
3439            return dataSizer
3440           
3441        def EllSizeDataSizer():
3442            parms = zip(['S11','S22','S33','S12','S13','S23'],UseList[item]['Size'][4],
3443                UseList[item]['Size'][5],range(6))
3444            dataSizer = wx.FlexGridSizer(1,6,5,5)
3445            for Pa,val,ref,id in parms:
3446                sizeRef = wx.CheckBox(DData,-1,label=Pa)
3447                sizeRef.thisown = False
3448                sizeRef.SetValue(ref)
3449                Indx[sizeRef.GetId()] = [item,id]
3450                sizeRef.Bind(wx.EVT_CHECKBOX, OnSizeRef)
3451                dataSizer.Add(sizeRef,0,wx.ALIGN_CENTER_VERTICAL)
3452                sizeVal = wx.TextCtrl(DData,wx.ID_ANY,'%.3f'%(val),style=wx.TE_PROCESS_ENTER)
3453                Indx[sizeVal.GetId()] = [item,id]
3454                sizeVal.Bind(wx.EVT_TEXT_ENTER,OnSizeVal)
3455                sizeVal.Bind(wx.EVT_KILL_FOCUS,OnSizeVal)
3456                dataSizer.Add(sizeVal,0,wx.ALIGN_CENTER_VERTICAL)
3457            return dataSizer
3458           
3459        def GenStrainDataSizer():
3460            Snames = G2spc.MustrainNames(SGData)
3461            numb = len(Snames)
3462            if len(UseList[item]['Mustrain'][4]) < numb:
3463                UseList[item]['Mustrain'][4] = numb*[0.0,]
3464                UseList[item]['Mustrain'][5] = numb*[False,]
3465            parms = zip(Snames,UseList[item]['Mustrain'][4],UseList[item]['Mustrain'][5],range(numb))
3466            dataSizer = wx.FlexGridSizer(1,6,5,5)
3467            for Pa,val,ref,id in parms:
3468                strainRef = wx.CheckBox(DData,-1,label=Pa)
3469                strainRef.thisown = False
3470                strainRef.SetValue(ref)
3471                Indx[strainRef.GetId()] = [item,id]
3472                strainRef.Bind(wx.EVT_CHECKBOX, OnStrainRef)
3473                dataSizer.Add(strainRef,0,wx.ALIGN_CENTER_VERTICAL)
3474                strainVal = wx.TextCtrl(DData,wx.ID_ANY,'%.5f'%(val),style=wx.TE_PROCESS_ENTER)
3475                Indx[strainVal.GetId()] = [item,id]
3476                strainVal.Bind(wx.EVT_TEXT_ENTER,OnStrainVal)
3477                strainVal.Bind(wx.EVT_KILL_FOCUS,OnStrainVal)
3478                dataSizer.Add(strainVal,0,wx.ALIGN_CENTER_VERTICAL)
3479            return dataSizer
3480           
3481        def HstrainSizer():
3482            hstrainSizer = wx.FlexGridSizer(1,6,5,5)
3483            Hsnames = G2spc.HStrainNames(SGData)
3484            parms = zip(Hsnames,UseList[item]['HStrain'][0],UseList[item]['HStrain'][1],range(len(Hsnames)))
3485            for Pa,val,ref,id in parms:
3486                hstrainRef = wx.CheckBox(DData,-1,label=Pa)
3487                hstrainRef.thisown = False
3488                hstrainRef.SetValue(ref)
3489                Indx[hstrainRef.GetId()] = [item,id]
3490                hstrainRef.Bind(wx.EVT_CHECKBOX, OnHstrainRef)
3491                hstrainSizer.Add(hstrainRef,0,wx.ALIGN_CENTER_VERTICAL)
3492                hstrainVal = wx.TextCtrl(DData,wx.ID_ANY,'%.5f'%(val),style=wx.TE_PROCESS_ENTER)
3493                Indx[hstrainVal.GetId()] = [item,id]
3494                hstrainVal.Bind(wx.EVT_TEXT_ENTER,OnHstrainVal)
3495                hstrainVal.Bind(wx.EVT_KILL_FOCUS,OnHstrainVal)
3496                hstrainSizer.Add(hstrainVal,0,wx.ALIGN_CENTER_VERTICAL)
3497            return hstrainSizer
3498           
3499        def PoTopSizer(POData):
3500            poSizer = wx.FlexGridSizer(1,6,5,5)
3501            choice = ['March-Dollase','Spherical harmonics']
3502            POtype = choice[['MD','SH'].index(POData[0])]
3503            poSizer.Add(wx.StaticText(DData,-1,' Preferred orientation model '),0,wx.ALIGN_CENTER_VERTICAL)
3504            POType = wx.ComboBox(DData,wx.ID_ANY,value=POtype,choices=choice,
3505                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3506            Indx[POType.GetId()] = item
3507            POType.Bind(wx.EVT_COMBOBOX, OnPOType)
3508            poSizer.Add(POType)
3509            if POData[0] == 'SH':
3510                poSizer.Add(wx.StaticText(DData,-1,' Harmonic order: '),0,wx.ALIGN_CENTER_VERTICAL)
3511                poOrder = wx.ComboBox(DData,wx.ID_ANY,value=str(POData[4]),choices=[str(2*i) for i in range(18)],
3512                    style=wx.CB_READONLY|wx.CB_DROPDOWN)
3513                Indx[poOrder.GetId()] = item
3514                poOrder.Bind(wx.EVT_COMBOBOX,OnPOOrder)
3515                poSizer.Add(poOrder,0,wx.ALIGN_CENTER_VERTICAL)
3516                poRef = wx.CheckBox(DData,-1,label=' Refine? ')
3517                poRef.SetValue(POData[2])
3518                Indx[poRef.GetId()] = item
3519                poRef.Bind(wx.EVT_CHECKBOX,OnPORef)
3520                poSizer.Add(poRef,0,wx.ALIGN_CENTER_VERTICAL)
3521            return poSizer
3522           
3523        def MDDataSizer(POData):
3524            poSizer = wx.BoxSizer(wx.HORIZONTAL)
3525            poRef = wx.CheckBox(DData,-1,label=' March-Dollase ratio: ')
3526            poRef.SetValue(POData[2])
3527            Indx[poRef.GetId()] = item
3528            poRef.Bind(wx.EVT_CHECKBOX,OnPORef)
3529            poSizer.Add(poRef,0,wx.ALIGN_CENTER_VERTICAL)
3530            poVal = wx.TextCtrl(DData,wx.ID_ANY,
3531                '%.3f'%(POData[1]),style=wx.TE_PROCESS_ENTER)
3532            Indx[poVal.GetId()] = item
3533            poVal.Bind(wx.EVT_TEXT_ENTER,OnPOVal)
3534            poVal.Bind(wx.EVT_KILL_FOCUS,OnPOVal)
3535            poSizer.Add(poVal,0,wx.ALIGN_CENTER_VERTICAL)
3536            poSizer.Add(wx.StaticText(DData,-1,' Unique axis, H K L: '),0,wx.ALIGN_CENTER_VERTICAL)
3537            h,k,l =POData[3]
3538            poAxis = wx.TextCtrl(DData,-1,'%3d %3d %3d'%(h,k,l),style=wx.TE_PROCESS_ENTER)
3539            Indx[poAxis.GetId()] = item
3540            poAxis.Bind(wx.EVT_TEXT_ENTER,OnPOAxis)
3541            poAxis.Bind(wx.EVT_KILL_FOCUS,OnPOAxis)
3542            poSizer.Add(poAxis,0,wx.ALIGN_CENTER_VERTICAL)
3543            return poSizer
3544           
3545        def SHDataSizer(POData):
3546            textJ = G2lat.textureIndex(POData[5])
3547            mainSizer.Add(wx.StaticText(DData,-1,' Spherical harmonic coefficients: '+'Texture index: %.3f'%(textJ)),0,wx.ALIGN_CENTER_VERTICAL)
3548            mainSizer.Add((0,5),0)
3549            ODFSizer = wx.FlexGridSizer(2,8,2,2)
3550            ODFIndx = {}
3551            ODFkeys = POData[5].keys()
3552            ODFkeys.sort()
3553            for odf in ODFkeys:
3554                ODFSizer.Add(wx.StaticText(DData,-1,odf),0,wx.ALIGN_CENTER_VERTICAL)
3555                ODFval = wx.TextCtrl(DData,wx.ID_ANY,'%8.3f'%(POData[5][odf]),style=wx.TE_PROCESS_ENTER)
3556                ODFIndx[ODFval.GetId()] = odf
3557#                ODFval.Bind(wx.EVT_TEXT_ENTER,OnODFValue)
3558#                ODFval.Bind(wx.EVT_KILL_FOCUS,OnODFValue)
3559                ODFSizer.Add(ODFval,0,wx.ALIGN_CENTER_VERTICAL)
3560            return ODFSizer
3561           
3562        def ExtSizer():           
3563            extSizer = wx.BoxSizer(wx.HORIZONTAL)
3564            extRef = wx.CheckBox(DData,-1,label=' Extinction: ')
3565            extRef.SetValue(UseList[item]['Extinction'][1])
3566            Indx[extRef.GetId()] = item
3567            extRef.Bind(wx.EVT_CHECKBOX, OnExtRef)
3568            extSizer.Add(extRef,0,wx.ALIGN_CENTER_VERTICAL)
3569            extVal = wx.TextCtrl(DData,wx.ID_ANY,
3570                '%.2f'%(UseList[item]['Extinction'][0]),style=wx.TE_PROCESS_ENTER)
3571            Indx[extVal.GetId()] = item
3572            extVal.Bind(wx.EVT_TEXT_ENTER,OnExtVal)
3573            extVal.Bind(wx.EVT_KILL_FOCUS,OnExtVal)
3574            extSizer.Add(extVal,0,wx.ALIGN_CENTER_VERTICAL)
3575            return extSizer
3576       
3577        def SCExtSizer():
3578            extSizer = wx.BoxSizer(wx.VERTICAL)
3579            typeSizer = wx.BoxSizer(wx.HORIZONTAL)           
3580            typeSizer.Add(wx.StaticText(DData,-1,' Extinction type: '),0,wx.ALIGN_CENTER_VERTICAL)
3581            Choices = ['Primary','Secondary Type I','Secondary Type II','Secondary Type I & II']
3582            typeTxt = wx.ComboBox(DData,-1,choices=Choices,value=UseList[item]['Extinction'][1],
3583                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3584            Indx[typeTxt.GetId()] = [item,1]
3585            typeTxt.Bind(wx.EVT_COMBOBOX,OnSCExtType)
3586            typeSizer.Add(typeTxt)
3587            typeSizer.Add(wx.StaticText(DData,-1,' Approx: '),0,wx.ALIGN_CENTER_VERTICAL)
3588            Choices=['Lorentzian','Gaussian']
3589            approxTxT = wx.ComboBox(DData,-1,choices=Choices,value=UseList[item]['Extinction'][0],
3590                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3591            Indx[approxTxT.GetId()] = [item,0]
3592            approxTxT.Bind(wx.EVT_COMBOBOX,OnSCExtType)
3593            typeSizer.Add(approxTxT)
3594            extSizer.Add(typeSizer,0,wx.ALIGN_CENTER_VERTICAL)
3595            extSizer.Add((0,5),)
3596            valSizer =wx.BoxSizer(wx.HORIZONTAL)
3597            valSizer.Add(wx.StaticText(DData,-1,' Tbar(mm):'),0,wx.ALIGN_CENTER_VERTICAL)
3598            tbarVal = wx.TextCtrl(DData,wx.ID_ANY,
3599                '%.3f'%(UseList[item]['Extinction'][2]['Tbar']),style=wx.TE_PROCESS_ENTER)
3600            Indx[tbarVal.GetId()] = item
3601            tbarVal.Bind(wx.EVT_TEXT_ENTER,OnTbarVal)
3602            tbarVal.Bind(wx.EVT_KILL_FOCUS,OnTbarVal)
3603            valSizer.Add(tbarVal,0,wx.ALIGN_CENTER_VERTICAL)
3604            if 'Primary' in UseList[item]['Extinction'][1]:
3605                Ekey = ['Ep',]
3606            elif 'Secondary Type II' == UseList[item]['Extinction'][1]:
3607                Ekey = ['Es',]
3608            elif 'Secondary Type I' == UseList[item]['Extinction'][1]:
3609                Ekey = ['Eg',]
3610            else:
3611                Ekey = ['Eg','Es']
3612            for ekey in Ekey:
3613                Eref = wx.CheckBox(DData,-1,label=ekey+' : ')
3614                Eref.SetValue(UseList[item]['Extinction'][2][ekey][1])
3615                Indx[Eref.GetId()] = [item,ekey]
3616                Eref.Bind(wx.EVT_CHECKBOX, OnEref)
3617                valSizer.Add(Eref,0,wx.ALIGN_CENTER_VERTICAL)
3618                Eval = wx.TextCtrl(DData,wx.ID_ANY,
3619                    '%9.3g'%(UseList[item]['Extinction'][2][ekey][0]),style=wx.TE_PROCESS_ENTER)
3620                Indx[Eval.GetId()] = [item,ekey]
3621                Eval.Bind(wx.EVT_TEXT_ENTER,OnEval)
3622                Eval.Bind(wx.EVT_KILL_FOCUS,OnEval)
3623                valSizer.Add(Eval,0,wx.ALIGN_CENTER_VERTICAL)
3624
3625            extSizer.Add(valSizer,0,wx.ALIGN_CENTER_VERTICAL)
3626            return extSizer
3627           
3628        if DData.GetSizer():
3629            DData.GetSizer().Clear(True)
3630        mainSizer = wx.BoxSizer(wx.VERTICAL)
3631        mainSizer.Add(wx.StaticText(DData,-1,'Histogram data for '+PhaseName+':'),0,wx.ALIGN_CENTER_VERTICAL)
3632        if PWDR:
3633            mainSizer.Add(PlotSizer())           
3634           
3635        for item in keyList:
3636            histData = UseList[item]
3637            if 'Use' not in UseList[item]:      #patch
3638                UseList[item]['Use'] = True
3639            showSizer = wx.BoxSizer(wx.HORIZONTAL)
3640            showData = wx.CheckBox(DData,-1,label=' Show '+item)
3641            showData.SetValue(UseList[item]['Show'])
3642            Indx[showData.GetId()] = item
3643            showData.Bind(wx.EVT_CHECKBOX, OnShowData)
3644            showSizer.Add(showData,0,wx.ALIGN_CENTER_VERTICAL)
3645            useData = wx.CheckBox(DData,-1,label='Use?')
3646            Indx[useData.GetId()] = item
3647            showSizer.Add(useData,0,wx.ALIGN_CENTER_VERTICAL)
3648            useData.Bind(wx.EVT_CHECKBOX, OnUseData)
3649            useData.SetValue(UseList[item]['Use'])
3650            copyData = wx.Button(DData,-1,label=' Copy?')
3651            Indx[copyData.GetId()] = item
3652            copyData.Bind(wx.EVT_BUTTON,OnCopyData)
3653            showSizer.Add(copyData,wx.ALIGN_CENTER_VERTICAL)
3654            copyFlags = wx.Button(DData,-1,label=' Copy flags?')
3655            Indx[copyFlags.GetId()] = item
3656            copyFlags.Bind(wx.EVT_BUTTON,OnCopyFlags)
3657            showSizer.Add(copyFlags,wx.ALIGN_CENTER_VERTICAL)
3658            mainSizer.Add((5,5),0)
3659            mainSizer.Add(showSizer,0,wx.ALIGN_CENTER_VERTICAL)
3660            mainSizer.Add((0,5),0)
3661           
3662            if UseList[item]['Show']:
3663                mainSizer.Add(ScaleSizer())
3664                mainSizer.Add((0,5),0)
3665               
3666            if item[:4] == 'PWDR' and UseList[item]['Show']:
3667                if UseList[item]['Size'][0] == 'isotropic':
3668                    isoSizer = wx.BoxSizer(wx.HORIZONTAL)
3669                    isoSizer.Add(TopSizer(' Size model: ',['isotropic','uniaxial','ellipsoidal'],
3670                        'Size',OnSizeType),0,wx.ALIGN_CENTER_VERTICAL)
3671                    isoSizer.Add(LGmixSizer('Size',OnLGmixVal,OnLGmixRef))
3672                    mainSizer.Add(isoSizer)
3673                    mainSizer.Add(IsoSizer(u' Cryst. size(\xb5m): ','Size','%.3f',
3674                        OnSizeVal,OnSizeRef),0,wx.ALIGN_CENTER_VERTICAL)
3675                elif UseList[item]['Size'][0] == 'uniaxial':
3676                    uniSizer = wx.BoxSizer(wx.HORIZONTAL)
3677                    uniSizer.Add(TopSizer(' Size model: ',['isotropic','uniaxial','ellipsoidal'],
3678                        'Size',OnSizeType),0,wx.ALIGN_CENTER_VERTICAL)
3679                    uniSizer.Add(LGmixSizer('Size',OnLGmixVal,OnLGmixRef))
3680                    uniSizer.Add(UniSizer('Size',OnSizeAxis),0,wx.ALIGN_CENTER_VERTICAL)
3681                    mainSizer.Add(uniSizer)
3682                    mainSizer.Add(UniDataSizer(u'size(\xb5m): ','Size','%.3f',OnSizeVal,OnSizeRef))
3683                elif UseList[item]['Size'][0] == 'ellipsoidal':
3684                    ellSizer = wx.BoxSizer(wx.HORIZONTAL)
3685                    ellSizer.Add(TopSizer(' Size model: ',['isotropic','uniaxial','ellipsoidal'],
3686                        'Size',OnSizeType),0,wx.ALIGN_CENTER_VERTICAL)
3687                    ellSizer.Add(LGmixSizer('Size',OnLGmixVal,OnLGmixRef))
3688                    mainSizer.Add(ellSizer)
3689                    mainSizer.Add(EllSizeDataSizer())
3690                mainSizer.Add((0,5),0)                   
3691               
3692                if UseList[item]['Mustrain'][0] == 'isotropic':
3693                    isoSizer = wx.BoxSizer(wx.HORIZONTAL)
3694                    isoSizer.Add(TopSizer(' Mustrain model: ',['isotropic','uniaxial','generalized',],
3695                        'Mustrain',OnStrainType),0,wx.ALIGN_CENTER_VERTICAL)
3696                    isoSizer.Add(LGmixSizer('Mustrain',OnLGmixVal,OnLGmixRef))
3697                    mainSizer.Add(isoSizer)
3698                    mainSizer.Add(IsoSizer(' microstrain: ','Mustrain','%.1f',
3699                        OnStrainVal,OnStrainRef),0,wx.ALIGN_CENTER_VERTICAL)                   
3700                    mainSizer.Add((0,5),0)
3701                elif UseList[item]['Mustrain'][0] == 'uniaxial':
3702                    uniSizer = wx.BoxSizer(wx.HORIZONTAL)
3703                    uniSizer.Add(TopSizer(' Mustrain model: ',['isotropic','uniaxial','generalized',],
3704                        'Mustrain',OnStrainType),0,wx.ALIGN_CENTER_VERTICAL)
3705                    uniSizer.Add(LGmixSizer('Mustrain',OnLGmixVal,OnLGmixRef))
3706                    uniSizer.Add(UniSizer('Mustrain',OnStrainAxis),0,wx.ALIGN_CENTER_VERTICAL)
3707                    mainSizer.Add(uniSizer)
3708                    mainSizer.Add(UniDataSizer('mustrain: ','Mustrain','%.1f',OnStrainVal,OnStrainRef))
3709                elif UseList[item]['Mustrain'][0] == 'generalized':
3710                    genSizer = wx.BoxSizer(wx.HORIZONTAL)
3711                    genSizer.Add(TopSizer(' Mustrain model: ',['isotropic','uniaxial','generalized',],
3712                        'Mustrain',OnStrainType),0,wx.ALIGN_CENTER_VERTICAL)
3713                    genSizer.Add(LGmixSizer('Mustrain',OnLGmixVal,OnLGmixRef))
3714                    mainSizer.Add(genSizer)
3715                    mainSizer.Add(GenStrainDataSizer())                       
3716                mainSizer.Add((0,5),0)
3717               
3718                mainSizer.Add(wx.StaticText(DData,-1,' Hydrostatic/elastic strain:'))
3719                mainSizer.Add(HstrainSizer())
3720                   
3721                #texture  'Pref. Ori.':['MD',1.0,False,[0,0,1],0,[]] last two for 'SH' are SHorder & coeff
3722                poSizer = wx.BoxSizer(wx.VERTICAL)
3723                POData = UseList[item]['Pref.Ori.']
3724                poSizer.Add(PoTopSizer(POData))
3725                if POData[0] == 'MD':
3726                    poSizer.Add(MDDataSizer(POData))
3727                else:           #'SH'
3728                    if POData[4]:       #SH order > 0
3729                        poSizer.Add(SHDataSizer(POData))
3730                       
3731                mainSizer.Add(poSizer)
3732                mainSizer.Add((0,5),0)               
3733                #Extinction  'Extinction':[0.0,False]
3734                mainSizer.Add(ExtSizer())
3735                mainSizer.Add((0,5),0)
3736            elif item[:4] == 'HKLF' and UseList[item]['Show']:
3737                mainSizer.Add((0,5),0)               
3738                mainSizer.Add(SCExtSizer())
3739                mainSizer.Add((0,5),0)
3740                pass
3741        mainSizer.Add((5,5),0)
3742
3743        DData.SetSizer(mainSizer,True)
3744        mainSizer.FitInside(G2frame.dataFrame)
3745        Size = mainSizer.GetMinSize()
3746        Size[0] += 40
3747        Size[1] = max(Size[1],290) + 35
3748        DData.SetSize(Size)
3749        DData.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
3750        Size[1] = min(Size[1],450)
3751        G2frame.dataFrame.setSizePosLeft(Size)
3752       
3753    def OnHklfAdd(event):
3754        UseList = data['Histograms']
3755        keyList = UseList.keys()
3756        TextList = []
3757        if G2frame.PatternTree.GetCount():
3758            item, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
3759            while item:
3760                name = G2frame.PatternTree.GetItemText(item)
3761                if name not in keyList and 'HKLF' in name:
3762                    TextList.append(name)
3763                item, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)                       
3764            dlg = wx.MultiChoiceDialog(G2frame, 'Which new data to use?', 'Use data', TextList, wx.CHOICEDLG_STYLE)
3765            try:
3766                if dlg.ShowModal() == wx.ID_OK:
3767                    result = dlg.GetSelections()
3768                    for i in result:
3769                        histoName = TextList[i]
3770                        UseList[histoName] = {'Histogram':histoName,'Show':False,'Scale':[1.0,True],
3771                            'Extinction':['Lorentzian','Secondary Type I',
3772                            {'Tbar':0.0,'Eg':[0.0,False],'Es':[0.0,False],'Ep':[0.0,False]},]}                       
3773                    data['Histograms'] = UseList
3774                    wx.BeginBusyCursor()
3775                    UpdateHKLFdata(histoName)
3776                    wx.EndBusyCursor()
3777                    wx.CallAfter(UpdateDData)
3778            finally:
3779                dlg.Destroy()
3780               
3781    def UpdateHKLFdata(histoName):
3782        generalData = data['General']
3783        Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,histoName)
3784        reflData = G2frame.PatternTree.GetItemPyData(Id)[1]
3785        SGData = generalData['SGData']
3786        Cell = generalData['Cell'][1:7]
3787        G,g = G2lat.cell2Gmat(Cell)
3788        for ref in reflData:
3789            H = ref[:3]
3790            ref[4] = np.sqrt(1./G2lat.calc_rDsq2(H,G))
3791            iabsnt,ref[3],ref[11],ref[12] = G2spc.GenHKLf(H,SGData)
3792        G2frame.PatternTree.SetItemPyData(Id,[histoName,reflData])
3793       
3794    def OnPwdrAdd(event):
3795        generalData = data['General']
3796        SGData = generalData['SGData']
3797        UseList = data['Histograms']
3798        newList = []
3799        NShkl = len(G2spc.MustrainNames(SGData))
3800        NDij = len(G2spc.HStrainNames(SGData))
3801        keyList = UseList.keys()
3802        TextList = ['All PWDR']
3803        if G2frame.PatternTree.GetCount():
3804            item, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
3805            while item:
3806                name = G2frame.PatternTree.GetItemText(item)
3807                if name not in keyList and 'PWDR' in name:
3808                    TextList.append(name)
3809                item, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
3810            dlg = wx.MultiChoiceDialog(G2frame, 'Which new data to use?', 'Use data', TextList, wx.CHOICEDLG_STYLE)
3811            try:
3812                if dlg.ShowModal() == wx.ID_OK:
3813                    result = dlg.GetSelections()
3814                    for i in result: newList.append(TextList[i])
3815                    if 'All PWDR' in newList:
3816                        newList = TextList[1:]
3817                    for histoName in newList:
3818                        pId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,histoName)
3819                        UseList[histoName] = {'Histogram':histoName,'Show':False,
3820                            'Scale':[1.0,False],'Pref.Ori.':['MD',1.0,False,[0,0,1],0,{}],
3821                            'Size':['isotropic',[4.,4.,1.0],[False,False,False],[0,0,1],
3822                                [4.,4.,4.,0.,0.,0.],6*[False,]],
3823                            'Mustrain':['isotropic',[1000.0,1000.0,1.0],[False,False,False],[0,0,1],
3824                                NShkl*[0.01,],NShkl*[False,]],
3825                            'HStrain':[NDij*[0.0,],NDij*[False,]],                         
3826                            'Extinction':[0.0,False]}
3827                        refList = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,pId,'Reflection Lists'))
3828                        refList[generalData['Name']] = []                       
3829                    data['Histograms'] = UseList
3830                    wx.CallAfter(UpdateDData)
3831            finally:
3832                dlg.Destroy()
3833       
3834    def OnDataDelete(event):
3835        UseList = data['Histograms']
3836        keyList = ['All',]+UseList.keys()
3837        keyList.sort()
3838        DelList = []
3839        if UseList:
3840            DelList = []
3841            dlg = wx.MultiChoiceDialog(G2frame, 
3842                'Which histogram to delete from this phase?', 'Delete histogram', 
3843                keyList, wx.CHOICEDLG_STYLE)
3844            try:
3845                if dlg.ShowModal() == wx.ID_OK:
3846                    result = dlg.GetSelections()
3847                    for i in result: 
3848                        DelList.append(keyList[i])
3849                    if 'All' in DelList:
3850                        DelList = keyList[1:]
3851                    for i in DelList:
3852                        del UseList[i]
3853                    wx.CallAfter(UpdateDData)
3854            finally:
3855                dlg.Destroy()
3856
3857################################################################################
3858##### Pawley routines
3859################################################################################
3860
3861    def FillPawleyReflectionsGrid():
3862        G2frame.dataFrame.SetStatusText('')
3863                       
3864        def KeyEditPawleyGrid(event):
3865            colList = G2frame.PawleyRefl.GetSelectedCols()
3866            PawleyPeaks = data['Pawley ref']
3867            if event.GetKeyCode() == wx.WXK_RETURN:
3868                event.Skip(True)
3869            elif event.GetKeyCode() == wx.WXK_CONTROL:
3870                event.Skip(True)
3871            elif event.GetKeyCode() == wx.WXK_SHIFT:
3872                event.Skip(True)
3873            elif colList:
3874                G2frame.PawleyRefl.ClearSelection()
3875                key = event.GetKeyCode()
3876                for col in colList:
3877                    if PawleyTable.GetTypeName(0,col) == wg.GRID_VALUE_BOOL:
3878                        if key == 89: #'Y'
3879                            for row in range(PawleyTable.GetNumberRows()): PawleyPeaks[row][col]=True
3880                        elif key == 78:  #'N'
3881                            for row in range(PawleyTable.GetNumberRows()): PawleyPeaks[row][col]=False
3882                        FillPawleyReflectionsGrid()
3883           
3884        if 'Pawley ref' in data:
3885            PawleyPeaks = data['Pawley ref']                       
3886            rowLabels = []
3887            for i in range(len(PawleyPeaks)): rowLabels.append(str(i))
3888            colLabels = ['h','k','l','mul','d','refine','Fsq(hkl)','sig(Fsq)']
3889            Types = 4*[wg.GRID_VALUE_LONG,]+[wg.GRID_VALUE_FLOAT+':10,4',wg.GRID_VALUE_BOOL,]+ \
3890                2*[wg.GRID_VALUE_FLOAT+':10,2',]
3891            PawleyTable = G2gd.Table(PawleyPeaks,rowLabels=rowLabels,colLabels=colLabels,types=Types)
3892            G2frame.PawleyRefl.SetTable(PawleyTable, True)
3893            G2frame.PawleyRefl.Bind(wx.EVT_KEY_DOWN, KeyEditPawleyGrid)                 
3894            for r in range(G2frame.PawleyRefl.GetNumberRows()):
3895                for c in range(G2frame.PawleyRefl.GetNumberCols()):
3896                    if c in [5,6]:
3897                        G2frame.PawleyRefl.SetReadOnly(r,c,isReadOnly=False)
3898                    else:
3899                        G2frame.PawleyRefl.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
3900            G2frame.PawleyRefl.SetMargins(0,0)
3901            G2frame.PawleyRefl.AutoSizeColumns(False)
3902            G2frame.dataFrame.setSizePosLeft([500,300])
3903                   
3904    def OnPawleyLoad(event):
3905        generalData = data['General']
3906        dmin = generalData['Pawley dmin']
3907        cell = generalData['Cell'][1:7]
3908        A = G2lat.cell2A(cell)
3909        SGData = generalData['SGData']
3910        HKLd = np.array(G2lat.GenHLaue(dmin,SGData,A))
3911        PawleyPeaks = []
3912        wx.BeginBusyCursor()
3913        try:
3914            for h,k,l,d in HKLd:
3915                ext,mul = G2spc.GenHKLf([h,k,l],SGData)[:2]
3916                if not ext:
3917                    mul *= 2        #for powder multiplicity
3918                    PawleyPeaks.append([h,k,l,mul,d,False,100.0,1.0])
3919        finally:
3920            wx.EndBusyCursor()
3921        data['Pawley ref'] = PawleyPeaks
3922        FillPawleyReflectionsGrid()
3923       
3924    def OnPawleyEstimate(event):
3925        try:
3926            Refs = data['Pawley ref']
3927            Histograms = data['Histograms']
3928        except KeyError:
3929            print '**** Error - no histograms defined for this phase ****'
3930            return
3931        HistoNames = Histograms.keys()
3932        PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,HistoNames[0])
3933        xdata = G2frame.PatternTree.GetItemPyData(PatternId)[1]
3934        Inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Instrument Parameters'))
3935        Inst = dict(zip(Inst[3],Inst[1]))
3936        Sample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Sample Parameters'))
3937        if 'Lam' in Inst:
3938            wave = Inst['Lam']
3939        else:
3940            wave = Inst['Lam1']
3941        posCorr = Inst['Zero']
3942        const = 9.e-2/(np.pi*Sample['Gonio. radius'])                  #shifts in microns
3943       
3944        wx.BeginBusyCursor()
3945        try:
3946            for ref in Refs:
3947                pos = 2.0*asind(wave/(2.0*ref[4]))
3948                if 'Bragg' in Sample['Type']:
3949                    pos -= const*(4.*Sample['Shift'][0]*cosd(pos/2.0)+ \
3950                        Sample['Transparency'][0]*sind(pos)*100.0)            #trans(=1/mueff) in cm
3951                else:               #Debye-Scherrer - simple but maybe not right
3952                    pos -= const*(Sample['DisplaceX'][0]*cosd(pos)+Sample['DisplaceY'][0]*sind(pos))
3953                indx = np.searchsorted(xdata[0],pos)
3954                try:
3955                    FWHM = max(0.001,G2pwd.getFWHM(pos,Inst))/2.
3956                    dx = xdata[0][indx+1]-xdata[0][indx]
3957                    ref[6] = FWHM*(xdata[1][indx]-xdata[4][indx])*cosd(pos/2.)**3/dx
3958                    Lorenz = 1./(2.*sind(xdata[0][indx]/2.)**2*cosd(xdata[0][indx]/2.))           #Lorentz correction
3959                    pola,dIdPola = G2pwd.Polarization(Inst['Polariz.'],xdata[0][indx],Inst['Azimuth'])
3960                    ref[6] /= (Lorenz*pola*ref[3])
3961                except IndexError:
3962                    pass
3963        finally:
3964            wx.EndBusyCursor()
3965        FillPawleyReflectionsGrid()
3966
3967    def OnPawleyUpdate(event):
3968        try:
3969            Refs = data['Pawley ref']
3970            Histograms = data['Histograms']
3971        except KeyError:
3972            print '**** Error - no histograms defined for this phase ****'
3973            return
3974        HistoNames = Histograms.keys()
3975        PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,HistoNames[0])
3976        refData = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Reflection Lists'))[PhaseName]
3977        wx.BeginBusyCursor()
3978        try:
3979            for iref,ref in enumerate(Refs):
3980                try:
3981                    ref[6] = abs(refData[iref][9])
3982                    ref[7] = 1.0
3983                except IndexError:
3984                    pass
3985        finally:
3986            wx.EndBusyCursor()
3987        FillPawleyReflectionsGrid()
3988                           
3989    def OnPawleyDelete(event):          #doesn't work
3990        dlg = wx.MessageDialog(G2frame,'Do you really want to delete selected Pawley reflections?','Delete', 
3991            wx.YES_NO | wx.ICON_QUESTION)
3992        try:
3993            result = dlg.ShowModal()
3994            if result == wx.ID_YES: 
3995                Refs = data['Pawley ref']
3996                Ind = G2frame.PawleyRefl.GetSelectedRows()
3997                Ind.sort()
3998                Ind.reverse()
3999                for ind in Ind:
4000                    Refs = np.delete(Refs,ind,0)
4001                data['Pawley ref'] = Refs
4002                FillPawleyReflectionsGrid()
4003        finally:
4004            dlg.Destroy()
4005
4006################################################################################
4007##### Fourier routines
4008################################################################################
4009
4010    def FillMapPeaksGrid():
4011                       
4012        def RowSelect(event):
4013            r,c =  event.GetRow(),event.GetCol()
4014            if r < 0 and c < 0:
4015                if MapPeaks.IsSelection():
4016                    MapPeaks.ClearSelection()
4017                else:
4018                    for row in range(MapPeaks.GetNumberRows()):
4019                        MapPeaks.SelectRow(row,True)
4020                   
4021            elif c < 0:                   #only row clicks
4022                if event.ControlDown():                   
4023                    if r in MapPeaks.GetSelectedRows():
4024                        MapPeaks.DeselectRow(r)
4025                    else:
4026                        MapPeaks.SelectRow(r,True)
4027                elif event.ShiftDown():
4028                    for row in range(r+1):
4029                        MapPeaks.SelectRow(row,True)
4030                else:
4031                    MapPeaks.ClearSelection()
4032                    MapPeaks.SelectRow(r,True)
4033            elif r < 0:                 #a column pick
4034                mapPeaks = data['Map Peaks']
4035                c =  event.GetCol()
4036                if colLabels[c] == 'mag':
4037                    mapPeaks = G2mth.sortArray(mapPeaks,0,reverse=True)
4038                elif colLabels[c] == 'dzero':
4039                    mapPeaks = G2mth.sortArray(mapPeaks,4)
4040                else:
4041                    return
4042                data['Map Peaks'] = mapPeaks
4043                wx.CallAfter(FillMapPeaksGrid)
4044            G2plt.PlotStructure(G2frame,data)                   
4045           
4046        G2frame.dataFrame.setSizePosLeft([450,300])
4047        G2frame.dataFrame.SetStatusText('')
4048        if 'Map Peaks' in data:
4049            G2frame.dataFrame.SetStatusText('Select mag or dzero columns to sort')
4050            mapPeaks = data['Map Peaks']                       
4051            rowLabels = []
4052            for i in range(len(mapPeaks)): rowLabels.append(str(i))
4053            colLabels = ['mag','x','y','z','dzero']
4054            Types = 5*[wg.GRID_VALUE_FLOAT+':10,4',]
4055            G2frame.MapPeaksTable = G2gd.Table(mapPeaks,rowLabels=rowLabels,colLabels=colLabels,types=Types)
4056            MapPeaks.SetTable(G2frame.MapPeaksTable, True)
4057            MapPeaks.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK, RowSelect)
4058            for r in range(MapPeaks.GetNumberRows()):
4059                for c in range(MapPeaks.GetNumberCols()):
4060                    MapPeaks.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
4061            MapPeaks.SetMargins(0,0)
4062            MapPeaks.AutoSizeColumns(False)
4063                   
4064    def OnPeaksMove(event):
4065        if 'Map Peaks' in data:
4066            mapPeaks = data['Map Peaks']                       
4067            Ind = MapPeaks.GetSelectedRows()
4068            for ind in Ind:
4069                x,y,z,d = mapPeaks[ind][1:]
4070                AtomAdd(x,y,z,'C')
4071   
4072    def OnPeaksClear(event):
4073        data['Map Peaks'] = []
4074        FillMapPeaksGrid()
4075        G2plt.PlotStructure(G2frame,data)
4076       
4077    def OnPeaksDelete(event):
4078        if 'Map Peaks' in data:
4079            mapPeaks = data['Map Peaks']
4080            Ind = MapPeaks.GetSelectedRows()
4081            Ind.sort()
4082            Ind.reverse()
4083            for ind in Ind:
4084                mapPeaks = np.delete(mapPeaks,ind,0)
4085            data['Map Peaks'] = mapPeaks
4086        FillMapPeaksGrid()
4087        G2plt.PlotStructure(G2frame,data)
4088               
4089    def OnPeaksUnique(event):
4090        if 'Map Peaks' in data:
4091            mapPeaks = data['Map Peaks']
4092            Ind = MapPeaks.GetSelectedRows()
4093            if Ind:
4094                wx.BeginBusyCursor()
4095                try:
4096                    Ind = G2mth.PeaksUnique(data,Ind)
4097                    for r in range(MapPeaks.GetNumberRows()):
4098                        if r in Ind:
4099                            MapPeaks.SelectRow(r,addToSelected=True)
4100                        else:
4101                            MapPeaks.DeselectRow(r)
4102                finally:
4103                    wx.EndBusyCursor()
4104                G2plt.PlotStructure(G2frame,data)
4105               
4106    def OnPeaksViewPoint(event):
4107        # set view point
4108        indx = MapPeaks.GetSelectedRows()
4109        if not indx:
4110            print '***** ERROR - no peaks selected'
4111            return
4112        mapPeaks = data['Map Peaks']
4113        drawingData = data['Drawing']
4114        drawingData['viewPoint'][0] = mapPeaks[indx[0]][1:4]
4115        G2plt.PlotStructure(G2frame,data)
4116   
4117    def OnPeaksDistVP(event):
4118        # distance to view point
4119        indx = MapPeaks.GetSelectedRows()
4120        if not indx:
4121            print '***** ERROR - no peaks selected'
4122            return
4123        generalData = data['General']
4124        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])           
4125        mapPeaks = data['Map Peaks']
4126        drawingData = data['Drawing']
4127        viewPt = np.array(drawingData['viewPoint'][0])
4128        print ' Distance from view point at %.3f %.3f %.3f to:'%(viewPt[0],viewPt[1],viewPt[2])
4129        colLabels = [MapPeaks.GetColLabelValue(c) for c in range(MapPeaks.GetNumberCols())]
4130        cx = colLabels.index('x')
4131        cm = colLabels.index('mag')
4132        for i in indx:
4133            peak = mapPeaks[i]
4134            Dx = np.array(peak[cx:cx+3])-viewPt
4135            dist = np.sqrt(np.sum(np.inner(Amat,Dx)**2,axis=0))
4136            print 'Peak: %5d mag= %8.2f distance = %.3f'%(i,peak[cm],dist)
4137
4138    def OnPeaksDA(event):
4139        #distance, angle
4140        indx = MapPeaks.GetSelectedRows()
4141        if len(indx) not in [2,3]:
4142            print '**** ERROR - wrong number of atoms for distance or angle calculation'
4143            return
4144        generalData = data['General']
4145        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])           
4146        mapPeaks = data['Map Peaks']
4147        xyz = []
4148        for i in indx:
4149            xyz.append(mapPeaks[i][1:4])
4150        if len(indx) == 2:
4151            print ' distance for atoms %s = %.3f'%(str(indx),G2mth.getRestDist(xyz,Amat))
4152        else:
4153            print ' angle for atoms %s = %.2f'%(str(indx),G2mth.getRestAngle(xyz,Amat))
4154                                   
4155    def OnFourierMaps(event):
4156        generalData = data['General']
4157        mapData = generalData['Map']
4158        reflName = mapData['RefList']
4159        phaseName = generalData['Name']
4160        if 'PWDR' in reflName:
4161            PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, reflName)
4162            reflSets = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Reflection Lists'))
4163            reflData = reflSets[phaseName]
4164        elif 'HKLF' in reflName:
4165            PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, reflName)
4166            reflData = G2frame.PatternTree.GetItemPyData(