source: trunk/GSASIIphsGUI.py @ 620

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

remove excessive tabs in source code
fix HKL controls GUI
change HKL reflection record to match the PWDR one
start getting HKLF into fourier & charge flip

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