source: trunk/GSASIIphsGUI.py @ 749

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

fix crash on delete atoms
couple roll & peak shift on charge flip maps

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