source: trunk/GSASIIphsGUI.py @ 574

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

fixed import of .gpx phases

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