source: trunk/GSASIIphsGUI.py @ 433

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

see mods to near bottom of UpdateDData (line 2609)

  • Property svn:keywords set to Date Author Revision URL Id
File size: 143.8 KB
Line 
1#GSASII - phase data display routines
2########### SVN repository information ###################
3# $Date: 2011-12-06 22:17:59 +0000 (Tue, 06 Dec 2011) $
4# $Author: vondreele $
5# $Revision: 433 $
6# $URL: trunk/GSASIIphsGUI.py $
7# $Id: GSASIIphsGUI.py 433 2011-12-06 22:17:59Z 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.Destroy()           #needed to clear away bad cellSizer, etc.
216                UpdateGeneral()
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.Destroy()           #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       
1898        shAngles = ['omega','chi','phi']
1899       
1900        def SetSHCoef():
1901            cofNames = G2lat.GenSHCoeff(SGData['SGLaue'],SamSym[textureData['Model']],textureData['Order'])
1902            newSHCoef = dict(zip(cofNames,np.zeros(len(cofNames))))
1903            SHCoeff = textureData['SH Coeff'][1]
1904            for cofName in SHCoeff:
1905                if cofName in  cofNames:
1906                    newSHCoef[cofName] = SHCoeff[cofName]
1907            return newSHCoef
1908       
1909        def OnShOrder(event):
1910            Obj = event.GetEventObject()
1911            textureData['Order'] = int(Obj.GetValue())
1912            textureData['SH Coeff'][1] = SetSHCoef()
1913            UpdateTexture()
1914            G2plt.PlotTexture(self,data,newPlot=False)
1915                       
1916        def OnShModel(event):
1917            Obj = event.GetEventObject()
1918            textureData['Model'] = Obj.GetValue()
1919            textureData['SH Coeff'][1] = SetSHCoef()
1920            UpdateTexture()
1921            G2plt.PlotTexture(self,data,newPlot=False)
1922           
1923        def OnSHRefine(event):
1924            Obj = event.GetEventObject()
1925            textureData['SH Coeff'][0] = Obj.GetValue()
1926           
1927        def OnSHShow(event):
1928            Obj = event.GetEventObject()
1929            textureData['SHShow'] = Obj.GetValue()
1930            UpdateTexture()
1931           
1932        def OnProjSel(event):
1933            Obj = event.GetEventObject()
1934            self.Projection = Obj.GetValue()
1935            G2plt.PlotTexture(self,data,newPlot=False)
1936           
1937        def OnColorSel(event):
1938            Obj = event.GetEventObject()
1939            self.ContourColor = Obj.GetValue()
1940            G2plt.PlotTexture(self,data,newPlot=False)
1941           
1942        def OnAngRef(event):
1943            Obj = event.GetEventObject()
1944            textureData[angIndx[Obj.GetId()]][0] = Obj.GetValue()
1945           
1946        def OnAngValue(event):
1947            Obj = event.GetEventObject()
1948            try:
1949                value =  float(Obj.GetValue())
1950            except ValueError:
1951                value = textureData[valIndx[Obj.GetId()]][1]
1952            Obj.SetValue('%8.2f'%(value))
1953            textureData[valIndx[Obj.GetId()]][1] = value
1954           
1955        def OnODFValue(event): 
1956            Obj = event.GetEventObject()
1957            try:
1958                value =  float(Obj.GetValue())
1959            except ValueError:
1960                value = textureData['SH Coeff'][1][ODFIndx[Obj.GetId()]]
1961            Obj.SetValue('%8.3f'%(value))
1962            textureData['SH Coeff'][1][ODFIndx[Obj.GetId()]] = value
1963            G2plt.PlotTexture(self,data,newPlot=False)
1964           
1965        def OnPfType(event):
1966            Obj = event.GetEventObject()
1967            textureData['PlotType'] = Obj.GetValue()
1968            UpdateTexture()
1969            G2plt.PlotTexture(self,data)
1970           
1971        def OnPFValue(event):
1972            Obj = event.GetEventObject()
1973            Saxis = Obj.GetValue().split()
1974            if textureData['PlotType'] in ['Pole figure','Axial pole distribution']:               
1975                try:
1976                    hkl = [int(Saxis[i]) for i in range(3)]
1977                except (ValueError,IndexError):
1978                    hkl = textureData['PFhkl']
1979                if not np.any(np.array(hkl)):       #can't be all zeros!
1980                    hkl = textureData['PFhkl']
1981                Obj.SetValue('%d %d %d'%(hkl[0],hkl[1],hkl[2]))
1982                textureData['PFhkl'] = hkl
1983            else:
1984                try:
1985                    xyz = [float(Saxis[i]) for i in range(3)]
1986                except (ValueError,IndexError):
1987                    xyz = textureData['PFxyz']
1988                if not np.any(np.array(xyz)):       #can't be all zeros!
1989                    xyz = textureData['PFxyz']
1990                Obj.SetValue('%3.1f %3.1f %3.1f'%(xyz[0],xyz[1],xyz[2]))
1991                textureData['PFxyz'] = xyz
1992            G2plt.PlotTexture(self,data)
1993               
1994        Texture.DestroyChildren()
1995        dataDisplay = wx.Panel(Texture)
1996        mainSizer = wx.BoxSizer(wx.VERTICAL)
1997        titleSizer = wx.BoxSizer(wx.HORIZONTAL)
1998        titleSizer.Add(wx.StaticText(dataDisplay,-1,'Spherical harmonics texture data for '+PhaseName+':'),0,wx.ALIGN_CENTER_VERTICAL)
1999        titleSizer.Add(wx.StaticText(dataDisplay,-1,
2000            ' Texture Index J = %7.3f'%(G2lat.textureIndex(textureData['SH Coeff'][1]))),
2001            0,wx.ALIGN_CENTER_VERTICAL)
2002        mainSizer.Add(titleSizer,0)
2003        mainSizer.Add((0,5),0)
2004        shSizer = wx.FlexGridSizer(1,6,5,5)
2005        shSizer.Add(wx.StaticText(dataDisplay,-1,'Texture model: '),0,wx.ALIGN_CENTER_VERTICAL)
2006        shModel = wx.ComboBox(dataDisplay,-1,value=textureData['Model'],choices=shModels,
2007            style=wx.CB_READONLY|wx.CB_DROPDOWN)
2008        shModel.Bind(wx.EVT_COMBOBOX,OnShModel)
2009        shSizer.Add(shModel,0,wx.ALIGN_CENTER_VERTICAL)
2010        shSizer.Add(wx.StaticText(dataDisplay,-1,'  Harmonic order: '),0,wx.ALIGN_CENTER_VERTICAL)
2011        shOrder = wx.ComboBox(dataDisplay,-1,value=str(textureData['Order']),choices=[str(2*i) for i in range(18)],
2012            style=wx.CB_READONLY|wx.CB_DROPDOWN)
2013        shOrder.Bind(wx.EVT_COMBOBOX,OnShOrder)
2014        shSizer.Add(shOrder,0,wx.ALIGN_CENTER_VERTICAL)
2015        shRef = wx.CheckBox(dataDisplay,-1,label=' Refine texture?')
2016        shRef.SetValue(textureData['SH Coeff'][0])
2017        shRef.Bind(wx.EVT_CHECKBOX, OnSHRefine)
2018        shSizer.Add(shRef,0,wx.ALIGN_CENTER_VERTICAL)
2019        shShow = wx.CheckBox(dataDisplay,-1,label=' Show coeff.?')
2020        shShow.SetValue(textureData['SHShow'])
2021        shShow.Bind(wx.EVT_CHECKBOX, OnSHShow)
2022        shSizer.Add(shShow,0,wx.ALIGN_CENTER_VERTICAL)
2023        mainSizer.Add(shSizer,0,0)
2024        mainSizer.Add((0,5),0)
2025        PTSizer = wx.FlexGridSizer(2,4,5,5)
2026        PTSizer.Add(wx.StaticText(dataDisplay,-1,' Texture plot type: '),0,wx.ALIGN_CENTER_VERTICAL)
2027        choices = ['Axial pole distribution','Pole figure','Inverse pole figure']           
2028        pfType = wx.ComboBox(dataDisplay,-1,value=str(textureData['PlotType']),choices=choices,
2029            style=wx.CB_READONLY|wx.CB_DROPDOWN)
2030        pfType.Bind(wx.EVT_COMBOBOX,OnPfType)
2031        PTSizer.Add(pfType,0,wx.ALIGN_CENTER_VERTICAL)
2032        if 'Axial' not in textureData['PlotType']:
2033            PTSizer.Add(wx.StaticText(dataDisplay,-1,' Projection type: '),0,wx.ALIGN_CENTER_VERTICAL)
2034            projSel = wx.ComboBox(dataDisplay,-1,value=self.Projection,choices=['equal area','stereographic','3D display'],
2035                style=wx.CB_READONLY|wx.CB_DROPDOWN)
2036            projSel.Bind(wx.EVT_COMBOBOX,OnProjSel)
2037            PTSizer.Add(projSel,0,wx.ALIGN_CENTER_VERTICAL)
2038        if textureData['PlotType'] in ['Pole figure','Axial pole distribution']:
2039            PTSizer.Add(wx.StaticText(dataDisplay,-1,' Pole figure HKL: '),0,wx.ALIGN_CENTER_VERTICAL)
2040            PH = textureData['PFhkl']
2041            pfVal = wx.TextCtrl(dataDisplay,-1,'%d %d %d'%(PH[0],PH[1],PH[2]),style=wx.TE_PROCESS_ENTER)
2042        else:
2043            PTSizer.Add(wx.StaticText(dataDisplay,-1,' Inverse pole figure XYZ: '),0,wx.ALIGN_CENTER_VERTICAL)
2044            PX = textureData['PFxyz']
2045            pfVal = wx.TextCtrl(dataDisplay,-1,'%3.1f %3.1f %3.1f'%(PX[0],PX[1],PX[2]),style=wx.TE_PROCESS_ENTER)
2046        pfVal.Bind(wx.EVT_TEXT_ENTER,OnPFValue)
2047        pfVal.Bind(wx.EVT_KILL_FOCUS,OnPFValue)
2048        PTSizer.Add(pfVal,0,wx.ALIGN_CENTER_VERTICAL)
2049        if 'Axial' not in textureData['PlotType']:
2050            PTSizer.Add(wx.StaticText(dataDisplay,-1,' Color scheme'),0,wx.ALIGN_CENTER_VERTICAL)
2051            choice = [m for m in mpl.cm.datad.keys() if not m.endswith("_r")]
2052            choice.sort()
2053            colorSel = wx.ComboBox(dataDisplay,-1,value=self.ContourColor,choices=choice,
2054                style=wx.CB_READONLY|wx.CB_DROPDOWN)
2055            colorSel.Bind(wx.EVT_COMBOBOX,OnColorSel)
2056            PTSizer.Add(colorSel,0,wx.ALIGN_CENTER_VERTICAL)       
2057        mainSizer.Add(PTSizer,0,wx.ALIGN_CENTER_VERTICAL)
2058        mainSizer.Add((0,5),0)
2059        if textureData['SHShow']:
2060            mainSizer.Add(wx.StaticText(dataDisplay,-1,'Spherical harmonic coefficients: '),0,wx.ALIGN_CENTER_VERTICAL)
2061            mainSizer.Add((0,5),0)
2062            ODFSizer = wx.FlexGridSizer(2,8,2,2)
2063            ODFIndx = {}
2064            ODFkeys = textureData['SH Coeff'][1].keys()
2065            ODFkeys.sort()
2066            for item in ODFkeys:
2067                ODFSizer.Add(wx.StaticText(dataDisplay,-1,item),0,wx.ALIGN_CENTER_VERTICAL)
2068                ODFval = wx.TextCtrl(dataDisplay,wx.ID_ANY,'%8.3f'%(textureData['SH Coeff'][1][item]),style=wx.TE_PROCESS_ENTER)
2069                ODFIndx[ODFval.GetId()] = item
2070                ODFval.Bind(wx.EVT_TEXT_ENTER,OnODFValue)
2071                ODFval.Bind(wx.EVT_KILL_FOCUS,OnODFValue)
2072                ODFSizer.Add(ODFval,0,wx.ALIGN_CENTER_VERTICAL)
2073            mainSizer.Add(ODFSizer,0,wx.ALIGN_CENTER_VERTICAL)
2074            mainSizer.Add((0,5),0)
2075        mainSizer.Add((0,5),0)
2076        mainSizer.Add(wx.StaticText(dataDisplay,-1,'Sample orientation angles: '),0,wx.ALIGN_CENTER_VERTICAL)
2077        mainSizer.Add((0,5),0)
2078        angSizer = wx.BoxSizer(wx.HORIZONTAL)
2079        angIndx = {}
2080        valIndx = {}
2081        for item in ['Sample omega','Sample chi','Sample phi']:
2082            angRef = wx.CheckBox(dataDisplay,-1,label=item+': ')
2083            angRef.SetValue(textureData[item][0])
2084            angIndx[angRef.GetId()] = item
2085            angRef.Bind(wx.EVT_CHECKBOX, OnAngRef)
2086            angSizer.Add(angRef,0,wx.ALIGN_CENTER_VERTICAL)
2087            angVal = wx.TextCtrl(dataDisplay,wx.ID_ANY,'%8.2f'%(textureData[item][1]),style=wx.TE_PROCESS_ENTER)
2088            valIndx[angVal.GetId()] = item
2089            angVal.Bind(wx.EVT_TEXT_ENTER,OnAngValue)
2090            angVal.Bind(wx.EVT_KILL_FOCUS,OnAngValue)
2091            angSizer.Add(angVal,0,wx.ALIGN_CENTER_VERTICAL)
2092            angSizer.Add((5,0),0)
2093        mainSizer.Add(angSizer,0,wx.ALIGN_CENTER_VERTICAL)
2094        dataDisplay.SetSizer(mainSizer,True)
2095        mainSizer.Fit(self.dataFrame)
2096        Size = mainSizer.GetMinSize()
2097        Size[0] += 40
2098        Size[1] = max(Size[1],250) + 20
2099        dataDisplay.SetSize(Size)
2100        Texture.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
2101        Size[1] = min(Size[1],450)
2102        self.dataFrame.setSizePosLeft(Size)
2103       
2104    def UpdateDData():
2105        UseList = data['Histograms']
2106        if UseList:
2107            self.dataFrame.DataMenu.Enable(G2gd.wxID_DATADELETE,True)
2108            self.Refine.Enable(True)
2109        else:
2110            self.dataFrame.DataMenu.Enable(G2gd.wxID_DATADELETE,False)
2111            self.Refine.Enable(False)           
2112        generalData = data['General']       
2113        SGData = generalData['SGData']
2114        keyList = UseList.keys()
2115        keyList.sort()
2116        Indx = {}
2117       
2118        def OnPlotSel(event):
2119            Obj = event.GetEventObject()
2120            generalData['Data plot type'] = Obj.GetStringSelection()
2121            UpdateDData()
2122            G2plt.PlotSizeStrainPO(self,data)
2123           
2124        def OnPOhkl(event):
2125            Obj = event.GetEventObject()
2126            Saxis = Obj.GetValue().split()
2127            try:
2128                hkl = [int(Saxis[i]) for i in range(3)]
2129            except (ValueError,IndexError):
2130                hkl = generalData['POhkl']
2131            if not np.any(np.array(hkl)):
2132                hkl = generalData['POhkl']
2133            generalData['POhkl'] = hkl
2134            h,k,l = hkl
2135            Obj.SetValue('%3d %3d %3d'%(h,k,l)) 
2136            G2plt.PlotSizeStrainPO(self,data)
2137       
2138        def OnShowData(event):
2139            Obj = event.GetEventObject()
2140            hist = Indx[Obj.GetId()]
2141            UseList[hist]['Show'] = Obj.GetValue()
2142            UpdateDData()
2143            G2plt.PlotSizeStrainPO(self,data)
2144           
2145        def OnCopyData(event):
2146            #how about HKLF data? This is only for PWDR data
2147            Obj = event.GetEventObject()
2148            hist = Indx[Obj.GetId()]
2149            sourceDict = UseList[hist]
2150            copyNames = ['Scale','Pref.Ori.','Size','Mustrain','HStrain','Extinction']
2151            copyDict = {}
2152            for name in copyNames: 
2153                copyDict[name] = copy.deepcopy(sourceDict[name])        #force copy
2154            keyList = ['All',]+UseList.keys()
2155            if UseList:
2156                copyList = []
2157                dlg = wx.MultiChoiceDialog(self, 
2158                    'Copy parameters to which histograms?', 'Copy parameters', 
2159                    keyList, wx.CHOICEDLG_STYLE)
2160                try:
2161                    if dlg.ShowModal() == wx.ID_OK:
2162                        result = dlg.GetSelections()
2163                        for i in result: 
2164                            copyList.append(keyList[i])
2165                        if 'All' in copyList: 
2166                            copyList = keyList[1:]
2167                        for item in copyList:
2168                            UseList[item].update(copy.deepcopy(copyDict))
2169                        UpdateDData()
2170                finally:
2171                    dlg.Destroy()
2172           
2173        def OnScaleRef(event):
2174            Obj = event.GetEventObject()
2175            UseList[Indx[Obj.GetId()]]['Scale'][1] = Obj.GetValue()
2176           
2177        def OnScaleVal(event):
2178            Obj = event.GetEventObject()
2179            try:
2180                scale = float(Obj.GetValue())
2181                if scale > 0:
2182                    UseList[Indx[Obj.GetId()]]['Scale'][0] = scale
2183            except ValueError:
2184                pass
2185            Obj.SetValue("%.4f"%(UseList[Indx[Obj.GetId()]]['Scale'][0]))          #reset in case of error
2186           
2187        def OnSizeType(event):
2188            Obj = event.GetEventObject()
2189            hist = Indx[Obj.GetId()]
2190            UseList[hist]['Size'][0] = Obj.GetValue()
2191            G2plt.PlotSizeStrainPO(self,data)
2192            UpdateDData()
2193           
2194        def OnSizeRef(event):
2195            Obj = event.GetEventObject()
2196            hist,pid = Indx[Obj.GetId()]
2197            if UseList[hist]['Size'][0] == 'ellipsoidal':
2198                UseList[hist]['Size'][5][pid] = Obj.GetValue()               
2199            else:
2200                UseList[hist]['Size'][2][pid] = Obj.GetValue()
2201           
2202        def OnSizeVal(event):
2203            print 'new val 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.01:            #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.01:            #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            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            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            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(dataDisplay,-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(dataDisplay,-1,' Plot preferred orientation for H K L: '),0,wx.ALIGN_CENTER_VERTICAL)
2394                h,k,l = generalData['POhkl']
2395                poAxis = wx.TextCtrl(dataDisplay,-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(dataDisplay,-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(dataDisplay,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(dataDisplay,-1,name),0,wx.ALIGN_CENTER_VERTICAL)
2420            sizeType = wx.ComboBox(dataDisplay,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(dataDisplay,-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(dataDisplay,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(dataDisplay,-1,' Unique axis, H K L: '),0,wx.ALIGN_CENTER_VERTICAL)
2447            h,k,l = UseList[item][parm][3]
2448            Axis = wx.TextCtrl(dataDisplay,-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(dataDisplay,-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(dataDisplay,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(dataDisplay,-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(dataDisplay,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(dataDisplay,-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(dataDisplay,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(dataDisplay,-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(dataDisplay,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(dataDisplay,-1,' Preferred orientation model '),0,wx.ALIGN_CENTER_VERTICAL)
2537            POType = wx.ComboBox(dataDisplay,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(dataDisplay,-1,' Harmonic order: '),0,wx.ALIGN_CENTER_VERTICAL)
2544                poOrder = wx.ComboBox(dataDisplay,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(dataDisplay,-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(dataDisplay,-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(dataDisplay,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(dataDisplay,-1,' Unique axis, H K L: '),0,wx.ALIGN_CENTER_VERTICAL)
2570            h,k,l =POData[3]
2571            poAxis = wx.TextCtrl(dataDisplay,-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(dataDisplay,-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(dataDisplay,-1,odf),0,wx.ALIGN_CENTER_VERTICAL)
2588                ODFval = wx.TextCtrl(dataDisplay,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(dataDisplay,-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(dataDisplay,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#1 DData must be global but still this didn't work!                                     
2610#        pageNo = self.dataDisplay.GetSelection()
2611#        if self.dataDisplay.GetPageText(pageNo) == 'Data':
2612#            self.dataDisplay.DeletePage(pageNo)
2613#            DData = wx.ScrolledWindow(self.dataDisplay)
2614#            self.dataDisplay.InsertPage(pageNo,DData,'Data')
2615#            self.dataDisplay.ChangeSelection(pageNo)
2616#2 This works but overwrites new sizer stuff on top of old stuff  both still active
2617#        if DData.GetChildren():
2618#            dataDisplay = DData.GetChildren()[0]
2619#            mainSizer = dataDisplay.GetSizer()
2620#            mainSizer.Clear()
2621#        else:
2622#            dataDisplay = wx.Panel(DData)
2623#            mainSizer = wx.BoxSizer(wx.VERTICAL)
2624
2625#        DData.DestroyChildren()        #not doing this is equiv to #2 above
2626        dataDisplay = wx.Panel(DData)
2627        mainSizer = wx.BoxSizer(wx.VERTICAL)
2628        mainSizer.Add(wx.StaticText(dataDisplay,-1,'Histogram data for '+PhaseName+':'),0,wx.ALIGN_CENTER_VERTICAL)
2629        mainSizer.Add(PlotSizer())           
2630           
2631        for item in keyList:
2632            histData = UseList[item]
2633            mainSizer.Add((5,5),0)
2634           
2635            showSizer = wx.BoxSizer(wx.HORIZONTAL)
2636            showData = wx.CheckBox(dataDisplay,-1,label=' Show '+item)
2637            showData.SetValue(UseList[item]['Show'])
2638            Indx[showData.GetId()] = item
2639            showData.Bind(wx.EVT_CHECKBOX, OnShowData)
2640            showSizer.Add(showData,0,wx.ALIGN_CENTER_VERTICAL)
2641            copyData = wx.Button(dataDisplay,-1,label=' Copy?')
2642            Indx[copyData.GetId()] = item
2643            copyData.Bind(wx.EVT_BUTTON,OnCopyData)
2644            showSizer.Add(copyData,wx.ALIGN_CENTER_VERTICAL)
2645            mainSizer.Add(showSizer,0,wx.ALIGN_CENTER_VERTICAL)
2646            mainSizer.Add((0,5),0)
2647           
2648            if UseList[item]['Show']:
2649                mainSizer.Add(ScaleSizer())
2650                mainSizer.Add((0,5),0)
2651               
2652            if item[:4] == 'PWDR' and UseList[item]['Show']:
2653                if UseList[item]['Size'][0] == 'isotropic':
2654                    isoSizer = wx.BoxSizer(wx.HORIZONTAL)
2655                    isoSizer.Add(TopSizer(' Size model: ',['isotropic','uniaxial','ellipsoidal'],
2656                        'Size',OnSizeType),0,wx.ALIGN_CENTER_VERTICAL)
2657                    isoSizer.Add(IsoSizer(u' Cryst. size(\xb5m): ','Size','%.3f',
2658                        OnSizeVal,OnSizeRef),0,wx.ALIGN_CENTER_VERTICAL)
2659                    mainSizer.Add(isoSizer)
2660                elif UseList[item]['Size'][0] == 'uniaxial':
2661                    uniSizer = wx.BoxSizer(wx.HORIZONTAL)
2662                    uniSizer.Add(TopSizer(' Size model: ',['isotropic','uniaxial','ellipsoidal'],
2663                        'Size',OnSizeType),0,wx.ALIGN_CENTER_VERTICAL)
2664                    uniSizer.Add(UniSizer('Size',OnSizeAxis),0,wx.ALIGN_CENTER_VERTICAL)
2665                    mainSizer.Add(uniSizer)
2666                    mainSizer.Add(UniDataSizer(u'size(\xb5m): ','Size','%.3f',OnSizeVal,OnSizeRef))
2667                elif UseList[item]['Size'][0] == 'ellipsoidal':
2668                    ellSizer = wx.BoxSizer(wx.HORIZONTAL)
2669                    ellSizer.Add(TopSizer(' Size model: ',['isotropic','uniaxial','ellipsoidal'],
2670                        'Size',OnSizeType),0,wx.ALIGN_CENTER_VERTICAL)
2671                    ellSizer.Add(wx.StaticText(dataDisplay,-1,u' Coefficients(\xb5m): '),0,wx.ALIGN_CENTER_VERTICAL)
2672                    mainSizer.Add(ellSizer)
2673                    mainSizer.Add(EllSizeDataSizer())
2674                mainSizer.Add((0,5),0)                   
2675               
2676                if UseList[item]['Mustrain'][0] == 'isotropic':
2677                    isoSizer = wx.BoxSizer(wx.HORIZONTAL)
2678                    isoSizer.Add(TopSizer(' Mustrain model: ',['isotropic','uniaxial','generalized',],
2679                        'Mustrain',OnStrainType),0,wx.ALIGN_CENTER_VERTICAL)
2680                    isoSizer.Add(IsoSizer(' microstrain: ','Mustrain','%.1f',
2681                        OnStrainVal,OnStrainRef),0,wx.ALIGN_CENTER_VERTICAL)                   
2682                    mainSizer.Add(isoSizer)
2683                    mainSizer.Add((0,5),0)
2684                elif UseList[item]['Mustrain'][0] == 'uniaxial':
2685                    uniSizer = wx.BoxSizer(wx.HORIZONTAL)
2686                    uniSizer.Add(TopSizer(' Mustrain model: ',['isotropic','uniaxial','generalized',],
2687                        'Mustrain',OnStrainType),0,wx.ALIGN_CENTER_VERTICAL)
2688                    uniSizer.Add(UniSizer('Mustrain',OnStrainAxis),0,wx.ALIGN_CENTER_VERTICAL)
2689                    mainSizer.Add(uniSizer)
2690                    mainSizer.Add(UniDataSizer('mustrain: ','Mustrain','%.1f',OnStrainVal,OnStrainRef))
2691                elif UseList[item]['Mustrain'][0] == 'generalized':
2692                    genSizer = wx.BoxSizer(wx.HORIZONTAL)
2693                    genSizer.Add(TopSizer(' Mustrain model: ',['isotropic','uniaxial','generalized',],
2694                        'Mustrain',OnStrainType),0,wx.ALIGN_CENTER_VERTICAL)
2695                    genSizer.Add(wx.StaticText(dataDisplay,-1,' Coefficients: '),0,wx.ALIGN_CENTER_VERTICAL)
2696                    mainSizer.Add(genSizer)
2697                    mainSizer.Add(GenStrainDataSizer())                       
2698                mainSizer.Add((0,5),0)
2699               
2700                mainSizer.Add(wx.StaticText(dataDisplay,-1,' Hydrostatic/elastic strain:'))
2701                mainSizer.Add(HstrainSizer())
2702                   
2703                #texture  'Pref. Ori.':['MD',1.0,False,[0,0,1],0,[]] last two for 'SH' are SHorder & coeff
2704                poSizer = wx.BoxSizer(wx.VERTICAL)
2705                POData = UseList[item]['Pref.Ori.']
2706                poSizer.Add(PoTopSizer(POData))
2707                if POData[0] == 'MD':
2708                    poSizer.Add(MDDataSizer(POData))
2709                else:           #'SH'
2710                    if POData[4]:       #SH order > 0
2711                        poSizer.Add(SHDataSizer(POData))
2712                mainSizer.Add(poSizer)
2713                mainSizer.Add((0,5),0)               
2714                #Extinction  'Extinction':[0.0,False]
2715                mainSizer.Add(ExtSizer())
2716                mainSizer.Add((0,5),0)
2717            elif item[:4] == 'HKLF' and UseList[item]['Show']:
2718                pass
2719        mainSizer.Add((5,5),0)
2720
2721        dataDisplay.SetSizer(mainSizer,True)
2722        mainSizer.Fit(self.dataFrame)
2723        Size = mainSizer.GetMinSize()
2724        Size[0] += 40
2725        Size[1] = max(Size[1],250) + 20
2726        dataDisplay.SetSize(Size)
2727        DData.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
2728        Size[1] = min(Size[1],450)
2729        self.dataFrame.setSizePosLeft(Size)
2730       
2731    def OnHklfAdd(event):
2732        UseList = data['Histograms']
2733        keyList = UseList.keys()
2734        TextList = []
2735        if self.PatternTree.GetCount():
2736            item, cookie = self.PatternTree.GetFirstChild(self.root)
2737            while item:
2738                name = self.PatternTree.GetItemText(item)
2739                if name not in keyList and 'HKLF' in name:
2740                    TextList.append(name)
2741                item, cookie = self.PatternTree.GetNextChild(self.root, cookie)                       
2742            dlg = wx.MultiChoiceDialog(self, 'Which new data to use?', 'Use data', TextList, wx.CHOICEDLG_STYLE)
2743            try:
2744                if dlg.ShowModal() == wx.ID_OK:
2745                    result = dlg.GetSelections()
2746                    for i in result:
2747                        histoName = TextList[i]
2748                        UseList[histoName] = {'Histogram':histoName,'Show':False,'Scale':[1.0,True],
2749                            'Extinction':['Lorentzian','Secondary Type I',{'Eg':[0.0,False]},]}                       
2750                    data['Histograms'] = UseList
2751                    UpdateDData()
2752            finally:
2753                dlg.Destroy()
2754       
2755    def OnPwdrAdd(event):
2756        generalData = data['General']
2757        SGData = generalData['SGData']
2758        UseList = data['Histograms']
2759        newList = []
2760        NShkl = len(G2spc.MustrainNames(SGData))
2761        NDij = len(G2spc.HStrainNames(SGData))
2762        keyList = UseList.keys()
2763        TextList = ['All PWDR']
2764        if self.PatternTree.GetCount():
2765            item, cookie = self.PatternTree.GetFirstChild(self.root)
2766            while item:
2767                name = self.PatternTree.GetItemText(item)
2768                if name not in keyList and 'PWDR' in name:
2769                    TextList.append(name)
2770                item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
2771            dlg = wx.MultiChoiceDialog(self, 'Which new data to use?', 'Use data', TextList, wx.CHOICEDLG_STYLE)
2772            try:
2773                if dlg.ShowModal() == wx.ID_OK:
2774                    result = dlg.GetSelections()
2775                    for i in result: newList.append(TextList[i])
2776                    if 'All PWDR' in newList:
2777                        newList = TextList[1:]
2778                    for histoName in newList:
2779                        pId = G2gd.GetPatternTreeItemId(self,self.root,histoName)
2780                        UseList[histoName] = {'Histogram':histoName,'Show':False,
2781                            'Scale':[1.0,False],'Pref.Ori.':['MD',1.0,False,[0,0,1],0,{}],
2782                            'Size':['isotropic',[4.,4.,],[False,False],[0,0,1],[4.,4.,4.,0.,0.,0.],6*[False,]],
2783                            'Mustrain':['isotropic',[1000.0,1000.0],[False,False],[0,0,1],
2784                                NShkl*[0.01,],NShkl*[False,]],
2785                            'HStrain':[NDij*[0.0,],NDij*[False,]],                         
2786                            'Extinction':[0.0,False]}
2787                        refList = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,pId,'Reflection Lists'))
2788                        refList[generalData['Name']] = []                       
2789                    data['Histograms'] = UseList
2790                    UpdateDData()
2791            finally:
2792                dlg.Destroy()
2793       
2794    def OnDataDelete(event):
2795        UseList = data['Histograms']
2796        keyList = ['All',]+UseList.keys()
2797        keyList.sort()
2798        DelList = []
2799        if UseList:
2800            DelList = []
2801            dlg = wx.MultiChoiceDialog(self, 
2802                'Which histogram to delete from this phase?', 'Delete histogram', 
2803                keyList, wx.CHOICEDLG_STYLE)
2804            try:
2805                if dlg.ShowModal() == wx.ID_OK:
2806                    result = dlg.GetSelections()
2807                    for i in result: 
2808                        DelList.append(keyList[i])
2809                    if 'All' in DelList:
2810                        DelList = keyList[1:]
2811                    for i in DelList:
2812                        del UseList[i]
2813                    UpdateDData()
2814            finally:
2815                dlg.Destroy()
2816
2817    def FillPawleyReflectionsGrid():
2818                       
2819        def KeyEditPawleyGrid(event):
2820            colList = self.PawleyRefl.GetSelectedCols()
2821            PawleyPeaks = data['Pawley ref']
2822            if event.GetKeyCode() == wx.WXK_RETURN:
2823                event.Skip(True)
2824            elif event.GetKeyCode() == wx.WXK_CONTROL:
2825                event.Skip(True)
2826            elif event.GetKeyCode() == wx.WXK_SHIFT:
2827                event.Skip(True)
2828            elif colList:
2829                self.PawleyRefl.ClearSelection()
2830                key = event.GetKeyCode()
2831                for col in colList:
2832                    if PawleyTable.GetTypeName(0,col) == wg.GRID_VALUE_BOOL:
2833                        if key == 89: #'Y'
2834                            for row in range(PawleyTable.GetNumberRows()): PawleyPeaks[row][col]=True
2835                        elif key == 78:  #'N'
2836                            for row in range(PawleyTable.GetNumberRows()): PawleyPeaks[row][col]=False
2837                        FillPawleyReflectionsGrid()
2838           
2839        if 'Pawley ref' in data:
2840            PawleyPeaks = data['Pawley ref']                       
2841            rowLabels = []
2842            for i in range(len(PawleyPeaks)): rowLabels.append(str(i))
2843            colLabels = ['h','k','l','mul','d','refine','Fsq(hkl)','sig(Fsq)']
2844            Types = 4*[wg.GRID_VALUE_LONG,]+[wg.GRID_VALUE_FLOAT+':10,4',wg.GRID_VALUE_BOOL,]+ \
2845                2*[wg.GRID_VALUE_FLOAT+':10,2',]
2846            PawleyTable = G2gd.Table(PawleyPeaks,rowLabels=rowLabels,colLabels=colLabels,types=Types)
2847            self.PawleyRefl.SetTable(PawleyTable, True)
2848            self.PawleyRefl.Bind(wx.EVT_KEY_DOWN, KeyEditPawleyGrid)                 
2849            self.PawleyRefl.SetMargins(0,0)
2850            self.PawleyRefl.AutoSizeColumns(False)
2851            self.dataFrame.setSizePosLeft([500,300])
2852                   
2853    def OnPawleyLoad(event):
2854        generalData = data['General']
2855        dmin = generalData['Pawley dmin']
2856        cell = generalData['Cell'][1:7]
2857        A = G2lat.cell2A(cell)
2858        SGData = generalData['SGData']
2859        HKLd = np.array(G2lat.GenHLaue(dmin,SGData,A))
2860        PawleyPeaks = []
2861        wx.BeginBusyCursor()
2862        try:
2863            for h,k,l,d in HKLd:
2864                ext,mul = G2spc.GenHKLf([h,k,l],SGData)[:2]
2865                if not ext:
2866                    PawleyPeaks.append([h,k,l,mul,d,False,100.0,1.0])
2867        finally:
2868            wx.EndBusyCursor()
2869        data['Pawley ref'] = PawleyPeaks
2870        FillPawleyReflectionsGrid()
2871       
2872    def OnPawleyEstimate(event):
2873        try:
2874            Refs = data['Pawley ref']
2875            Histograms = data['Histograms']
2876        except KeyError:
2877            print '**** Error - no histograms defined for this phase ****'
2878            return
2879        HistoNames = Histograms.keys()
2880        PatternId = G2gd.GetPatternTreeItemId(self,self.root,HistoNames[0])
2881        xdata = self.PatternTree.GetItemPyData(PatternId)[1]
2882        Inst = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId,'Instrument Parameters'))
2883        Inst = dict(zip(Inst[3],Inst[1]))
2884        Sample = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId,'Sample Parameters'))
2885        if 'Lam' in Inst:
2886            wave = Inst['Lam']
2887        else:
2888            wave = Inst['Lam1']
2889       
2890        posCorr = Inst['Zero']
2891        print Sample
2892        const = 9.e-2/(np.pi*Sample['Gonio. radius'])                  #shifts in microns
2893       
2894        for ref in Refs:
2895            pos = 2.0*asind(wave/(2.0*ref[4]))
2896            if 'Bragg' in Sample['Type']:
2897                pos -= const*(4.*Sample['Shift'][0]*cosd(pos/2.0)+ \
2898                    Sample['Transparency'][0]*sind(pos)*100.0)            #trans(=1/mueff) in cm
2899            else:               #Debye-Scherrer - simple but maybe not right
2900                pos -= const*(Sample['DisplaceX'][0]*cosd(pos)+Sample['DisplaceY'][0]*sind(pos))
2901            indx = np.searchsorted(xdata[0],pos)
2902            try:
2903                ref[6] = xdata[1][indx]
2904                print ref[:7],indx,pos
2905            except IndexError:
2906                pass
2907        FillPawleyReflectionsGrid()
2908                           
2909    def OnPawleyDelete(event):
2910        dlg = wx.MessageDialog(self,'Do you really want to delete Pawley reflections?','Delete', 
2911            wx.YES_NO | wx.ICON_QUESTION)
2912        try:
2913            result = dlg.ShowModal()
2914        finally:
2915            dlg.Destroy()
2916        if result == wx.ID_YES: 
2917            data['Pawley ref'] = []
2918            FillPawleyReflectionsGrid()
2919           
2920    def OnTextureClear(event):
2921        event.Skip()
2922
2923    def OnPageChanged(event):
2924        page = event.GetSelection()
2925        text = self.dataDisplay.GetPageText(page)
2926        if text == 'Atoms':
2927            self.dataFrame.SetMenuBar(self.dataFrame.AtomsMenu)
2928            self.dataFrame.Bind(wx.EVT_MENU, OnAtomAdd, id=G2gd.wxID_ATOMSEDITADD)
2929            self.dataFrame.Bind(wx.EVT_MENU, OnAtomTestAdd, id=G2gd.wxID_ATOMSTESTADD)
2930            self.dataFrame.Bind(wx.EVT_MENU, OnAtomInsert, id=G2gd.wxID_ATOMSEDITINSERT)
2931            self.dataFrame.Bind(wx.EVT_MENU, OnAtomTestInsert, id=G2gd.wxID_ATONTESTINSERT)
2932            self.dataFrame.Bind(wx.EVT_MENU, AtomDelete, id=G2gd.wxID_ATOMSEDITDELETE)
2933            self.dataFrame.Bind(wx.EVT_MENU, AtomRefine, id=G2gd.wxID_ATOMSREFINE)
2934            self.dataFrame.Bind(wx.EVT_MENU, AtomModify, id=G2gd.wxID_ATOMSMODIFY)
2935            self.dataFrame.Bind(wx.EVT_MENU, AtomTransform, id=G2gd.wxID_ATOMSTRANSFORM)
2936            self.dataFrame.Bind(wx.EVT_MENU, OnReloadDrawAtoms, id=G2gd.wxID_RELOADDRAWATOMS)
2937            FillAtomsGrid()
2938        elif text == 'General':
2939            UpdateGeneral()
2940            self.dataFrame.SetMenuBar(self.dataFrame.BlankMenu)
2941        elif text == 'Data':
2942            self.dataFrame.SetMenuBar(self.dataFrame.DataMenu)
2943            self.dataFrame.Bind(wx.EVT_MENU, OnPwdrAdd, id=G2gd.wxID_PWDRADD)
2944            self.dataFrame.Bind(wx.EVT_MENU, OnHklfAdd, id=G2gd.wxID_HKLFADD)
2945            self.dataFrame.Bind(wx.EVT_MENU, OnDataDelete, id=G2gd.wxID_DATADELETE)
2946            UpdateDData()
2947            G2plt.PlotSizeStrainPO(self,data,Start=True)
2948        elif text == 'Draw Options':
2949            self.dataFrame.SetMenuBar(self.dataFrame.BlankMenu)
2950            UpdateDrawOptions()
2951            G2plt.PlotStructure(self,data)
2952        elif text == 'Draw Atoms':
2953            self.dataFrame.SetMenuBar(self.dataFrame.DrawAtomsMenu)
2954            self.dataFrame.Bind(wx.EVT_MENU, DrawAtomStyle, id=G2gd.wxID_DRAWATOMSTYLE)
2955            self.dataFrame.Bind(wx.EVT_MENU, DrawAtomLabel, id=G2gd.wxID_DRAWATOMLABEL)
2956            self.dataFrame.Bind(wx.EVT_MENU, DrawAtomColor, id=G2gd.wxID_DRAWATOMCOLOR)
2957            self.dataFrame.Bind(wx.EVT_MENU, ResetAtomColors, id=G2gd.wxID_DRAWATOMRESETCOLOR)
2958            self.dataFrame.Bind(wx.EVT_MENU, SetViewPoint, id=G2gd.wxID_DRAWVIEWPOINT)
2959            self.dataFrame.Bind(wx.EVT_MENU, AddSymEquiv, id=G2gd.wxID_DRAWADDEQUIV)
2960            self.dataFrame.Bind(wx.EVT_MENU, TransformSymEquiv, id=G2gd.wxID_DRAWTRANSFORM)
2961            self.dataFrame.Bind(wx.EVT_MENU, FillCoordSphere, id=G2gd.wxID_DRAWFILLCOORD)           
2962            self.dataFrame.Bind(wx.EVT_MENU, FillUnitCell, id=G2gd.wxID_DRAWFILLCELL)
2963            self.dataFrame.Bind(wx.EVT_MENU, DrawAtomsDelete, id=G2gd.wxID_DRAWDELETE)
2964            UpdateDrawAtoms()
2965            G2plt.PlotStructure(self,data)
2966        elif text == 'Pawley reflections':
2967            self.dataFrame.SetMenuBar(self.dataFrame.PawleyMenu)
2968            self.dataFrame.Bind(wx.EVT_MENU, OnPawleyLoad, id=G2gd.wxID_PAWLEYLOAD)
2969            self.dataFrame.Bind(wx.EVT_MENU, OnPawleyEstimate, id=G2gd.wxID_PAWLEYESTIMATE)
2970            self.dataFrame.Bind(wx.EVT_MENU, OnPawleyDelete, id=G2gd.wxID_PAWLEYDELETE)           
2971            FillPawleyReflectionsGrid()
2972        elif text == 'Texture':
2973            self.dataFrame.SetMenuBar(self.dataFrame.TextureMenu)
2974            self.dataFrame.Bind(wx.EVT_MENU, OnTextureClear, id=G2gd.wxID_CLEARTEXTURE)
2975            UpdateTexture()                       
2976            G2plt.PlotTexture(self,data,Start=True)
2977        else:
2978            self.dataFrame.SetMenuBar(self.dataFrame.BlankMenu)
2979        event.Skip()
2980       
2981    General = wx.Window(self.dataDisplay)
2982    self.dataDisplay.AddPage(General,'General')
2983    SetupGeneral()
2984    GeneralData = data['General']
2985    UpdateGeneral()
2986
2987    if GeneralData['Type'] == 'Pawley':
2988        DData = wx.ScrolledWindow(self.dataDisplay)
2989        self.dataDisplay.AddPage(DData,'Data')
2990        self.PawleyRefl = G2gd.GSGrid(self.dataDisplay)
2991        self.dataDisplay.AddPage(self.PawleyRefl,'Pawley reflections')
2992    else:
2993        DData = wx.ScrolledWindow(self.dataDisplay)
2994        self.dataDisplay.AddPage(DData,'Data')
2995        Texture = wx.ScrolledWindow(self.dataDisplay)
2996        self.dataDisplay.AddPage(Texture,'Texture')
2997        Atoms = G2gd.GSGrid(self.dataDisplay)
2998        self.dataDisplay.AddPage(Atoms,'Atoms')
2999        drawOptions = wx.Window(self.dataDisplay)
3000        self.dataDisplay.AddPage(drawOptions,'Draw Options')
3001        drawAtoms = G2gd.GSGrid(self.dataDisplay)
3002        self.dataDisplay.AddPage(drawAtoms,'Draw Atoms')
3003
3004    self.dataDisplay.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, OnPageChanged)
3005    self.dataDisplay.SetSelection(oldPage)
3006   
3007           
Note: See TracBrowser for help on using the repository browser.