source: trunk/GSASIIphsGUI.py @ 773

Last change on this file since 773 was 773, checked in by vondreele, 11 years ago

improve atom, drawatom & mappeak selection

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