source: trunk/GSASIIphsGUI.py @ 747

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

fix to Pawley estimate - subtract background
get neg weight on penalty derivs

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