source: trunk/GSASIIphsGUI.py @ 751

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

peak search limit now 1000 peaks
allow modification of view point in draw options window
add view direction (incomplete) - should be editable as well

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