source: trunk/GSASIIphsGUI.py @ 757

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

remove inverse check from peak search - didn't work
implement Zshift in structure plot
fix (mostly) the view direction

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