source: trunk/GSASIIphsGUI.py @ 755

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

fix rotation about view direction
eliminate divide by zero error in quaternion stuff

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