source: trunk/GSASIIphsGUI.py @ 609

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

adding more tutorials & fix some uncovered bugs

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