source: trunk/GSASIIphsGUI.py @ 443

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

make sum powder profiles numpy arrays
change name UpdateBackgroundGrid? to UpdateBackground?
min size is 1 nanometer = 10A
implement diffuse scattering model for background
iso/aniso Size & Mustrain are now Size:i/a instead of 0/1

  • Property svn:keywords set to Date Author Revision URL Id
File size: 143.2 KB
Line 
1#GSASII - phase data display routines
2########### SVN repository information ###################
3# $Date: 2011-12-16 19:15:09 +0000 (Fri, 16 Dec 2011) $
4# $Author: vondreele $
5# $Revision: 443 $
6# $URL: trunk/GSASIIphsGUI.py $
7# $Id: GSASIIphsGUI.py 443 2011-12-16 19:15:09Z 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 GSASIIplot as G2plt
23import GSASIIgrid as G2gd
24import GSASIIIO as G2IO
25import numpy as np
26import numpy.linalg as nl
27
28VERY_LIGHT_GREY = wx.Colour(235,235,235)
29WHITE = wx.Colour(255,255,255)
30BLACK = wx.Colour(0,0,0)
31
32# trig functions in degrees
33sind = lambda x: math.sin(x*math.pi/180.)
34tand = lambda x: math.tan(x*math.pi/180.)
35cosd = lambda x: math.cos(x*math.pi/180.)
36asind = lambda x: 180.*math.asin(x)/math.pi
37
38class SymOpDialog(wx.Dialog):
39    def __init__(self,parent,SGData,New=True):
40        wx.Dialog.__init__(self,parent,-1,'Select symmetry operator',
41            pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE)
42        panel = wx.Panel(self)
43        self.SGData = SGData
44        self.New = New
45        self.OpSelected = [0,0,0,[0,0,0],False]
46        mainSizer = wx.BoxSizer(wx.VERTICAL)
47        mainSizer.Add((5,5),0)
48        if SGData['SGInv']:
49            choice = ['No','Yes']
50            self.inv = wx.RadioBox(panel,-1,'Choose inversion?',choices=choice)
51            self.inv.Bind(wx.EVT_RADIOBOX, self.OnOpSelect)
52            mainSizer.Add(self.inv,0,wx.ALIGN_CENTER_VERTICAL)
53        mainSizer.Add((5,5),0)
54        if SGData['SGLatt'] != 'P':
55            LattOp = G2spc.Latt2text(SGData['SGLatt']).split(';')
56            self.latt = wx.RadioBox(panel,-1,'Choose cell centering?',choices=LattOp)
57            self.latt.Bind(wx.EVT_RADIOBOX, self.OnOpSelect)
58            mainSizer.Add(self.latt,0,wx.ALIGN_CENTER_VERTICAL)
59        mainSizer.Add((5,5),0)
60        if SGData['SGLaue'] in ['-1','2/m','mmm','4/m','4/mmm']:
61            Ncol = 2
62        else:
63            Ncol = 3
64        OpList = []
65        for M,T in SGData['SGOps']:
66            OpList.append(G2spc.MT2text(M,T))
67        self.oprs = wx.RadioBox(panel,-1,'Choose space group operator?',choices=OpList,
68            majorDimension=Ncol)
69        self.oprs.Bind(wx.EVT_RADIOBOX, self.OnOpSelect)
70        mainSizer.Add(self.oprs,0,wx.ALIGN_CENTER_VERTICAL)
71        mainSizer.Add((5,5),0)
72        mainSizer.Add(wx.StaticText(panel,-1,"   Choose unit cell?"),0,wx.ALIGN_CENTER_VERTICAL)
73        mainSizer.Add((5,5),0)
74        cellSizer = wx.BoxSizer(wx.HORIZONTAL)
75        cellSizer.Add((5,0),0)
76        cellName = ['X','Y','Z']
77        self.cell = []
78        for i in range(3):
79            self.cell.append(wx.SpinCtrl(panel,-1,cellName[i],size=wx.Size(50,20)))
80            self.cell[-1].SetRange(-3,3)
81            self.cell[-1].SetValue(0)
82            self.cell[-1].Bind(wx.EVT_SPINCTRL, self.OnOpSelect)
83            cellSizer.Add(self.cell[-1],0,wx.ALIGN_CENTER_VERTICAL)
84        mainSizer.Add(cellSizer,0,)
85        if self.New:
86            choice = ['No','Yes']
87            self.new = wx.RadioBox(panel,-1,'Generate new positions?',choices=choice)
88            self.new.Bind(wx.EVT_RADIOBOX, self.OnOpSelect)
89            mainSizer.Add(self.new,0,wx.ALIGN_CENTER_VERTICAL)
90        mainSizer.Add((5,5),0)
91
92        OkBtn = wx.Button(panel,-1,"Ok")
93        OkBtn.Bind(wx.EVT_BUTTON, self.OnOk)
94        cancelBtn = wx.Button(panel,-1,"Cancel")
95        cancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel)
96        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
97        btnSizer.Add((20,20),1)
98        btnSizer.Add(OkBtn)
99        btnSizer.Add((20,20),1)
100        btnSizer.Add(cancelBtn)
101        btnSizer.Add((20,20),1)
102
103        mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
104        panel.SetSizer(mainSizer)
105        panel.Fit()
106        self.Fit()
107
108    def OnOpSelect(self,event):
109        if self.SGData['SGInv']:
110            self.OpSelected[0] = self.inv.GetSelection()
111        if self.SGData['SGLatt'] != 'P':
112            self.OpSelected[1] = self.latt.GetSelection()
113        self.OpSelected[2] = self.oprs.GetSelection()
114        for i in range(3):
115            self.OpSelected[3][i] = float(self.cell[i].GetValue())
116        if self.New:
117            self.OpSelected[4] = self.new.GetSelection()
118
119    def GetSelection(self):
120        return self.OpSelected
121
122    def OnOk(self,event):
123        parent = self.GetParent()
124        parent.Raise()
125        self.EndModal(wx.ID_OK)
126        self.Destroy()
127
128    def OnCancel(self,event):
129        parent = self.GetParent()
130        parent.Raise()
131        self.EndModal(wx.ID_CANCEL)
132        self.Destroy()
133
134def UpdatePhaseData(self,Item,data,oldPage):
135
136    Atoms = []
137    if self.dataDisplay:
138        self.dataDisplay.Destroy()
139    PhaseName = self.PatternTree.GetItemText(Item)
140    self.dataFrame.SetMenuBar(self.dataFrame.BlankMenu)
141    self.dataFrame.SetLabel('Phase Data for '+PhaseName)
142    self.dataFrame.CreateStatusBar()
143    self.dataDisplay = G2gd.GSNoteBook(parent=self.dataFrame,size=self.dataFrame.GetClientSize())
144
145    def SetupGeneral():
146        generalData = data['General']
147        atomData = data['Atoms']
148        generalData['AtomTypes'] = []
149        generalData['Isotopes'] = {}
150        if 'Isotope' not in generalData:
151            generalData['Isotope'] = {}
152        if 'Data plot type' not in generalData:
153            generalData['Data plot type'] = 'Mustrain'
154        if 'POhkl' not in generalData:
155            generalData['POhkl'] = [0,0,1]
156        generalData['NoAtoms'] = {}
157        generalData['BondRadii'] = []
158        generalData['AngleRadii'] = []
159        generalData['vdWRadii'] = []
160        generalData['AtomMass'] = []
161        generalData['Color'] = []
162        generalData['Mydir'] = self.dirname
163        cx,ct,cs,cia = [3,1,7,9]
164        generalData['AtomPtrs'] = [cx,ct,cs,cia]
165        if generalData['Type'] =='macromolecular':
166            cx,ct,cs,cia = [6,4,10,12]
167            generalData['AtomPtrs'] = [cx,ct,cs,cia]
168        for atom in atomData:
169            atom[ct] = atom[ct].lower().capitalize()              #force to standard form
170            if generalData['AtomTypes'].count(atom[ct]):
171                generalData['NoAtoms'][atom[ct]] += atom[cs-1]*float(atom[cs+1])
172            elif atom[ct] != 'UNK':
173                Info = G2elem.GetAtomInfo(atom[ct])
174                generalData['AtomTypes'].append(atom[ct])
175                generalData['Isotopes'][atom[ct]] = Info['Isotopes']
176                generalData['BondRadii'].append(Info['Drad'])
177                generalData['AngleRadii'].append(Info['Arad'])
178                generalData['vdWRadii'].append(Info['Vdrad'])
179                if atom[ct] in generalData['Isotope']:
180                    generalData['AtomMass'].append(Info['Isotopes'][generalData['Isotope'][atom[ct]]][0])
181                else:
182                    generalData['AtomMass'].append(Info['Mass'])
183                generalData['NoAtoms'][atom[ct]] = atom[cs-1]*float(atom[cs+1])
184                generalData['Color'].append(Info['Color'])
185
186    def UpdateGeneral():
187       
188        ''' default dictionary structure for phase data: (taken from GSASII.py)
189        'General':{
190            'Name':PhaseName
191            'Type':'nuclear'
192            'SGData':SGData
193            'Cell':[False,10.,10.,10.,90.,90.,90,1000.]
194            'AtomPtrs':[]
195            'Histogram list':['',]
196            'Pawley dmin':1.0}
197        'Atoms':[]
198        'Drawing':{}
199        '''
200        phaseTypes = ['nuclear','modulated','magnetic','macromolecular','Pawley']
201        SetupGeneral()
202        generalData = data['General']
203       
204        def OnPhaseName(event):
205            oldName = generalData['Name']
206            generalData['Name'] = NameTxt.GetValue()
207            self.G2plotNB.Rename(oldName,generalData['Name'])
208            self.dataFrame.SetLabel('Phase Data for '+generalData['Name'])
209            self.PatternTree.SetItemText(Item,generalData['Name'])
210            #Hmm, need to change phase name key in Reflection Lists for each histogram
211                       
212        def OnPhaseType(event):
213            if not generalData['AtomTypes']:             #can change only if no atoms!
214                generalData['Type'] = TypeTxt.GetValue()
215                dataDisplay.DestroyChildren()           #needed to clear away bad cellSizer, etc.
216                UpdateGeneral()         #must use this way!
217                if generalData['Type'] == 'Pawley':
218                    if self.dataDisplay.FindPage('Atoms'):
219                        self.dataDisplay.DeletePage(self.dataDisplay.FindPage('Atoms'))
220                        self.dataDisplay.DeletePage(self.dataDisplay.FindPage('Draw Options'))
221                        self.dataDisplay.DeletePage(self.dataDisplay.FindPage('Draw Atoms'))
222                    if not self.dataDisplay.FindPage('Pawley reflections'):
223                        self.PawleyRefl = G2gd.GSGrid(self.dataDisplay)     
224                        self.dataDisplay.AddPage(self.PawleyRefl,'Pawley reflections')
225            else:
226                TypeTxt.SetValue(generalData['Type'])               
227               
228        def OnSpaceGroup(event):
229            SpcGp = SGTxt.GetValue()
230            SGErr,SGData = G2spc.SpcGroup(SpcGp)
231            if SGErr:
232                text = [G2spc.SGErrors(SGErr)+'\nSpace Group set to previous']
233                SGTxt.SetValue(generalData['SGData']['SpGrp'])
234                msg = 'Space Group Error'
235                Style = wx.ICON_EXCLAMATION
236            else:
237                text = G2spc.SGPrint(SGData)
238                generalData['SGData'] = SGData
239                msg = 'Space Group Information'
240                Style = wx.ICON_INFORMATION
241            Text = ''
242            for line in text:
243                Text += line+'\n'
244            wx.MessageBox(Text,caption=msg,style=Style)
245            dataDisplay.DestroyChildren()           #needed to clear away bad cellSizer, etc.
246            UpdateGeneral()
247           
248        def OnCellRef(event):
249            generalData['Cell'][0] = cellRef.GetValue()
250           
251        def OnCellChange(event):
252            SGData = generalData['SGData']
253            laue = SGData['SGLaue']
254            if laue == '2/m':
255                laue += SGData['SGUniq']
256            cell = generalData['Cell']
257            Obj = event.GetEventObject()
258            ObjId = cellList.index(Obj.GetId())
259            try:
260                value = max(1.0,float(Obj.GetValue()))
261            except ValueError:
262                if ObjId < 3:               #bad cell edge - reset
263                    value = controls[6+ObjId]
264                else:                       #bad angle
265                    value = 90.
266            if laue in ['m3','m3m']:
267                cell[1] = cell[2] = cell[3] = value
268                cell[4] = cell[5] = cell[6] = 90.0
269                Obj.SetValue("%.5f"%(cell[1]))
270            elif laue in ['3R','3mR']:
271                if ObjId == 0:
272                    cell[1] = cell[2] = cell[3] = value
273                    Obj.SetValue("%.5f"%(cell[1]))
274                else:
275                    cell[4] = cell[5] = cell[6] = value
276                    Obj.SetValue("%.5f"%(cell[4]))
277            elif laue in ['3','3m1','31m','6/m','6/mmm','4/m','4/mmm']:                   
278                cell[4] = cell[5] = 90.
279                cell[6] = 120.
280                if ObjId == 0:
281                    cell[1] = cell[2] = value
282                    Obj.SetValue("%.5f"%(cell[1]))
283                else:
284                    cell[3] = value
285                    Obj.SetValue("%.5f"%(cell[3]))
286            elif laue in ['mmm']:
287                cell[ObjId+1] = value
288                cell[4] = cell[5] = cell[6] = 90.
289                Obj.SetValue("%.5f"%(cell[ObjId+1]))
290            elif laue in ['2/m'+'a']:
291                cell[5] = cell[6] = 90.
292                if ObjId != 3:
293                    cell[ObjId+1] = value
294                    Obj.SetValue("%.5f"%(cell[ObjId+1]))
295                else:
296                    cell[4] = value
297                    Obj.SetValue("%.3f"%(cell[4]))
298            elif laue in ['2/m'+'b']:
299                cell[4] = cell[6] = 90.
300                if ObjId != 3:
301                    cell[ObjId+1] = value
302                    Obj.SetValue("%.5f"%(cell[ObjId+1]))
303                else:
304                    cell[5] = value
305                    Obj.SetValue("%.3f"%(cell[5]))
306            elif laue in ['2/m'+'c']:
307                cell[5] = cell[6] = 90.
308                if ObjId != 3:
309                    cell[ObjId+1] = value
310                    Obj.SetValue("%.5f"%(cell[ObjId+1]))
311                else:
312                    cell[6] = value
313                    Obj.SetValue("%.3f"%(cell[6]))
314            else:
315                cell[ObjId+1] = value
316                if ObjId < 3:
317                    Obj.SetValue("%.5f"%(cell[1+ObjId]))
318                else:
319                    Obj.SetValue("%.3f"%(cell[1+ObjId]))
320            cell[7] = G2lat.calc_V(G2lat.cell2A(cell[1:7]))
321            volVal.SetValue("%.3f"%(cell[7]))
322            generalData['Cell'] = cell
323            dataDisplay.DestroyChildren()           #needed to clear away bad cellSizer, etc.
324            UpdateGeneral()
325                       
326        def OnPawleyVal(event):
327            try:
328                dmin = float(pawlVal.GetValue())
329                if 0.25 <= dmin <= 20.:
330                    generalData['Pawley dmin'] = dmin
331            except ValueError:
332                pass
333            pawlVal.SetValue("%.3f"%(generalData['Pawley dmin']))          #reset in case of error       
334           
335        def OnIsotope(event):
336            Obj = event.GetEventObject()
337            item = Indx[Obj.GetId()]
338            isotope = Obj.GetValue()
339            generalData['Isotope'][item] = isotope
340            indx = generalData['AtomTypes'].index(item)
341            data['General']['AtomMass'][indx] = generalData['Isotopes'][item][isotope][0]
342            UpdateGeneral()
343                                               
344        cellGUIlist = [[['m3','m3m'],4,zip([" Unit cell: a = "," Vol = "],["%.5f","%.3f"],[True,False],[0,0])],
345        [['3R','3mR'],6,zip([" a = "," alpha = "," Vol = "],["%.5f","%.3f","%.3f"],[True,True,False],[0,2,0])],
346        [['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])],
347        [['mmm'],8,zip([" a = "," b = "," c = "," Vol = "],["%.5f","%.5f","%.5f","%.3f"],
348            [True,True,True,False],[0,1,2,0])],
349        [['2/m'+'a'],10,zip([" a = "," b = "," c = "," alpha = "," Vol = "],
350            ["%.5f","%.5f","%.5f","%.3f","%.3f"],[True,True,True,True,False],[0,1,2,4,0])],
351        [['2/m'+'b'],10,zip([" a = "," b = "," c = "," beta = "," Vol = "],
352            ["%.5f","%.5f","%.5f","%.3f","%.3f"],[True,True,True,True,False],[0,1,2,4,0])],
353        [['2/m'+'c'],10,zip([" a = "," b = "," c = "," gamma = "," Vol = "],
354            ["%.5f","%.5f","%.5f","%.3f","%.3f"],[True,True,True,True,False],[0,1,2,4,0])],
355        [['-1'],8,zip([" a = "," b = "," c = "," Vol = "," alpha = "," beta = "," gamma = "],
356            ["%.5f","%.5f","%.5f","%.3f","%.3f","%.3f","%.3f"],
357            [True,True,True,False,True,True,True],[0,1,2,0,3,4,5])]]
358       
359        General.DestroyChildren()
360        dataDisplay = wx.Panel(General)
361        mainSizer = wx.BoxSizer(wx.VERTICAL)
362        mainSizer.Add((5,5),0)
363        mainSizer.Add(wx.StaticText(dataDisplay,-1,'General phase data:'),0,wx.ALIGN_CENTER_VERTICAL)
364        mainSizer.Add((5,5),0)
365        nameSizer = wx.BoxSizer(wx.HORIZONTAL)
366        nameSizer.Add(wx.StaticText(dataDisplay,-1,' Phase name: '),0,wx.ALIGN_CENTER_VERTICAL)
367        NameTxt = wx.TextCtrl(dataDisplay,-1,value=generalData['Name'],style=wx.TE_PROCESS_ENTER)
368        NameTxt.Bind(wx.EVT_TEXT_ENTER,OnPhaseName)
369        NameTxt.Bind(wx.EVT_KILL_FOCUS,OnPhaseName)
370        nameSizer.Add(NameTxt,0,wx.ALIGN_CENTER_VERTICAL)
371        nameSizer.Add(wx.StaticText(dataDisplay,-1,'  Phase type: '),0,wx.ALIGN_CENTER_VERTICAL)
372        if len(data['Atoms']):
373            choices = phaseTypes[:-1]
374        else:
375            choices = phaseTypes           
376        TypeTxt = wx.ComboBox(dataDisplay,-1,value=generalData['Type'],choices=choices,
377            style=wx.CB_READONLY|wx.CB_DROPDOWN)
378        TypeTxt.Bind(wx.EVT_COMBOBOX, OnPhaseType)
379        nameSizer.Add(TypeTxt,0,wx.ALIGN_CENTER_VERTICAL)
380        nameSizer.Add(wx.StaticText(dataDisplay,-1,'  Space group: '),0,wx.ALIGN_CENTER_VERTICAL)
381        SGTxt = wx.TextCtrl(dataDisplay,-1,value=generalData['SGData']['SpGrp'],style=wx.TE_PROCESS_ENTER)
382        SGTxt.Bind(wx.EVT_TEXT_ENTER,OnSpaceGroup)
383        nameSizer.Add(SGTxt,0,wx.ALIGN_CENTER_VERTICAL)
384        mainSizer.Add(nameSizer,0)
385        mainSizer.Add((5,5),0)
386        cell = generalData['Cell']
387        laue = generalData['SGData']['SGLaue']
388        if laue == '2/m':
389            laue += generalData['SGData']['SGUniq']
390        for cellGUI in cellGUIlist:
391            if laue in cellGUI[0]:
392                useGUI = cellGUI
393        cellList = []
394        cellSizer = wx.FlexGridSizer(2,useGUI[1]+1,5,5)
395        cellRef = wx.CheckBox(dataDisplay,-1,label='Refine unit cell:')
396        cellSizer.Add(cellRef,0,wx.ALIGN_CENTER_VERTICAL)
397        cellRef.Bind(wx.EVT_CHECKBOX, OnCellRef)
398        cellRef.SetValue(cell[0])
399        for txt,fmt,ifEdit,Id in useGUI[2]:
400            cellSizer.Add(wx.StaticText(dataDisplay,label=txt),0,wx.ALIGN_CENTER_VERTICAL)
401            if ifEdit:          #a,b,c,etc.
402                cellVal = wx.TextCtrl(dataDisplay,value=(fmt%(cell[Id+1])),
403                    style=wx.TE_PROCESS_ENTER)
404                cellVal.Bind(wx.EVT_TEXT_ENTER,OnCellChange)       
405                cellVal.Bind(wx.EVT_KILL_FOCUS,OnCellChange)
406                cellSizer.Add(cellVal,0,wx.ALIGN_CENTER_VERTICAL)
407                cellList.append(cellVal.GetId())
408            else:               #volume
409                volVal = wx.TextCtrl(dataDisplay,value=(fmt%(cell[7])),style=wx.TE_READONLY)
410                volVal.SetBackgroundColour(VERY_LIGHT_GREY)
411                cellSizer.Add(volVal,0,wx.ALIGN_CENTER_VERTICAL)
412        mainSizer.Add(cellSizer,0)
413        mainSizer.Add((5,5),0)
414       
415        Indx = {}
416        if len(generalData['AtomTypes']):
417            mass = 0.
418            for i,elem in enumerate(generalData['AtomTypes']):
419                mass += generalData['NoAtoms'][elem]*generalData['AtomMass'][i]
420            denSizer = wx.BoxSizer(wx.HORIZONTAL)
421            denSizer.Add(wx.StaticText(dataDisplay,-1,' Density: '),0,wx.ALIGN_CENTER_VERTICAL)
422            Volume = generalData['Cell'][7]
423            density = mass/(0.6022137*Volume)
424            denTxt = wx.TextCtrl(dataDisplay,-1,'%.3f'%(density),style=wx.TE_READONLY)
425            denTxt.SetBackgroundColour(VERY_LIGHT_GREY)
426            denSizer.Add(denTxt,0,wx.ALIGN_CENTER_VERTICAL)       
427            if generalData['Type'] == 'macromolecular' and mass > 0.0:
428                denSizer.Add(wx.StaticText(dataDisplay,-1,' Matthews coeff.: '),
429                    0,wx.ALIGN_CENTER_VERTICAL)
430                mattTxt = wx.TextCtrl(dataDisplay,-1,'%.3f'%(Volume/mass),style=wx.TE_READONLY)
431                mattTxt.SetBackgroundColour(VERY_LIGHT_GREY)
432                denSizer.Add(mattTxt,0,wx.ALIGN_CENTER_VERTICAL)
433            mainSizer.Add(denSizer)
434            mainSizer.Add((5,5),0)
435           
436            elemSizer = wx.FlexGridSizer(8,len(generalData['AtomTypes'])+1,1,1)
437            elemSizer.Add(wx.StaticText(dataDisplay,label='Elements'),0,wx.ALIGN_CENTER_VERTICAL)
438            for elem in generalData['AtomTypes']:
439                typTxt = wx.TextCtrl(dataDisplay,value=elem,style=wx.TE_READONLY)
440                typTxt.SetBackgroundColour(VERY_LIGHT_GREY)
441                elemSizer.Add(typTxt,0,wx.ALIGN_CENTER_VERTICAL)
442            elemSizer.Add(wx.StaticText(dataDisplay,label='Isotope'),0,wx.ALIGN_CENTER_VERTICAL)
443            for elem in generalData['AtomTypes']:
444                choices = generalData['Isotopes'][elem].keys()
445                if elem not in generalData['Isotope']:
446                    generalData['Isotope'][elem] = 'Nat. Abund.'
447                isoSel = wx.ComboBox(dataDisplay,-1,value=generalData['Isotope'][elem],choices=choices,
448                    style=wx.CB_READONLY|wx.CB_DROPDOWN)
449                isoSel.Bind(wx.EVT_COMBOBOX,OnIsotope)
450                Indx[isoSel.GetId()] = elem
451                elemSizer.Add(isoSel,1,wx.ALIGN_CENTER_VERTICAL|wx.EXPAND)
452            elemSizer.Add(wx.StaticText(dataDisplay,label='No. per cell'),0,wx.ALIGN_CENTER_VERTICAL)
453            for elem in generalData['AtomTypes']:
454                numbTxt = wx.TextCtrl(dataDisplay,value='%.1f'%(generalData['NoAtoms'][elem]),
455                    style=wx.TE_READONLY)
456                numbTxt.SetBackgroundColour(VERY_LIGHT_GREY)
457                elemSizer.Add(numbTxt,0,wx.ALIGN_CENTER_VERTICAL)
458            elemSizer.Add(wx.StaticText(dataDisplay,label='Atom weight'),0,wx.ALIGN_CENTER_VERTICAL)
459            for wt in generalData['AtomMass']:
460                wtTxt = wx.TextCtrl(dataDisplay,value='%.3f'%(wt),style=wx.TE_READONLY)
461                wtTxt.SetBackgroundColour(VERY_LIGHT_GREY)
462                elemSizer.Add(wtTxt,0,wx.ALIGN_CENTER_VERTICAL)
463            elemSizer.Add(wx.StaticText(dataDisplay,label='Bond radii'),0,wx.ALIGN_CENTER_VERTICAL)
464            for rad in generalData['BondRadii']:
465                bondRadii = wx.TextCtrl(dataDisplay,value='%.2f'%(rad),style=wx.TE_READONLY)
466                bondRadii.SetBackgroundColour(VERY_LIGHT_GREY)
467                elemSizer.Add(bondRadii,0,wx.ALIGN_CENTER_VERTICAL)
468            elemSizer.Add(wx.StaticText(dataDisplay,label='Angle radii'),0,wx.ALIGN_CENTER_VERTICAL)
469            for rad in generalData['AngleRadii']:
470                elemTxt = wx.TextCtrl(dataDisplay,value='%.2f'%(rad),style=wx.TE_READONLY)
471                elemTxt.SetBackgroundColour(VERY_LIGHT_GREY)
472                elemSizer.Add(elemTxt,0,wx.ALIGN_CENTER_VERTICAL)
473            elemSizer.Add(wx.StaticText(dataDisplay,label='van der Waals radii'),0,wx.ALIGN_CENTER_VERTICAL)
474            for rad in generalData['vdWRadii']:
475                elemTxt = wx.TextCtrl(dataDisplay,value='%.2f'%(rad),style=wx.TE_READONLY)
476                elemTxt.SetBackgroundColour(VERY_LIGHT_GREY)
477                elemSizer.Add(elemTxt,0,wx.ALIGN_CENTER_VERTICAL)
478            elemSizer.Add(wx.StaticText(dataDisplay,label='Default color'),0,wx.ALIGN_CENTER_VERTICAL)
479            for color in generalData['Color']:
480                colorTxt = wx.TextCtrl(dataDisplay,value='',style=wx.TE_READONLY)
481                colorTxt.SetBackgroundColour(color)
482                elemSizer.Add(colorTxt,0,wx.ALIGN_CENTER_VERTICAL)
483            mainSizer.Add(elemSizer)
484           
485        elif generalData['Type'] == 'Pawley':
486            pawlSizer = wx.BoxSizer(wx.HORIZONTAL)
487            pawlSizer.Add(wx.StaticText(dataDisplay,label=' Pawley dmin: '),0,wx.ALIGN_CENTER_VERTICAL)
488            pawlVal = wx.TextCtrl(dataDisplay,value='%.3f'%(generalData['Pawley dmin']),style=wx.TE_PROCESS_ENTER)
489            pawlVal.Bind(wx.EVT_TEXT_ENTER,OnPawleyVal)       
490            pawlVal.Bind(wx.EVT_KILL_FOCUS,OnPawleyVal)
491            pawlSizer.Add(pawlVal,0,wx.ALIGN_CENTER_VERTICAL)
492            mainSizer.Add(pawlSizer)
493
494        dataDisplay.SetSizer(mainSizer)
495        Size = mainSizer.Fit(self.dataFrame)
496        Size[1] += 26                           #compensate for status bar
497        dataDisplay.SetSize(Size)
498        self.dataFrame.setSizePosLeft(Size)
499
500    def FillAtomsGrid():
501
502        self.dataFrame.setSizePosLeft([700,300])
503        generalData = data['General']
504        atomData = data['Atoms']
505        Items = [G2gd.wxID_ATOMSEDITINSERT, G2gd.wxID_ATOMSEDITDELETE, G2gd.wxID_ATOMSREFINE, 
506            G2gd.wxID_ATOMSMODIFY, G2gd.wxID_ATOMSTRANSFORM, G2gd.wxID_ATONTESTINSERT]
507        if atomData:
508            for item in Items:   
509                self.dataFrame.AtomsMenu.Enable(item,True)
510        else:
511            for item in Items:
512                self.dataFrame.AtomsMenu.Enable(item,False)           
513           
514        AAchoice = ": ,ALA,ARG,ASN,ASP,CYS,GLN,GLU,GLY,HIS,ILE,LEU,LYS,MET,PHE,PRO,SER,THR,TRP,TYR,VAL,MSE,HOH,UNK"
515        Types = [wg.GRID_VALUE_STRING,wg.GRID_VALUE_STRING,wg.GRID_VALUE_CHOICE+": ,X,XU,U,F,FX,FXU,FU",]+ \
516            3*[wg.GRID_VALUE_FLOAT+':10,5',]+[wg.GRID_VALUE_FLOAT+':10,4', #x,y,z,frac
517            wg.GRID_VALUE_STRING,wg.GRID_VALUE_STRING,wg.GRID_VALUE_CHOICE+":I,A",]
518        Types += 7*[wg.GRID_VALUE_FLOAT+':10,5',]
519        colLabels = ['Name','Type','refine','x','y','z','frac','site sym','mult','I/A','Uiso','U11','U22','U33','U12','U13','U23']
520        if generalData['Type'] == 'magnetic':
521            colLabels += ['Mx','My','Mz']
522            Types[2] = wg.GRID_VALUE_CHOICE+": ,X,XU,U,M,MX,MXU,MU,F,FX,FXU,FU,FM,FMX,FMU,"
523            Types += 3*[wg.GRID_VALUE_FLOAT+':10,4',]
524        elif generalData['Type'] == 'macromolecular':
525            colLabels = ['res no','residue','chain'] + colLabels
526            Types = [wg.GRID_VALUE_STRING,
527                wg.GRID_VALUE_CHOICE+AAchoice,
528                wg.GRID_VALUE_STRING] + Types
529        elif generalData['Type'] == 'modulated':
530            Types += []
531            colLabels += []
532
533        def RefreshAtomGrid(event):
534
535            r,c =  event.GetRow(),event.GetCol()
536            if r < 0 and c < 0:
537                for row in range(Atoms.GetNumberRows()):
538                    Atoms.SelectRow(row,True)                   
539            if r < 0:                          #double click on col label! Change all atoms!
540                sel = -1
541                noSkip = True
542                if Atoms.GetColLabelValue(c) == 'refine':
543                    Type = generalData['Type']
544                    if Type in ['nuclear','macromolecular']:
545                        choice = ['F - site fraction','X - coordinates','U - thermal parameters']
546                    elif Type in ['magnetic',]:
547                        choice = ['F - site fraction','X - coordinates','U - thermal parameters','M - magnetic moment']
548                    dlg = wx.MultiChoiceDialog(self,'Select','Refinement controls',choice)
549                    if dlg.ShowModal() == wx.ID_OK:
550                        sel = dlg.GetSelections()
551                        parms = ''
552                        for x in sel:
553                            parms += choice[x][0]
554                    dlg.Destroy()
555                elif Atoms.GetColLabelValue(c) == 'I/A':
556                    choice = ['Isotropic','Anisotropic']
557                    dlg = wx.SingleChoiceDialog(self,'Select','Thermal Motion',choice)
558                    if dlg.ShowModal() == wx.ID_OK:
559                        sel = dlg.GetSelection()
560                        parms = choice[sel][0]
561                    dlg.Destroy()
562                elif Atoms.GetColLabelValue(c) == 'Type':
563                    choice = generalData['AtomTypes']
564                    dlg = wx.SingleChoiceDialog(self,'Select','Atom types',choice)
565                    if dlg.ShowModal() == wx.ID_OK:
566                        sel = dlg.GetSelection()
567                        parms = choice[sel]
568                        noSkip = False
569                        Atoms.ClearSelection()
570                        for row in range(Atoms.GetNumberRows()):
571                            if parms == atomData[row][c]:
572                                Atoms.SelectRow(row,True)
573                elif Atoms.GetColLabelValue(c) == 'residue':
574                    choice = []
575                    for r in range(Atoms.GetNumberRows()):
576                        if str(atomData[r][c]) not in choice:
577                            choice.append(str(atomData[r][c]))
578                    choice.sort()
579                    dlg = wx.SingleChoiceDialog(self,'Select','Residue',choice)
580                    if dlg.ShowModal() == wx.ID_OK:
581                        sel = dlg.GetSelection()
582                        parms = choice[sel]
583                        noSkip = False
584                        Atoms.ClearSelection()
585                        for row in range(Atoms.GetNumberRows()):
586                            if parms == atomData[row][c]:
587                                Atoms.SelectRow(row,True)
588                elif Atoms.GetColLabelValue(c) == 'res no':
589                    choice = []
590                    for r in range(Atoms.GetNumberRows()):
591                        if str(atomData[r][c]) not in choice:
592                            choice.append(str(atomData[r][c]))
593                    dlg = wx.SingleChoiceDialog(self,'Select','Residue no.',choice)
594                    if dlg.ShowModal() == wx.ID_OK:
595                        sel = dlg.GetSelection()
596                        parms = choice[sel]
597                        noSkip = False
598                        Atoms.ClearSelection()
599                        for row in range(Atoms.GetNumberRows()):
600                            if int(parms) == atomData[row][c]:
601                                Atoms.SelectRow(row,True)
602                elif Atoms.GetColLabelValue(c) == 'chain':
603                    choice = []
604                    for r in range(Atoms.GetNumberRows()):
605                        if atomData[r][c] not in choice:
606                            choice.append(atomData[r][c])
607                    dlg = wx.SingleChoiceDialog(self,'Select','Chain',choice)
608                    if dlg.ShowModal() == wx.ID_OK:
609                        sel = dlg.GetSelection()
610                        parms = choice[sel]
611                        noSkip = False
612                        Atoms.ClearSelection()
613                        for row in range(Atoms.GetNumberRows()):
614                            if parms == atomData[row][c]:
615                                Atoms.SelectRow(row,True)
616                    dlg.Destroy()
617                elif Atoms.GetColLabelValue(c) == 'Uiso':       #this needs to ask for value
618                    pass                                        #& then change all 'I' atoms
619                if sel >= 0 and noSkip:
620                    ui = colLabels.index('U11')
621                    us = colLabels.index('Uiso')
622                    ss = colLabels.index('site sym')
623                    for r in range(Atoms.GetNumberRows()):
624                        ID = atomData[r][-1]
625                        if parms != atomData[r][c] and Atoms.GetColLabelValue(c) == 'I/A':
626                            if parms == 'A':                #'I' --> 'A'
627                                Uiso = float(Atoms.GetCellValue(r,us))
628                                sytsym = atomData[r][ss]
629                                CSI = G2spc.GetCSuinel(sytsym)
630                                atomData[r][ui:ui+6] = Uiso*np.array(CSI[3])
631                                atomData[r][us] = 0.0
632                                Atoms.SetCellStyle(r,us,VERY_LIGHT_GREY,True)
633                                for i in range(6):
634                                    ci = ui+i
635                                    Atoms.SetCellStyle(r,ci,VERY_LIGHT_GREY,True)
636                                    if CSI[2][i]:
637                                        Atoms.SetCellStyle(r,ci,WHITE,False)
638                            else:                           #'A' --> 'I'
639                                Uij = atomData[r][ui:ui+6]
640                                Uiso = (Uij[0]+Uij[1]+Uij[2])/3.0
641                                atomData[r][us] = Uiso
642                                Atoms.SetCellStyle(r,us,WHITE,False)
643                                for i in range(6):
644                                    ci = ui+i
645                                    atomData[r][ci] = 0.0
646                                    Atoms.SetCellStyle(r,ci,VERY_LIGHT_GREY,True)
647                        atomData[r][c] = parms
648                        if 'Atoms' in data['Drawing']:
649                            DrawAtomsReplaceByID(data['Drawing'],atomData[r],ID)
650                    FillAtomsGrid()
651                   
652        def ChangeAtomCell(event):
653           
654            def chkUij(Uij,CSI): #needs to do something!!!
655                return Uij
656
657            r,c =  event.GetRow(),event.GetCol()
658            if r >= 0 and c >= 0:
659                ID = atomData[r][-1]
660                if Atoms.GetColLabelValue(c) in ['x','y','z']:
661                    ci = colLabels.index('x')
662                    XYZ = atomData[r][ci:ci+3]
663                    if None in XYZ:
664                        XYZ = [0,0,0]
665                    SScol = colLabels.index('site sym')
666                    Mulcol = colLabels.index('mult')
667                    E,SGData = G2spc.SpcGroup(generalData['SGData']['SpGrp'])
668                    Sytsym,Mult = G2spc.SytSym(XYZ,SGData)
669                    atomData[r][SScol] = Sytsym
670                    atomData[r][Mulcol] = Mult
671                    if atomData[r][colLabels.index('I/A')] == 'A':
672                        ui = colLabels.index('U11')
673                        CSI = G2spc.GetCSuinel(Sytsym)
674                        atomData[r][ui:ui+6] = chkUij(atomData[r][ui:ui+6],Sytsym)
675                        for i in range(6):
676                            ci = i+ui
677                            Atoms.SetCellStyle(r,ci,VERY_LIGHT_GREY,True)
678                            if CSI[2][i]:
679                                Atoms.SetCellStyle(r,ci,WHITE,False)
680                    SetupGeneral()
681                elif Atoms.GetColLabelValue(c) == 'I/A':            #note use of text color to make it vanish!
682                    if atomData[r][c] == 'I':
683                        Uij = atomData[r][c+2:c+8]
684                        atomData[r][c+1] = (Uij[0]+Uij[1]+Uij[2])/3.0
685                        Atoms.SetCellStyle(r,c+1,WHITE,False)
686                        Atoms.SetCellTextColour(r,c+1,BLACK)
687                        for i in range(6):
688                            ci = i+colLabels.index('U11')
689                            Atoms.SetCellStyle(r,ci,VERY_LIGHT_GREY,True)
690                            Atoms.SetCellTextColour(r,ci,VERY_LIGHT_GREY)
691                            atomData[r][ci] = 0.0
692                    else:
693                        value = atomData[r][c+1]
694                        CSI = G2spc.GetCSuinel(atomData[r][colLabels.index('site sym')])
695                        atomData[r][c+1] =  0.0
696                        Atoms.SetCellStyle(r,c+1,VERY_LIGHT_GREY,True)
697                        Atoms.SetCellTextColour(r,c+1,VERY_LIGHT_GREY)
698                        for i in range(6):
699                            ci = i+colLabels.index('U11')
700                            atomData[r][ci] = value*CSI[3][i]
701                            Atoms.SetCellStyle(r,ci,VERY_LIGHT_GREY,True)
702                            Atoms.SetCellTextColour(r,ci,BLACK)
703                            if CSI[2][i]:
704                                Atoms.SetCellStyle(r,ci,WHITE,False)
705                elif Atoms.GetColLabelValue(c) in ['U11','U22','U33','U12','U13','U23']:
706                    value = atomData[r][c]
707                    CSI = G2spc.GetCSuinel(atomData[r][colLabels.index('site sym')])
708                    iUij = CSI[0][c-colLabels.index('U11')]
709                    for i in range(6):
710                        if iUij == CSI[0][i]:
711                            atomData[r][i+colLabels.index('U11')] = value*CSI[1][i]
712                if 'Atoms' in data['Drawing']:
713                    DrawAtomsReplaceByID(data['Drawing'],atomData[r],ID)
714                    FindBonds()
715                   
716        def AtomTypeSelect(event):
717            r,c =  event.GetRow(),event.GetCol()
718            if Atoms.GetColLabelValue(c) == 'Type':
719                PE = G2elem.PickElement(self)
720                if PE.ShowModal() == wx.ID_OK:
721                    atomData[r][c] = PE.Elem.strip()
722                    name = atomData[r][c]
723                    if len(name) in [2,4]:
724                        atomData[r][c-1] = name[:2]+'(%d)'%(r+1)
725                    else:
726                        atomData[r][c-1] = name[:1]+'(%d)'%(r+1)
727                PE.Destroy()
728                SetupGeneral()
729                FillAtomsGrid()
730                value = Atoms.GetCellValue(r,c)
731                atomData[r][c] = value
732                ID = atomData[r][-1]
733                if 'Atoms' in data['Drawing']:
734                    DrawAtomsReplaceByID(data['Drawing'],atomData[r],ID)
735            else:
736                event.Skip()
737
738        def RowSelect(event):
739            r,c =  event.GetRow(),event.GetCol()
740            if r < 0 and c < 0:
741                if Atoms.IsSelection():
742                    Atoms.ClearSelection()
743            elif c < 0:                   #only row clicks
744                if event.ControlDown():                   
745                    if r in Atoms.GetSelectedRows():
746                        Atoms.DeselectRow(r)
747                    else:
748                        Atoms.SelectRow(r,True)
749                elif event.ShiftDown():
750                    for row in range(r+1):
751                        Atoms.SelectRow(row,True)
752                else:
753                    Atoms.ClearSelection()
754                    Atoms.SelectRow(r,True)               
755               
756        def ChangeSelection(event):
757            r,c =  event.GetRow(),event.GetCol()
758            if r < 0 and c < 0:
759                Atoms.ClearSelection()
760            if c < 0:
761                if r in Atoms.GetSelectedRows():
762                    Atoms.DeselectRow(r)
763                else:
764                    Atoms.SelectRow(r,True)
765            if r < 0:
766                if c in Atoms.GetSelectedCols():
767                    Atoms.DeselectCol(c)
768                else:
769                    Atoms.SelectCol(c,True)
770       
771        SGData = data['General']['SGData']
772        if SGData['SGPolax']:
773            self.dataFrame.SetStatusText('Warning: The location of the origin is arbitrary in '+SGData['SGPolax'])
774        table = []
775        rowLabels = []
776        for i,atom in enumerate(atomData):
777            table.append(atom)
778            rowLabels.append(str(i))
779        atomTable = G2gd.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
780        Atoms.SetTable(atomTable, True)
781        Atoms.Bind(wg.EVT_GRID_CELL_CHANGE, ChangeAtomCell)
782        Atoms.Bind(wg.EVT_GRID_CELL_LEFT_DCLICK, AtomTypeSelect)
783        Atoms.Bind(wg.EVT_GRID_LABEL_LEFT_DCLICK, RefreshAtomGrid)
784        Atoms.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK, RowSelect)
785        Atoms.Bind(wg.EVT_GRID_LABEL_RIGHT_CLICK, ChangeSelection)
786        Atoms.SetMargins(0,0)
787        Atoms.AutoSizeColumns(False)
788        colType = colLabels.index('Type')
789        colSS = colLabels.index('site sym')
790        colIA = colLabels.index('I/A')
791        colU11 = colLabels.index('U11')
792        colUiso = colLabels.index('Uiso')
793        for i in range(colU11-1,colU11+6):
794            Atoms.SetColSize(i,50)           
795        for row in range(Atoms.GetNumberRows()):
796            Atoms.SetReadOnly(row,colType,True)
797            Atoms.SetReadOnly(row,colSS,True)                         #site sym
798            Atoms.SetReadOnly(row,colSS+1,True)                       #Mult
799            if Atoms.GetCellValue(row,colIA) == 'A':
800                CSI = G2spc.GetCSuinel(atomData[row][colLabels.index('site sym')])
801                Atoms.SetCellStyle(row,colUiso,VERY_LIGHT_GREY,True)
802                Atoms.SetCellTextColour(row,colUiso,VERY_LIGHT_GREY)
803                for i in range(6):
804                    ci = colU11+i
805                    Atoms.SetCellTextColour(row,ci,BLACK)
806                    Atoms.SetCellStyle(row,ci,VERY_LIGHT_GREY,True)
807                    if CSI[2][i]:
808                        Atoms.SetCellStyle(row,ci,WHITE,False)
809            else:
810                Atoms.SetCellStyle(row,colUiso,WHITE,False)
811                Atoms.SetCellTextColour(row,colUiso,BLACK)
812                for i in range(6):
813                    ci = colU11+i
814                    Atoms.SetCellStyle(row,ci,VERY_LIGHT_GREY,True)
815                    Atoms.SetCellTextColour(row,ci,VERY_LIGHT_GREY)
816
817    def OnAtomAdd(event):
818        AtomAdd(0,0,0)
819        FillAtomsGrid()
820        event.StopPropagation()
821       
822    def OnAtomTestAdd(event):
823        try:
824            drawData = data['Drawing']
825            x,y,z = drawData['testPos'][0]
826            AtomAdd(x,y,z)
827        except:
828            AtomAdd(0,0,0)
829        FillAtomsGrid()
830        event.StopPropagation()
831               
832    def AtomAdd(x,y,z):
833        atomData = data['Atoms']
834        generalData = data['General']
835        Ncol = Atoms.GetNumberCols()
836        atId = ran.randint(0,sys.maxint)
837        E,SGData = G2spc.SpcGroup(generalData['SGData']['SpGrp'])
838        Sytsym,Mult = G2spc.SytSym([x,y,z],SGData)
839        if generalData['Type'] == 'macromolecular':
840            atomData.append([0,'UNK','','UNK','H','',x,y,z,1,Sytsym,Mult,'I',0.10,0,0,0,0,0,0,atId])
841        elif generalData['Type'] == 'nuclear':
842            atomData.append(['UNK','H','',x,y,z,1,Sytsym,Mult,'I',0.01,0,0,0,0,0,0,atId])
843        elif generalData['Type'] == 'magnetic':
844            atomData.append(['UNK','H','',x,y,z,1,Sytsym,Mult,0,'I',0.01,0,0,0,0,0,0,0,0,0,atId])
845        SetupGeneral()
846        if 'Atoms' in data['Drawing']:           
847            DrawAtomAdd(data['Drawing'],atomData[-1])
848            G2plt.PlotStructure(self,data)
849
850    def OnAtomInsert(event):
851        AtomInsert(0,0,0)
852        FillAtomsGrid()
853        event.StopPropagation()
854       
855    def OnAtomTestInsert(event):
856        if 'Drawing' in data:
857            drawData = data['Drawing']
858            x,y,z = drawData['testPos'][0]
859            AtomAdd(x,y,z)
860            FillAtomsGrid()
861        event.StopPropagation()
862           
863    def AtomInsert(x,y,z):
864        indx = Atoms.GetSelectedRows()
865        if indx:
866            indx = indx[0]
867            atomData = data['Atoms']
868            generalData = data['General']
869            Ncol = Atoms.GetNumberCols()
870            E,SGData = G2spc.SpcGroup(generalData['SGData']['SpGrp'])
871            Sytsym,Mult = G2spc.SytSym([0,0,0],SGData)
872            atId = ran.randint(0,sys.maxint)
873            if generalData['Type'] == 'macromolecular':
874                atomData.insert(indx,[0,'UNK','','UNK','UNK','',x,y,z,1,Sytsym,Mult,'I',0.10,0,0,0,0,0,0,atId])
875            elif generalData['Type'] == 'nuclear':
876                atomData.insert(indx,['UNK','UNK','',x,y,z,1,Sytsym,Mult,'I',0.01,0,0,0,0,0,0,atId])
877            elif generalData['Type'] == 'magnetic':
878                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])
879            SetupGeneral()
880
881    def AtomDelete(event):
882        indx = Atoms.GetSelectedRows()
883        IDs = []
884        if indx:
885            atomData = data['Atoms']
886            indx.reverse()
887            for ind in indx:
888                atom = atomData[ind]
889                IDs.append(atom[-1])
890                del atomData[ind]
891            if 'Atoms' in data['Drawing']:
892                DrawAtomsDeleteByIDs(IDs)
893                FillAtomsGrid()
894                G2plt.PlotStructure(self,data)
895        event.StopPropagation()
896
897    def AtomRefine(event):
898        colLabels = [Atoms.GetColLabelValue(c) for c in range(Atoms.GetNumberCols())]
899        c = colLabels.index('refine')
900        indx = Atoms.GetSelectedRows()
901        if indx:
902            atomData = data['Atoms']
903            generalData = data['General']
904            Type = generalData['Type']
905            if Type in ['nuclear','macromolecular']:
906                choice = ['F - site fraction','X - coordinates','U - thermal parameters']
907            elif Type == 'magnetic':
908                choice = ['F - site fraction','X - coordinates','U - thermal parameters','M - magnetic moment']
909            dlg = wx.MultiChoiceDialog(self,'Select','Refinement controls',choice)
910            if dlg.ShowModal() == wx.ID_OK:
911                sel = dlg.GetSelections()
912                parms = ''
913                for x in sel:
914                    parms += choice[x][0]
915                for r in indx:
916                    atomData[r][c] = parms
917                Atoms.ForceRefresh()
918            dlg.Destroy()
919
920    def AtomModify(event):                  #intent to implement global modifications (+,-,*,/, etc.)?
921        indx = Atoms.GetSelectedRows()
922        if indx:
923            atomData = data['Atoms']
924            generalData = data['General']
925
926    def AtomTransform(event):
927        indx = Atoms.GetSelectedRows()
928        if indx:
929            colLabels = [Atoms.GetColLabelValue(c) for c in range(Atoms.GetNumberCols())]
930            cx = colLabels.index('x')
931            cuia = colLabels.index('I/A')
932            cuij = colLabels.index('U11')
933            css = colLabels.index('site sym')
934            atomData = data['Atoms']
935            generalData = data['General']
936            SGData = generalData['SGData']
937            dlg = SymOpDialog(self,SGData,True)
938            try:
939                if dlg.ShowModal() == wx.ID_OK:
940                    Inv,Cent,Opr,Cell,New = dlg.GetSelection()
941                    Cell = np.array(Cell)
942                    cent = SGData['SGCen'][Cent]
943                    M,T = SGData['SGOps'][Opr]
944                    for ind in indx:
945                        XYZ = np.array(atomData[ind][cx:cx+3])
946                        XYZ = np.inner(M,XYZ)+T
947                        if Inv:
948                            XYZ = -XYZ
949                        XYZ = XYZ+cent+Cell
950                        if New:
951                            atom = copy.copy(atomData[ind])
952                        else:
953                            atom = atomData[ind]
954                        atom[cx:cx+3] = XYZ
955                        atom[css:css+2] = G2spc.SytSym(XYZ,SGData)
956                        if atom[cuia] == 'A':
957                            Uij = atom[cuij:cuij+6]
958                            U = G2spc.Uij2U(Uij)
959                            U = np.inner(np.inner(M,U),M)
960                            Uij = G2spc.U2Uij(U)
961                            atom[cuij:cuij+6] = Uij
962                        if New:
963                            atomData.append(atom)
964            finally:
965                dlg.Destroy()
966            Atoms.ClearSelection()
967            if New:
968                FillAtomsGrid()
969            else:
970                Atoms.ForceRefresh()
971               
972#Structure drawing GUI stuff               
973
974    def SetupDrawingData():
975        generalData = data['General']
976        atomData = data['Atoms']
977        AA3letter = ['ALA','ARG','ASN','ASP','CYS','GLN','GLU','GLY','HIS','ILE',
978            'LEU','LYS','MET','PHE','PRO','SER','THR','TRP','TYR','VAL','MSE','HOH','WAT','UNK']
979        AA1letter = ['A','R','N','D','C','Q','E','G','H','I',
980            'L','K','M','F','P','S','T','W','Y','V','M',' ',' ',' ']
981        defaultDrawing = {'viewPoint':[[0.5,0.5,0.5],[]],'showHydrogen':True,'backColor':[0,0,0],'depthFog':False,
982            'Zclip':50.0,'cameraPos':50.,'radiusFactor':0.85,
983            'bondRadius':0.1,'ballScale':0.33,'vdwScale':0.67,'ellipseProb':50,'sizeH':0.50,
984            'unitCellBox':False,'showABC':True,'selectedAtoms':[],
985            'Rotation':[0.0,0.0,0.0,[]],'bondList':{},'testPos':[[-.1,-.1,-.1],[0.0,0.0,0.0],[0,0]]}
986        try:
987            drawingData = data['Drawing']
988        except KeyError:
989            data['Drawing'] = {}
990            drawingData = data['Drawing']
991        if not drawingData:                 #fill with defaults if empty
992            drawingData = copy.copy(defaultDrawing)
993            drawingData['Atoms'] = []
994        cx,ct,cs = [0,0,0]
995        if generalData['Type'] == 'nuclear':
996            cx,ct,cs = [2,1,6]         #x, type & style
997        elif generalData['Type'] == 'macromolecular':
998            cx,ct,cs = [5,4,9]         #x, type & style
999        elif generalData['Type'] == 'magnetic':
1000            cx,ct,cs = [2,1,6]         #x, type & style
1001#        elif generalData['Type'] == 'modulated':
1002#           ?????   for future
1003        if not drawingData['Atoms']:
1004            for atom in atomData:
1005                DrawAtomAdd(drawingData,atom)
1006            drawingData['atomPtrs'] = [cx,ct,cs]
1007            data['Drawing'] = drawingData
1008           
1009    def MakeDrawAtom(atom,oldatom=None):
1010        AA3letter = ['ALA','ARG','ASN','ASP','CYS','GLN','GLU','GLY','HIS','ILE',
1011            'LEU','LYS','MET','PHE','PRO','SER','THR','TRP','TYR','VAL','MSE','HOH','WAT','UNK']
1012        AA1letter = ['A','R','N','D','C','Q','E','G','H','I',
1013            'L','K','M','F','P','S','T','W','Y','V','M',' ',' ',' ']
1014        generalData = data['General']
1015        SGData = generalData['SGData']
1016        if generalData['Type'] == 'nuclear':
1017            if oldatom:
1018                opr = oldatom[5]
1019                if atom[9] == 'A':                   
1020                    X,U = G2spc.ApplyStringOps(opr,SGData,atom[3:6],atom[11:17])
1021                    atomInfo = [atom[:2]+list(X)+oldatom[5:9]+atom[9:11]+list(U)+oldatom[17:]][0]
1022                else:
1023                    X = G2spc.ApplyStringOps(opr,SGData,atom[3:6])
1024                    atomInfo = [atom[:2]+list(X)+oldatom[5:9]+atom[9:]+[oldatom[-1]]][0]
1025            else:
1026                atomInfo = [atom[:2]+atom[3:6]+['1',]+['vdW balls',]+
1027                    ['',]+[[255,255,255],]+atom[9:]+[[],[]]][0]
1028            ct,cs = [1,8]         #type & color
1029        elif generalData['Type'] == 'macromolecular':
1030            try:
1031                oneLetter = AA3letter.index(atom[1])
1032            except ValueError:
1033                oneLetter = -1
1034            atomInfo = [[atom[1].strip()+atom[0],]+
1035                [AA1letter[oneLetter]+atom[0],]+atom[2:5]+
1036                atom[6:9]+['1',]+['sticks',]+['',]+[[255,255,255],]+atom[12:]+[[],[]]][0]
1037            ct,cs = [4,11]         #type & color
1038        elif generalData['Type'] == 'magnetic':
1039            if oldatom:
1040                atomInfo = [atom[:2]+oldatom[3:]][0]
1041            else:
1042                atomInfo = [atom[:2]+atom[3:6]+['vdW balls',]+['',]+atom[9:]+[[],[]]][0]
1043            ct,cs = [1,8]         #type & color
1044#        elif generalData['Type'] == 'modulated':
1045#           ?????   for future
1046        atNum = generalData['AtomTypes'].index(atom[ct])
1047        atomInfo[cs] = list(generalData['Color'][atNum])
1048        return atomInfo
1049           
1050    def DrawAtomAdd(drawingData,atom):
1051        drawingData['Atoms'].append(MakeDrawAtom(atom))
1052       
1053    def DrawAtomsReplaceByID(drawingData,atom,ID):
1054        IDs = [ID,]
1055        atomData = drawingData['Atoms']
1056        indx = FindAtomIndexByIDs(atomData,IDs)
1057        for ind in indx:
1058            atomData[ind] = MakeDrawAtom(atom,atomData[ind])
1059           
1060    def UpdateDrawAtoms():
1061        generalData = data['General']
1062        SetupDrawingData()
1063        drawingData = data['Drawing']
1064        cx,ct,cs = drawingData['atomPtrs']
1065        atomData = drawingData['Atoms']
1066        Types = [wg.GRID_VALUE_STRING,wg.GRID_VALUE_STRING,]+3*[wg.GRID_VALUE_FLOAT+':10,5',]+ \
1067            [wg.GRID_VALUE_STRING,wg.GRID_VALUE_CHOICE+": ,lines,vdW balls,sticks,balls & sticks,ellipsoids,polyhedra",
1068            wg.GRID_VALUE_CHOICE+": ,type,name,number",wg.GRID_VALUE_STRING,wg.GRID_VALUE_STRING,]
1069        styleChoice = [' ','lines','vdW balls','sticks','balls & sticks','ellipsoids','polyhedra']
1070        labelChoice = [' ','type','name','number']
1071        colLabels = ['Name','Type','x','y','z','Sym Op','Style','Label','Color','I/A']
1072        if generalData['Type'] == 'macromolecular':
1073            colLabels = ['Residue','1-letter','Chain'] + colLabels
1074            Types = 3*[wg.GRID_VALUE_STRING,]+Types
1075            Types[8] = wg.GRID_VALUE_CHOICE+": ,lines,vdW balls,sticks,balls & sticks,ellipsoids,backbone,ribbons,schematic"
1076            styleChoice = [' ','lines','vdW balls','sticks','balls & sticks','ellipsoids','backbone','ribbons','schematic']
1077            labelChoice = [' ','type','name','number','residue','1-letter','chain']
1078            Types[9] = wg.GRID_VALUE_CHOICE+": ,type,name,number,residue,1-letter,chain"
1079#        elif generalData['Type'] == 'modulated':
1080#            Types += []
1081#            colLabels += []
1082
1083        def RefreshAtomGrid(event):
1084
1085            def SetChoice(name,c,n=0):
1086                choice = []
1087                for r in range(len(atomData)):
1088                    if n:
1089                        srchStr = str(atomData[r][c][:n])
1090                    else:
1091                        srchStr = str(atomData[r][c])
1092                    if srchStr not in choice:
1093                        if n:
1094                            choice.append(str(atomData[r][c][:n]))
1095                        else:
1096                            choice.append(str(atomData[r][c]))
1097                choice.sort()
1098
1099                dlg = wx.MultiChoiceDialog(self,'Select',name,choice)
1100                if dlg.ShowModal() == wx.ID_OK:
1101                    sel = dlg.GetSelections()
1102                    parms = []
1103                    for x in sel:
1104                        parms.append(choice[x])
1105                    noSkip = False
1106                    drawAtoms.ClearSelection()
1107                    drawingData['selectedAtoms'] = []
1108                    for row in range(len(atomData)):
1109                        test = atomData[row][c]
1110                        if n:
1111                            test = test[:n]
1112                        if  test in parms:
1113                            drawAtoms.SelectRow(row,True)
1114                            drawingData['selectedAtoms'].append(row)
1115                    G2plt.PlotStructure(self,data)                   
1116                dlg.Destroy()
1117               
1118            r,c =  event.GetRow(),event.GetCol()
1119            if r < 0 and c < 0:
1120                for row in range(drawAtoms.GetNumberRows()):
1121                    drawingData['selectedAtoms'].append(row)
1122                    drawAtoms.SelectRow(row,True)                   
1123            elif r < 0:                          #dclick on col label
1124                sel = -1
1125                Parms = False
1126                noSkip = True
1127                if drawAtoms.GetColLabelValue(c) == 'Style':
1128                    dlg = wx.SingleChoiceDialog(self,'Select','Atom drawing style',styleChoice)
1129                    if dlg.ShowModal() == wx.ID_OK:
1130                        sel = dlg.GetSelection()
1131                        parms = styleChoice[sel]
1132                        for r in range(len(atomData)):
1133                            atomData[r][c] = parms
1134                            drawAtoms.SetCellValue(r,c,parms)
1135                        FindBonds()
1136                        G2plt.PlotStructure(self,data)
1137                    dlg.Destroy()
1138                elif drawAtoms.GetColLabelValue(c) == 'Label':
1139                    dlg = wx.SingleChoiceDialog(self,'Select','Atom labelling style',labelChoice)
1140                    if dlg.ShowModal() == wx.ID_OK:
1141                        sel = dlg.GetSelection()
1142                        parms = labelChoice[sel]
1143                        for r in range(len(atomData)):
1144                            atomData[r][c] = parms
1145                            drawAtoms.SetCellValue(r,c,parms)
1146                    dlg.Destroy()                   
1147                elif drawAtoms.GetColLabelValue(c) == 'Color':
1148                    dlg = wx.ColourDialog(self)
1149                    if dlg.ShowModal() == wx.ID_OK:
1150                        color = dlg.GetColourData().GetColour()
1151                        attr = wg.GridCellAttr()                #needs to be here - gets lost if outside loop!
1152                        attr.SetReadOnly(True)
1153                        attr.SetBackgroundColour(color)
1154                        for r in range(len(atomData)):
1155                            atomData[r][c] = color
1156                            drawingData['Atoms'][r][c] = color
1157                            drawAtoms.SetAttr(r,c,attr)
1158                        UpdateDrawAtoms()
1159                    dlg.Destroy()
1160                elif drawAtoms.GetColLabelValue(c) == 'Residue':
1161                    SetChoice('Residue',c,3)
1162                elif drawAtoms.GetColLabelValue(c) == '1-letter':
1163                    SetChoice('1-letter',c,1)
1164                elif drawAtoms.GetColLabelValue(c) == 'Chain':
1165                    SetChoice('Chain',c)
1166                elif drawAtoms.GetColLabelValue(c) == 'Name':
1167                    SetChoice('Name',c)
1168                elif drawAtoms.GetColLabelValue(c) == 'Sym Op':
1169                    SetChoice('Name',c)
1170                elif drawAtoms.GetColLabelValue(c) == 'Type':
1171                    SetChoice('Type',c)
1172                elif drawAtoms.GetColLabelValue(c) in ['x','y','z','I/A']:
1173                    drawAtoms.ClearSelection()
1174            else:
1175                if drawAtoms.GetColLabelValue(c) in ['Style','Label']:
1176                    atomData[r][c] = drawAtoms.GetCellValue(r,c)
1177                    FindBonds()
1178                elif drawAtoms.GetColLabelValue(c) == 'Color':
1179                    color = atomData[r][c]
1180                    colors = wx.ColourData()
1181                    colors.SetChooseFull(True)
1182                    colors.SetCustomColour(0,color)
1183                    colors.SetColour(color)
1184                    dlg = wx.ColourDialog(self,colors)
1185                    dlg.GetColourData().SetCustomColour(0,color)
1186                    if dlg.ShowModal() == wx.ID_OK:
1187                        color = dlg.GetColourData().GetColour()
1188                        attr = wg.GridCellAttr()                #needs to be here - gets lost if outside loop!
1189                        attr.SetReadOnly(True)
1190                        attr.SetBackgroundColour(color)
1191                        atomData[r][c] = color
1192                        drawingData['Atoms'][r][c] = color
1193                        drawAtoms.SetAttr(i,cs+2,attr)
1194                    dlg.Destroy()
1195                    event.StopPropagation()
1196                    UpdateDrawAtoms()
1197            G2plt.PlotStructure(self,data)
1198                   
1199        def RowSelect(event):
1200            r,c =  event.GetRow(),event.GetCol()
1201            if r < 0 and c < 0:
1202                if drawAtoms.IsSelection():
1203                    drawAtoms.ClearSelection()
1204            elif c < 0:                   #only row clicks
1205                if event.ControlDown():                   
1206                    if r in drawAtoms.GetSelectedRows():
1207                        drawAtoms.DeselectRow(r)
1208                    else:
1209                        drawAtoms.SelectRow(r,True)
1210                elif event.ShiftDown():
1211                    for row in range(r+1):
1212                        drawAtoms.SelectRow(row,True)
1213                else:
1214                    drawAtoms.ClearSelection()
1215                    drawAtoms.SelectRow(r,True)               
1216            drawingData['selectedAtoms'] = []
1217            drawingData['selectedAtoms'] = drawAtoms.GetSelectedRows()
1218            G2plt.PlotStructure(self,data)                   
1219               
1220        table = []
1221        rowLabels = []
1222        for i,atom in enumerate(drawingData['Atoms']):
1223            table.append(atom[:colLabels.index('I/A')+1])
1224            rowLabels.append(str(i))
1225
1226        atomTable = G2gd.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
1227        drawAtoms.SetTable(atomTable, True)
1228        drawAtoms.SetMargins(0,0)
1229        drawAtoms.AutoSizeColumns(True)
1230        drawAtoms.SetColSize(colLabels.index('Style'),80)
1231        drawAtoms.SetColSize(colLabels.index('Color'),50)
1232        drawAtoms.Bind(wg.EVT_GRID_CELL_CHANGE, RefreshAtomGrid)
1233        drawAtoms.Bind(wg.EVT_GRID_LABEL_LEFT_DCLICK, RefreshAtomGrid)
1234        drawAtoms.Bind(wg.EVT_GRID_CELL_LEFT_DCLICK, RefreshAtomGrid)
1235        drawAtoms.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK, RowSelect)
1236        for i,atom in enumerate(drawingData['Atoms']):
1237            attr = wg.GridCellAttr()                #needs to be here - gets lost if outside loop!
1238            attr.SetReadOnly(True)
1239            attr.SetBackgroundColour(atom[cs+2])
1240            drawAtoms.SetAttr(i,cs+2,attr)
1241            drawAtoms.SetCellValue(i,cs+2,'')
1242        indx = drawingData['selectedAtoms']
1243        if indx:
1244            for r in range(len(atomData)):
1245                if r in indx:
1246                    drawAtoms.SelectRow(r)
1247        for c in range(len(colLabels)):
1248           attr = wg.GridCellAttr()                #needs to be here - gets lost if outside loop!
1249           attr.SetReadOnly(True)
1250           attr.SetBackgroundColour(VERY_LIGHT_GREY)
1251           if colLabels[c] not in ['Style','Label','Color']:
1252                drawAtoms.SetColAttr(c,attr)
1253        self.dataFrame.setSizePosLeft([600,300])
1254       
1255        FindBonds()
1256        drawAtoms.ClearSelection()
1257        G2plt.PlotStructure(self,data)
1258
1259    def DrawAtomStyle(event):
1260        indx = drawAtoms.GetSelectedRows()
1261        if indx:
1262            generalData = data['General']
1263            atomData = data['Drawing']['Atoms']
1264            cx,ct,cs = data['Drawing']['atomPtrs']
1265            styleChoice = [' ','lines','vdW balls','sticks','balls & sticks','ellipsoids','polyhedra']
1266            if generalData['Type'] == 'macromolecular':
1267                styleChoice = [' ','lines','vdW balls','sticks','balls & sticks','ellipsoids',
1268                'backbone','ribbons','schematic']
1269            dlg = wx.SingleChoiceDialog(self,'Select','Atom drawing style',styleChoice)
1270            if dlg.ShowModal() == wx.ID_OK:
1271                sel = dlg.GetSelection()
1272                parms = styleChoice[sel]
1273                for r in indx:
1274                    atomData[r][cs] = parms
1275                    drawAtoms.SetCellValue(r,cs,parms)
1276            dlg.Destroy()
1277            FindBonds()
1278            drawAtoms.ClearSelection()
1279            G2plt.PlotStructure(self,data)
1280
1281    def DrawAtomLabel(event):
1282        indx = drawAtoms.GetSelectedRows()
1283        if indx:
1284            generalData = data['General']
1285            atomData = data['Drawing']['Atoms']
1286            cx,ct,cs = data['Drawing']['atomPtrs']
1287            styleChoice = [' ','type','name','number']
1288            if generalData['Type'] == 'macromolecular':
1289                styleChoice = [' ','type','name','number','residue','1-letter','chain']
1290            dlg = wx.SingleChoiceDialog(self,'Select','Atom label style',styleChoice)
1291            if dlg.ShowModal() == wx.ID_OK:
1292                sel = dlg.GetSelection()
1293                parms = styleChoice[sel]
1294                for r in indx:
1295                    atomData[r][cs+1] = parms
1296                    drawAtoms.SetCellValue(r,cs+1,parms)
1297            dlg.Destroy()
1298            drawAtoms.ClearSelection()
1299            G2plt.PlotStructure(self,data)
1300           
1301    def DrawAtomColor(event):
1302
1303        indx = drawAtoms.GetSelectedRows()
1304        if indx:
1305            if len(indx) > 1:
1306                self.dataFrame.SetStatusText('Select Custom Color, change color, Add to Custom Colors, then OK')
1307            else:
1308                self.dataFrame.SetStatusText('Change color, Add to Custom Colors, then OK')
1309            generalData = data['General']
1310            atomData = data['Drawing']['Atoms']
1311            cx,ct,cs = data['Drawing']['atomPtrs']
1312            atmColors = []
1313            atmTypes = []
1314            for r in indx:
1315                if atomData[r][cs+2] not in atmColors:
1316                    atmColors.append(atomData[r][cs+2])
1317                    atmTypes.append(atomData[r][ct])
1318                    if len(atmColors) > 16:
1319                        break
1320            colors = wx.ColourData()
1321            colors.SetChooseFull(True)
1322            for i,color in enumerate(atmColors):
1323                colors.SetCustomColour(i,color)
1324            dlg = wx.ColourDialog(self,colors)
1325            if dlg.ShowModal() == wx.ID_OK:
1326                for i in range(len(atmColors)):                   
1327                    atmColors[i] = dlg.GetColourData().GetCustomColour(i)
1328                colorDict = dict(zip(atmTypes,atmColors))
1329                for r in indx:
1330                    color = colorDict[atomData[r][ct]]
1331                    atomData[r][cs+2] = color
1332                    attr = wg.GridCellAttr()                #needs to be here - gets lost if outside loop!
1333                    attr.SetBackgroundColour(color)
1334                    drawAtoms.SetAttr(r,cs+2,attr)
1335                    data['Drawing']['Atoms'][r][cs+2] = color
1336            drawAtoms.ClearSelection()
1337            dlg.Destroy()
1338            self.dataFrame.SetStatusText('')
1339           
1340    def ResetAtomColors(event):
1341        generalData = data['General']
1342        atomData = data['Drawing']['Atoms']
1343        cx,ct,cs = data['Drawing']['atomPtrs']
1344        for atom in atomData:           
1345            atNum = generalData['AtomTypes'].index(atom[ct])
1346            atom[cs+2] = list(generalData['Color'][atNum])
1347        UpdateDrawAtoms()
1348        drawAtoms.ClearSelection()
1349        G2plt.PlotStructure(self,data)       
1350       
1351    def SetViewPoint(event):
1352        indx = drawAtoms.GetSelectedRows()
1353        if indx:
1354            atomData = data['Drawing']['Atoms']
1355            cx = data['Drawing']['atomPtrs'][0]
1356            data['Drawing']['viewPoint'] = [atomData[indx[0]][cx:cx+3],[indx[0],0]]
1357            drawAtoms.ClearSelection()                                  #do I really want to do this?
1358            G2plt.PlotStructure(self,data)
1359           
1360    def noDuplicate(xyz,atomData):                  #be careful where this is used - it's slow
1361        cx = data['Drawing']['atomPtrs'][0]
1362        if True in [np.allclose(np.array(xyz),np.array(atom[cx:cx+3]),atol=0.0002) for atom in atomData]:
1363            return False
1364        else:
1365            return True
1366               
1367    def AddSymEquiv(event):
1368        indx = drawAtoms.GetSelectedRows()
1369        indx.sort()
1370        if indx:
1371            colLabels = [drawAtoms.GetColLabelValue(c) for c in range(drawAtoms.GetNumberCols())]
1372            cx = colLabels.index('x')
1373            cuia = colLabels.index('I/A')
1374            cuij = cuia+2
1375            atomData = data['Drawing']['Atoms']
1376            generalData = data['General']
1377            SGData = generalData['SGData']
1378            dlg = SymOpDialog(self,SGData,False)
1379            try:
1380                if dlg.ShowModal() == wx.ID_OK:
1381                    Inv,Cent,Opr,Cell,New = dlg.GetSelection()
1382                    Cell = np.array(Cell)
1383                    cent = SGData['SGCen'][Cent]
1384                    M,T = SGData['SGOps'][Opr]
1385                    for ind in indx:
1386                        XYZ = np.array(atomData[ind][cx:cx+3])
1387                        XYZ = np.inner(M,XYZ)+T
1388                        if Inv:
1389                            XYZ = -XYZ
1390                        XYZ = XYZ+cent+Cell
1391                        if noDuplicate(XYZ,atomData):
1392                            atom = copy.copy(atomData[ind])
1393                            atom[cx:cx+3] = XYZ
1394                            atomOp = atom[cx+3]
1395                            newOp = str(((Opr+1)+100*Cent)*(1-2*Inv))+'+'+ \
1396                                str(int(Cell[0]))+','+str(int(Cell[1]))+','+str(int(Cell[2]))                           
1397                            atom[cx+3] = G2spc.StringOpsProd(atomOp,newOp,SGData)
1398                            if atom[cuia] == 'A':
1399                                Uij = atom[cuij:cuij+6]
1400                                U = G2spc.Uij2U(Uij)
1401                                U = np.inner(np.inner(M,U),M)
1402                                Uij = G2spc.U2Uij(U)
1403                                atom[cuij:cuij+6] = Uij
1404                            atomData.append(atom)
1405            finally:
1406                dlg.Destroy()
1407            UpdateDrawAtoms()
1408            drawAtoms.ClearSelection()
1409            G2plt.PlotStructure(self,data)
1410           
1411    def TransformSymEquiv(event):
1412        indx = drawAtoms.GetSelectedRows()
1413        indx.sort()
1414        if indx:
1415            atomData = data['Drawing']['Atoms']
1416            colLabels = [drawAtoms.GetColLabelValue(c) for c in range(drawAtoms.GetNumberCols())]
1417            cx = colLabels.index('x')
1418            cuia = colLabels.index('I/A')
1419            cuij = cuia+2
1420            atomData = data['Drawing']['Atoms']
1421            generalData = data['General']
1422            SGData = generalData['SGData']
1423            dlg = SymOpDialog(self,SGData,False)
1424            try:
1425                if dlg.ShowModal() == wx.ID_OK:
1426                    Inv,Cent,Opr,Cell,New = dlg.GetSelection()
1427                    Cell = np.array(Cell)
1428                    cent = SGData['SGCen'][Cent]
1429                    M,T = SGData['SGOps'][Opr]
1430                    for ind in indx:
1431                        XYZ = np.array(atomData[ind][cx:cx+3])
1432                        XYZ = np.inner(M,XYZ)+T
1433                        if Inv:
1434                            XYZ = -XYZ
1435                        XYZ = XYZ+cent+Cell
1436                        atom = atomData[ind]
1437                        atom[cx:cx+3] = XYZ
1438                        atomOp = atom[cx+3]
1439                        newOp = str(((Opr+1)+100*Cent)*(1-2*Inv))+'+'+ \
1440                            str(int(Cell[0]))+','+str(int(Cell[1]))+','+str(int(Cell[2]))
1441                        atom[cx+3] = G2spc.StringOpsProd(atomOp,newOp,SGData)
1442                        if atom[cuia] == 'A':
1443                            Uij = atom[cuij:cuij+6]
1444                            U = G2spc.Uij2U(Uij)
1445                            U = np.inner(np.inner(M,U),M)
1446                            Uij = G2spc.U2Uij(U)
1447                            atom[cuij:cuij+6] = Uij
1448                    data['Drawing']['Atoms'] = atomData
1449            finally:
1450                dlg.Destroy()
1451            UpdateDrawAtoms()
1452            drawAtoms.ClearSelection()
1453            G2plt.PlotStructure(self,data)
1454           
1455    def FillCoordSphere(event):
1456        generalData = data['General']
1457        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])
1458        radii = generalData['BondRadii']
1459        atomTypes = generalData['AtomTypes']
1460        try:
1461            indH = atomTypes.index('H')
1462            radii[indH] = 0.5
1463        except:
1464            pass           
1465        indx = drawAtoms.GetSelectedRows()
1466        if indx:
1467            indx.sort()
1468            atomData = data['Drawing']['Atoms']
1469            numAtoms = len(atomData)
1470            cx,ct,cs = data['Drawing']['atomPtrs']
1471            generalData = data['General']
1472            SGData = generalData['SGData']
1473            cellArray = G2lat.CellBlock(1)
1474            for ind in indx:
1475                atomA = atomData[ind]
1476                xyzA = np.array(atomA[cx:cx+3])
1477                indA = atomTypes.index(atomA[ct])
1478                for atomB in atomData[:numAtoms]:
1479                    indB = atomTypes.index(atomB[ct])
1480                    sumR = radii[indA]+radii[indB]
1481                    xyzB = np.array(atomB[cx:cx+3])
1482                    for xyz in cellArray+xyzB:
1483                        dist = np.sqrt(np.sum(np.inner(Amat,xyz-xyzA)**2))
1484                        if 0 < dist <= data['Drawing']['radiusFactor']*sumR:
1485                            if noDuplicate(xyz,atomData):
1486                                oprB = atomB[cx+3]
1487                                C = xyz-xyzB
1488                                newOp = '1+'+str(int(round(C[0])))+','+str(int(round(C[1])))+','+str(int(round(C[2])))
1489                                newAtom = atomB[:]
1490                                newAtom[cx:cx+3] = xyz
1491                                newAtom[cx+3] = G2spc.StringOpsProd(oprB,newOp,SGData)
1492                                atomData.append(newAtom)
1493            data['Drawing']['Atoms'] = atomData
1494            UpdateDrawAtoms()
1495            drawAtoms.ClearSelection()
1496            G2plt.PlotStructure(self,data)
1497           
1498    def FillUnitCell(event):
1499        indx = drawAtoms.GetSelectedRows()
1500        indx.sort()
1501        if indx:
1502            atomData = data['Drawing']['Atoms']
1503            colLabels = [drawAtoms.GetColLabelValue(c) for c in range(drawAtoms.GetNumberCols())]
1504            cx = colLabels.index('x')
1505            cuia = colLabels.index('I/A')
1506            cuij = cuia+2
1507            generalData = data['General']
1508            SGData = generalData['SGData']
1509            for ind in indx:
1510                atom = atomData[ind]
1511                XYZ = np.array(atom[cx:cx+3])
1512                if atom[cuia] == 'A':
1513                    Uij = atom[cuij:cuij+6]
1514                    result = G2spc.GenAtom(XYZ,SGData,False,Uij)
1515                    for item in result:
1516                        atom = copy.copy(atomData[ind])
1517                        atom[cx:cx+3] = item[0]
1518                        atom[cx+3] = str(item[2])+'+' \
1519                            +str(item[3][0])+','+str(item[3][1])+','+str(item[3][2])
1520                        atom[cuij:cuij+6] = item[1]
1521                        Opp = G2spc.Opposite(item[0])
1522                        for xyz in Opp:
1523                            if noDuplicate(xyz,atomData):
1524                                cell = np.asarray(np.rint(xyz-atom[cx:cx+3]),dtype=np.int32)
1525                                cell = '1'+'+'+ \
1526                                    str(cell[0])+','+str(cell[1])+','+str(cell[2])
1527                                atom[cx:cx+3] = xyz
1528                                atom[cx+3] = G2spc.StringOpsProd(cell,atom[cx+3],SGData)
1529                                atomData.append(atom[:])
1530                else:
1531                    result = G2spc.GenAtom(XYZ,SGData,False)
1532                    for item in result:
1533                        atom = copy.copy(atomData[ind])
1534                        atom[cx:cx+3] = item[0]
1535                        atom[cx+3] = str(item[1])+'+' \
1536                            +str(item[2][0])+','+str(item[2][1])+','+str(item[2][2])
1537                        Opp = G2spc.Opposite(item[0])
1538                        for xyz in Opp:
1539                            if noDuplicate(xyz,atomData):
1540                                cell = np.asarray(np.rint(xyz-atom[cx:cx+3]),dtype=np.int32)
1541                                cell = '1'+'+'+ \
1542                                    str(cell[0])+','+str(cell[1])+','+str(cell[2])
1543                                atom[cx:cx+3] = xyz
1544                                atom[cx+3] = G2spc.StringOpsProd(cell,atom[cx+3],SGData)
1545                                atomData.append(atom[:])               
1546                data['Drawing']['Atoms'] = atomData
1547            UpdateDrawAtoms()
1548            drawAtoms.ClearSelection()
1549            G2plt.PlotStructure(self,data)
1550           
1551    def FindBondsToo():                         #works but slow for large structures - keep as reference
1552        cx,ct,cs = data['Drawing']['atomPtrs']
1553        atomData = data['Drawing']['Atoms']
1554        generalData = data['General']
1555        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])
1556        radii = generalData['BondRadii']
1557        atomTypes = generalData['AtomTypes']
1558        try:
1559            indH = atomTypes.index('H')
1560            radii[indH] = 0.5
1561        except:
1562            pass           
1563        for atom in atomData:
1564            atom[-1] = []
1565        Atoms = []
1566        for i,atom in enumerate(atomData):
1567            Atoms.append([i,np.array(atom[cx:cx+3]),atom[cs],radii[atomTypes.index(atom[ct])]])
1568        for atomA in Atoms:
1569            if atomA[2] in ['lines','sticks','ellipsoids','balls & sticks','polyhedra']:
1570                for atomB in Atoms:                   
1571                    Dx = atomB[1]-atomA[1]
1572                    DX = np.inner(Amat,Dx)
1573                    dist = np.sqrt(np.sum(DX**2))
1574                    sumR = atomA[3]+atomB[3]
1575                    if 0.5 < dist <= 0.85*sumR:
1576                        i = atomA[0]
1577                        if atomA[2] == 'polyhedra':
1578                            atomData[i][-1].append(DX)
1579                        elif atomB[1] != 'polyhedra':
1580                            j = atomB[0]
1581                            atomData[i][-1].append(Dx*atomA[3]/sumR)
1582                            atomData[j][-1].append(-Dx*atomB[3]/sumR)
1583                   
1584    def FindBonds():                    #uses numpy & masks - very fast even for proteins!
1585        import numpy.ma as ma
1586        cx,ct,cs = data['Drawing']['atomPtrs']
1587        hydro = data['Drawing']['showHydrogen']
1588        atomData = data['Drawing']['Atoms']
1589        generalData = data['General']
1590        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])
1591        radii = generalData['BondRadii']
1592        atomTypes = generalData['AtomTypes']
1593        try:
1594            indH = atomTypes.index('H')
1595            radii[indH] = 0.5
1596        except:
1597            pass           
1598        for atom in atomData:
1599            atom[-2] = []               #clear out old bonds/polyhedra
1600            atom[-1] = []
1601        Indx = range(len(atomData))
1602        Atoms = []
1603        Styles = []
1604        Radii = []
1605        for atom in atomData:
1606            Atoms.append(np.array(atom[cx:cx+3]))
1607            Styles.append(atom[cs])
1608            try:
1609                if not hydro and atom[ct] == 'H':
1610                    Radii.append(0.0)
1611                else:
1612                    Radii.append(radii[atomTypes.index(atom[ct])])
1613            except ValueError:          #changed atom type!
1614                Radii.append(0.20)
1615        Atoms = np.array(Atoms)
1616        Radii = np.array(Radii)
1617        IASR = zip(Indx,Atoms,Styles,Radii)
1618        for atomA in IASR:
1619            if atomA[2] in ['lines','sticks','ellipsoids','balls & sticks','polyhedra']:
1620                Dx = Atoms-atomA[1]
1621                dist = ma.masked_less(np.sqrt(np.sum(np.inner(Amat,Dx)**2,axis=0)),0.5) #gets rid of self & disorder "bonds" < 0.5A
1622                sumR = atomA[3]+Radii
1623                IndB = ma.nonzero(ma.masked_greater(dist-data['Drawing']['radiusFactor']*sumR,0.))                 #get indices of bonded atoms
1624                i = atomA[0]
1625                for j in IndB[0]:
1626                    if Styles[i] == 'polyhedra':
1627                        atomData[i][-2].append(np.inner(Amat,Dx[j]))
1628                    elif Styles[j] != 'polyhedra' and j > i:
1629                        atomData[i][-2].append(Dx[j]*Radii[i]/sumR[j])
1630                        atomData[j][-2].append(-Dx[j]*Radii[j]/sumR[j])
1631                if Styles[i] == 'polyhedra':
1632                    Bonds = atomData[i][-2]
1633                    Faces = []
1634                    if len(Bonds) > 2:
1635                        FaceGen = G2lat.uniqueCombinations(Bonds,3)     #N.B. this is a generator
1636                        for face in FaceGen:
1637                            vol = nl.det(face)
1638                            if abs(vol) > 1. or len(Bonds) == 3:
1639                                if vol < 0.:
1640                                    face = [face[0],face[2],face[1]]
1641                                face = np.array(face)
1642                                if not np.array([np.array(nl.det(face-bond))+0.0001 < 0 for bond in Bonds]).any():
1643                                    norm = np.cross(face[1]-face[0],face[2]-face[0])
1644                                    norm /= np.sqrt(np.sum(norm**2))
1645                                    Faces.append([face,norm])
1646                        atomData[i][-1] = Faces
1647                       
1648    def DrawAtomsDelete(event):   
1649        indx = drawAtoms.GetSelectedRows()
1650        indx.sort()
1651        if indx:
1652            atomData = data['Drawing']['Atoms']
1653            indx.reverse()
1654            for ind in indx:
1655                del atomData[ind]
1656            UpdateDrawAtoms()
1657            drawAtoms.ClearSelection()
1658            G2plt.PlotStructure(self,data)
1659        event.StopPropagation()
1660       
1661    def OnReloadDrawAtoms(event):
1662        data['Drawing']['Atoms'] = []
1663        UpdateDrawAtoms()
1664        drawAtoms.ClearSelection()
1665        G2plt.PlotStructure(self,data)
1666        event.StopPropagation()
1667       
1668    def FindAtomIndexByIDs(atomData,IDs):
1669        indx = []
1670        for i,atom in enumerate(atomData):
1671            if atom[-2] in IDs:
1672                indx.append(i)
1673        return indx
1674       
1675    def DrawAtomsDeleteByIDs(IDs):
1676        atomData = data['Drawing']['Atoms']
1677        indx = FindAtomIndexByIDs(atomData,IDs)
1678        indx.reverse()
1679        for ind in indx:
1680            del atomData[ind]
1681           
1682    def ChangeDrawAtomsByIDs(colName,IDs,value):
1683        atomData = data['Drawing']['Atoms']
1684        cx,ct,cs = data['Drawing']['atomPtrs']
1685        if colName == 'Name':
1686            col = ct-1
1687        elif colName == 'Type':
1688            col = ct
1689        elif colName == 'I/A':
1690            col = cs
1691        indx = FindAtomIndexByIDs(atomData,IDs)
1692        for ind in indx:
1693            atomData[ind][col] = value
1694               
1695    def UpdateDrawOptions():
1696        import copy
1697        import wx.lib.colourselect as wcs
1698        generalData = data['General']
1699        SetupDrawingData()
1700        drawingData = data['Drawing']
1701        if generalData['Type'] == 'nuclear':
1702            pickChoice = ['Atoms','Bonds','Torsions','Planes']
1703        elif generalData['Type'] == 'macromolecular':
1704            pickChoice = ['Atoms','Residues','Chains','Bonds','Torsions','Planes','phi/psi']
1705
1706        def OnZclip(event):
1707            drawingData['Zclip'] = Zclip.GetValue()
1708            ZclipTxt.SetLabel('Z clipping: '+'%.2fA'%(drawingData['Zclip']*drawingData['cameraPos']/100.))
1709            G2plt.PlotStructure(self,data)
1710           
1711        def OnCameraPos(event):
1712            drawingData['cameraPos'] = cameraPos.GetValue()
1713            cameraPosTxt.SetLabel('Camera Distance: '+'%.2f'%(drawingData['cameraPos']))
1714            ZclipTxt.SetLabel('Z clipping: '+'%.2fA'%(drawingData['Zclip']*drawingData['cameraPos']/100.))
1715            G2plt.PlotStructure(self,data)
1716
1717        def OnBackColor(event):
1718            drawingData['backColor'] = event.GetValue()
1719            G2plt.PlotStructure(self,data)
1720
1721        def OnBallScale(event):
1722            drawingData['ballScale'] = ballScale.GetValue()/100.
1723            ballScaleTxt.SetLabel('Ball scale: '+'%.2f'%(drawingData['ballScale']))
1724            G2plt.PlotStructure(self,data)
1725
1726        def OnVdWScale(event):
1727            drawingData['vdwScale'] = vdwScale.GetValue()/100.
1728            vdwScaleTxt.SetLabel('van der Waals scale: '+'%.2f'%(drawingData['vdwScale']))
1729            G2plt.PlotStructure(self,data)
1730
1731        def OnEllipseProb(event):
1732            drawingData['ellipseProb'] = ellipseProb.GetValue()
1733            ellipseProbTxt.SetLabel('Ellipsoid probability: '+'%d%%'%(drawingData['ellipseProb']))
1734            G2plt.PlotStructure(self,data)
1735
1736        def OnBondRadius(event):
1737            drawingData['bondRadius'] = bondRadius.GetValue()/100.
1738            bondRadiusTxt.SetLabel('Bond radius, A: '+'%.2f'%(drawingData['bondRadius']))
1739            G2plt.PlotStructure(self,data)
1740
1741        def OnShowABC(event):
1742            drawingData['showABC'] = showABC.GetValue()
1743            G2plt.PlotStructure(self,data)
1744
1745        def OnShowUnitCell(event):
1746            drawingData['unitCellBox'] = unitCellBox.GetValue()
1747            G2plt.PlotStructure(self,data)
1748
1749        def OnShowHyd(event):
1750            drawingData['showHydrogen'] = showHydrogen.GetValue()
1751            FindBonds()
1752            G2plt.PlotStructure(self,data)
1753
1754        def OnSizeHatoms(event):
1755            try:
1756                value = max(0.1,min(1.2,float(sizeH.GetValue())))
1757            except ValueError:
1758                value = 0.5
1759            drawingData['sizeH'] = value
1760            sizeH.SetValue("%.2f"%(value))
1761            G2plt.PlotStructure(self,data)
1762           
1763        def OnRadFactor(event):
1764            try:
1765                value = max(0.1,min(1.2,float(radFactor.GetValue())))
1766            except ValueError:
1767                value = 0.85
1768            drawingData['radiusFactor'] = value
1769            radFactor.SetValue("%.2f"%(value))
1770            FindBonds()
1771            G2plt.PlotStructure(self,data)
1772
1773        dataDisplay = wx.Panel(drawOptions)
1774        mainSizer = wx.BoxSizer(wx.VERTICAL)
1775        mainSizer.Add((5,5),0)
1776        mainSizer.Add(wx.StaticText(dataDisplay,-1,'Drawing controls:'),0,wx.ALIGN_CENTER_VERTICAL)
1777        mainSizer.Add((5,5),0)
1778       
1779        slopSizer = wx.BoxSizer(wx.HORIZONTAL)
1780        slideSizer = wx.FlexGridSizer(6,2)
1781        slideSizer.AddGrowableCol(1,1)
1782
1783        cameraPosTxt = wx.StaticText(dataDisplay,-1,
1784            'Camera Distance: '+'%.2f'%(drawingData['cameraPos']),name='cameraPos')
1785        slideSizer.Add(cameraPosTxt,0,wx.ALIGN_CENTER_VERTICAL)
1786        cameraPos = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=drawingData['cameraPos'],name='cameraSlider')
1787        cameraPos.SetRange(10,500)
1788        cameraPos.Bind(wx.EVT_SLIDER, OnCameraPos)
1789        slideSizer.Add(cameraPos,1,wx.EXPAND|wx.RIGHT)
1790       
1791        ZclipTxt = wx.StaticText(dataDisplay,-1,'Z clipping: '+'%.2fA'%(drawingData['Zclip']*drawingData['cameraPos']/100.))
1792        slideSizer.Add(ZclipTxt,0,wx.ALIGN_CENTER_VERTICAL)
1793        Zclip = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=drawingData['Zclip'])
1794        Zclip.SetRange(1,99)
1795        Zclip.Bind(wx.EVT_SLIDER, OnZclip)
1796        slideSizer.Add(Zclip,1,wx.EXPAND|wx.RIGHT)
1797       
1798        vdwScaleTxt = wx.StaticText(dataDisplay,-1,'van der Waals scale: '+'%.2f'%(drawingData['vdwScale']))
1799        slideSizer.Add(vdwScaleTxt,0,wx.ALIGN_CENTER_VERTICAL)
1800        vdwScale = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=int(100*drawingData['vdwScale']))
1801        vdwScale.Bind(wx.EVT_SLIDER, OnVdWScale)
1802        slideSizer.Add(vdwScale,1,wx.EXPAND|wx.RIGHT)
1803
1804        ellipseProbTxt = wx.StaticText(dataDisplay,-1,'Ellipsoid probability: '+'%d%%'%(drawingData['ellipseProb']))
1805        slideSizer.Add(ellipseProbTxt,0,wx.ALIGN_CENTER_VERTICAL)
1806        ellipseProb = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=drawingData['ellipseProb'])
1807        ellipseProb.SetRange(1,99)
1808        ellipseProb.Bind(wx.EVT_SLIDER, OnEllipseProb)
1809        slideSizer.Add(ellipseProb,1,wx.EXPAND|wx.RIGHT)
1810
1811        ballScaleTxt = wx.StaticText(dataDisplay,-1,'Ball scale: '+'%.2f'%(drawingData['ballScale']))
1812        slideSizer.Add(ballScaleTxt,0,wx.ALIGN_CENTER_VERTICAL)
1813        ballScale = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=int(100*drawingData['ballScale']))
1814        ballScale.Bind(wx.EVT_SLIDER, OnBallScale)
1815        slideSizer.Add(ballScale,1,wx.EXPAND|wx.RIGHT)
1816
1817        bondRadiusTxt = wx.StaticText(dataDisplay,-1,'Bond radius, A: '+'%.2f'%(drawingData['bondRadius']))
1818        slideSizer.Add(bondRadiusTxt,0,wx.ALIGN_CENTER_VERTICAL)
1819        bondRadius = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=int(100*drawingData['bondRadius']))
1820        bondRadius.SetRange(1,25)
1821        bondRadius.Bind(wx.EVT_SLIDER, OnBondRadius)
1822        slideSizer.Add(bondRadius,1,wx.EXPAND|wx.RIGHT)
1823       
1824        slopSizer.Add(slideSizer,1,wx.EXPAND|wx.RIGHT)
1825        slopSizer.Add((10,5),0)
1826        slopSizer.SetMinSize(wx.Size(300,10))
1827        mainSizer.Add(slopSizer,0)
1828        mainSizer.Add((5,5),0)
1829
1830        flexSizer = wx.FlexGridSizer(5,2,5,0)
1831        flexSizer.Add(wx.StaticText(dataDisplay,-1,'View Point:  '),0,wx.ALIGN_CENTER_VERTICAL)
1832        VP = drawingData['viewPoint'][0]
1833        viewPoint = wx.TextCtrl(dataDisplay,value='%.3f, %.3f, %.3f'%(VP[0],VP[1],VP[2]),
1834            style=wx.TE_READONLY,size=wx.Size(120,20),name='viewPoint')
1835        viewPoint.SetBackgroundColour(VERY_LIGHT_GREY)
1836        flexSizer.Add(viewPoint,0,wx.ALIGN_CENTER_VERTICAL)
1837       
1838        showABC = wx.CheckBox(dataDisplay,-1,label='Show test point?')
1839        showABC.Bind(wx.EVT_CHECKBOX, OnShowABC)
1840        showABC.SetValue(drawingData['showABC'])
1841        flexSizer.Add(showABC,0,wx.ALIGN_CENTER_VERTICAL)
1842
1843        unitCellBox = wx.CheckBox(dataDisplay,-1,label='Show unit cell?')
1844        unitCellBox.Bind(wx.EVT_CHECKBOX, OnShowUnitCell)
1845        unitCellBox.SetValue(drawingData['unitCellBox'])
1846        flexSizer.Add(unitCellBox,0,wx.ALIGN_CENTER_VERTICAL)
1847
1848        showHydrogen = wx.CheckBox(dataDisplay,-1,label='Show hydrogens?')
1849        showHydrogen.Bind(wx.EVT_CHECKBOX, OnShowHyd)
1850        showHydrogen.SetValue(drawingData['showHydrogen'])
1851        flexSizer.Add(showHydrogen,0,wx.ALIGN_CENTER_VERTICAL)
1852
1853        lineSizer = wx.BoxSizer(wx.HORIZONTAL)
1854        lineSizer.Add(wx.StaticText(dataDisplay,-1,'Background color:'),0,wx.ALIGN_CENTER_VERTICAL)
1855        backColor = wcs.ColourSelect(dataDisplay, -1,colour=drawingData['backColor'],size=wx.Size(25,25))
1856        backColor.Bind(wcs.EVT_COLOURSELECT, OnBackColor)
1857        lineSizer.Add(backColor,0,wx.ALIGN_CENTER_VERTICAL)
1858        flexSizer.Add(lineSizer,0,)
1859
1860        flexSizer.Add(wx.StaticText(dataDisplay,-1,'Hydrogen radius, A:  '),0,wx.ALIGN_CENTER_VERTICAL)
1861        sizeH = wx.TextCtrl(dataDisplay,-1,value='%.2f'%(drawingData['sizeH']),style=wx.TE_PROCESS_ENTER)
1862        sizeH.Bind(wx.EVT_TEXT_ENTER,OnSizeHatoms)
1863        sizeH.Bind(wx.EVT_KILL_FOCUS,OnSizeHatoms)
1864        flexSizer.Add(sizeH,0,wx.ALIGN_CENTER_VERTICAL)
1865
1866        flexSizer.Add(wx.StaticText(dataDisplay,-1,'Bond search factor:  '),0,wx.ALIGN_CENTER_VERTICAL)
1867        radFactor = wx.TextCtrl(dataDisplay,value='%.2f'%(drawingData['radiusFactor']),style=wx.TE_PROCESS_ENTER)
1868        radFactor.Bind(wx.EVT_TEXT_ENTER,OnRadFactor)
1869        radFactor.Bind(wx.EVT_KILL_FOCUS,OnRadFactor)
1870        flexSizer.Add(radFactor,0,wx.ALIGN_CENTER_VERTICAL)
1871        mainSizer.Add(flexSizer,0,)
1872
1873        dataDisplay.SetSizer(mainSizer)
1874        Size = mainSizer.Fit(self.dataFrame)
1875        Size[1] += 26                           #compensate for status bar
1876        dataDisplay.SetSize(Size)
1877        self.dataFrame.setSizePosLeft(Size)
1878       
1879    def UpdateTexture():
1880        generalData = data['General']       
1881        SGData = generalData['SGData']
1882        try:
1883            textureData = generalData['SH Texture']
1884        except KeyError:            #fix old files!
1885            textureData = generalData['SH Texture'] = {'Order':0,'Model':'cylindrical',
1886                'Sample omega':[False,0.0],'Sample chi':[False,0.0],'Sample phi':[False,0.0],
1887                'SH Coeff':[False,{}],'SHShow':False,'PFhkl':[0,0,1],
1888                'PFxyz':[0,0,1.],'PlotType':'Pole figure'}
1889        if 'SHShow' not in textureData:     #another fix
1890            textureData.update({'SHShow':False,'PFhkl':[0,0,1],'PFxyz':[0,0,1.],'PlotType':'Pole figure'})
1891        try:                        #another fix!
1892            x = textureData['PlotType']
1893        except KeyError:
1894            textureData.update({'PFxyz':[0,0,1.],'PlotType':'Pole figure'})
1895        shModels = ['cylindrical','none','shear - 2/m','rolling - mmm']
1896        SamSym = dict(zip(shModels,['0','-1','2/m','mmm']))
1897        if generalData['Type'] == 'Pawley' and G2gd.GetPatternTreeItemId(self,self.root,'Sequental results'):
1898            self.dataFrame.RefineTexture.Enable(True)
1899        shAngles = ['omega','chi','phi']
1900       
1901        def SetSHCoef():
1902            cofNames = G2lat.GenSHCoeff(SGData['SGLaue'],SamSym[textureData['Model']],textureData['Order'])
1903            newSHCoef = dict(zip(cofNames,np.zeros(len(cofNames))))
1904            SHCoeff = textureData['SH Coeff'][1]
1905            for cofName in SHCoeff:
1906                if cofName in  cofNames:
1907                    newSHCoef[cofName] = SHCoeff[cofName]
1908            return newSHCoef
1909       
1910        def OnShOrder(event):
1911            Obj = event.GetEventObject()
1912            textureData['Order'] = int(Obj.GetValue())
1913            textureData['SH Coeff'][1] = SetSHCoef()
1914            wx.CallAfter(UpdateTexture)
1915            G2plt.PlotTexture(self,data,newPlot=False)
1916                       
1917        def OnShModel(event):
1918            Obj = event.GetEventObject()
1919            textureData['Model'] = Obj.GetValue()
1920            textureData['SH Coeff'][1] = SetSHCoef()
1921            wx.CallAfter(UpdateTexture)
1922            G2plt.PlotTexture(self,data,newPlot=False)
1923           
1924        def OnSHRefine(event):
1925            Obj = event.GetEventObject()
1926            textureData['SH Coeff'][0] = Obj.GetValue()
1927           
1928        def OnSHShow(event):
1929            Obj = event.GetEventObject()
1930            textureData['SHShow'] = Obj.GetValue()
1931            wx.CallAfter(UpdateTexture)
1932           
1933        def OnProjSel(event):
1934            Obj = event.GetEventObject()
1935            self.Projection = Obj.GetValue()
1936            G2plt.PlotTexture(self,data,newPlot=False)
1937           
1938        def OnColorSel(event):
1939            Obj = event.GetEventObject()
1940            self.ContourColor = Obj.GetValue()
1941            G2plt.PlotTexture(self,data,newPlot=False)
1942           
1943        def OnAngRef(event):
1944            Obj = event.GetEventObject()
1945            textureData[angIndx[Obj.GetId()]][0] = Obj.GetValue()
1946           
1947        def OnAngValue(event):
1948            Obj = event.GetEventObject()
1949            try:
1950                value =  float(Obj.GetValue())
1951            except ValueError:
1952                value = textureData[valIndx[Obj.GetId()]][1]
1953            Obj.SetValue('%8.2f'%(value))
1954            textureData[valIndx[Obj.GetId()]][1] = value
1955           
1956        def OnODFValue(event): 
1957            Obj = event.GetEventObject()
1958            try:
1959                value =  float(Obj.GetValue())
1960            except ValueError:
1961                value = textureData['SH Coeff'][1][ODFIndx[Obj.GetId()]]
1962            Obj.SetValue('%8.3f'%(value))
1963            textureData['SH Coeff'][1][ODFIndx[Obj.GetId()]] = value
1964            G2plt.PlotTexture(self,data,newPlot=False)
1965           
1966        def OnPfType(event):
1967            Obj = event.GetEventObject()
1968            textureData['PlotType'] = Obj.GetValue()
1969            wx.CallAfter(UpdateTexture)
1970            G2plt.PlotTexture(self,data)
1971           
1972        def OnPFValue(event):
1973            Obj = event.GetEventObject()
1974            Saxis = Obj.GetValue().split()
1975            if textureData['PlotType'] in ['Pole figure','Axial pole distribution']:               
1976                try:
1977                    hkl = [int(Saxis[i]) for i in range(3)]
1978                except (ValueError,IndexError):
1979                    hkl = textureData['PFhkl']
1980                if not np.any(np.array(hkl)):       #can't be all zeros!
1981                    hkl = textureData['PFhkl']
1982                Obj.SetValue('%d %d %d'%(hkl[0],hkl[1],hkl[2]))
1983                textureData['PFhkl'] = hkl
1984            else:
1985                try:
1986                    xyz = [float(Saxis[i]) for i in range(3)]
1987                except (ValueError,IndexError):
1988                    xyz = textureData['PFxyz']
1989                if not np.any(np.array(xyz)):       #can't be all zeros!
1990                    xyz = textureData['PFxyz']
1991                Obj.SetValue('%3.1f %3.1f %3.1f'%(xyz[0],xyz[1],xyz[2]))
1992                textureData['PFxyz'] = xyz
1993            G2plt.PlotTexture(self,data)
1994
1995        if Texture.GetSizer():
1996            Texture.GetSizer().Clear(True)
1997        mainSizer = wx.BoxSizer(wx.VERTICAL)
1998        titleSizer = wx.BoxSizer(wx.HORIZONTAL)
1999        titleSizer.Add(wx.StaticText(Texture,-1,'Spherical harmonics texture data for '+PhaseName+':'),0,wx.ALIGN_CENTER_VERTICAL)
2000        titleSizer.Add(wx.StaticText(Texture,-1,
2001            ' Texture Index J = %7.3f'%(G2lat.textureIndex(textureData['SH Coeff'][1]))),
2002            0,wx.ALIGN_CENTER_VERTICAL)
2003        mainSizer.Add(titleSizer,0)
2004        mainSizer.Add((0,5),0)
2005        shSizer = wx.FlexGridSizer(1,6,5,5)
2006        shSizer.Add(wx.StaticText(Texture,-1,'Texture model: '),0,wx.ALIGN_CENTER_VERTICAL)
2007        shModel = wx.ComboBox(Texture,-1,value=textureData['Model'],choices=shModels,
2008            style=wx.CB_READONLY|wx.CB_DROPDOWN)
2009        shModel.Bind(wx.EVT_COMBOBOX,OnShModel)
2010        shSizer.Add(shModel,0,wx.ALIGN_CENTER_VERTICAL)
2011        shSizer.Add(wx.StaticText(Texture,-1,'  Harmonic order: '),0,wx.ALIGN_CENTER_VERTICAL)
2012        shOrder = wx.ComboBox(Texture,-1,value=str(textureData['Order']),choices=[str(2*i) for i in range(18)],
2013            style=wx.CB_READONLY|wx.CB_DROPDOWN)
2014        shOrder.Bind(wx.EVT_COMBOBOX,OnShOrder)
2015        shSizer.Add(shOrder,0,wx.ALIGN_CENTER_VERTICAL)
2016        shRef = wx.CheckBox(Texture,-1,label=' Refine texture?')
2017        shRef.SetValue(textureData['SH Coeff'][0])
2018        shRef.Bind(wx.EVT_CHECKBOX, OnSHRefine)
2019        shSizer.Add(shRef,0,wx.ALIGN_CENTER_VERTICAL)
2020        shShow = wx.CheckBox(Texture,-1,label=' Show coeff.?')
2021        shShow.SetValue(textureData['SHShow'])
2022        shShow.Bind(wx.EVT_CHECKBOX, OnSHShow)
2023        shSizer.Add(shShow,0,wx.ALIGN_CENTER_VERTICAL)
2024        mainSizer.Add(shSizer,0,0)
2025        mainSizer.Add((0,5),0)
2026        PTSizer = wx.FlexGridSizer(2,4,5,5)
2027        PTSizer.Add(wx.StaticText(Texture,-1,' Texture plot type: '),0,wx.ALIGN_CENTER_VERTICAL)
2028        choices = ['Axial pole distribution','Pole figure','Inverse pole figure']           
2029        pfType = wx.ComboBox(Texture,-1,value=str(textureData['PlotType']),choices=choices,
2030            style=wx.CB_READONLY|wx.CB_DROPDOWN)
2031        pfType.Bind(wx.EVT_COMBOBOX,OnPfType)
2032        PTSizer.Add(pfType,0,wx.ALIGN_CENTER_VERTICAL)
2033        if 'Axial' not in textureData['PlotType']:
2034            PTSizer.Add(wx.StaticText(Texture,-1,' Projection type: '),0,wx.ALIGN_CENTER_VERTICAL)
2035            projSel = wx.ComboBox(Texture,-1,value=self.Projection,choices=['equal area','stereographic','3D display'],
2036                style=wx.CB_READONLY|wx.CB_DROPDOWN)
2037            projSel.Bind(wx.EVT_COMBOBOX,OnProjSel)
2038            PTSizer.Add(projSel,0,wx.ALIGN_CENTER_VERTICAL)
2039        if textureData['PlotType'] in ['Pole figure','Axial pole distribution']:
2040            PTSizer.Add(wx.StaticText(Texture,-1,' Pole figure HKL: '),0,wx.ALIGN_CENTER_VERTICAL)
2041            PH = textureData['PFhkl']
2042            pfVal = wx.TextCtrl(Texture,-1,'%d %d %d'%(PH[0],PH[1],PH[2]),style=wx.TE_PROCESS_ENTER)
2043        else:
2044            PTSizer.Add(wx.StaticText(Texture,-1,' Inverse pole figure XYZ: '),0,wx.ALIGN_CENTER_VERTICAL)
2045            PX = textureData['PFxyz']
2046            pfVal = wx.TextCtrl(Texture,-1,'%3.1f %3.1f %3.1f'%(PX[0],PX[1],PX[2]),style=wx.TE_PROCESS_ENTER)
2047        pfVal.Bind(wx.EVT_TEXT_ENTER,OnPFValue)
2048        pfVal.Bind(wx.EVT_KILL_FOCUS,OnPFValue)
2049        PTSizer.Add(pfVal,0,wx.ALIGN_CENTER_VERTICAL)
2050        if 'Axial' not in textureData['PlotType']:
2051            PTSizer.Add(wx.StaticText(Texture,-1,' Color scheme'),0,wx.ALIGN_CENTER_VERTICAL)
2052            choice = [m for m in mpl.cm.datad.keys() if not m.endswith("_r")]
2053            choice.sort()
2054            colorSel = wx.ComboBox(Texture,-1,value=self.ContourColor,choices=choice,
2055                style=wx.CB_READONLY|wx.CB_DROPDOWN)
2056            colorSel.Bind(wx.EVT_COMBOBOX,OnColorSel)
2057            PTSizer.Add(colorSel,0,wx.ALIGN_CENTER_VERTICAL)       
2058        mainSizer.Add(PTSizer,0,wx.ALIGN_CENTER_VERTICAL)
2059        mainSizer.Add((0,5),0)
2060        if textureData['SHShow']:
2061            mainSizer.Add(wx.StaticText(Texture,-1,'Spherical harmonic coefficients: '),0,wx.ALIGN_CENTER_VERTICAL)
2062            mainSizer.Add((0,5),0)
2063            ODFSizer = wx.FlexGridSizer(2,8,2,2)
2064            ODFIndx = {}
2065            ODFkeys = textureData['SH Coeff'][1].keys()
2066            ODFkeys.sort()
2067            for item in ODFkeys:
2068                ODFSizer.Add(wx.StaticText(Texture,-1,item),0,wx.ALIGN_CENTER_VERTICAL)
2069                ODFval = wx.TextCtrl(Texture,wx.ID_ANY,'%8.3f'%(textureData['SH Coeff'][1][item]),style=wx.TE_PROCESS_ENTER)
2070                ODFIndx[ODFval.GetId()] = item
2071                ODFval.Bind(wx.EVT_TEXT_ENTER,OnODFValue)
2072                ODFval.Bind(wx.EVT_KILL_FOCUS,OnODFValue)
2073                ODFSizer.Add(ODFval,0,wx.ALIGN_CENTER_VERTICAL)
2074            mainSizer.Add(ODFSizer,0,wx.ALIGN_CENTER_VERTICAL)
2075            mainSizer.Add((0,5),0)
2076        mainSizer.Add((0,5),0)
2077        mainSizer.Add(wx.StaticText(Texture,-1,'Sample orientation angles: '),0,wx.ALIGN_CENTER_VERTICAL)
2078        mainSizer.Add((0,5),0)
2079        angSizer = wx.BoxSizer(wx.HORIZONTAL)
2080        angIndx = {}
2081        valIndx = {}
2082        for item in ['Sample omega','Sample chi','Sample phi']:
2083            angRef = wx.CheckBox(Texture,-1,label=item+': ')
2084            angRef.SetValue(textureData[item][0])
2085            angIndx[angRef.GetId()] = item
2086            angRef.Bind(wx.EVT_CHECKBOX, OnAngRef)
2087            angSizer.Add(angRef,0,wx.ALIGN_CENTER_VERTICAL)
2088            angVal = wx.TextCtrl(Texture,wx.ID_ANY,'%8.2f'%(textureData[item][1]),style=wx.TE_PROCESS_ENTER)
2089            valIndx[angVal.GetId()] = item
2090            angVal.Bind(wx.EVT_TEXT_ENTER,OnAngValue)
2091            angVal.Bind(wx.EVT_KILL_FOCUS,OnAngValue)
2092            angSizer.Add(angVal,0,wx.ALIGN_CENTER_VERTICAL)
2093            angSizer.Add((5,0),0)
2094        mainSizer.Add(angSizer,0,wx.ALIGN_CENTER_VERTICAL)
2095        Texture.SetSizer(mainSizer,True)
2096        mainSizer.Fit(self.dataFrame)
2097        Size = mainSizer.GetMinSize()
2098        Size[0] += 40
2099        Size[1] = max(Size[1],250) + 20
2100        Texture.SetSize(Size)
2101        Texture.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
2102        Size[1] = min(Size[1],450)
2103        self.dataFrame.setSizePosLeft(Size)
2104       
2105    def UpdateDData():
2106        UseList = data['Histograms']
2107        if UseList:
2108            self.dataFrame.DataMenu.Enable(G2gd.wxID_DATADELETE,True)
2109            self.Refine.Enable(True)
2110        else:
2111            self.dataFrame.DataMenu.Enable(G2gd.wxID_DATADELETE,False)
2112            self.Refine.Enable(False)           
2113        generalData = data['General']       
2114        SGData = generalData['SGData']
2115        keyList = UseList.keys()
2116        keyList.sort()
2117        Indx = {}
2118       
2119        def OnPlotSel(event):
2120            Obj = event.GetEventObject()
2121            generalData['Data plot type'] = Obj.GetStringSelection()
2122            wx.CallAfter(UpdateDData)
2123            G2plt.PlotSizeStrainPO(self,data)
2124           
2125        def OnPOhkl(event):
2126            Obj = event.GetEventObject()
2127            Saxis = Obj.GetValue().split()
2128            try:
2129                hkl = [int(Saxis[i]) for i in range(3)]
2130            except (ValueError,IndexError):
2131                hkl = generalData['POhkl']
2132            if not np.any(np.array(hkl)):
2133                hkl = generalData['POhkl']
2134            generalData['POhkl'] = hkl
2135            h,k,l = hkl
2136            Obj.SetValue('%3d %3d %3d'%(h,k,l)) 
2137            G2plt.PlotSizeStrainPO(self,data)
2138       
2139        def OnShowData(event):
2140            Obj = event.GetEventObject()
2141            hist = Indx[Obj.GetId()]
2142            UseList[hist]['Show'] = Obj.GetValue()
2143            wx.CallAfter(UpdateDData)
2144            G2plt.PlotSizeStrainPO(self,data)
2145           
2146        def OnCopyData(event):
2147            #how about HKLF data? This is only for PWDR data
2148            Obj = event.GetEventObject()
2149            hist = Indx[Obj.GetId()]
2150            sourceDict = UseList[hist]
2151            copyNames = ['Scale','Pref.Ori.','Size','Mustrain','HStrain','Extinction']
2152            copyDict = {}
2153            for name in copyNames: 
2154                copyDict[name] = copy.deepcopy(sourceDict[name])        #force copy
2155            keyList = ['All',]+UseList.keys()
2156            if UseList:
2157                copyList = []
2158                dlg = wx.MultiChoiceDialog(self, 
2159                    'Copy parameters to which histograms?', 'Copy parameters', 
2160                    keyList, wx.CHOICEDLG_STYLE)
2161                try:
2162                    if dlg.ShowModal() == wx.ID_OK:
2163                        result = dlg.GetSelections()
2164                        for i in result: 
2165                            copyList.append(keyList[i])
2166                        if 'All' in copyList: 
2167                            copyList = keyList[1:]
2168                        for item in copyList:
2169                            UseList[item].update(copy.deepcopy(copyDict))
2170                        wx.CallAfter(UpdateDData)
2171                finally:
2172                    dlg.Destroy()
2173           
2174        def OnScaleRef(event):
2175            Obj = event.GetEventObject()
2176            UseList[Indx[Obj.GetId()]]['Scale'][1] = Obj.GetValue()
2177           
2178        def OnScaleVal(event):
2179            Obj = event.GetEventObject()
2180            try:
2181                scale = float(Obj.GetValue())
2182                if scale > 0:
2183                    UseList[Indx[Obj.GetId()]]['Scale'][0] = scale
2184            except ValueError:
2185                pass
2186            Obj.SetValue("%.4f"%(UseList[Indx[Obj.GetId()]]['Scale'][0]))          #reset in case of error
2187           
2188        def OnSizeType(event):
2189            Obj = event.GetEventObject()
2190            hist = Indx[Obj.GetId()]
2191            UseList[hist]['Size'][0] = Obj.GetValue()
2192            G2plt.PlotSizeStrainPO(self,data)
2193            wx.CallAfter(UpdateDData)
2194           
2195        def OnSizeRef(event):
2196            Obj = event.GetEventObject()
2197            hist,pid = Indx[Obj.GetId()]
2198            if UseList[hist]['Size'][0] == 'ellipsoidal':
2199                UseList[hist]['Size'][5][pid] = Obj.GetValue()               
2200            else:
2201                UseList[hist]['Size'][2][pid] = Obj.GetValue()
2202           
2203        def OnSizeVal(event):
2204            Obj = event.GetEventObject()
2205            hist,pid = Indx[Obj.GetId()]
2206            if UseList[hist]['Size'][0] == 'ellipsoidal':
2207                try:
2208                    size = float(Obj.GetValue())
2209                    if pid < 3 and size <= 0.001:            #10A lower limit!
2210                        raise ValueError
2211                    UseList[hist]['Size'][4][pid] = size                   
2212                except ValueError:
2213                    pass
2214                Obj.SetValue("%.3f"%(UseList[hist]['Size'][4][pid]))          #reset in case of error
2215            else:
2216                try:
2217                    size = float(Obj.GetValue())
2218                    if size <= 0.001:            #10A lower limit!
2219                        raise ValueError
2220                    UseList[hist]['Size'][1][pid] = size
2221                except ValueError:
2222                    pass
2223                Obj.SetValue("%.3f"%(UseList[hist]['Size'][1][pid]))          #reset in case of error
2224            G2plt.PlotSizeStrainPO(self,data)
2225           
2226        def OnSizeAxis(event):           
2227            Obj = event.GetEventObject()
2228            hist = Indx[Obj.GetId()]
2229            Saxis = Obj.GetValue().split()
2230            try:
2231                hkl = [int(Saxis[i]) for i in range(3)]
2232            except (ValueError,IndexError):
2233                hkl = UseList[hist]['Size'][3]
2234            if not np.any(np.array(hkl)):
2235                hkl = UseList[hist]['Size'][3]
2236            UseList[hist]['Size'][3] = hkl
2237            h,k,l = hkl
2238            Obj.SetValue('%3d %3d %3d'%(h,k,l)) 
2239                       
2240        def OnStrainType(event):
2241            Obj = event.GetEventObject()
2242            hist = Indx[Obj.GetId()]
2243            UseList[hist]['Mustrain'][0] = Obj.GetValue()
2244            G2plt.PlotSizeStrainPO(self,data)
2245            wx.CallAfter(UpdateDData)
2246           
2247        def OnStrainRef(event):
2248            Obj = event.GetEventObject()
2249            hist,pid = Indx[Obj.GetId()]
2250            if UseList[hist]['Mustrain'][0] == 'generalized':
2251                UseList[hist]['Mustrain'][5][pid] = Obj.GetValue()
2252            else:
2253                UseList[hist]['Mustrain'][2][pid] = Obj.GetValue()
2254           
2255        def OnStrainVal(event):
2256            Snames = G2spc.MustrainNames(SGData)
2257            Obj = event.GetEventObject()
2258            hist,pid = Indx[Obj.GetId()]
2259            try:
2260                strain = float(Obj.GetValue())
2261                if UseList[hist]['Mustrain'][0] == 'generalized':
2262                    if '4' in Snames[pid] and strain < 0:
2263                        raise ValueError
2264                    UseList[hist]['Mustrain'][4][pid] = strain
2265                else:
2266                    if strain <= 0:
2267                        raise ValueError
2268                    UseList[hist]['Mustrain'][1][pid] = strain
2269            except ValueError:
2270                pass
2271            if UseList[hist]['Mustrain'][0] == 'generalized':
2272                Obj.SetValue("%.3f"%(UseList[hist]['Mustrain'][4][pid]))          #reset in case of error
2273            else:
2274                Obj.SetValue("%.1f"%(UseList[hist]['Mustrain'][1][pid]))          #reset in case of error
2275            G2plt.PlotSizeStrainPO(self,data)
2276           
2277        def OnStrainAxis(event):
2278            Obj = event.GetEventObject()
2279            hist = Indx[Obj.GetId()]
2280            Saxis = Obj.GetValue().split()
2281            try:
2282                hkl = [int(Saxis[i]) for i in range(3)]
2283            except (ValueError,IndexError):
2284                hkl = UseList[hist]['Mustrain'][3]
2285            if not np.any(np.array(hkl)):
2286                hkl = UseList[hist]['Mustrain'][3]
2287            UseList[hist]['Mustrain'][3] = hkl
2288            h,k,l = hkl
2289            Obj.SetValue('%3d %3d %3d'%(h,k,l)) 
2290            G2plt.PlotSizeStrainPO(self,data)
2291           
2292        def OnHstrainRef(event):
2293            Obj = event.GetEventObject()
2294            hist,pid = Indx[Obj.GetId()]
2295            UseList[hist]['HStrain'][1][pid] = Obj.GetValue()
2296           
2297        def OnHstrainVal(event):
2298            Snames = G2spc.HStrainNames(SGData)
2299            Obj = event.GetEventObject()
2300            hist,pid = Indx[Obj.GetId()]
2301            try:
2302                strain = float(Obj.GetValue())
2303                UseList[hist]['HStrain'][0][pid] = strain
2304            except ValueError:
2305                pass
2306            Obj.SetValue("%.5f"%(UseList[hist]['HStrain'][0][pid]))          #reset in case of error
2307
2308        def OnPOType(event):
2309            Obj = event.GetEventObject()
2310            hist = Indx[Obj.GetId()]
2311            if 'March' in Obj.GetValue():
2312                UseList[hist]['Pref.Ori.'][0] = 'MD'
2313            else:
2314                UseList[hist]['Pref.Ori.'][0] = 'SH'
2315            wx.CallAfter(UpdateDData)           
2316
2317        def OnPORef(event):
2318            Obj = event.GetEventObject()
2319            hist = Indx[Obj.GetId()]
2320            UseList[hist]['Pref.Ori.'][2] = Obj.GetValue()
2321           
2322        def OnPOVal(event):
2323            Obj = event.GetEventObject()
2324            hist = Indx[Obj.GetId()]
2325            try:
2326                mdVal = float(Obj.GetValue())
2327                if mdVal > 0:
2328                    UseList[hist]['Pref.Ori.'][1] = mdVal
2329            except ValueError:
2330                pass
2331            Obj.SetValue("%.3f"%(UseList[hist]['Pref.Ori.'][1]))          #reset in case of error
2332           
2333        def OnPOAxis(event):
2334            Obj = event.GetEventObject()
2335            hist = Indx[Obj.GetId()]
2336            Saxis = Obj.GetValue().split()
2337            try:
2338                hkl = [int(Saxis[i]) for i in range(3)]
2339            except (ValueError,IndexError):
2340                hkl = UseList[hist]['Pref.Ori.'][3]
2341            if not np.any(np.array(hkl)):
2342                hkl = UseList[hist]['Pref.Ori.'][3]
2343            UseList[hist]['Pref.Ori.'][3] = hkl
2344            h,k,l = hkl
2345            Obj.SetValue('%3d %3d %3d'%(h,k,l)) 
2346           
2347        def OnPOOrder(event):
2348            Obj = event.GetEventObject()
2349            hist = Indx[Obj.GetId()]
2350            Order = int(Obj.GetValue())
2351            UseList[hist]['Pref.Ori.'][4] = Order
2352            UseList[hist]['Pref.Ori.'][5] = SetPOCoef(Order,hist)
2353            wx.CallAfter(UpdateDData)
2354
2355        def SetPOCoef(Order,hist):
2356            cofNames = G2lat.GenSHCoeff(SGData['SGLaue'],'0',Order,False)     #cylindrical & no M
2357            newPOCoef = dict(zip(cofNames,np.zeros(len(cofNames))))
2358            POCoeff = UseList[hist]['Pref.Ori.'][5]
2359            for cofName in POCoeff:
2360                if cofName in  cofNames:
2361                    newPOCoef[cofName] = POCoeff[cofName]
2362            return newPOCoef
2363       
2364        def OnExtRef(event):
2365            Obj = event.GetEventObject()
2366            UseList[Indx[Obj.GetId()]]['Extinction'][1] = Obj.GetValue()
2367           
2368        def OnExtVal(event):
2369            Obj = event.GetEventObject()
2370            try:
2371                ext = float(Obj.GetValue())
2372                if ext >= 0:
2373                    UseList[Indx[Obj.GetId()]]['Extinction'][0] = ext
2374            except ValueError:
2375                pass
2376            Obj.SetValue("%.2f"%(UseList[Indx[Obj.GetId()]]['Extinction'][0]))          #reset in case of error
2377           
2378        def checkAxis(axis):
2379            if not np.any(np.array(axis)):
2380                return False
2381            return axis
2382           
2383        def PlotSizer():
2384            plotSizer = wx.BoxSizer(wx.VERTICAL)
2385            choice = ['Mustrain','Size','Preferred orientation']
2386            plotSel = wx.RadioBox(DData,-1,'Select plot type:',choices=choice,
2387                majorDimension=3,style=wx.RA_SPECIFY_COLS)
2388            plotSel.SetStringSelection(generalData['Data plot type'])
2389            plotSel.Bind(wx.EVT_RADIOBOX,OnPlotSel)   
2390            plotSizer.Add(plotSel)
2391            if generalData['Data plot type'] == 'Preferred orientation':
2392                POhklSizer = wx.BoxSizer(wx.HORIZONTAL)
2393                POhklSizer.Add(wx.StaticText(DData,-1,' Plot preferred orientation for H K L: '),0,wx.ALIGN_CENTER_VERTICAL)
2394                h,k,l = generalData['POhkl']
2395                poAxis = wx.TextCtrl(DData,-1,'%3d %3d %3d'%(h,k,l),style=wx.TE_PROCESS_ENTER)
2396                poAxis.Bind(wx.EVT_TEXT_ENTER,OnPOhkl)
2397                poAxis.Bind(wx.EVT_KILL_FOCUS,OnPOhkl)
2398                POhklSizer.Add(poAxis,0,wx.ALIGN_CENTER_VERTICAL)
2399                plotSizer.Add(POhklSizer)           
2400            return plotSizer
2401           
2402        def ScaleSizer():
2403            scaleSizer = wx.BoxSizer(wx.HORIZONTAL)
2404            scaleRef = wx.CheckBox(DData,-1,label=' Phase fraction: ')
2405            scaleRef.SetValue(UseList[item]['Scale'][1])
2406            Indx[scaleRef.GetId()] = item
2407            scaleRef.Bind(wx.EVT_CHECKBOX, OnScaleRef)
2408            scaleSizer.Add(scaleRef,0,wx.ALIGN_CENTER_VERTICAL)
2409            scaleVal = wx.TextCtrl(DData,wx.ID_ANY,
2410                '%.4f'%(UseList[item]['Scale'][0]),style=wx.TE_PROCESS_ENTER)
2411            Indx[scaleVal.GetId()] = item
2412            scaleVal.Bind(wx.EVT_TEXT_ENTER,OnScaleVal)
2413            scaleVal.Bind(wx.EVT_KILL_FOCUS,OnScaleVal)
2414            scaleSizer.Add(scaleVal,0,wx.ALIGN_CENTER_VERTICAL)
2415            return scaleSizer
2416           
2417        def TopSizer(name,choices,parm,OnType):
2418            topSizer = wx.BoxSizer(wx.HORIZONTAL)
2419            topSizer.Add(wx.StaticText(DData,-1,name),0,wx.ALIGN_CENTER_VERTICAL)
2420            sizeType = wx.ComboBox(DData,wx.ID_ANY,value=UseList[item][parm][0],choices=choices,
2421                style=wx.CB_READONLY|wx.CB_DROPDOWN)
2422            sizeType.Bind(wx.EVT_COMBOBOX, OnType)
2423            Indx[sizeType.GetId()] = item
2424            topSizer.Add(sizeType)
2425            topSizer.Add((5,0),0)
2426            return topSizer
2427           
2428        def IsoSizer(name,parm,fmt,OnVal,OnRef):
2429            isoSizer = wx.BoxSizer(wx.HORIZONTAL)
2430            sizeRef = wx.CheckBox(DData,-1,label=name)
2431            sizeRef.thisown = False
2432            sizeRef.SetValue(UseList[item][parm][2][0])
2433            Indx[sizeRef.GetId()] = [item,0]
2434            sizeRef.Bind(wx.EVT_CHECKBOX, OnRef)
2435            isoSizer.Add(sizeRef,0,wx.ALIGN_CENTER_VERTICAL)
2436            sizeVal = wx.TextCtrl(DData,wx.ID_ANY,
2437                fmt%(UseList[item][parm][1][0]),style=wx.TE_PROCESS_ENTER)
2438            Indx[sizeVal.GetId()] = [item,0]
2439            sizeVal.Bind(wx.EVT_TEXT_ENTER,OnVal)
2440            sizeVal.Bind(wx.EVT_KILL_FOCUS,OnVal)
2441            isoSizer.Add(sizeVal,0,wx.ALIGN_CENTER_VERTICAL)
2442            return isoSizer
2443           
2444        def UniSizer(parm,OnAxis):
2445            uniSizer = wx.BoxSizer(wx.HORIZONTAL)
2446            uniSizer.Add(wx.StaticText(DData,-1,' Unique axis, H K L: '),0,wx.ALIGN_CENTER_VERTICAL)
2447            h,k,l = UseList[item][parm][3]
2448            Axis = wx.TextCtrl(DData,-1,'%3d %3d %3d'%(h,k,l),style=wx.TE_PROCESS_ENTER)
2449            Indx[Axis.GetId()] = item
2450            Axis.Bind(wx.EVT_TEXT_ENTER,OnAxis)
2451            Axis.Bind(wx.EVT_KILL_FOCUS,OnAxis)
2452            uniSizer.Add(Axis,0,wx.ALIGN_CENTER_VERTICAL)
2453            return uniSizer
2454           
2455        def UniDataSizer(parmName,parm,fmt,OnVal,OnRef):
2456            dataSizer = wx.BoxSizer(wx.HORIZONTAL)
2457            parms = zip([' Equatorial '+parmName,' Axial '+parmName],
2458                UseList[item][parm][1],UseList[item][parm][2],range(2))
2459            for Pa,val,ref,id in parms:
2460                sizeRef = wx.CheckBox(DData,-1,label=Pa)
2461                sizeRef.thisown = False
2462                sizeRef.SetValue(ref)
2463                Indx[sizeRef.GetId()] = [item,id]
2464                sizeRef.Bind(wx.EVT_CHECKBOX, OnRef)
2465                dataSizer.Add(sizeRef,0,wx.ALIGN_CENTER_VERTICAL)
2466                sizeVal = wx.TextCtrl(DData,wx.ID_ANY,fmt%(val),style=wx.TE_PROCESS_ENTER)
2467                Indx[sizeVal.GetId()] = [item,id]
2468                sizeVal.Bind(wx.EVT_TEXT_ENTER,OnVal)
2469                sizeVal.Bind(wx.EVT_KILL_FOCUS,OnVal)
2470                dataSizer.Add(sizeVal,0,wx.ALIGN_CENTER_VERTICAL)
2471                dataSizer.Add((5,0),0)
2472            return dataSizer
2473           
2474        def EllSizeDataSizer():
2475            parms = zip(['S11','S22','S33','S12','S13','S23'],UseList[item]['Size'][4],
2476                UseList[item]['Size'][5],range(6))
2477            dataSizer = wx.FlexGridSizer(1,6,5,5)
2478            for Pa,val,ref,id in parms:
2479                sizeRef = wx.CheckBox(DData,-1,label=Pa)
2480                sizeRef.thisown = False
2481                sizeRef.SetValue(ref)
2482                Indx[sizeRef.GetId()] = [item,id]
2483                sizeRef.Bind(wx.EVT_CHECKBOX, OnSizeRef)
2484                dataSizer.Add(sizeRef,0,wx.ALIGN_CENTER_VERTICAL)
2485                sizeVal = wx.TextCtrl(DData,wx.ID_ANY,'%.3f'%(val),style=wx.TE_PROCESS_ENTER)
2486                Indx[sizeVal.GetId()] = [item,id]
2487                sizeVal.Bind(wx.EVT_TEXT_ENTER,OnSizeVal)
2488                sizeVal.Bind(wx.EVT_KILL_FOCUS,OnSizeVal)
2489                dataSizer.Add(sizeVal,0,wx.ALIGN_CENTER_VERTICAL)
2490            return dataSizer
2491           
2492        def GenStrainDataSizer():
2493            Snames = G2spc.MustrainNames(SGData)
2494            numb = len(Snames)
2495            if len(UseList[item]['Mustrain'][4]) < numb:
2496                UseList[item]['Mustrain'][4] = numb*[0.0,]
2497                UseList[item]['Mustrain'][5] = numb*[False,]
2498            parms = zip(Snames,UseList[item]['Mustrain'][4],UseList[item]['Mustrain'][5],range(numb))
2499            dataSizer = wx.FlexGridSizer(1,6,5,5)
2500            for Pa,val,ref,id in parms:
2501                strainRef = wx.CheckBox(DData,-1,label=Pa)
2502                strainRef.thisown = False
2503                strainRef.SetValue(ref)
2504                Indx[strainRef.GetId()] = [item,id]
2505                strainRef.Bind(wx.EVT_CHECKBOX, OnStrainRef)
2506                dataSizer.Add(strainRef,0,wx.ALIGN_CENTER_VERTICAL)
2507                strainVal = wx.TextCtrl(DData,wx.ID_ANY,'%.5f'%(val),style=wx.TE_PROCESS_ENTER)
2508                Indx[strainVal.GetId()] = [item,id]
2509                strainVal.Bind(wx.EVT_TEXT_ENTER,OnStrainVal)
2510                strainVal.Bind(wx.EVT_KILL_FOCUS,OnStrainVal)
2511                dataSizer.Add(strainVal,0,wx.ALIGN_CENTER_VERTICAL)
2512            return dataSizer
2513           
2514        def HstrainSizer():
2515            hstrainSizer = wx.FlexGridSizer(1,6,5,5)
2516            Hsnames = G2spc.HStrainNames(SGData)
2517            parms = zip(Hsnames,UseList[item]['HStrain'][0],UseList[item]['HStrain'][1],range(len(Hsnames)))
2518            for Pa,val,ref,id in parms:
2519                hstrainRef = wx.CheckBox(DData,-1,label=Pa)
2520                hstrainRef.thisown = False
2521                hstrainRef.SetValue(ref)
2522                Indx[hstrainRef.GetId()] = [item,id]
2523                hstrainRef.Bind(wx.EVT_CHECKBOX, OnHstrainRef)
2524                hstrainSizer.Add(hstrainRef,0,wx.ALIGN_CENTER_VERTICAL)
2525                hstrainVal = wx.TextCtrl(DData,wx.ID_ANY,'%.5f'%(val),style=wx.TE_PROCESS_ENTER)
2526                Indx[hstrainVal.GetId()] = [item,id]
2527                hstrainVal.Bind(wx.EVT_TEXT_ENTER,OnHstrainVal)
2528                hstrainVal.Bind(wx.EVT_KILL_FOCUS,OnHstrainVal)
2529                hstrainSizer.Add(hstrainVal,0,wx.ALIGN_CENTER_VERTICAL)
2530            return hstrainSizer
2531           
2532        def PoTopSizer(POData):
2533            poSizer = wx.FlexGridSizer(1,6,5,5)
2534            choice = ['March-Dollase','Spherical harmonics']
2535            POtype = choice[['MD','SH'].index(POData[0])]
2536            poSizer.Add(wx.StaticText(DData,-1,' Preferred orientation model '),0,wx.ALIGN_CENTER_VERTICAL)
2537            POType = wx.ComboBox(DData,wx.ID_ANY,value=POtype,choices=choice,
2538                style=wx.CB_READONLY|wx.CB_DROPDOWN)
2539            Indx[POType.GetId()] = item
2540            POType.Bind(wx.EVT_COMBOBOX, OnPOType)
2541            poSizer.Add(POType)
2542            if POData[0] == 'SH':
2543                poSizer.Add(wx.StaticText(DData,-1,' Harmonic order: '),0,wx.ALIGN_CENTER_VERTICAL)
2544                poOrder = wx.ComboBox(DData,wx.ID_ANY,value=str(POData[4]),choices=[str(2*i) for i in range(18)],
2545                    style=wx.CB_READONLY|wx.CB_DROPDOWN)
2546                Indx[poOrder.GetId()] = item
2547                poOrder.Bind(wx.EVT_COMBOBOX,OnPOOrder)
2548                poSizer.Add(poOrder,0,wx.ALIGN_CENTER_VERTICAL)
2549                poRef = wx.CheckBox(DData,-1,label=' Refine? ')
2550                poRef.SetValue(POData[2])
2551                Indx[poRef.GetId()] = item
2552                poRef.Bind(wx.EVT_CHECKBOX,OnPORef)
2553                poSizer.Add(poRef,0,wx.ALIGN_CENTER_VERTICAL)
2554            return poSizer
2555           
2556        def MDDataSizer(POData):
2557            poSizer = wx.BoxSizer(wx.HORIZONTAL)
2558            poRef = wx.CheckBox(DData,-1,label=' March-Dollase ratio: ')
2559            poRef.SetValue(POData[2])
2560            Indx[poRef.GetId()] = item
2561            poRef.Bind(wx.EVT_CHECKBOX,OnPORef)
2562            poSizer.Add(poRef,0,wx.ALIGN_CENTER_VERTICAL)
2563            poVal = wx.TextCtrl(DData,wx.ID_ANY,
2564                '%.3f'%(POData[1]),style=wx.TE_PROCESS_ENTER)
2565            Indx[poVal.GetId()] = item
2566            poVal.Bind(wx.EVT_TEXT_ENTER,OnPOVal)
2567            poVal.Bind(wx.EVT_KILL_FOCUS,OnPOVal)
2568            poSizer.Add(poVal,0,wx.ALIGN_CENTER_VERTICAL)
2569            poSizer.Add(wx.StaticText(DData,-1,' Unique axis, H K L: '),0,wx.ALIGN_CENTER_VERTICAL)
2570            h,k,l =POData[3]
2571            poAxis = wx.TextCtrl(DData,-1,'%3d %3d %3d'%(h,k,l),style=wx.TE_PROCESS_ENTER)
2572            Indx[poAxis.GetId()] = item
2573            poAxis.Bind(wx.EVT_TEXT_ENTER,OnPOAxis)
2574            poAxis.Bind(wx.EVT_KILL_FOCUS,OnPOAxis)
2575            poSizer.Add(poAxis,0,wx.ALIGN_CENTER_VERTICAL)
2576            return poSizer
2577           
2578        def SHDataSizer(POData):
2579            textJ = G2lat.textureIndex(POData[5])
2580            mainSizer.Add(wx.StaticText(DData,-1,' Spherical harmonic coefficients: '+'Texture index: %.3f'%(textJ)),0,wx.ALIGN_CENTER_VERTICAL)
2581            mainSizer.Add((0,5),0)
2582            ODFSizer = wx.FlexGridSizer(2,8,2,2)
2583            ODFIndx = {}
2584            ODFkeys = POData[5].keys()
2585            ODFkeys.sort()
2586            for odf in ODFkeys:
2587                ODFSizer.Add(wx.StaticText(DData,-1,odf),0,wx.ALIGN_CENTER_VERTICAL)
2588                ODFval = wx.TextCtrl(DData,wx.ID_ANY,'%8.3f'%(POData[5][odf]),style=wx.TE_PROCESS_ENTER)
2589                ODFIndx[ODFval.GetId()] = odf
2590#                ODFval.Bind(wx.EVT_TEXT_ENTER,OnODFValue)
2591#                ODFval.Bind(wx.EVT_KILL_FOCUS,OnODFValue)
2592                ODFSizer.Add(ODFval,0,wx.ALIGN_CENTER_VERTICAL)
2593            return ODFSizer
2594           
2595        def ExtSizer():           
2596            extSizer = wx.BoxSizer(wx.HORIZONTAL)
2597            extRef = wx.CheckBox(DData,-1,label=' Extinction: ')
2598            extRef.SetValue(UseList[item]['Extinction'][1])
2599            Indx[extRef.GetId()] = item
2600            extRef.Bind(wx.EVT_CHECKBOX, OnExtRef)
2601            extSizer.Add(extRef,0,wx.ALIGN_CENTER_VERTICAL)
2602            extVal = wx.TextCtrl(DData,wx.ID_ANY,
2603                '%.2f'%(UseList[item]['Extinction'][0]),style=wx.TE_PROCESS_ENTER)
2604            Indx[extVal.GetId()] = item
2605            extVal.Bind(wx.EVT_TEXT_ENTER,OnExtVal)
2606            extVal.Bind(wx.EVT_KILL_FOCUS,OnExtVal)
2607            extSizer.Add(extVal,0,wx.ALIGN_CENTER_VERTICAL)
2608            return extSizer
2609           
2610        if DData.GetSizer():
2611            DData.GetSizer().Clear(True)
2612        mainSizer = wx.BoxSizer(wx.VERTICAL)
2613        mainSizer.Add(wx.StaticText(DData,-1,'Histogram data for '+PhaseName+':'),0,wx.ALIGN_CENTER_VERTICAL)
2614        mainSizer.Add(PlotSizer())           
2615           
2616        for item in keyList:
2617            histData = UseList[item]
2618           
2619            showSizer = wx.BoxSizer(wx.HORIZONTAL)
2620            showData = wx.CheckBox(DData,-1,label=' Show '+item)
2621            showData.SetValue(UseList[item]['Show'])
2622            Indx[showData.GetId()] = item
2623            showData.Bind(wx.EVT_CHECKBOX, OnShowData)
2624            showSizer.Add(showData,0,wx.ALIGN_CENTER_VERTICAL)
2625            copyData = wx.Button(DData,-1,label=' Copy?')
2626            Indx[copyData.GetId()] = item
2627            copyData.Bind(wx.EVT_BUTTON,OnCopyData)
2628            showSizer.Add(copyData,wx.ALIGN_CENTER_VERTICAL)
2629            mainSizer.Add((5,5),0)
2630            mainSizer.Add(showSizer,0,wx.ALIGN_CENTER_VERTICAL)
2631            mainSizer.Add((0,5),0)
2632           
2633            if UseList[item]['Show']:
2634                mainSizer.Add(ScaleSizer())
2635                mainSizer.Add((0,5),0)
2636               
2637            if item[:4] == 'PWDR' and UseList[item]['Show']:
2638                if UseList[item]['Size'][0] == 'isotropic':
2639                    isoSizer = wx.BoxSizer(wx.HORIZONTAL)
2640                    isoSizer.Add(TopSizer(' Size model: ',['isotropic','uniaxial','ellipsoidal'],
2641                        'Size',OnSizeType),0,wx.ALIGN_CENTER_VERTICAL)
2642                    isoSizer.Add(IsoSizer(u' Cryst. size(\xb5m): ','Size','%.3f',
2643                        OnSizeVal,OnSizeRef),0,wx.ALIGN_CENTER_VERTICAL)
2644                    mainSizer.Add(isoSizer)
2645                elif UseList[item]['Size'][0] == 'uniaxial':
2646                    uniSizer = wx.BoxSizer(wx.HORIZONTAL)
2647                    uniSizer.Add(TopSizer(' Size model: ',['isotropic','uniaxial','ellipsoidal'],
2648                        'Size',OnSizeType),0,wx.ALIGN_CENTER_VERTICAL)
2649                    uniSizer.Add(UniSizer('Size',OnSizeAxis),0,wx.ALIGN_CENTER_VERTICAL)
2650                    mainSizer.Add(uniSizer)
2651                    mainSizer.Add(UniDataSizer(u'size(\xb5m): ','Size','%.3f',OnSizeVal,OnSizeRef))
2652                elif UseList[item]['Size'][0] == 'ellipsoidal':
2653                    ellSizer = wx.BoxSizer(wx.HORIZONTAL)
2654                    ellSizer.Add(TopSizer(' Size model: ',['isotropic','uniaxial','ellipsoidal'],
2655                        'Size',OnSizeType),0,wx.ALIGN_CENTER_VERTICAL)
2656                    ellSizer.Add(wx.StaticText(DData,-1,u' Coefficients(\xb5m): '),0,wx.ALIGN_CENTER_VERTICAL)
2657                    mainSizer.Add(ellSizer)
2658                    mainSizer.Add(EllSizeDataSizer())
2659                mainSizer.Add((0,5),0)                   
2660               
2661                if UseList[item]['Mustrain'][0] == 'isotropic':
2662                    isoSizer = wx.BoxSizer(wx.HORIZONTAL)
2663                    isoSizer.Add(TopSizer(' Mustrain model: ',['isotropic','uniaxial','generalized',],
2664                        'Mustrain',OnStrainType),0,wx.ALIGN_CENTER_VERTICAL)
2665                    isoSizer.Add(IsoSizer(' microstrain: ','Mustrain','%.1f',
2666                        OnStrainVal,OnStrainRef),0,wx.ALIGN_CENTER_VERTICAL)                   
2667                    mainSizer.Add(isoSizer)
2668                    mainSizer.Add((0,5),0)
2669                elif UseList[item]['Mustrain'][0] == 'uniaxial':
2670                    uniSizer = wx.BoxSizer(wx.HORIZONTAL)
2671                    uniSizer.Add(TopSizer(' Mustrain model: ',['isotropic','uniaxial','generalized',],
2672                        'Mustrain',OnStrainType),0,wx.ALIGN_CENTER_VERTICAL)
2673                    uniSizer.Add(UniSizer('Mustrain',OnStrainAxis),0,wx.ALIGN_CENTER_VERTICAL)
2674                    mainSizer.Add(uniSizer)
2675                    mainSizer.Add(UniDataSizer('mustrain: ','Mustrain','%.1f',OnStrainVal,OnStrainRef))
2676                elif UseList[item]['Mustrain'][0] == 'generalized':
2677                    genSizer = wx.BoxSizer(wx.HORIZONTAL)
2678                    genSizer.Add(TopSizer(' Mustrain model: ',['isotropic','uniaxial','generalized',],
2679                        'Mustrain',OnStrainType),0,wx.ALIGN_CENTER_VERTICAL)
2680                    genSizer.Add(wx.StaticText(DData,-1,' Coefficients: '),0,wx.ALIGN_CENTER_VERTICAL)
2681                    mainSizer.Add(genSizer)
2682                    mainSizer.Add(GenStrainDataSizer())                       
2683                mainSizer.Add((0,5),0)
2684               
2685                mainSizer.Add(wx.StaticText(DData,-1,' Hydrostatic/elastic strain:'))
2686                mainSizer.Add(HstrainSizer())
2687                   
2688                #texture  'Pref. Ori.':['MD',1.0,False,[0,0,1],0,[]] last two for 'SH' are SHorder & coeff
2689                poSizer = wx.BoxSizer(wx.VERTICAL)
2690                POData = UseList[item]['Pref.Ori.']
2691                poSizer.Add(PoTopSizer(POData))
2692                if POData[0] == 'MD':
2693                    poSizer.Add(MDDataSizer(POData))
2694                else:           #'SH'
2695                    if POData[4]:       #SH order > 0
2696                        poSizer.Add(SHDataSizer(POData))
2697                       
2698                mainSizer.Add(poSizer)
2699                mainSizer.Add((0,5),0)               
2700                #Extinction  'Extinction':[0.0,False]
2701                mainSizer.Add(ExtSizer())
2702                mainSizer.Add((0,5),0)
2703            elif item[:4] == 'HKLF' and UseList[item]['Show']:
2704                pass
2705        mainSizer.Add((5,5),0)
2706
2707        DData.SetSizer(mainSizer,True)
2708        mainSizer.FitInside(self.dataFrame)
2709        Size = mainSizer.GetMinSize()
2710        Size[0] += 40
2711        Size[1] = max(Size[1],250) + 20
2712        DData.SetSize(Size)
2713        DData.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
2714        Size[1] = min(Size[1],450)
2715        self.dataFrame.setSizePosLeft(Size)
2716       
2717    def OnHklfAdd(event):
2718        UseList = data['Histograms']
2719        keyList = UseList.keys()
2720        TextList = []
2721        if self.PatternTree.GetCount():
2722            item, cookie = self.PatternTree.GetFirstChild(self.root)
2723            while item:
2724                name = self.PatternTree.GetItemText(item)
2725                if name not in keyList and 'HKLF' in name:
2726                    TextList.append(name)
2727                item, cookie = self.PatternTree.GetNextChild(self.root, cookie)                       
2728            dlg = wx.MultiChoiceDialog(self, 'Which new data to use?', 'Use data', TextList, wx.CHOICEDLG_STYLE)
2729            try:
2730                if dlg.ShowModal() == wx.ID_OK:
2731                    result = dlg.GetSelections()
2732                    for i in result:
2733                        histoName = TextList[i]
2734                        UseList[histoName] = {'Histogram':histoName,'Show':False,'Scale':[1.0,True],
2735                            'Extinction':['Lorentzian','Secondary Type I',{'Eg':[0.0,False]},]}                       
2736                    data['Histograms'] = UseList
2737                    wx.CallAfter(UpdateDData)
2738            finally:
2739                dlg.Destroy()
2740       
2741    def OnPwdrAdd(event):
2742        generalData = data['General']
2743        SGData = generalData['SGData']
2744        UseList = data['Histograms']
2745        newList = []
2746        NShkl = len(G2spc.MustrainNames(SGData))
2747        NDij = len(G2spc.HStrainNames(SGData))
2748        keyList = UseList.keys()
2749        TextList = ['All PWDR']
2750        if self.PatternTree.GetCount():
2751            item, cookie = self.PatternTree.GetFirstChild(self.root)
2752            while item:
2753                name = self.PatternTree.GetItemText(item)
2754                if name not in keyList and 'PWDR' in name:
2755                    TextList.append(name)
2756                item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
2757            dlg = wx.MultiChoiceDialog(self, 'Which new data to use?', 'Use data', TextList, wx.CHOICEDLG_STYLE)
2758            try:
2759                if dlg.ShowModal() == wx.ID_OK:
2760                    result = dlg.GetSelections()
2761                    for i in result: newList.append(TextList[i])
2762                    if 'All PWDR' in newList:
2763                        newList = TextList[1:]
2764                    for histoName in newList:
2765                        pId = G2gd.GetPatternTreeItemId(self,self.root,histoName)
2766                        UseList[histoName] = {'Histogram':histoName,'Show':False,
2767                            'Scale':[1.0,False],'Pref.Ori.':['MD',1.0,False,[0,0,1],0,{}],
2768                            'Size':['isotropic',[4.,4.,],[False,False],[0,0,1],[4.,4.,4.,0.,0.,0.],6*[False,]],
2769                            'Mustrain':['isotropic',[1000.0,1000.0],[False,False],[0,0,1],
2770                                NShkl*[0.01,],NShkl*[False,]],
2771                            'HStrain':[NDij*[0.0,],NDij*[False,]],                         
2772                            'Extinction':[0.0,False]}
2773                        refList = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,pId,'Reflection Lists'))
2774                        refList[generalData['Name']] = []                       
2775                    data['Histograms'] = UseList
2776                    wx.CallAfter(UpdateDData)
2777            finally:
2778                dlg.Destroy()
2779       
2780    def OnDataDelete(event):
2781        UseList = data['Histograms']
2782        keyList = ['All',]+UseList.keys()
2783        keyList.sort()
2784        DelList = []
2785        if UseList:
2786            DelList = []
2787            dlg = wx.MultiChoiceDialog(self, 
2788                'Which histogram to delete from this phase?', 'Delete histogram', 
2789                keyList, wx.CHOICEDLG_STYLE)
2790            try:
2791                if dlg.ShowModal() == wx.ID_OK:
2792                    result = dlg.GetSelections()
2793                    for i in result: 
2794                        DelList.append(keyList[i])
2795                    if 'All' in DelList:
2796                        DelList = keyList[1:]
2797                    for i in DelList:
2798                        del UseList[i]
2799                    wx.CallAfter(UpdateDData)
2800            finally:
2801                dlg.Destroy()
2802
2803    def FillPawleyReflectionsGrid():
2804                       
2805        def KeyEditPawleyGrid(event):
2806            colList = self.PawleyRefl.GetSelectedCols()
2807            PawleyPeaks = data['Pawley ref']
2808            if event.GetKeyCode() == wx.WXK_RETURN:
2809                event.Skip(True)
2810            elif event.GetKeyCode() == wx.WXK_CONTROL:
2811                event.Skip(True)
2812            elif event.GetKeyCode() == wx.WXK_SHIFT:
2813                event.Skip(True)
2814            elif colList:
2815                self.PawleyRefl.ClearSelection()
2816                key = event.GetKeyCode()
2817                for col in colList:
2818                    if PawleyTable.GetTypeName(0,col) == wg.GRID_VALUE_BOOL:
2819                        if key == 89: #'Y'
2820                            for row in range(PawleyTable.GetNumberRows()): PawleyPeaks[row][col]=True
2821                        elif key == 78:  #'N'
2822                            for row in range(PawleyTable.GetNumberRows()): PawleyPeaks[row][col]=False
2823                        FillPawleyReflectionsGrid()
2824           
2825        if 'Pawley ref' in data:
2826            PawleyPeaks = data['Pawley ref']                       
2827            rowLabels = []
2828            for i in range(len(PawleyPeaks)): rowLabels.append(str(i))
2829            colLabels = ['h','k','l','mul','d','refine','Fsq(hkl)','sig(Fsq)']
2830            Types = 4*[wg.GRID_VALUE_LONG,]+[wg.GRID_VALUE_FLOAT+':10,4',wg.GRID_VALUE_BOOL,]+ \
2831                2*[wg.GRID_VALUE_FLOAT+':10,2',]
2832            PawleyTable = G2gd.Table(PawleyPeaks,rowLabels=rowLabels,colLabels=colLabels,types=Types)
2833            self.PawleyRefl.SetTable(PawleyTable, True)
2834            self.PawleyRefl.Bind(wx.EVT_KEY_DOWN, KeyEditPawleyGrid)                 
2835            self.PawleyRefl.SetMargins(0,0)
2836            self.PawleyRefl.AutoSizeColumns(False)
2837            self.dataFrame.setSizePosLeft([500,300])
2838                   
2839    def OnPawleyLoad(event):
2840        generalData = data['General']
2841        dmin = generalData['Pawley dmin']
2842        cell = generalData['Cell'][1:7]
2843        A = G2lat.cell2A(cell)
2844        SGData = generalData['SGData']
2845        HKLd = np.array(G2lat.GenHLaue(dmin,SGData,A))
2846        PawleyPeaks = []
2847        wx.BeginBusyCursor()
2848        try:
2849            for h,k,l,d in HKLd:
2850                ext,mul = G2spc.GenHKLf([h,k,l],SGData)[:2]
2851                if not ext:
2852                    PawleyPeaks.append([h,k,l,mul,d,False,100.0,1.0])
2853        finally:
2854            wx.EndBusyCursor()
2855        data['Pawley ref'] = PawleyPeaks
2856        FillPawleyReflectionsGrid()
2857       
2858    def OnPawleyEstimate(event):
2859        try:
2860            Refs = data['Pawley ref']
2861            Histograms = data['Histograms']
2862        except KeyError:
2863            print '**** Error - no histograms defined for this phase ****'
2864            return
2865        HistoNames = Histograms.keys()
2866        PatternId = G2gd.GetPatternTreeItemId(self,self.root,HistoNames[0])
2867        xdata = self.PatternTree.GetItemPyData(PatternId)[1]
2868        Inst = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId,'Instrument Parameters'))
2869        Inst = dict(zip(Inst[3],Inst[1]))
2870        Sample = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId,'Sample Parameters'))
2871        if 'Lam' in Inst:
2872            wave = Inst['Lam']
2873        else:
2874            wave = Inst['Lam1']
2875       
2876        posCorr = Inst['Zero']
2877        const = 9.e-2/(np.pi*Sample['Gonio. radius'])                  #shifts in microns
2878       
2879        for ref in Refs:
2880            pos = 2.0*asind(wave/(2.0*ref[4]))
2881            if 'Bragg' in Sample['Type']:
2882                pos -= const*(4.*Sample['Shift'][0]*cosd(pos/2.0)+ \
2883                    Sample['Transparency'][0]*sind(pos)*100.0)            #trans(=1/mueff) in cm
2884            else:               #Debye-Scherrer - simple but maybe not right
2885                pos -= const*(Sample['DisplaceX'][0]*cosd(pos)+Sample['DisplaceY'][0]*sind(pos))
2886            indx = np.searchsorted(xdata[0],pos)
2887            try:
2888                ref[6] = xdata[1][indx]
2889            except IndexError:
2890                pass
2891        FillPawleyReflectionsGrid()
2892                           
2893    def OnPawleyDelete(event):
2894        dlg = wx.MessageDialog(self,'Do you really want to delete Pawley reflections?','Delete', 
2895            wx.YES_NO | wx.ICON_QUESTION)
2896        try:
2897            result = dlg.ShowModal()
2898        finally:
2899            dlg.Destroy()
2900        if result == wx.ID_YES: 
2901            data['Pawley ref'] = []
2902            FillPawleyReflectionsGrid()
2903   
2904    def OnTextureRefine(event):
2905        event.Skip()       
2906           
2907    def OnTextureClear(event):
2908        event.Skip()
2909
2910    def OnPageChanged(event):
2911        page = event.GetSelection()
2912        text = self.dataDisplay.GetPageText(page)
2913        if text == 'Atoms':
2914            self.dataFrame.SetMenuBar(self.dataFrame.AtomsMenu)
2915            self.dataFrame.Bind(wx.EVT_MENU, OnAtomAdd, id=G2gd.wxID_ATOMSEDITADD)
2916            self.dataFrame.Bind(wx.EVT_MENU, OnAtomTestAdd, id=G2gd.wxID_ATOMSTESTADD)
2917            self.dataFrame.Bind(wx.EVT_MENU, OnAtomInsert, id=G2gd.wxID_ATOMSEDITINSERT)
2918            self.dataFrame.Bind(wx.EVT_MENU, OnAtomTestInsert, id=G2gd.wxID_ATONTESTINSERT)
2919            self.dataFrame.Bind(wx.EVT_MENU, AtomDelete, id=G2gd.wxID_ATOMSEDITDELETE)
2920            self.dataFrame.Bind(wx.EVT_MENU, AtomRefine, id=G2gd.wxID_ATOMSREFINE)
2921            self.dataFrame.Bind(wx.EVT_MENU, AtomModify, id=G2gd.wxID_ATOMSMODIFY)
2922            self.dataFrame.Bind(wx.EVT_MENU, AtomTransform, id=G2gd.wxID_ATOMSTRANSFORM)
2923            self.dataFrame.Bind(wx.EVT_MENU, OnReloadDrawAtoms, id=G2gd.wxID_RELOADDRAWATOMS)
2924            FillAtomsGrid()
2925        elif text == 'General':
2926            UpdateGeneral()
2927            self.dataFrame.SetMenuBar(self.dataFrame.BlankMenu)
2928        elif text == 'Data':
2929            self.dataFrame.SetMenuBar(self.dataFrame.DataMenu)
2930            self.dataFrame.Bind(wx.EVT_MENU, OnPwdrAdd, id=G2gd.wxID_PWDRADD)
2931            self.dataFrame.Bind(wx.EVT_MENU, OnHklfAdd, id=G2gd.wxID_HKLFADD)
2932            self.dataFrame.Bind(wx.EVT_MENU, OnDataDelete, id=G2gd.wxID_DATADELETE)
2933            UpdateDData()
2934            G2plt.PlotSizeStrainPO(self,data,Start=True)
2935        elif text == 'Draw Options':
2936            self.dataFrame.SetMenuBar(self.dataFrame.BlankMenu)
2937            UpdateDrawOptions()
2938            G2plt.PlotStructure(self,data)
2939        elif text == 'Draw Atoms':
2940            self.dataFrame.SetMenuBar(self.dataFrame.DrawAtomsMenu)
2941            self.dataFrame.Bind(wx.EVT_MENU, DrawAtomStyle, id=G2gd.wxID_DRAWATOMSTYLE)
2942            self.dataFrame.Bind(wx.EVT_MENU, DrawAtomLabel, id=G2gd.wxID_DRAWATOMLABEL)
2943            self.dataFrame.Bind(wx.EVT_MENU, DrawAtomColor, id=G2gd.wxID_DRAWATOMCOLOR)
2944            self.dataFrame.Bind(wx.EVT_MENU, ResetAtomColors, id=G2gd.wxID_DRAWATOMRESETCOLOR)
2945            self.dataFrame.Bind(wx.EVT_MENU, SetViewPoint, id=G2gd.wxID_DRAWVIEWPOINT)
2946            self.dataFrame.Bind(wx.EVT_MENU, AddSymEquiv, id=G2gd.wxID_DRAWADDEQUIV)
2947            self.dataFrame.Bind(wx.EVT_MENU, TransformSymEquiv, id=G2gd.wxID_DRAWTRANSFORM)
2948            self.dataFrame.Bind(wx.EVT_MENU, FillCoordSphere, id=G2gd.wxID_DRAWFILLCOORD)           
2949            self.dataFrame.Bind(wx.EVT_MENU, FillUnitCell, id=G2gd.wxID_DRAWFILLCELL)
2950            self.dataFrame.Bind(wx.EVT_MENU, DrawAtomsDelete, id=G2gd.wxID_DRAWDELETE)
2951            UpdateDrawAtoms()
2952            G2plt.PlotStructure(self,data)
2953        elif text == 'Pawley reflections':
2954            self.dataFrame.SetMenuBar(self.dataFrame.PawleyMenu)
2955            self.dataFrame.Bind(wx.EVT_MENU, OnPawleyLoad, id=G2gd.wxID_PAWLEYLOAD)
2956            self.dataFrame.Bind(wx.EVT_MENU, OnPawleyEstimate, id=G2gd.wxID_PAWLEYESTIMATE)
2957            self.dataFrame.Bind(wx.EVT_MENU, OnPawleyDelete, id=G2gd.wxID_PAWLEYDELETE)           
2958            FillPawleyReflectionsGrid()
2959        elif text == 'Texture':
2960            self.dataFrame.SetMenuBar(self.dataFrame.TextureMenu)
2961            self.dataFrame.Bind(wx.EVT_MENU, OnTextureRefine, id=G2gd.wxID_REFINETEXTURE)
2962            self.dataFrame.Bind(wx.EVT_MENU, OnTextureClear, id=G2gd.wxID_CLEARTEXTURE)
2963            UpdateTexture()                       
2964            G2plt.PlotTexture(self,data,Start=True)
2965        else:
2966            self.dataFrame.SetMenuBar(self.dataFrame.BlankMenu)
2967        event.Skip()
2968       
2969    General = wx.Window(self.dataDisplay)
2970    self.dataDisplay.AddPage(General,'General')
2971    SetupGeneral()
2972    GeneralData = data['General']
2973    UpdateGeneral()
2974
2975    if GeneralData['Type'] == 'Pawley':
2976        DData = wx.ScrolledWindow(self.dataDisplay)
2977        self.dataDisplay.AddPage(DData,'Data')
2978        self.PawleyRefl = G2gd.GSGrid(self.dataDisplay)
2979        self.dataDisplay.AddPage(self.PawleyRefl,'Pawley reflections')
2980        Texture = wx.ScrolledWindow(self.dataDisplay)
2981        self.dataDisplay.AddPage(Texture,'Texture')
2982    else:
2983        DData = wx.ScrolledWindow(self.dataDisplay)
2984        self.dataDisplay.AddPage(DData,'Data')
2985        Texture = wx.ScrolledWindow(self.dataDisplay)
2986        self.dataDisplay.AddPage(Texture,'Texture')
2987        Atoms = G2gd.GSGrid(self.dataDisplay)
2988        self.dataDisplay.AddPage(Atoms,'Atoms')
2989        drawOptions = wx.Window(self.dataDisplay)
2990        self.dataDisplay.AddPage(drawOptions,'Draw Options')
2991        drawAtoms = G2gd.GSGrid(self.dataDisplay)
2992        self.dataDisplay.AddPage(drawAtoms,'Draw Atoms')
2993
2994    self.dataDisplay.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, OnPageChanged)
2995    self.dataDisplay.SetSelection(oldPage)
2996   
2997           
Note: See TracBrowser for help on using the repository browser.