source: trunk/GSASIIphsGUI.py @ 752

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

add peak distance, view point selection & distance options
allow modification of view direction

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