source: trunk/GSASIIphsGUI.py @ 789

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

different solution to the move atom problem - works better

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