source: trunk/GSASIIphsGUI.py @ 630

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

major mods for HKLF data
remove some dead code
mark more code as dead (#)
implement cif data style as 'val(esd)' for f & f_squared
continue implementation of HKLF data in refinement
HKLF now OK in Fourier & charge flip calcs.

  • Property svn:keywords set to Date Author Revision URL Id
File size: 189.9 KB
Line 
1# -*- coding: utf-8 -*-
2#GSASII - phase data display routines
3########### SVN repository information ###################
4# $Date: 2012-05-21 20:44:17 +0000 (Mon, 21 May 2012) $
5# $Author: vondreele $
6# $Revision: 630 $
7# $URL: trunk/GSASIIphsGUI.py $
8# $Id: GSASIIphsGUI.py 630 2012-05-21 20:44:17Z 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.1 <= 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.1-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            if 'PWDR' in item:
2731                scaleRef = wx.CheckBox(DData,-1,label=' Phase fraction: ')
2732            elif 'HKLF' in item:
2733                scaleRef = wx.CheckBox(DData,-1,label=' Scale factor: ')               
2734            scaleRef.SetValue(UseList[item]['Scale'][1])
2735            Indx[scaleRef.GetId()] = item
2736            scaleRef.Bind(wx.EVT_CHECKBOX, OnScaleRef)
2737            scaleSizer.Add(scaleRef,0,wx.ALIGN_CENTER_VERTICAL)
2738            scaleVal = wx.TextCtrl(DData,wx.ID_ANY,
2739                '%.4f'%(UseList[item]['Scale'][0]),style=wx.TE_PROCESS_ENTER)
2740            Indx[scaleVal.GetId()] = item
2741            scaleVal.Bind(wx.EVT_TEXT_ENTER,OnScaleVal)
2742            scaleVal.Bind(wx.EVT_KILL_FOCUS,OnScaleVal)
2743            scaleSizer.Add(scaleVal,0,wx.ALIGN_CENTER_VERTICAL)
2744            return scaleSizer
2745           
2746        def OnShowData(event):
2747            Obj = event.GetEventObject()
2748            hist = Indx[Obj.GetId()]
2749            UseList[hist]['Show'] = Obj.GetValue()
2750            wx.CallAfter(UpdateDData)
2751            G2plt.PlotSizeStrainPO(G2frame,data)
2752           
2753        def OnCopyData(event):
2754            #how about HKLF data? This is only for PWDR data
2755            Obj = event.GetEventObject()
2756            hist = Indx[Obj.GetId()]
2757            sourceDict = UseList[hist]
2758            copyNames = ['Scale','Pref.Ori.','Size','Mustrain','HStrain','Extinction']
2759            copyDict = {}
2760            for name in copyNames: 
2761                copyDict[name] = copy.deepcopy(sourceDict[name])        #force copy
2762            keyList = ['All',]+UseList.keys()
2763            if UseList:
2764                copyList = []
2765                dlg = wx.MultiChoiceDialog(G2frame, 
2766                    'Copy parameters to which histograms?', 'Copy parameters', 
2767                    keyList, wx.CHOICEDLG_STYLE)
2768                try:
2769                    if dlg.ShowModal() == wx.ID_OK:
2770                        result = dlg.GetSelections()
2771                        for i in result: 
2772                            copyList.append(keyList[i])
2773                        if 'All' in copyList: 
2774                            copyList = keyList[1:]
2775                        for item in copyList:
2776                            UseList[item].update(copy.deepcopy(copyDict))
2777                        wx.CallAfter(UpdateDData)
2778                finally:
2779                    dlg.Destroy()
2780                   
2781        def OnCopyFlags(event):
2782            Obj = event.GetEventObject()
2783            hist = Indx[Obj.GetId()]
2784            sourceDict = UseList[hist]
2785            copyDict = {}
2786            copyNames = ['Scale','Pref.Ori.','Size','Mustrain','HStrain','Extinction']
2787            for name in copyNames:
2788                if name in ['Scale','Extinction','HStrain']:
2789                    copyDict[name] = sourceDict[name][1]
2790                elif name in ['Size','Mustrain']:
2791                    copyDict[name] = [sourceDict[name][0],sourceDict[name][2],sourceDict[name][4]]
2792                elif name == 'Pref.Ori.':
2793                    copyDict[name] = [sourceDict[name][0],sourceDict[name][2]]
2794                    if sourceDict[name][0] == 'SH':
2795                        SHterms = sourceDict[name][5]
2796                        SHflags = {}
2797                        for item in SHterms:
2798                            SHflags[item] = SHterms[item][1]
2799                        copyDict[name].append(SHflags)                       
2800            keyList = ['All',]+UseList.keys()
2801            if UseList:
2802                copyList = []
2803                dlg = wx.MultiChoiceDialog(G2frame, 
2804                    'Copy parameters to which histograms?', 'Copy parameters', 
2805                    keyList, wx.CHOICEDLG_STYLE)
2806                try:
2807                    if dlg.ShowModal() == wx.ID_OK:
2808                        result = dlg.GetSelections()
2809                        for i in result: 
2810                            copyList.append(keyList[i])
2811                        if 'All' in copyList: 
2812                            copyList = keyList[1:]
2813                        for item in copyList:
2814                            UseList[item]                           
2815                            for name in copyNames:
2816                                if name in ['Scale','Extinction','HStrain']:
2817                                    UseList[item][name][1] = copy.copy(copyDict[name])
2818                                elif name in ['Size','Mustrain']:
2819                                    UseList[item][name][0] = copy.copy(copyDict[name][0])
2820                                    UseList[item][name][2] = copy.copy(copyDict[name][1])
2821                                    UseList[item][name][4] = copy.copy(copyDict[name][2])
2822                                elif name == 'Pref.Ori.':
2823                                    UseList[item][name][0] = copy.copy(copyDict[name][0])
2824                                    UseList[item][name][2] = copy.copy(copyDict[name][1])
2825                                    if sourceDict[name][0] == 'SH':
2826                                        SHflags = copy.copy(copyDict[name][2])
2827                                        SHterms = copy.copy(sourceDict[name][5])
2828                                        for item in SHflags:
2829                                            SHterms[item][1] = copy.copy(SHflags[item])                                             
2830                        wx.CallAfter(UpdateDData)
2831                finally:
2832                    dlg.Destroy()
2833           
2834           
2835        def OnLGmixRef(event):
2836            Obj = event.GetEventObject()
2837            hist,name = Indx[Obj.GetId()]
2838            UseList[hist][name][2][2] = Obj.GetValue()
2839           
2840        def OnLGmixVal(event):
2841            Obj = event.GetEventObject()
2842            hist,name = Indx[Obj.GetId()]
2843            try:
2844                value = float(Obj.GetValue())
2845                if 0.1 <= value <= 1:
2846                    UseList[hist][name][1][2] = value
2847                else:
2848                    raise ValueError
2849            except ValueError:
2850                pass
2851            Obj.SetValue("%.4f"%(UseList[hist][name][1][2]))          #reset in case of error
2852
2853        def OnSizeType(event):
2854            Obj = event.GetEventObject()
2855            hist = Indx[Obj.GetId()]
2856            UseList[hist]['Size'][0] = Obj.GetValue()
2857            G2plt.PlotSizeStrainPO(G2frame,data)
2858            wx.CallAfter(UpdateDData)
2859           
2860        def OnSizeRef(event):
2861            Obj = event.GetEventObject()
2862            hist,pid = Indx[Obj.GetId()]
2863            if UseList[hist]['Size'][0] == 'ellipsoidal':
2864                UseList[hist]['Size'][5][pid] = Obj.GetValue()               
2865            else:
2866                UseList[hist]['Size'][2][pid] = Obj.GetValue()
2867           
2868        def OnSizeVal(event):
2869            Obj = event.GetEventObject()
2870            hist,pid = Indx[Obj.GetId()]
2871            if UseList[hist]['Size'][0] == 'ellipsoidal':
2872                try:
2873                    size = float(Obj.GetValue())
2874                    if pid < 3 and size <= 0.001:            #10A lower limit!
2875                        raise ValueError
2876                    UseList[hist]['Size'][4][pid] = size                   
2877                except ValueError:
2878                    pass
2879                Obj.SetValue("%.3f"%(UseList[hist]['Size'][4][pid]))          #reset in case of error
2880            else:
2881                try:
2882                    size = float(Obj.GetValue())
2883                    if size <= 0.001:            #10A lower limit!
2884                        raise ValueError
2885                    UseList[hist]['Size'][1][pid] = size
2886                except ValueError:
2887                    pass
2888                Obj.SetValue("%.3f"%(UseList[hist]['Size'][1][pid]))          #reset in case of error
2889            G2plt.PlotSizeStrainPO(G2frame,data)
2890           
2891        def OnSizeAxis(event):           
2892            Obj = event.GetEventObject()
2893            hist = Indx[Obj.GetId()]
2894            Saxis = Obj.GetValue().split()
2895            try:
2896                hkl = [int(Saxis[i]) for i in range(3)]
2897            except (ValueError,IndexError):
2898                hkl = UseList[hist]['Size'][3]
2899            if not np.any(np.array(hkl)):
2900                hkl = UseList[hist]['Size'][3]
2901            UseList[hist]['Size'][3] = hkl
2902            h,k,l = hkl
2903            Obj.SetValue('%3d %3d %3d'%(h,k,l)) 
2904                       
2905        def OnStrainType(event):
2906            Obj = event.GetEventObject()
2907            hist = Indx[Obj.GetId()]
2908            UseList[hist]['Mustrain'][0] = Obj.GetValue()
2909            wx.CallAfter(UpdateDData)
2910            G2plt.PlotSizeStrainPO(G2frame,data)
2911           
2912        def OnStrainRef(event):
2913            Obj = event.GetEventObject()
2914            hist,pid = Indx[Obj.GetId()]
2915            if UseList[hist]['Mustrain'][0] == 'generalized':
2916                UseList[hist]['Mustrain'][5][pid] = Obj.GetValue()
2917            else:
2918                UseList[hist]['Mustrain'][2][pid] = Obj.GetValue()
2919           
2920        def OnStrainVal(event):
2921            Snames = G2spc.MustrainNames(SGData)
2922            Obj = event.GetEventObject()
2923            hist,pid = Indx[Obj.GetId()]
2924            try:
2925                strain = float(Obj.GetValue())
2926                if UseList[hist]['Mustrain'][0] == 'generalized':
2927                    if '4' in Snames[pid] and strain < 0:
2928                        raise ValueError
2929                    UseList[hist]['Mustrain'][4][pid] = strain
2930                else:
2931                    if strain <= 0:
2932                        raise ValueError
2933                    UseList[hist]['Mustrain'][1][pid] = strain
2934            except ValueError:
2935                pass
2936            if UseList[hist]['Mustrain'][0] == 'generalized':
2937                Obj.SetValue("%.3f"%(UseList[hist]['Mustrain'][4][pid]))          #reset in case of error
2938            else:
2939                Obj.SetValue("%.1f"%(UseList[hist]['Mustrain'][1][pid]))          #reset in case of error
2940            G2plt.PlotSizeStrainPO(G2frame,data)
2941           
2942        def OnStrainAxis(event):
2943            Obj = event.GetEventObject()
2944            hist = Indx[Obj.GetId()]
2945            Saxis = Obj.GetValue().split()
2946            try:
2947                hkl = [int(Saxis[i]) for i in range(3)]
2948            except (ValueError,IndexError):
2949                hkl = UseList[hist]['Mustrain'][3]
2950            if not np.any(np.array(hkl)):
2951                hkl = UseList[hist]['Mustrain'][3]
2952            UseList[hist]['Mustrain'][3] = hkl
2953            h,k,l = hkl
2954            Obj.SetValue('%3d %3d %3d'%(h,k,l)) 
2955            G2plt.PlotSizeStrainPO(G2frame,data)
2956           
2957        def OnHstrainRef(event):
2958            Obj = event.GetEventObject()
2959            hist,pid = Indx[Obj.GetId()]
2960            UseList[hist]['HStrain'][1][pid] = Obj.GetValue()
2961           
2962        def OnHstrainVal(event):
2963            Snames = G2spc.HStrainNames(SGData)
2964            Obj = event.GetEventObject()
2965            hist,pid = Indx[Obj.GetId()]
2966            try:
2967                strain = float(Obj.GetValue())
2968                UseList[hist]['HStrain'][0][pid] = strain
2969            except ValueError:
2970                pass
2971            Obj.SetValue("%.5f"%(UseList[hist]['HStrain'][0][pid]))          #reset in case of error
2972
2973        def OnPOVal(event):
2974            Obj = event.GetEventObject()
2975            hist = Indx[Obj.GetId()]
2976            try:
2977                mdVal = float(Obj.GetValue())
2978                if mdVal > 0:
2979                    UseList[hist]['Pref.Ori.'][1] = mdVal
2980            except ValueError:
2981                pass
2982            Obj.SetValue("%.3f"%(UseList[hist]['Pref.Ori.'][1]))          #reset in case of error
2983           
2984        def OnPOAxis(event):
2985            Obj = event.GetEventObject()
2986            hist = Indx[Obj.GetId()]
2987            Saxis = Obj.GetValue().split()
2988            try:
2989                hkl = [int(Saxis[i]) for i in range(3)]
2990            except (ValueError,IndexError):
2991                hkl = UseList[hist]['Pref.Ori.'][3]
2992            if not np.any(np.array(hkl)):
2993                hkl = UseList[hist]['Pref.Ori.'][3]
2994            UseList[hist]['Pref.Ori.'][3] = hkl
2995            h,k,l = hkl
2996            Obj.SetValue('%3d %3d %3d'%(h,k,l)) 
2997           
2998        def OnPOOrder(event):
2999            Obj = event.GetEventObject()
3000            hist = Indx[Obj.GetId()]
3001            Order = int(Obj.GetValue())
3002            UseList[hist]['Pref.Ori.'][4] = Order
3003            UseList[hist]['Pref.Ori.'][5] = SetPOCoef(Order,hist)
3004            wx.CallAfter(UpdateDData)
3005
3006        def OnPOType(event):
3007            Obj = event.GetEventObject()
3008            hist = Indx[Obj.GetId()]
3009            if 'March' in Obj.GetValue():
3010                UseList[hist]['Pref.Ori.'][0] = 'MD'
3011            else:
3012                UseList[hist]['Pref.Ori.'][0] = 'SH'
3013            wx.CallAfter(UpdateDData)           
3014   
3015        def OnPORef(event):
3016            Obj = event.GetEventObject()
3017            hist = Indx[Obj.GetId()]
3018            UseList[hist]['Pref.Ori.'][2] = Obj.GetValue()
3019               
3020        def SetPOCoef(Order,hist):
3021            cofNames = G2lat.GenSHCoeff(SGData['SGLaue'],'0',Order,False)     #cylindrical & no M
3022            newPOCoef = dict(zip(cofNames,np.zeros(len(cofNames))))
3023            POCoeff = UseList[hist]['Pref.Ori.'][5]
3024            for cofName in POCoeff:
3025                if cofName in  cofNames:
3026                    newPOCoef[cofName] = POCoeff[cofName]
3027            return newPOCoef
3028       
3029        def OnExtRef(event):
3030            Obj = event.GetEventObject()
3031            UseList[Indx[Obj.GetId()]]['Extinction'][1] = Obj.GetValue()
3032           
3033        def OnExtVal(event):
3034            Obj = event.GetEventObject()
3035            try:
3036                ext = float(Obj.GetValue())
3037                if ext >= 0:
3038                    UseList[Indx[Obj.GetId()]]['Extinction'][0] = ext
3039            except ValueError:
3040                pass
3041            Obj.SetValue("%.2f"%(UseList[Indx[Obj.GetId()]]['Extinction'][0]))
3042           
3043        def OnTbarVal(event):
3044            Obj = event.GetEventObject()
3045            try:
3046                tbar = float(Obj.GetValue())
3047                if tbar >= 0:
3048                    UseList[Indx[Obj.GetId()]]['Extinction'][2]['Tbar'] = tbar
3049            except ValueError:
3050                pass
3051            Obj.SetValue("%.2f"%(UseList[Indx[Obj.GetId()]]['Extinction'][2]['Tbar']))
3052           
3053        def OnEval(event):
3054            Obj = event.GetEventObject()
3055            item = Indx[Obj.GetId()]
3056            try:
3057                val = float(Obj.GetValue())
3058                if val >= 0:
3059                    UseList[item[0]]['Extinction'][2][item[1]][0] = val
3060            except ValueError:
3061                pass
3062            Obj.SetValue("%9.3g"%(UseList[item[0]]['Extinction'][2][item[1]][0]))
3063           
3064        def OnEref(event):
3065            Obj = event.GetEventObject()
3066            item = Indx[Obj.GetId()]
3067            UseList[item[0]]['Extinction'][2][item[1]][1] = Obj.GetValue()
3068
3069        def OnSCExtType(event):
3070            Obj = event.GetEventObject()
3071            item = Indx[Obj.GetId()]
3072            UseList[item[0]]['Extinction'][item[1]] = Obj.GetValue()
3073            wx.CallAfter(UpdateDData)
3074               
3075        def checkAxis(axis):
3076            if not np.any(np.array(axis)):
3077                return False
3078            return axis
3079           
3080        def TopSizer(name,choices,parm,OnType):
3081            topSizer = wx.BoxSizer(wx.HORIZONTAL)
3082            topSizer.Add(wx.StaticText(DData,-1,name),0,wx.ALIGN_CENTER_VERTICAL)
3083            sizeType = wx.ComboBox(DData,wx.ID_ANY,value=UseList[item][parm][0],choices=choices,
3084                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3085            sizeType.Bind(wx.EVT_COMBOBOX, OnType)
3086            Indx[sizeType.GetId()] = item
3087            topSizer.Add(sizeType)
3088            topSizer.Add((5,0),0)
3089            return topSizer
3090           
3091        def LGmixSizer(name,OnVal,OnRef):
3092            lgmixSizer = wx.BoxSizer(wx.HORIZONTAL)
3093            lgmixRef = wx.CheckBox(DData,-1,label='LGmix')
3094            lgmixRef.thisown = False
3095            lgmixRef.SetValue(UseList[item][name][2][2])
3096            Indx[lgmixRef.GetId()] = [item,name]
3097            lgmixRef.Bind(wx.EVT_CHECKBOX, OnRef)
3098            lgmixSizer.Add(lgmixRef,0,wx.ALIGN_CENTER_VERTICAL)
3099            lgmixVal = wx.TextCtrl(DData,wx.ID_ANY,
3100                '%.4f'%(UseList[item][name][1][2]),style=wx.TE_PROCESS_ENTER)
3101            Indx[lgmixVal.GetId()] = [item,name]
3102            lgmixVal.Bind(wx.EVT_TEXT_ENTER,OnVal)
3103            lgmixVal.Bind(wx.EVT_KILL_FOCUS,OnVal)
3104            lgmixSizer.Add(lgmixVal,0,wx.ALIGN_CENTER_VERTICAL)
3105            return lgmixSizer
3106                       
3107        def IsoSizer(name,parm,fmt,OnVal,OnRef):
3108            isoSizer = wx.BoxSizer(wx.HORIZONTAL)
3109            sizeRef = wx.CheckBox(DData,-1,label=name)
3110            sizeRef.thisown = False
3111            sizeRef.SetValue(UseList[item][parm][2][0])
3112            Indx[sizeRef.GetId()] = [item,0]
3113            sizeRef.Bind(wx.EVT_CHECKBOX, OnRef)
3114            isoSizer.Add(sizeRef,0,wx.ALIGN_CENTER_VERTICAL)
3115            sizeVal = wx.TextCtrl(DData,wx.ID_ANY,
3116                fmt%(UseList[item][parm][1][0]),style=wx.TE_PROCESS_ENTER)
3117            Indx[sizeVal.GetId()] = [item,0]
3118            sizeVal.Bind(wx.EVT_TEXT_ENTER,OnVal)
3119            sizeVal.Bind(wx.EVT_KILL_FOCUS,OnVal)
3120            isoSizer.Add(sizeVal,0,wx.ALIGN_CENTER_VERTICAL)
3121            return isoSizer
3122           
3123        def UniSizer(parm,OnAxis):
3124            uniSizer = wx.BoxSizer(wx.HORIZONTAL)
3125            uniSizer.Add(wx.StaticText(DData,-1,' Unique axis, H K L: '),0,wx.ALIGN_CENTER_VERTICAL)
3126            h,k,l = UseList[item][parm][3]
3127            Axis = wx.TextCtrl(DData,-1,'%3d %3d %3d'%(h,k,l),style=wx.TE_PROCESS_ENTER)
3128            Indx[Axis.GetId()] = item
3129            Axis.Bind(wx.EVT_TEXT_ENTER,OnAxis)
3130            Axis.Bind(wx.EVT_KILL_FOCUS,OnAxis)
3131            uniSizer.Add(Axis,0,wx.ALIGN_CENTER_VERTICAL)
3132            return uniSizer
3133           
3134        def UniDataSizer(parmName,parm,fmt,OnVal,OnRef):
3135            dataSizer = wx.BoxSizer(wx.HORIZONTAL)
3136            parms = zip([' Equatorial '+parmName,' Axial '+parmName],
3137                UseList[item][parm][1],UseList[item][parm][2],range(2))
3138            for Pa,val,ref,id in parms:
3139                sizeRef = wx.CheckBox(DData,-1,label=Pa)
3140                sizeRef.thisown = False
3141                sizeRef.SetValue(ref)
3142                Indx[sizeRef.GetId()] = [item,id]
3143                sizeRef.Bind(wx.EVT_CHECKBOX, OnRef)
3144                dataSizer.Add(sizeRef,0,wx.ALIGN_CENTER_VERTICAL)
3145                sizeVal = wx.TextCtrl(DData,wx.ID_ANY,fmt%(val),style=wx.TE_PROCESS_ENTER)
3146                Indx[sizeVal.GetId()] = [item,id]
3147                sizeVal.Bind(wx.EVT_TEXT_ENTER,OnVal)
3148                sizeVal.Bind(wx.EVT_KILL_FOCUS,OnVal)
3149                dataSizer.Add(sizeVal,0,wx.ALIGN_CENTER_VERTICAL)
3150                dataSizer.Add((5,0),0)
3151            return dataSizer
3152           
3153        def EllSizeDataSizer():
3154            parms = zip(['S11','S22','S33','S12','S13','S23'],UseList[item]['Size'][4],
3155                UseList[item]['Size'][5],range(6))
3156            dataSizer = wx.FlexGridSizer(1,6,5,5)
3157            for Pa,val,ref,id in parms:
3158                sizeRef = wx.CheckBox(DData,-1,label=Pa)
3159                sizeRef.thisown = False
3160                sizeRef.SetValue(ref)
3161                Indx[sizeRef.GetId()] = [item,id]
3162                sizeRef.Bind(wx.EVT_CHECKBOX, OnSizeRef)
3163                dataSizer.Add(sizeRef,0,wx.ALIGN_CENTER_VERTICAL)
3164                sizeVal = wx.TextCtrl(DData,wx.ID_ANY,'%.3f'%(val),style=wx.TE_PROCESS_ENTER)
3165                Indx[sizeVal.GetId()] = [item,id]
3166                sizeVal.Bind(wx.EVT_TEXT_ENTER,OnSizeVal)
3167                sizeVal.Bind(wx.EVT_KILL_FOCUS,OnSizeVal)
3168                dataSizer.Add(sizeVal,0,wx.ALIGN_CENTER_VERTICAL)
3169            return dataSizer
3170           
3171        def GenStrainDataSizer():
3172            Snames = G2spc.MustrainNames(SGData)
3173            numb = len(Snames)
3174            if len(UseList[item]['Mustrain'][4]) < numb:
3175                UseList[item]['Mustrain'][4] = numb*[0.0,]
3176                UseList[item]['Mustrain'][5] = numb*[False,]
3177            parms = zip(Snames,UseList[item]['Mustrain'][4],UseList[item]['Mustrain'][5],range(numb))
3178            dataSizer = wx.FlexGridSizer(1,6,5,5)
3179            for Pa,val,ref,id in parms:
3180                strainRef = wx.CheckBox(DData,-1,label=Pa)
3181                strainRef.thisown = False
3182                strainRef.SetValue(ref)
3183                Indx[strainRef.GetId()] = [item,id]
3184                strainRef.Bind(wx.EVT_CHECKBOX, OnStrainRef)
3185                dataSizer.Add(strainRef,0,wx.ALIGN_CENTER_VERTICAL)
3186                strainVal = wx.TextCtrl(DData,wx.ID_ANY,'%.5f'%(val),style=wx.TE_PROCESS_ENTER)
3187                Indx[strainVal.GetId()] = [item,id]
3188                strainVal.Bind(wx.EVT_TEXT_ENTER,OnStrainVal)
3189                strainVal.Bind(wx.EVT_KILL_FOCUS,OnStrainVal)
3190                dataSizer.Add(strainVal,0,wx.ALIGN_CENTER_VERTICAL)
3191            return dataSizer
3192           
3193        def HstrainSizer():
3194            hstrainSizer = wx.FlexGridSizer(1,6,5,5)
3195            Hsnames = G2spc.HStrainNames(SGData)
3196            parms = zip(Hsnames,UseList[item]['HStrain'][0],UseList[item]['HStrain'][1],range(len(Hsnames)))
3197            for Pa,val,ref,id in parms:
3198                hstrainRef = wx.CheckBox(DData,-1,label=Pa)
3199                hstrainRef.thisown = False
3200                hstrainRef.SetValue(ref)
3201                Indx[hstrainRef.GetId()] = [item,id]
3202                hstrainRef.Bind(wx.EVT_CHECKBOX, OnHstrainRef)
3203                hstrainSizer.Add(hstrainRef,0,wx.ALIGN_CENTER_VERTICAL)
3204                hstrainVal = wx.TextCtrl(DData,wx.ID_ANY,'%.5f'%(val),style=wx.TE_PROCESS_ENTER)
3205                Indx[hstrainVal.GetId()] = [item,id]
3206                hstrainVal.Bind(wx.EVT_TEXT_ENTER,OnHstrainVal)
3207                hstrainVal.Bind(wx.EVT_KILL_FOCUS,OnHstrainVal)
3208                hstrainSizer.Add(hstrainVal,0,wx.ALIGN_CENTER_VERTICAL)
3209            return hstrainSizer
3210           
3211        def PoTopSizer(POData):
3212            poSizer = wx.FlexGridSizer(1,6,5,5)
3213            choice = ['March-Dollase','Spherical harmonics']
3214            POtype = choice[['MD','SH'].index(POData[0])]
3215            poSizer.Add(wx.StaticText(DData,-1,' Preferred orientation model '),0,wx.ALIGN_CENTER_VERTICAL)
3216            POType = wx.ComboBox(DData,wx.ID_ANY,value=POtype,choices=choice,
3217                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3218            Indx[POType.GetId()] = item
3219            POType.Bind(wx.EVT_COMBOBOX, OnPOType)
3220            poSizer.Add(POType)
3221            if POData[0] == 'SH':
3222                poSizer.Add(wx.StaticText(DData,-1,' Harmonic order: '),0,wx.ALIGN_CENTER_VERTICAL)
3223                poOrder = wx.ComboBox(DData,wx.ID_ANY,value=str(POData[4]),choices=[str(2*i) for i in range(18)],
3224                    style=wx.CB_READONLY|wx.CB_DROPDOWN)
3225                Indx[poOrder.GetId()] = item
3226                poOrder.Bind(wx.EVT_COMBOBOX,OnPOOrder)
3227                poSizer.Add(poOrder,0,wx.ALIGN_CENTER_VERTICAL)
3228                poRef = wx.CheckBox(DData,-1,label=' Refine? ')
3229                poRef.SetValue(POData[2])
3230                Indx[poRef.GetId()] = item
3231                poRef.Bind(wx.EVT_CHECKBOX,OnPORef)
3232                poSizer.Add(poRef,0,wx.ALIGN_CENTER_VERTICAL)
3233            return poSizer
3234           
3235        def MDDataSizer(POData):
3236            poSizer = wx.BoxSizer(wx.HORIZONTAL)
3237            poRef = wx.CheckBox(DData,-1,label=' March-Dollase ratio: ')
3238            poRef.SetValue(POData[2])
3239            Indx[poRef.GetId()] = item
3240            poRef.Bind(wx.EVT_CHECKBOX,OnPORef)
3241            poSizer.Add(poRef,0,wx.ALIGN_CENTER_VERTICAL)
3242            poVal = wx.TextCtrl(DData,wx.ID_ANY,
3243                '%.3f'%(POData[1]),style=wx.TE_PROCESS_ENTER)
3244            Indx[poVal.GetId()] = item
3245            poVal.Bind(wx.EVT_TEXT_ENTER,OnPOVal)
3246            poVal.Bind(wx.EVT_KILL_FOCUS,OnPOVal)
3247            poSizer.Add(poVal,0,wx.ALIGN_CENTER_VERTICAL)
3248            poSizer.Add(wx.StaticText(DData,-1,' Unique axis, H K L: '),0,wx.ALIGN_CENTER_VERTICAL)
3249            h,k,l =POData[3]
3250            poAxis = wx.TextCtrl(DData,-1,'%3d %3d %3d'%(h,k,l),style=wx.TE_PROCESS_ENTER)
3251            Indx[poAxis.GetId()] = item
3252            poAxis.Bind(wx.EVT_TEXT_ENTER,OnPOAxis)
3253            poAxis.Bind(wx.EVT_KILL_FOCUS,OnPOAxis)
3254            poSizer.Add(poAxis,0,wx.ALIGN_CENTER_VERTICAL)
3255            return poSizer
3256           
3257        def SHDataSizer(POData):
3258            textJ = G2lat.textureIndex(POData[5])
3259            mainSizer.Add(wx.StaticText(DData,-1,' Spherical harmonic coefficients: '+'Texture index: %.3f'%(textJ)),0,wx.ALIGN_CENTER_VERTICAL)
3260            mainSizer.Add((0,5),0)
3261            ODFSizer = wx.FlexGridSizer(2,8,2,2)
3262            ODFIndx = {}
3263            ODFkeys = POData[5].keys()
3264            ODFkeys.sort()
3265            for odf in ODFkeys:
3266                ODFSizer.Add(wx.StaticText(DData,-1,odf),0,wx.ALIGN_CENTER_VERTICAL)
3267                ODFval = wx.TextCtrl(DData,wx.ID_ANY,'%8.3f'%(POData[5][odf]),style=wx.TE_PROCESS_ENTER)
3268                ODFIndx[ODFval.GetId()] = odf
3269#                ODFval.Bind(wx.EVT_TEXT_ENTER,OnODFValue)
3270#                ODFval.Bind(wx.EVT_KILL_FOCUS,OnODFValue)
3271                ODFSizer.Add(ODFval,0,wx.ALIGN_CENTER_VERTICAL)
3272            return ODFSizer
3273           
3274        def ExtSizer():           
3275            extSizer = wx.BoxSizer(wx.HORIZONTAL)
3276            extRef = wx.CheckBox(DData,-1,label=' Extinction: ')
3277            extRef.SetValue(UseList[item]['Extinction'][1])
3278            Indx[extRef.GetId()] = item
3279            extRef.Bind(wx.EVT_CHECKBOX, OnExtRef)
3280            extSizer.Add(extRef,0,wx.ALIGN_CENTER_VERTICAL)
3281            extVal = wx.TextCtrl(DData,wx.ID_ANY,
3282                '%.2f'%(UseList[item]['Extinction'][0]),style=wx.TE_PROCESS_ENTER)
3283            Indx[extVal.GetId()] = item
3284            extVal.Bind(wx.EVT_TEXT_ENTER,OnExtVal)
3285            extVal.Bind(wx.EVT_KILL_FOCUS,OnExtVal)
3286            extSizer.Add(extVal,0,wx.ALIGN_CENTER_VERTICAL)
3287            return extSizer
3288       
3289        def SCExtSizer():
3290#'Extinction':['Lorentzian','Secondary Type I',{'Tbar':0.20,'Eg':[0.0,False],'Es':[0.0,False],'Ep':[0.0,False]},]}
3291            extSizer = wx.BoxSizer(wx.VERTICAL)
3292            typeSizer = wx.BoxSizer(wx.HORIZONTAL)           
3293            typeSizer.Add(wx.StaticText(DData,-1,' Extinction type: '),0,wx.ALIGN_CENTER_VERTICAL)
3294            Choices = ['Primary','Secondary Type I','Secondary Type II','Secondary Type I & II']
3295            typeTxt = wx.ComboBox(DData,-1,choices=Choices,value=UseList[item]['Extinction'][1],
3296                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3297            Indx[typeTxt.GetId()] = [item,1]
3298            typeTxt.Bind(wx.EVT_COMBOBOX,OnSCExtType)
3299            typeSizer.Add(typeTxt)
3300            typeSizer.Add(wx.StaticText(DData,-1,' Approx: '),0,wx.ALIGN_CENTER_VERTICAL)
3301            Choices=['Lorentzian','Gaussian']
3302            approxTxT = wx.ComboBox(DData,-1,choices=Choices,value=UseList[item]['Extinction'][0],
3303                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3304            Indx[approxTxT.GetId()] = [item,0]
3305            approxTxT.Bind(wx.EVT_COMBOBOX,OnSCExtType)
3306            typeSizer.Add(approxTxT)
3307            extSizer.Add(typeSizer,0,wx.ALIGN_CENTER_VERTICAL)
3308            extSizer.Add((0,5),)
3309            valSizer =wx.BoxSizer(wx.HORIZONTAL)
3310            valSizer.Add(wx.StaticText(DData,-1,' Tbar(mm):'),0,wx.ALIGN_CENTER_VERTICAL)
3311            tbarVal = wx.TextCtrl(DData,wx.ID_ANY,
3312                '%.3f'%(UseList[item]['Extinction'][2]['Tbar']),style=wx.TE_PROCESS_ENTER)
3313            Indx[tbarVal.GetId()] = item
3314            tbarVal.Bind(wx.EVT_TEXT_ENTER,OnTbarVal)
3315            tbarVal.Bind(wx.EVT_KILL_FOCUS,OnTbarVal)
3316            valSizer.Add(tbarVal,0,wx.ALIGN_CENTER_VERTICAL)
3317            if 'Primary' in UseList[item]['Extinction'][1]:
3318                Ekey = ['Ep',]
3319            elif 'Secondary Type II' == UseList[item]['Extinction'][1]:
3320                Ekey = ['Es',]
3321            elif 'Secondary Type I' == UseList[item]['Extinction'][1]:
3322                Ekey = ['Eg',]
3323            else:
3324                Ekey = ['Eg','Es']
3325            for ekey in Ekey:
3326                Eref = wx.CheckBox(DData,-1,label=ekey+' : ')
3327                Eref.SetValue(UseList[item]['Extinction'][2][ekey][1])
3328                Indx[Eref.GetId()] = [item,ekey]
3329                Eref.Bind(wx.EVT_CHECKBOX, OnEref)
3330                valSizer.Add(Eref,0,wx.ALIGN_CENTER_VERTICAL)
3331                Eval = wx.TextCtrl(DData,wx.ID_ANY,
3332                    '%9.3g'%(UseList[item]['Extinction'][2][ekey][0]),style=wx.TE_PROCESS_ENTER)
3333                Indx[Eval.GetId()] = [item,ekey]
3334                Eval.Bind(wx.EVT_TEXT_ENTER,OnEval)
3335                Eval.Bind(wx.EVT_KILL_FOCUS,OnEval)
3336                valSizer.Add(Eval,0,wx.ALIGN_CENTER_VERTICAL)
3337
3338            extSizer.Add(valSizer,0,wx.ALIGN_CENTER_VERTICAL)
3339            return extSizer
3340           
3341        if DData.GetSizer():
3342            DData.GetSizer().Clear(True)
3343        mainSizer = wx.BoxSizer(wx.VERTICAL)
3344        mainSizer.Add(wx.StaticText(DData,-1,'Histogram data for '+PhaseName+':'),0,wx.ALIGN_CENTER_VERTICAL)
3345        mainSizer.Add(PlotSizer())           
3346           
3347        for item in keyList:
3348            histData = UseList[item]
3349            showSizer = wx.BoxSizer(wx.HORIZONTAL)
3350            showData = wx.CheckBox(DData,-1,label=' Show '+item)
3351            showData.SetValue(UseList[item]['Show'])
3352            Indx[showData.GetId()] = item
3353            showData.Bind(wx.EVT_CHECKBOX, OnShowData)
3354            showSizer.Add(showData,0,wx.ALIGN_CENTER_VERTICAL)
3355            copyData = wx.Button(DData,-1,label=' Copy?')
3356            Indx[copyData.GetId()] = item
3357            copyData.Bind(wx.EVT_BUTTON,OnCopyData)
3358            showSizer.Add(copyData,wx.ALIGN_CENTER_VERTICAL)
3359            copyFlags = wx.Button(DData,-1,label=' Copy flags?')
3360            Indx[copyFlags.GetId()] = item
3361            copyFlags.Bind(wx.EVT_BUTTON,OnCopyFlags)
3362            showSizer.Add(copyFlags,wx.ALIGN_CENTER_VERTICAL)
3363            mainSizer.Add((5,5),0)
3364            mainSizer.Add(showSizer,0,wx.ALIGN_CENTER_VERTICAL)
3365            mainSizer.Add((0,5),0)
3366           
3367            if UseList[item]['Show']:
3368                mainSizer.Add(ScaleSizer())
3369                mainSizer.Add((0,5),0)
3370               
3371            if item[:4] == 'PWDR' and UseList[item]['Show']:
3372                if UseList[item]['Size'][0] == 'isotropic':
3373                    isoSizer = wx.BoxSizer(wx.HORIZONTAL)
3374                    isoSizer.Add(TopSizer(' Size model: ',['isotropic','uniaxial','ellipsoidal'],
3375                        'Size',OnSizeType),0,wx.ALIGN_CENTER_VERTICAL)
3376                    isoSizer.Add(LGmixSizer('Size',OnLGmixVal,OnLGmixRef))
3377                    mainSizer.Add(isoSizer)
3378                    mainSizer.Add(IsoSizer(u' Cryst. size(\xb5m): ','Size','%.3f',
3379                        OnSizeVal,OnSizeRef),0,wx.ALIGN_CENTER_VERTICAL)
3380                elif UseList[item]['Size'][0] == 'uniaxial':
3381                    uniSizer = wx.BoxSizer(wx.HORIZONTAL)
3382                    uniSizer.Add(TopSizer(' Size model: ',['isotropic','uniaxial','ellipsoidal'],
3383                        'Size',OnSizeType),0,wx.ALIGN_CENTER_VERTICAL)
3384                    uniSizer.Add(LGmixSizer('Size',OnLGmixVal,OnLGmixRef))
3385                    uniSizer.Add(UniSizer('Size',OnSizeAxis),0,wx.ALIGN_CENTER_VERTICAL)
3386                    mainSizer.Add(uniSizer)
3387                    mainSizer.Add(UniDataSizer(u'size(\xb5m): ','Size','%.3f',OnSizeVal,OnSizeRef))
3388                elif UseList[item]['Size'][0] == 'ellipsoidal':
3389                    ellSizer = wx.BoxSizer(wx.HORIZONTAL)
3390                    ellSizer.Add(TopSizer(' Size model: ',['isotropic','uniaxial','ellipsoidal'],
3391                        'Size',OnSizeType),0,wx.ALIGN_CENTER_VERTICAL)
3392                    ellSizer.Add(LGmixSizer('Size',OnLGmixVal,OnLGmixRef))
3393                    mainSizer.Add(ellSizer)
3394                    mainSizer.Add(EllSizeDataSizer())
3395                mainSizer.Add((0,5),0)                   
3396               
3397                if UseList[item]['Mustrain'][0] == 'isotropic':
3398                    isoSizer = wx.BoxSizer(wx.HORIZONTAL)
3399                    isoSizer.Add(TopSizer(' Mustrain model: ',['isotropic','uniaxial','generalized',],
3400                        'Mustrain',OnStrainType),0,wx.ALIGN_CENTER_VERTICAL)
3401                    isoSizer.Add(LGmixSizer('Mustrain',OnLGmixVal,OnLGmixRef))
3402                    mainSizer.Add(isoSizer)
3403                    mainSizer.Add(IsoSizer(' microstrain: ','Mustrain','%.1f',
3404                        OnStrainVal,OnStrainRef),0,wx.ALIGN_CENTER_VERTICAL)                   
3405                    mainSizer.Add((0,5),0)
3406                elif UseList[item]['Mustrain'][0] == 'uniaxial':
3407                    uniSizer = wx.BoxSizer(wx.HORIZONTAL)
3408                    uniSizer.Add(TopSizer(' Mustrain model: ',['isotropic','uniaxial','generalized',],
3409                        'Mustrain',OnStrainType),0,wx.ALIGN_CENTER_VERTICAL)
3410                    uniSizer.Add(LGmixSizer('Mustrain',OnLGmixVal,OnLGmixRef))
3411                    uniSizer.Add(UniSizer('Mustrain',OnStrainAxis),0,wx.ALIGN_CENTER_VERTICAL)
3412                    mainSizer.Add(uniSizer)
3413                    mainSizer.Add(UniDataSizer('mustrain: ','Mustrain','%.1f',OnStrainVal,OnStrainRef))
3414                elif UseList[item]['Mustrain'][0] == 'generalized':
3415                    genSizer = wx.BoxSizer(wx.HORIZONTAL)
3416                    genSizer.Add(TopSizer(' Mustrain model: ',['isotropic','uniaxial','generalized',],
3417                        'Mustrain',OnStrainType),0,wx.ALIGN_CENTER_VERTICAL)
3418                    genSizer.Add(LGmixSizer('Mustrain',OnLGmixVal,OnLGmixRef))
3419                    mainSizer.Add(genSizer)
3420                    mainSizer.Add(GenStrainDataSizer())                       
3421                mainSizer.Add((0,5),0)
3422               
3423                mainSizer.Add(wx.StaticText(DData,-1,' Hydrostatic/elastic strain:'))
3424                mainSizer.Add(HstrainSizer())
3425                   
3426                #texture  'Pref. Ori.':['MD',1.0,False,[0,0,1],0,[]] last two for 'SH' are SHorder & coeff
3427                poSizer = wx.BoxSizer(wx.VERTICAL)
3428                POData = UseList[item]['Pref.Ori.']
3429                poSizer.Add(PoTopSizer(POData))
3430                if POData[0] == 'MD':
3431                    poSizer.Add(MDDataSizer(POData))
3432                else:           #'SH'
3433                    if POData[4]:       #SH order > 0
3434                        poSizer.Add(SHDataSizer(POData))
3435                       
3436                mainSizer.Add(poSizer)
3437                mainSizer.Add((0,5),0)               
3438                #Extinction  'Extinction':[0.0,False]
3439                mainSizer.Add(ExtSizer())
3440                mainSizer.Add((0,5),0)
3441            elif item[:4] == 'HKLF' and UseList[item]['Show']:
3442                mainSizer.Add((0,5),0)               
3443                mainSizer.Add(SCExtSizer())
3444                mainSizer.Add((0,5),0)
3445                pass
3446        mainSizer.Add((5,5),0)
3447
3448        DData.SetSizer(mainSizer,True)
3449        mainSizer.FitInside(G2frame.dataFrame)
3450        Size = mainSizer.GetMinSize()
3451        Size[0] += 40
3452        Size[1] = max(Size[1],290) + 20
3453        DData.SetSize(Size)
3454        DData.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
3455        Size[1] = min(Size[1],450)
3456        G2frame.dataFrame.setSizePosLeft(Size)
3457       
3458    def OnHklfAdd(event):
3459        UseList = data['Histograms']
3460        keyList = UseList.keys()
3461        TextList = []
3462        if G2frame.PatternTree.GetCount():
3463            item, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
3464            while item:
3465                name = G2frame.PatternTree.GetItemText(item)
3466                if name not in keyList and 'HKLF' in name:
3467                    TextList.append(name)
3468                item, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)                       
3469            dlg = wx.MultiChoiceDialog(G2frame, 'Which new data to use?', 'Use data', TextList, wx.CHOICEDLG_STYLE)
3470            try:
3471                if dlg.ShowModal() == wx.ID_OK:
3472                    result = dlg.GetSelections()
3473                    for i in result:
3474                        histoName = TextList[i]
3475                        UseList[histoName] = {'Histogram':histoName,'Show':False,'Scale':[1.0,True],
3476                            'Extinction':['Lorentzian','Secondary Type I',
3477                            {'Tbar':0.0,'Eg':[0.0,False],'Es':[0.0,False],'Ep':[0.0,False]},]}                       
3478                    data['Histograms'] = UseList
3479                    wx.BeginBusyCursor()
3480                    UpdateHKLFdata(histoName)
3481                    wx.EndBusyCursor()
3482                    wx.CallAfter(UpdateDData)
3483            finally:
3484                dlg.Destroy()
3485               
3486    def UpdateHKLFdata(histoName):
3487        generalData = data['General']
3488        Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,histoName)
3489        reflData = G2frame.PatternTree.GetItemPyData(Id)[1]
3490        SGData = generalData['SGData']
3491        Cell = generalData['Cell'][1:7]
3492        G,g = G2lat.cell2Gmat(Cell)
3493        for ref in reflData:
3494            H = ref[:3]
3495            ref[4] = np.sqrt(1./G2lat.calc_rDsq2(H,G))
3496            iabsnt,mulp,Uniq,phi = G2spc.GenHKLf(H,SGData,Friedel=False)
3497            ref[3] = mulp/2             #convert from powder mulp.
3498            ref[11] = Uniq
3499            ref[12] = phi
3500        G2frame.PatternTree.SetItemPyData(Id,[histoName,reflData])
3501       
3502    def OnPwdrAdd(event):
3503        generalData = data['General']
3504        SGData = generalData['SGData']
3505        UseList = data['Histograms']
3506        newList = []
3507        NShkl = len(G2spc.MustrainNames(SGData))
3508        NDij = len(G2spc.HStrainNames(SGData))
3509        keyList = UseList.keys()
3510        TextList = ['All PWDR']
3511        if G2frame.PatternTree.GetCount():
3512            item, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
3513            while item:
3514                name = G2frame.PatternTree.GetItemText(item)
3515                if name not in keyList and 'PWDR' in name:
3516                    TextList.append(name)
3517                item, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
3518            dlg = wx.MultiChoiceDialog(G2frame, 'Which new data to use?', 'Use data', TextList, wx.CHOICEDLG_STYLE)
3519            try:
3520                if dlg.ShowModal() == wx.ID_OK:
3521                    result = dlg.GetSelections()
3522                    for i in result: newList.append(TextList[i])
3523                    if 'All PWDR' in newList:
3524                        newList = TextList[1:]
3525                    for histoName in newList:
3526                        pId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,histoName)
3527                        UseList[histoName] = {'Histogram':histoName,'Show':False,
3528                            'Scale':[1.0,False],'Pref.Ori.':['MD',1.0,False,[0,0,1],0,{}],
3529                            'Size':['isotropic',[4.,4.,1.0],[False,False,False],[0,0,1],
3530                                [4.,4.,4.,0.,0.,0.],6*[False,]],
3531                            'Mustrain':['isotropic',[1000.0,1000.0,1.0],[False,False,False],[0,0,1],
3532                                NShkl*[0.01,],NShkl*[False,]],
3533                            'HStrain':[NDij*[0.0,],NDij*[False,]],                         
3534                            'Extinction':[0.0,False]}
3535                        refList = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,pId,'Reflection Lists'))
3536                        refList[generalData['Name']] = []                       
3537                    data['Histograms'] = UseList
3538                    wx.CallAfter(UpdateDData)
3539            finally:
3540                dlg.Destroy()
3541       
3542    def OnDataDelete(event):
3543        UseList = data['Histograms']
3544        keyList = ['All',]+UseList.keys()
3545        keyList.sort()
3546        DelList = []
3547        if UseList:
3548            DelList = []
3549            dlg = wx.MultiChoiceDialog(G2frame, 
3550                'Which histogram to delete from this phase?', 'Delete histogram', 
3551                keyList, wx.CHOICEDLG_STYLE)
3552            try:
3553                if dlg.ShowModal() == wx.ID_OK:
3554                    result = dlg.GetSelections()
3555                    for i in result: 
3556                        DelList.append(keyList[i])
3557                    if 'All' in DelList:
3558                        DelList = keyList[1:]
3559                    for i in DelList:
3560                        del UseList[i]
3561                    wx.CallAfter(UpdateDData)
3562            finally:
3563                dlg.Destroy()
3564
3565################################################################################
3566##### Pawley routines
3567################################################################################
3568
3569    def FillPawleyReflectionsGrid():
3570                       
3571        def KeyEditPawleyGrid(event):
3572            colList = G2frame.PawleyRefl.GetSelectedCols()
3573            PawleyPeaks = data['Pawley ref']
3574            if event.GetKeyCode() == wx.WXK_RETURN:
3575                event.Skip(True)
3576            elif event.GetKeyCode() == wx.WXK_CONTROL:
3577                event.Skip(True)
3578            elif event.GetKeyCode() == wx.WXK_SHIFT:
3579                event.Skip(True)
3580            elif colList:
3581                G2frame.PawleyRefl.ClearSelection()
3582                key = event.GetKeyCode()
3583                for col in colList:
3584                    if PawleyTable.GetTypeName(0,col) == wg.GRID_VALUE_BOOL:
3585                        if key == 89: #'Y'
3586                            for row in range(PawleyTable.GetNumberRows()): PawleyPeaks[row][col]=True
3587                        elif key == 78:  #'N'
3588                            for row in range(PawleyTable.GetNumberRows()): PawleyPeaks[row][col]=False
3589                        FillPawleyReflectionsGrid()
3590           
3591        if 'Pawley ref' in data:
3592            PawleyPeaks = data['Pawley ref']                       
3593            rowLabels = []
3594            for i in range(len(PawleyPeaks)): rowLabels.append(str(i))
3595            colLabels = ['h','k','l','mul','d','refine','Fsq(hkl)','sig(Fsq)']
3596            Types = 4*[wg.GRID_VALUE_LONG,]+[wg.GRID_VALUE_FLOAT+':10,4',wg.GRID_VALUE_BOOL,]+ \
3597                2*[wg.GRID_VALUE_FLOAT+':10,2',]
3598            PawleyTable = G2gd.Table(PawleyPeaks,rowLabels=rowLabels,colLabels=colLabels,types=Types)
3599            G2frame.PawleyRefl.SetTable(PawleyTable, True)
3600            G2frame.PawleyRefl.Bind(wx.EVT_KEY_DOWN, KeyEditPawleyGrid)                 
3601            for r in range(G2frame.PawleyRefl.GetNumberRows()):
3602                for c in range(G2frame.PawleyRefl.GetNumberCols()):
3603                    if c in [5,6]:
3604                        G2frame.PawleyRefl.SetReadOnly(r,c,isReadOnly=False)
3605                    else:
3606                        G2frame.PawleyRefl.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
3607            G2frame.PawleyRefl.SetMargins(0,0)
3608            G2frame.PawleyRefl.AutoSizeColumns(False)
3609            G2frame.dataFrame.setSizePosLeft([500,300])
3610                   
3611    def OnPawleyLoad(event):
3612        generalData = data['General']
3613        dmin = generalData['Pawley dmin']
3614        cell = generalData['Cell'][1:7]
3615        A = G2lat.cell2A(cell)
3616        SGData = generalData['SGData']
3617        HKLd = np.array(G2lat.GenHLaue(dmin,SGData,A))
3618        PawleyPeaks = []
3619        wx.BeginBusyCursor()
3620        try:
3621            for h,k,l,d in HKLd:
3622                ext,mul = G2spc.GenHKLf([h,k,l],SGData)[:2]
3623                if not ext:
3624                    PawleyPeaks.append([h,k,l,mul,d,False,100.0,1.0])
3625        finally:
3626            wx.EndBusyCursor()
3627        data['Pawley ref'] = PawleyPeaks
3628        FillPawleyReflectionsGrid()
3629       
3630    def OnPawleyEstimate(event):
3631        try:
3632            Refs = data['Pawley ref']
3633            Histograms = data['Histograms']
3634        except KeyError:
3635            print '**** Error - no histograms defined for this phase ****'
3636            return
3637        HistoNames = Histograms.keys()
3638        PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,HistoNames[0])
3639        xdata = G2frame.PatternTree.GetItemPyData(PatternId)[1]
3640        Inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Instrument Parameters'))
3641        Inst = dict(zip(Inst[3],Inst[1]))
3642        Sample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Sample Parameters'))
3643        if 'Lam' in Inst:
3644            wave = Inst['Lam']
3645        else:
3646            wave = Inst['Lam1']
3647        posCorr = Inst['Zero']
3648        const = 9.e-2/(np.pi*Sample['Gonio. radius'])                  #shifts in microns
3649       
3650        for ref in Refs:
3651            pos = 2.0*asind(wave/(2.0*ref[4]))
3652            if 'Bragg' in Sample['Type']:
3653                pos -= const*(4.*Sample['Shift'][0]*cosd(pos/2.0)+ \
3654                    Sample['Transparency'][0]*sind(pos)*100.0)            #trans(=1/mueff) in cm
3655            else:               #Debye-Scherrer - simple but maybe not right
3656                pos -= const*(Sample['DisplaceX'][0]*cosd(pos)+Sample['DisplaceY'][0]*sind(pos))
3657            indx = np.searchsorted(xdata[0],pos)
3658            try:
3659                ref[6] = xdata[1][indx]/ref[3]
3660                pola,dIdPola = G2pwd.Polarization(Inst['Polariz.'],xdata[0][indx],0.0)
3661                ref[6] /= pola
3662            except IndexError:
3663                pass
3664        FillPawleyReflectionsGrid()
3665                           
3666    def OnPawleyDelete(event):
3667        dlg = wx.MessageDialog(G2frame,'Do you really want to delete Pawley reflections?','Delete', 
3668            wx.YES_NO | wx.ICON_QUESTION)
3669        try:
3670            result = dlg.ShowModal()
3671        finally:
3672            dlg.Destroy()
3673        if result == wx.ID_YES: 
3674            data['Pawley ref'] = []
3675            FillPawleyReflectionsGrid()
3676
3677################################################################################
3678##### Fourier routines
3679################################################################################
3680
3681    def FillMapPeaksGrid():
3682                       
3683        def RowSelect(event):
3684            r,c =  event.GetRow(),event.GetCol()
3685            if r < 0 and c < 0:
3686                if MapPeaks.IsSelection():
3687                    MapPeaks.ClearSelection()
3688                else:
3689                    for row in range(MapPeaks.GetNumberRows()):
3690                        MapPeaks.SelectRow(row,True)
3691                   
3692            elif c < 0:                   #only row clicks
3693                if event.ControlDown():                   
3694                    if r in MapPeaks.GetSelectedRows():
3695                        MapPeaks.DeselectRow(r)
3696                    else:
3697                        MapPeaks.SelectRow(r,True)
3698                elif event.ShiftDown():
3699                    for row in range(r+1):
3700                        MapPeaks.SelectRow(row,True)
3701                else:
3702                    MapPeaks.ClearSelection()
3703                    MapPeaks.SelectRow(r,True)               
3704            G2plt.PlotStructure(G2frame,data)                   
3705           
3706        G2frame.dataFrame.setSizePosLeft([450,300])
3707        if 'Map Peaks' in data:
3708            mapPeaks = data['Map Peaks']                       
3709            rowLabels = []
3710            for i in range(len(mapPeaks)): rowLabels.append(str(i))
3711            colLabels = ['mag','x','y','z']
3712            Types = 4*[wg.GRID_VALUE_FLOAT+':10,4',]
3713            MapPeaksTable = G2gd.Table(mapPeaks,rowLabels=rowLabels,colLabels=colLabels,types=Types)
3714            MapPeaks.SetTable(MapPeaksTable, True)
3715            MapPeaks.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK, RowSelect)
3716            for r in range(MapPeaks.GetNumberRows()):
3717                for c in range(MapPeaks.GetNumberCols()):
3718                    MapPeaks.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
3719            MapPeaks.SetMargins(0,0)
3720            MapPeaks.AutoSizeColumns(False)
3721                   
3722    def OnPeaksMove(event):
3723        if 'Map Peaks' in data:
3724            mapPeaks = data['Map Peaks']                       
3725            Ind = MapPeaks.GetSelectedRows()
3726            for ind in Ind:
3727                print mapPeaks[ind]
3728                x,y,z = mapPeaks[ind][1:]
3729                AtomAdd(x,y,z,'C')
3730   
3731    def OnPeaksClear(event):
3732        data['Map Peaks'] = []
3733        FillMapPeaksGrid()
3734        G2plt.PlotStructure(G2frame,data)
3735   
3736    def OnFourierMaps(event):
3737        generalData = data['General']
3738        mapData = generalData['Map']
3739        reflName = mapData['RefList']
3740        phaseName = generalData['Name']
3741        if 'PWDR' in reflName:
3742            PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, reflName)
3743            reflSets = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Reflection Lists'))
3744            reflData = reflSets[phaseName]
3745        elif 'HKLF' in reflName:
3746            PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, reflName)
3747            reflData = G2frame.PatternTree.GetItemPyData(PatternId)[1]
3748        mapData.update(G2mth.FourierMap(data,reflData))
3749        mapData['Flip'] = False
3750        mapSig = np.std(mapData['rho'])
3751        if not data['Drawing']:                 #if new drawing - no drawing data!
3752            SetupDrawingData()
3753        data['Drawing']['contourLevel'] = 1.
3754        data['Drawing']['mapSize'] = 10.
3755        print mapData['MapType']+' computed: rhomax = %.3f rhomin = %.3f sigma = %.3f'%(np.max(mapData['rho']),np.min(mapData['rho']),mapSig)
3756        UpdateDrawAtoms()
3757        G2plt.PlotStructure(G2frame,data)
3758       
3759    def printRho(SGLaue,rho,rhoMax):                         
3760# map printing for testing purposes
3761        dim = len(rho.shape)
3762        if dim == 2:
3763            ix,jy = rho.shape
3764            for j in range(jy):
3765                line = ''
3766                if SGLaue in ['3','3m1','31m','6/m','6/mmm']:
3767                    line += (jy-j)*'  '
3768                for i in range(ix):
3769                    r = int(100*rho[i,j]/rhoMax)
3770                    line += '%4d'%(r)
3771                print line+'\n'
3772        else:
3773            ix,jy,kz = rho.shape
3774            for k in range(kz):
3775                print 'k = ',k
3776                for j in range(jy):
3777                    line = ''
3778                    if SGLaue in ['3','3m1','31m','6/m','6/mmm']:
3779                        line += (jy-j)*'  '
3780                    for i in range(ix):
3781                        r = int(100*rho[i,j,k]/rhoMax)
3782                        line += '%4d'%(r)
3783                    print line+'\n'
3784## keep this               
3785   
3786    def OnSearchMaps(event):
3787       
3788        peaks = []
3789        mags = []
3790        print ' Begin fourier map search - can take some time'
3791        time0 = time.time()
3792        wx.BeginBusyCursor()
3793        try:
3794            peaks,mags = G2mth.SearchMap(data,keepDup=True)
3795        finally:
3796            wx.EndBusyCursor()
3797        sortIdx = np.argsort(mags.flatten())
3798        if len(peaks):
3799            data['Map Peaks'] = np.concatenate((mags,peaks),axis=1)
3800           
3801            print ' Map search peaks found:'
3802            print '  No.    Mag.      x        y        z'
3803            for j,i in enumerate(sortIdx[::-1]):
3804                print ' %3d %8.3f %8.5f %8.5f %8.5f'%(j,mags[i],peaks[i][0],peaks[i][1],peaks[i][2])
3805            print ' Map search finished, time = %.2fs'%(time.time()-time0)
3806        Page = G2frame.dataDisplay.FindPage('Map peaks')
3807        G2frame.dataDisplay.ChangeSelection(Page)
3808        G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.MapPeaksMenu)
3809        G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksMove, id=G2gd.wxID_PEAKSMOVE)
3810        G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksClear, id=G2gd.wxID_PEAKSCLEAR)
3811        UpdateDrawAtoms()
3812        FillMapPeaksGrid()
3813        G2plt.PlotStructure(G2frame,data)
3814       
3815    def OnChargeFlip(event):
3816        generalData = data['General']
3817        mapData = generalData['Map']
3818        flipData = generalData['Flip']
3819        reflName = flipData['RefList']
3820        phaseName = generalData['Name']
3821        if 'PWDR' in reflName:
3822            PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, reflName)
3823            reflSets = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Reflection Lists'))
3824            reflData = reflSets[phaseName]
3825        elif 'HKLF' in reflName:
3826            PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, reflName)
3827            reflData = G2frame.PatternTree.GetItemPyData(PatternId)[1]
3828        else:
3829            print '**** ERROR - No data defined for charge flipping'
3830            return
3831        pgbar = wx.ProgressDialog('Charge flipping','Residual Rcf =',101.0, 
3832            style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_CAN_ABORT)
3833        screenSize = wx.ClientDisplayRect()
3834        Size = pgbar.GetSize()
3835        Size = (int(Size[0]*1.2),Size[1]) # increase size a bit along x
3836        pgbar.SetPosition(wx.Point(screenSize[2]-Size[0]-305,screenSize[1]+5))
3837        pgbar.SetSize(Size)
3838        try:
3839            mapData.update(G2mth.ChargeFlip(data,reflData,pgbar))
3840        finally:
3841            pgbar.Destroy()
3842        mapData['Flip'] = True       
3843        mapSig = np.std(mapData['rho'])
3844        if not data['Drawing']:                 #if new drawing - no drawing data!
3845            SetupDrawingData()
3846        data['Drawing']['contourLevel'] = 1.
3847        data['Drawing']['mapSize'] = 10.
3848        print ' Charge flip map computed: rhomax = %.3f rhomin = %.3f sigma = %.3f'%(np.max(mapData['rho']),np.min(mapData['rho']),mapSig)
3849        if mapData['Rcf'] < 99.:
3850            OnSearchMaps(event)             #does a plot structure at end
3851        else:
3852            print 'Bad charge flip map - no peak search done'
3853               
3854    def OnTextureRefine(event):
3855        print 'refine texture?'
3856        event.Skip()       
3857           
3858    def OnTextureClear(event):
3859        print 'clear texture?'
3860        event.Skip()
3861
3862    def OnPageChanged(event):
3863        page = event.GetSelection()
3864        text = G2frame.dataDisplay.GetPageText(page)
3865        if text == 'Atoms':
3866            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.AtomsMenu)
3867            G2frame.dataFrame.Bind(wx.EVT_MENU, OnAtomAdd, id=G2gd.wxID_ATOMSEDITADD)
3868            G2frame.dataFrame.Bind(wx.EVT_MENU, OnAtomTestAdd, id=G2gd.wxID_ATOMSTESTADD)
3869            G2frame.dataFrame.Bind(wx.EVT_MENU, OnAtomInsert, id=G2gd.wxID_ATOMSEDITINSERT)
3870            G2frame.dataFrame.Bind(wx.EVT_MENU, OnAtomTestInsert, id=G2gd.wxID_ATONTESTINSERT)
3871            G2frame.dataFrame.Bind(wx.EVT_MENU, AtomDelete, id=G2gd.wxID_ATOMSEDITDELETE)
3872            G2frame.dataFrame.Bind(wx.EVT_MENU, AtomRefine, id=G2gd.wxID_ATOMSREFINE)
3873            G2frame.dataFrame.Bind(wx.EVT_MENU, AtomModify, id=G2gd.wxID_ATOMSMODIFY)
3874            G2frame.dataFrame.Bind(wx.EVT_MENU, AtomTransform, id=G2gd.wxID_ATOMSTRANSFORM)
3875            G2frame.dataFrame.Bind(wx.EVT_MENU, OnReloadDrawAtoms, id=G2gd.wxID_RELOADDRAWATOMS)
3876            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDistAngle, id=G2gd.wxID_ATOMSDISAGL)
3877            FillAtomsGrid()
3878        elif text == 'General':
3879            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.DataGeneral)
3880            G2frame.dataFrame.Bind(wx.EVT_MENU, OnFourierMaps, id=G2gd.wxID_FOURCALC)
3881            G2frame.dataFrame.Bind(wx.EVT_MENU, OnSearchMaps, id=G2gd.wxID_FOURSEARCH)
3882            G2frame.dataFrame.Bind(wx.EVT_MENU, OnChargeFlip, id=G2gd.wxID_CHARGEFLIP)
3883            UpdateGeneral()
3884        elif text == 'Data':
3885            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.DataMenu)
3886            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPwdrAdd, id=G2gd.wxID_PWDRADD)
3887            G2frame.dataFrame.Bind(wx.EVT_MENU, OnHklfAdd, id=G2gd.wxID_HKLFADD)
3888            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDataDelete, id=G2gd.wxID_DATADELETE)
3889            UpdateDData()
3890            G2plt.PlotSizeStrainPO(G2frame,data,Start=True)
3891        elif text == 'Draw Options':
3892            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.DataDrawOptions)
3893            UpdateDrawOptions()
3894            G2plt.PlotStructure(G2frame,data)
3895        elif text == 'Draw Atoms':
3896            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.DrawAtomsMenu)
3897            G2frame.dataFrame.Bind(wx.EVT_MENU, DrawAtomStyle, id=G2gd.wxID_DRAWATOMSTYLE)
3898            G2frame.dataFrame.Bind(wx.EVT_MENU, DrawAtomLabel, id=G2gd.wxID_DRAWATOMLABEL)
3899            G2frame.dataFrame.Bind(wx.EVT_MENU, DrawAtomColor, id=G2gd.wxID_DRAWATOMCOLOR)
3900            G2frame.dataFrame.Bind(wx.EVT_MENU, ResetAtomColors, id=G2gd.wxID_DRAWATOMRESETCOLOR)
3901            G2frame.dataFrame.Bind(wx.EVT_MENU, SetViewPoint, id=G2gd.wxID_DRAWVIEWPOINT)
3902            G2frame.dataFrame.Bind(wx.EVT_MENU, AddSymEquiv, id=G2gd.wxID_DRAWADDEQUIV)
3903            G2frame.dataFrame.Bind(wx.EVT_MENU, TransformSymEquiv, id=G2gd.wxID_DRAWTRANSFORM)
3904            G2frame.dataFrame.Bind(wx.EVT_MENU, FillCoordSphere, id=G2gd.wxID_DRAWFILLCOORD)           
3905            G2frame.dataFrame.Bind(wx.EVT_MENU, FillUnitCell, id=G2gd.wxID_DRAWFILLCELL)
3906            G2frame.dataFrame.Bind(wx.EVT_MENU, DrawAtomsDelete, id=G2gd.wxID_DRAWDELETE)
3907            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDrawDAT, id=G2gd.wxID_DRAWDISAGLTOR)
3908            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDrawPlane, id=G2gd.wxID_DRAWPLANE)
3909            UpdateDrawAtoms()
3910            G2plt.PlotStructure(G2frame,data)
3911        elif text == 'Pawley reflections':
3912            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.PawleyMenu)
3913            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPawleyLoad, id=G2gd.wxID_PAWLEYLOAD)
3914            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPawleyEstimate, id=G2gd.wxID_PAWLEYESTIMATE)
3915            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPawleyDelete, id=G2gd.wxID_PAWLEYDELETE)           
3916            FillPawleyReflectionsGrid()
3917        elif text == 'Texture':
3918            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.TextureMenu)
3919            G2frame.dataFrame.Bind(wx.EVT_MENU, OnTextureRefine, id=G2gd.wxID_REFINETEXTURE)
3920            G2frame.dataFrame.Bind(wx.EVT_MENU, OnTextureClear, id=G2gd.wxID_CLEARTEXTURE)
3921            UpdateTexture()                       
3922            G2plt.PlotTexture(G2frame,data,Start=True)
3923        elif text == 'Map peaks':
3924            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.MapPeaksMenu)
3925            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksMove, id=G2gd.wxID_PEAKSMOVE)
3926            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksClear, id=G2gd.wxID_PEAKSCLEAR)
3927            FillMapPeaksGrid()
3928            G2plt.PlotStructure(G2frame,data)
3929           
3930        else:
3931            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.BlankMenu)
3932        event.Skip()
3933       
3934    General = wx.Window(G2frame.dataDisplay)
3935    G2frame.dataDisplay.AddPage(General,'General')
3936    G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.DataGeneral)
3937    G2frame.dataFrame.Bind(wx.EVT_MENU, OnFourierMaps, id=G2gd.wxID_FOURCALC)
3938    G2frame.dataFrame.Bind(wx.EVT_MENU, OnSearchMaps, id=G2gd.wxID_FOURSEARCH)
3939    G2frame.dataFrame.Bind(wx.EVT_MENU, OnChargeFlip, id=G2gd.wxID_CHARGEFLIP)
3940    SetupGeneral()
3941    GeneralData = data['General']
3942    UpdateGeneral()
3943
3944    DData = wx.ScrolledWindow(G2frame.dataDisplay)
3945    G2frame.dataDisplay.AddPage(DData,'Data')
3946    Atoms = G2gd.GSGrid(G2frame.dataDisplay)
3947    G2frame.dataDisplay.AddPage(Atoms,'Atoms')
3948    drawOptions = wx.Window(G2frame.dataDisplay)
3949    G2frame.dataDisplay.AddPage(drawOptions,'Draw Options')
3950    drawAtoms = G2gd.GSGrid(G2frame.dataDisplay)
3951    G2frame.dataDisplay.AddPage(drawAtoms,'Draw Atoms')
3952    Texture = wx.ScrolledWindow(G2frame.dataDisplay)
3953    G2frame.dataDisplay.AddPage(Texture,'Texture')
3954    MapPeaks = G2gd.GSGrid(G2frame.dataDisplay)
3955    G2frame.dataDisplay.AddPage(MapPeaks,'Map peaks')
3956    G2frame.PawleyRefl = G2gd.GSGrid(G2frame.dataDisplay)
3957    G2frame.dataDisplay.AddPage(G2frame.PawleyRefl,'Pawley reflections')
3958           
3959    G2frame.dataDisplay.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, OnPageChanged)
3960    G2frame.dataDisplay.SetSelection(oldPage)
3961   
3962           
Note: See TracBrowser for help on using the repository browser.