source: trunk/GSASIIphsGUI.py @ 430

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

NB: There are a few stray print statements in this version
Some work on help stuff in GSASIIgrid.py
change default sum for constraints to 1.0
get data plots to include size & preferred orientation
modify plot toolbar - eliminate subplot button & add a Help button; doesn't do anything except recognize what plot it is from
Edited gsasII.html with Word - probably messed up all the bookmarks - but added a lot of text

  • Property svn:keywords set to Date Author Revision URL Id
File size: 142.7 KB
Line 
1#GSASII - phase data display routines
2########### SVN repository information ###################
3# $Date: 2011-11-30 23:02:08 +0000 (Wed, 30 Nov 2011) $
4# $Author: vondreele $
5# $Revision: 430 $
6# $URL: trunk/GSASIIphsGUI.py $
7# $Id: GSASIIphsGUI.py 430 2011-11-30 23:02:08Z 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        PTSizer.Add(wx.StaticText(dataDisplay,-1,' Projection type: '),0,wx.ALIGN_CENTER_VERTICAL)
2033        projSel = wx.ComboBox(dataDisplay,-1,value=self.Projection,choices=['equal area','stereographic'],
2034            style=wx.CB_READONLY|wx.CB_DROPDOWN)
2035        projSel.Bind(wx.EVT_COMBOBOX,OnProjSel)
2036        PTSizer.Add(projSel,0,wx.ALIGN_CENTER_VERTICAL)
2037        if textureData['PlotType'] in ['Pole figure','Axial pole distribution']:
2038            PTSizer.Add(wx.StaticText(dataDisplay,-1,' Pole figure HKL: '),0,wx.ALIGN_CENTER_VERTICAL)
2039            PH = textureData['PFhkl']
2040            pfVal = wx.TextCtrl(dataDisplay,-1,'%d %d %d'%(PH[0],PH[1],PH[2]),style=wx.TE_PROCESS_ENTER)
2041        else:
2042            PTSizer.Add(wx.StaticText(dataDisplay,-1,' Inverse pole figure XYZ: '),0,wx.ALIGN_CENTER_VERTICAL)
2043            PX = textureData['PFxyz']
2044            pfVal = wx.TextCtrl(dataDisplay,-1,'%3.1f %3.1f %3.1f'%(PX[0],PX[1],PX[2]),style=wx.TE_PROCESS_ENTER)
2045        pfVal.Bind(wx.EVT_TEXT_ENTER,OnPFValue)
2046        pfVal.Bind(wx.EVT_KILL_FOCUS,OnPFValue)
2047        PTSizer.Add(pfVal,0,wx.ALIGN_CENTER_VERTICAL)
2048        PTSizer.Add(wx.StaticText(dataDisplay,-1,' Color scheme'),0,wx.ALIGN_CENTER_VERTICAL)
2049        choice = [m for m in mpl.cm.datad.keys() if not m.endswith("_r")]
2050        choice.sort()
2051        colorSel = wx.ComboBox(dataDisplay,-1,value=self.ContourColor,choices=choice,
2052            style=wx.CB_READONLY|wx.CB_DROPDOWN)
2053        colorSel.Bind(wx.EVT_COMBOBOX,OnColorSel)
2054        PTSizer.Add(colorSel,0,wx.ALIGN_CENTER_VERTICAL)       
2055        mainSizer.Add(PTSizer,0,wx.ALIGN_CENTER_VERTICAL)
2056        mainSizer.Add((0,5),0)
2057        if textureData['SHShow']:
2058            mainSizer.Add(wx.StaticText(dataDisplay,-1,'Spherical harmonic coefficients: '),0,wx.ALIGN_CENTER_VERTICAL)
2059            mainSizer.Add((0,5),0)
2060            ODFSizer = wx.FlexGridSizer(2,8,2,2)
2061            ODFIndx = {}
2062            ODFkeys = textureData['SH Coeff'][1].keys()
2063            ODFkeys.sort()
2064            for item in ODFkeys:
2065                ODFSizer.Add(wx.StaticText(dataDisplay,-1,item),0,wx.ALIGN_CENTER_VERTICAL)
2066                ODFval = wx.TextCtrl(dataDisplay,wx.ID_ANY,'%8.3f'%(textureData['SH Coeff'][1][item]),style=wx.TE_PROCESS_ENTER)
2067                ODFIndx[ODFval.GetId()] = item
2068                ODFval.Bind(wx.EVT_TEXT_ENTER,OnODFValue)
2069                ODFval.Bind(wx.EVT_KILL_FOCUS,OnODFValue)
2070                ODFSizer.Add(ODFval,0,wx.ALIGN_CENTER_VERTICAL)
2071            mainSizer.Add(ODFSizer,0,wx.ALIGN_CENTER_VERTICAL)
2072            mainSizer.Add((0,5),0)
2073        mainSizer.Add((0,5),0)
2074        mainSizer.Add(wx.StaticText(dataDisplay,-1,'Sample orientation angles: '),0,wx.ALIGN_CENTER_VERTICAL)
2075        mainSizer.Add((0,5),0)
2076        angSizer = wx.BoxSizer(wx.HORIZONTAL)
2077        angIndx = {}
2078        valIndx = {}
2079        for item in ['Sample omega','Sample chi','Sample phi']:
2080            angRef = wx.CheckBox(dataDisplay,-1,label=item+': ')
2081            angRef.SetValue(textureData[item][0])
2082            angIndx[angRef.GetId()] = item
2083            angRef.Bind(wx.EVT_CHECKBOX, OnAngRef)
2084            angSizer.Add(angRef,0,wx.ALIGN_CENTER_VERTICAL)
2085            angVal = wx.TextCtrl(dataDisplay,wx.ID_ANY,'%8.2f'%(textureData[item][1]),style=wx.TE_PROCESS_ENTER)
2086            valIndx[angVal.GetId()] = item
2087            angVal.Bind(wx.EVT_TEXT_ENTER,OnAngValue)
2088            angVal.Bind(wx.EVT_KILL_FOCUS,OnAngValue)
2089            angSizer.Add(angVal,0,wx.ALIGN_CENTER_VERTICAL)
2090            angSizer.Add((5,0),0)
2091        mainSizer.Add(angSizer,0,wx.ALIGN_CENTER_VERTICAL)
2092        dataDisplay.SetSizer(mainSizer,True)
2093        mainSizer.Fit(self.dataFrame)
2094        Size = mainSizer.GetMinSize()
2095        Size[0] += 40
2096        Size[1] = max(Size[1],250) + 20
2097        dataDisplay.SetSize(Size)
2098        Texture.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
2099        Size[1] = min(Size[1],450)
2100        self.dataFrame.setSizePosLeft(Size)
2101       
2102    def UpdateDData():
2103        UseList = data['Histograms']
2104        if UseList:
2105            self.dataFrame.DataMenu.Enable(G2gd.wxID_DATADELETE,True)
2106            self.Refine.Enable(True)
2107        else:
2108            self.dataFrame.DataMenu.Enable(G2gd.wxID_DATADELETE,False)
2109            self.Refine.Enable(False)           
2110        generalData = data['General']       
2111        SGData = generalData['SGData']
2112        keyList = UseList.keys()
2113        keyList.sort()
2114        Indx = {}
2115       
2116        def OnPlotSel(event):
2117            Obj = event.GetEventObject()
2118            generalData['Data plot type'] = Obj.GetStringSelection()
2119            UpdateDData()
2120            G2plt.PlotSizeStrainPO(self,data)
2121           
2122        def OnPOhkl(event):
2123            Obj = event.GetEventObject()
2124            Saxis = Obj.GetValue().split()
2125            try:
2126                hkl = [int(Saxis[i]) for i in range(3)]
2127            except (ValueError,IndexError):
2128                hkl = generalData['POhkl']
2129            if not np.any(np.array(hkl)):
2130                hkl = generalData['POhkl']
2131            generalData['POhkl'] = hkl
2132            h,k,l = hkl
2133            Obj.SetValue('%3d %3d %3d'%(h,k,l)) 
2134            G2plt.PlotSizeStrainPO(self,data)
2135       
2136        def OnShowData(event):
2137            Obj = event.GetEventObject()
2138            hist = Indx[Obj.GetId()]
2139            UseList[hist]['Show'] = Obj.GetValue()
2140            UpdateDData()
2141            G2plt.PlotSizeStrainPO(self,data)
2142           
2143        def OnCopyData(event):
2144            #how about HKLF data? This is only for PWDR data
2145            Obj = event.GetEventObject()
2146            hist = Indx[Obj.GetId()]
2147            sourceDict = UseList[hist]
2148            copyNames = ['Scale','Pref.Ori.','Size','Mustrain','HStrain','Extinction']
2149            copyDict = {}
2150            for name in copyNames: 
2151                copyDict[name] = copy.deepcopy(sourceDict[name])        #force copy
2152            keyList = ['All',]+UseList.keys()
2153            if UseList:
2154                copyList = []
2155                dlg = wx.MultiChoiceDialog(self, 
2156                    'Copy parameters to which histograms?', 'Copy parameters', 
2157                    keyList, wx.CHOICEDLG_STYLE)
2158                try:
2159                    if dlg.ShowModal() == wx.ID_OK:
2160                        result = dlg.GetSelections()
2161                        for i in result: 
2162                            copyList.append(keyList[i])
2163                        if 'All' in copyList: 
2164                            copyList = keyList[1:]
2165                        for item in copyList:
2166                            UseList[item].update(copy.deepcopy(copyDict))
2167                        UpdateDData()
2168                finally:
2169                    dlg.Destroy()
2170           
2171        def OnScaleRef(event):
2172            Obj = event.GetEventObject()
2173            UseList[Indx[Obj.GetId()]]['Scale'][1] = Obj.GetValue()
2174           
2175        def OnScaleVal(event):
2176            Obj = event.GetEventObject()
2177            try:
2178                scale = float(Obj.GetValue())
2179                if scale > 0:
2180                    UseList[Indx[Obj.GetId()]]['Scale'][0] = scale
2181            except ValueError:
2182                pass
2183            Obj.SetValue("%.4f"%(UseList[Indx[Obj.GetId()]]['Scale'][0]))          #reset in case of error
2184           
2185        def OnSizeType(event):
2186            Obj = event.GetEventObject()
2187            hist = Indx[Obj.GetId()]
2188            UseList[hist]['Size'][0] = Obj.GetValue()
2189            UpdateDData()
2190           
2191        def OnSizeRef(event):
2192            Obj = event.GetEventObject()
2193            hist,pid = Indx[Obj.GetId()]
2194            if UseList[hist]['Size'][0] == 'ellipsoidal':
2195                UseList[hist]['Size'][5][pid] = Obj.GetValue()               
2196            else:
2197                UseList[hist]['Size'][2][pid] = Obj.GetValue()
2198           
2199        def OnSizeVal(event):
2200            Obj = event.GetEventObject()
2201            hist,pid = Indx[Obj.GetId()]
2202            if UseList[hist]['Size'][0] == 'ellipsoidal':
2203                try:
2204                    size = float(Obj.GetValue())
2205                    if pid < 3 and size <= 0.01:            #10A lower limit!
2206                        raise ValueError                   
2207                except ValueError:
2208                    pass
2209            else:
2210                try:
2211                    size = float(Obj.GetValue())
2212                    if size <= 0.01:            #10A lower limit!
2213                        raise ValueError
2214                    UseList[hist]['Size'][1][pid] = size
2215                except ValueError:
2216                    pass
2217            Obj.SetValue("%.3f"%(UseList[hist]['Size'][1][pid]))          #reset in case of error
2218           
2219        def OnSizeAxis(event):           
2220            Obj = event.GetEventObject()
2221            hist = Indx[Obj.GetId()]
2222            Saxis = Obj.GetValue().split()
2223            try:
2224                hkl = [int(Saxis[i]) for i in range(3)]
2225            except (ValueError,IndexError):
2226                hkl = UseList[hist]['Size'][3]
2227            if not np.any(np.array(hkl)):
2228                hkl = UseList[hist]['Size'][3]
2229            UseList[hist]['Size'][3] = hkl
2230            h,k,l = hkl
2231            Obj.SetValue('%3d %3d %3d'%(h,k,l)) 
2232                       
2233        def OnStrainType(event):
2234            Obj = event.GetEventObject()
2235            hist = Indx[Obj.GetId()]
2236            UseList[hist]['Mustrain'][0] = Obj.GetValue()
2237            UpdateDData()
2238            G2plt.PlotSizeStrainPO(self,data)
2239           
2240        def OnStrainRef(event):
2241            Obj = event.GetEventObject()
2242            hist,pid = Indx[Obj.GetId()]
2243            if UseList[hist]['Mustrain'][0] == 'generalized':
2244                UseList[hist]['Mustrain'][5][pid] = Obj.GetValue()
2245            else:
2246                UseList[hist]['Mustrain'][2][pid] = Obj.GetValue()
2247           
2248        def OnStrainVal(event):
2249            Snames = G2spc.MustrainNames(SGData)
2250            Obj = event.GetEventObject()
2251            hist,pid = Indx[Obj.GetId()]
2252            try:
2253                strain = float(Obj.GetValue())
2254                if UseList[hist]['Mustrain'][0] == 'generalized':
2255                    if '4' in Snames[pid] and strain < 0:
2256                        raise ValueError
2257                    UseList[hist]['Mustrain'][4][pid] = strain
2258                else:
2259                    if strain <= 0:
2260                        raise ValueError
2261                    UseList[hist]['Mustrain'][1][pid] = strain
2262            except ValueError:
2263                pass
2264            if UseList[hist]['Mustrain'][0] == 'generalized':
2265                Obj.SetValue("%.3f"%(UseList[hist]['Mustrain'][4][pid]))          #reset in case of error
2266            else:
2267                Obj.SetValue("%.1f"%(UseList[hist]['Mustrain'][1][pid]))          #reset in case of error
2268            G2plt.PlotSizeStrainPO(self,data)
2269           
2270        def OnStrainAxis(event):
2271            Obj = event.GetEventObject()
2272            hist = Indx[Obj.GetId()]
2273            Saxis = Obj.GetValue().split()
2274            try:
2275                hkl = [int(Saxis[i]) for i in range(3)]
2276            except (ValueError,IndexError):
2277                hkl = UseList[hist]['Mustrain'][3]
2278            if not np.any(np.array(hkl)):
2279                hkl = UseList[hist]['Mustrain'][3]
2280            UseList[hist]['Mustrain'][3] = hkl
2281            h,k,l = hkl
2282            Obj.SetValue('%3d %3d %3d'%(h,k,l)) 
2283            G2plt.PlotSizeStrainPO(self,data)
2284           
2285        def OnHstrainRef(event):
2286            Obj = event.GetEventObject()
2287            hist,pid = Indx[Obj.GetId()]
2288            UseList[hist]['HStrain'][1][pid] = Obj.GetValue()
2289           
2290        def OnHstrainVal(event):
2291            Snames = G2spc.HStrainNames(SGData)
2292            Obj = event.GetEventObject()
2293            hist,pid = Indx[Obj.GetId()]
2294            try:
2295                strain = float(Obj.GetValue())
2296                UseList[hist]['HStrain'][0][pid] = strain
2297            except ValueError:
2298                pass
2299            Obj.SetValue("%.5f"%(UseList[hist]['HStrain'][0][pid]))          #reset in case of error
2300
2301        def OnPOType(event):
2302            Obj = event.GetEventObject()
2303            hist = Indx[Obj.GetId()]
2304            if 'March' in Obj.GetValue():
2305                UseList[hist]['Pref.Ori.'][0] = 'MD'
2306            else:
2307                UseList[hist]['Pref.Ori.'][0] = 'SH'
2308            UpdateDData()           
2309
2310        def OnPORef(event):
2311            Obj = event.GetEventObject()
2312            hist = Indx[Obj.GetId()]
2313            UseList[hist]['Pref.Ori.'][2] = Obj.GetValue()
2314           
2315        def OnPOVal(event):
2316            Obj = event.GetEventObject()
2317            hist = Indx[Obj.GetId()]
2318            try:
2319                mdVal = float(Obj.GetValue())
2320                if mdVal > 0:
2321                    UseList[hist]['Pref.Ori.'][1] = mdVal
2322            except ValueError:
2323                pass
2324            Obj.SetValue("%.3f"%(UseList[hist]['Pref.Ori.'][1]))          #reset in case of error
2325           
2326        def OnPOAxis(event):
2327            Obj = event.GetEventObject()
2328            hist = Indx[Obj.GetId()]
2329            Saxis = Obj.GetValue().split()
2330            try:
2331                hkl = [int(Saxis[i]) for i in range(3)]
2332            except (ValueError,IndexError):
2333                hkl = UseList[hist]['Pref.Ori.'][3]
2334            if not np.any(np.array(hkl)):
2335                hkl = UseList[hist]['Pref.Ori.'][3]
2336            UseList[hist]['Pref.Ori.'][3] = hkl
2337            h,k,l = hkl
2338            Obj.SetValue('%3d %3d %3d'%(h,k,l)) 
2339           
2340        def OnPOOrder(event):
2341            Obj = event.GetEventObject()
2342            hist = Indx[Obj.GetId()]
2343            Order = int(Obj.GetValue())
2344            UseList[hist]['Pref.Ori.'][4] = Order
2345            UseList[hist]['Pref.Ori.'][5] = SetPOCoef(Order,hist)
2346            UpdateDData()
2347
2348        def SetPOCoef(Order,hist):
2349            cofNames = G2lat.GenSHCoeff(SGData['SGLaue'],'0',Order,False)     #cylindrical & no M
2350            newPOCoef = dict(zip(cofNames,np.zeros(len(cofNames))))
2351            POCoeff = UseList[hist]['Pref.Ori.'][5]
2352            for cofName in POCoeff:
2353                if cofName in  cofNames:
2354                    newPOCoef[cofName] = POCoeff[cofName]
2355            return newPOCoef
2356       
2357        def OnExtRef(event):
2358            Obj = event.GetEventObject()
2359            UseList[Indx[Obj.GetId()]]['Extinction'][1] = Obj.GetValue()
2360           
2361        def OnExtVal(event):
2362            Obj = event.GetEventObject()
2363            try:
2364                ext = float(Obj.GetValue())
2365                if ext >= 0:
2366                    UseList[Indx[Obj.GetId()]]['Extinction'][0] = ext
2367            except ValueError:
2368                pass
2369            Obj.SetValue("%.2f"%(UseList[Indx[Obj.GetId()]]['Extinction'][0]))          #reset in case of error
2370           
2371        def checkAxis(axis):
2372            if not np.any(np.array(axis)):
2373                return False
2374            return axis
2375           
2376        def PlotSizer():
2377            plotSizer = wx.BoxSizer(wx.VERTICAL)
2378            choice = ['Mustrain','Size','Preferred orientation']
2379            plotSel = wx.RadioBox(dataDisplay,-1,'Select plot type:',choices=choice,
2380                majorDimension=3,style=wx.RA_SPECIFY_COLS)
2381            plotSel.SetStringSelection(generalData['Data plot type'])
2382            plotSel.Bind(wx.EVT_RADIOBOX,OnPlotSel)   
2383            plotSizer.Add(plotSel)
2384            if generalData['Data plot type'] == 'Preferred orientation':
2385                POhklSizer = wx.BoxSizer(wx.HORIZONTAL)
2386                POhklSizer.Add(wx.StaticText(dataDisplay,-1,' Plot preferred orientation for H K L: '),0,wx.ALIGN_CENTER_VERTICAL)
2387                h,k,l = generalData['POhkl']
2388                poAxis = wx.TextCtrl(dataDisplay,-1,'%3d %3d %3d'%(h,k,l),style=wx.TE_PROCESS_ENTER)
2389                poAxis.Bind(wx.EVT_TEXT_ENTER,OnPOhkl)
2390                poAxis.Bind(wx.EVT_KILL_FOCUS,OnPOhkl)
2391                POhklSizer.Add(poAxis,0,wx.ALIGN_CENTER_VERTICAL)
2392                plotSizer.Add(POhklSizer)           
2393            return plotSizer
2394           
2395        def ScaleSizer():
2396            scaleSizer = wx.BoxSizer(wx.HORIZONTAL)
2397            scaleRef = wx.CheckBox(dataDisplay,-1,label=' Phase fraction: ')
2398            scaleRef.SetValue(UseList[item]['Scale'][1])
2399            Indx[scaleRef.GetId()] = item
2400            scaleRef.Bind(wx.EVT_CHECKBOX, OnScaleRef)
2401            scaleSizer.Add(scaleRef,0,wx.ALIGN_CENTER_VERTICAL)
2402            scaleVal = wx.TextCtrl(dataDisplay,wx.ID_ANY,
2403                '%.4f'%(UseList[item]['Scale'][0]),style=wx.TE_PROCESS_ENTER)
2404            Indx[scaleVal.GetId()] = item
2405            scaleVal.Bind(wx.EVT_TEXT_ENTER,OnScaleVal)
2406            scaleVal.Bind(wx.EVT_KILL_FOCUS,OnScaleVal)
2407            scaleSizer.Add(scaleVal,0,wx.ALIGN_CENTER_VERTICAL)
2408            return scaleSizer
2409           
2410        def TopSizer(name,choices,parm,OnType):
2411            topSizer = wx.BoxSizer(wx.HORIZONTAL)
2412            topSizer.Add(wx.StaticText(dataDisplay,-1,name),0,wx.ALIGN_CENTER_VERTICAL)
2413            sizeType = wx.ComboBox(dataDisplay,wx.ID_ANY,value=UseList[item][parm][0],choices=choices,
2414                style=wx.CB_READONLY|wx.CB_DROPDOWN)
2415            sizeType.Bind(wx.EVT_COMBOBOX, OnType)
2416            Indx[sizeType.GetId()] = item
2417            topSizer.Add(sizeType)
2418            topSizer.Add((5,0),0)
2419            return topSizer
2420           
2421        def IsoSizer(name,parm,fmt,OnVal,OnRef):
2422            isoSizer = wx.BoxSizer(wx.HORIZONTAL)
2423            sizeRef = wx.CheckBox(dataDisplay,-1,label=name)
2424            sizeRef.thisown = False
2425            sizeRef.SetValue(UseList[item][parm][2][0])
2426            Indx[sizeRef.GetId()] = [item,0]
2427            sizeRef.Bind(wx.EVT_CHECKBOX, OnRef)
2428            isoSizer.Add(sizeRef,0,wx.ALIGN_CENTER_VERTICAL)
2429            sizeVal = wx.TextCtrl(dataDisplay,wx.ID_ANY,
2430                fmt%(UseList[item][parm][1][0]),style=wx.TE_PROCESS_ENTER)
2431            Indx[sizeVal.GetId()] = [item,0]
2432            sizeVal.Bind(wx.EVT_TEXT_ENTER,OnVal)
2433            sizeVal.Bind(wx.EVT_KILL_FOCUS,OnVal)
2434            isoSizer.Add(sizeVal,0,wx.ALIGN_CENTER_VERTICAL)
2435            return isoSizer
2436           
2437        def UniSizer(parm,OnAxis):
2438            uniSizer = wx.BoxSizer(wx.HORIZONTAL)
2439            uniSizer.Add(wx.StaticText(dataDisplay,-1,' Unique axis, H K L: '),0,wx.ALIGN_CENTER_VERTICAL)
2440            h,k,l = UseList[item][parm][3]
2441            Axis = wx.TextCtrl(dataDisplay,-1,'%3d %3d %3d'%(h,k,l),style=wx.TE_PROCESS_ENTER)
2442            Indx[Axis.GetId()] = item
2443            Axis.Bind(wx.EVT_TEXT_ENTER,OnAxis)
2444            Axis.Bind(wx.EVT_KILL_FOCUS,OnAxis)
2445            uniSizer.Add(Axis,0,wx.ALIGN_CENTER_VERTICAL)
2446            return uniSizer
2447           
2448        def UniDataSizer(parmName,parm,fmt,OnVal,OnRef):
2449            dataSizer = wx.BoxSizer(wx.HORIZONTAL)
2450            parms = zip([' Equatorial '+parmName,' Axial '+parmName],
2451                UseList[item][parm][1],UseList[item][parm][2],range(2))
2452            for Pa,val,ref,id in parms:
2453                sizeRef = wx.CheckBox(dataDisplay,-1,label=Pa)
2454                sizeRef.thisown = False
2455                sizeRef.SetValue(ref)
2456                Indx[sizeRef.GetId()] = [item,id]
2457                sizeRef.Bind(wx.EVT_CHECKBOX, OnRef)
2458                dataSizer.Add(sizeRef,0,wx.ALIGN_CENTER_VERTICAL)
2459                sizeVal = wx.TextCtrl(dataDisplay,wx.ID_ANY,fmt%(val),style=wx.TE_PROCESS_ENTER)
2460                Indx[sizeVal.GetId()] = [item,id]
2461                sizeVal.Bind(wx.EVT_TEXT_ENTER,OnVal)
2462                sizeVal.Bind(wx.EVT_KILL_FOCUS,OnVal)
2463                dataSizer.Add(sizeVal,0,wx.ALIGN_CENTER_VERTICAL)
2464                dataSizer.Add((5,0),0)
2465            return dataSizer
2466           
2467        def EllSizeDataSizer():
2468            parms = zip(['S11','S22','S33','S12','S13','S23'],UseList[item]['Size'][4],
2469                UseList[item]['Size'][5],range(6))
2470            dataSizer = wx.FlexGridSizer(1,6,5,5)
2471            for Pa,val,ref,id in parms:
2472                sizeRef = wx.CheckBox(dataDisplay,-1,label=Pa)
2473                sizeRef.thisown = False
2474                sizeRef.SetValue(ref)
2475                Indx[sizeRef.GetId()] = [item,id]
2476                sizeRef.Bind(wx.EVT_CHECKBOX, OnSizeRef)
2477                dataSizer.Add(sizeRef,0,wx.ALIGN_CENTER_VERTICAL)
2478                sizeVal = wx.TextCtrl(dataDisplay,wx.ID_ANY,'%.3f'%(val),style=wx.TE_PROCESS_ENTER)
2479                Indx[sizeVal.GetId()] = [item,id]
2480                sizeVal.Bind(wx.EVT_TEXT_ENTER,OnSizeVal)
2481                sizeVal.Bind(wx.EVT_KILL_FOCUS,OnSizeVal)
2482                dataSizer.Add(sizeVal,0,wx.ALIGN_CENTER_VERTICAL)
2483            return dataSizer
2484           
2485        def GenStrainDataSizer():
2486            Snames = G2spc.MustrainNames(SGData)
2487            numb = len(Snames)
2488            if len(UseList[item]['Mustrain'][4]) < numb:
2489                UseList[item]['Mustrain'][4] = numb*[0.0,]
2490                UseList[item]['Mustrain'][5] = numb*[False,]
2491            parms = zip(Snames,UseList[item]['Mustrain'][4],UseList[item]['Mustrain'][5],range(numb))
2492            dataSizer = wx.FlexGridSizer(1,6,5,5)
2493            for Pa,val,ref,id in parms:
2494                strainRef = wx.CheckBox(dataDisplay,-1,label=Pa)
2495                strainRef.thisown = False
2496                strainRef.SetValue(ref)
2497                Indx[strainRef.GetId()] = [item,id]
2498                strainRef.Bind(wx.EVT_CHECKBOX, OnStrainRef)
2499                dataSizer.Add(strainRef,0,wx.ALIGN_CENTER_VERTICAL)
2500                strainVal = wx.TextCtrl(dataDisplay,wx.ID_ANY,'%.5f'%(val),style=wx.TE_PROCESS_ENTER)
2501                Indx[strainVal.GetId()] = [item,id]
2502                strainVal.Bind(wx.EVT_TEXT_ENTER,OnStrainVal)
2503                strainVal.Bind(wx.EVT_KILL_FOCUS,OnStrainVal)
2504                dataSizer.Add(strainVal,0,wx.ALIGN_CENTER_VERTICAL)
2505            return dataSizer
2506           
2507        def HstrainSizer():
2508            hstrainSizer = wx.FlexGridSizer(1,6,5,5)
2509            Hsnames = G2spc.HStrainNames(SGData)
2510            parms = zip(Hsnames,UseList[item]['HStrain'][0],UseList[item]['HStrain'][1],range(len(Hsnames)))
2511            for Pa,val,ref,id in parms:
2512                hstrainRef = wx.CheckBox(dataDisplay,-1,label=Pa)
2513                hstrainRef.thisown = False
2514                hstrainRef.SetValue(ref)
2515                Indx[hstrainRef.GetId()] = [item,id]
2516                hstrainRef.Bind(wx.EVT_CHECKBOX, OnHstrainRef)
2517                hstrainSizer.Add(hstrainRef,0,wx.ALIGN_CENTER_VERTICAL)
2518                hstrainVal = wx.TextCtrl(dataDisplay,wx.ID_ANY,'%.5f'%(val),style=wx.TE_PROCESS_ENTER)
2519                Indx[hstrainVal.GetId()] = [item,id]
2520                hstrainVal.Bind(wx.EVT_TEXT_ENTER,OnHstrainVal)
2521                hstrainVal.Bind(wx.EVT_KILL_FOCUS,OnHstrainVal)
2522                hstrainSizer.Add(hstrainVal,0,wx.ALIGN_CENTER_VERTICAL)
2523            return hstrainSizer
2524           
2525        def PoTopSizer(POData):
2526            poSizer = wx.FlexGridSizer(1,6,5,5)
2527            choice = ['March-Dollase','Spherical harmonics']
2528            POtype = choice[['MD','SH'].index(POData[0])]
2529            poSizer.Add(wx.StaticText(dataDisplay,-1,' Preferred orientation model '),0,wx.ALIGN_CENTER_VERTICAL)
2530            POType = wx.ComboBox(dataDisplay,wx.ID_ANY,value=POtype,choices=choice,
2531                style=wx.CB_READONLY|wx.CB_DROPDOWN)
2532            Indx[POType.GetId()] = item
2533            POType.Bind(wx.EVT_COMBOBOX, OnPOType)
2534            poSizer.Add(POType)
2535            if POData[0] == 'SH':
2536                poSizer.Add(wx.StaticText(dataDisplay,-1,' Harmonic order: '),0,wx.ALIGN_CENTER_VERTICAL)
2537                poOrder = wx.ComboBox(dataDisplay,wx.ID_ANY,value=str(POData[4]),choices=[str(2*i) for i in range(18)],
2538                    style=wx.CB_READONLY|wx.CB_DROPDOWN)
2539                Indx[poOrder.GetId()] = item
2540                poOrder.Bind(wx.EVT_COMBOBOX,OnPOOrder)
2541                poSizer.Add(poOrder,0,wx.ALIGN_CENTER_VERTICAL)
2542                poRef = wx.CheckBox(dataDisplay,-1,label=' Refine? ')
2543                poRef.SetValue(POData[2])
2544                Indx[poRef.GetId()] = item
2545                poRef.Bind(wx.EVT_CHECKBOX,OnPORef)
2546                poSizer.Add(poRef,0,wx.ALIGN_CENTER_VERTICAL)
2547            return poSizer
2548           
2549        def MDDataSizer(POData):
2550            poSizer = wx.BoxSizer(wx.HORIZONTAL)
2551            poRef = wx.CheckBox(dataDisplay,-1,label=' March-Dollase ratio: ')
2552            poRef.SetValue(POData[2])
2553            Indx[poRef.GetId()] = item
2554            poRef.Bind(wx.EVT_CHECKBOX,OnPORef)
2555            poSizer.Add(poRef,0,wx.ALIGN_CENTER_VERTICAL)
2556            poVal = wx.TextCtrl(dataDisplay,wx.ID_ANY,
2557                '%.3f'%(POData[1]),style=wx.TE_PROCESS_ENTER)
2558            Indx[poVal.GetId()] = item
2559            poVal.Bind(wx.EVT_TEXT_ENTER,OnPOVal)
2560            poVal.Bind(wx.EVT_KILL_FOCUS,OnPOVal)
2561            poSizer.Add(poVal,0,wx.ALIGN_CENTER_VERTICAL)
2562            poSizer.Add(wx.StaticText(dataDisplay,-1,' Unique axis, H K L: '),0,wx.ALIGN_CENTER_VERTICAL)
2563            h,k,l =POData[3]
2564            poAxis = wx.TextCtrl(dataDisplay,-1,'%3d %3d %3d'%(h,k,l),style=wx.TE_PROCESS_ENTER)
2565            Indx[poAxis.GetId()] = item
2566            poAxis.Bind(wx.EVT_TEXT_ENTER,OnPOAxis)
2567            poAxis.Bind(wx.EVT_KILL_FOCUS,OnPOAxis)
2568            poSizer.Add(poAxis,0,wx.ALIGN_CENTER_VERTICAL)
2569            return poSizer
2570           
2571        def SHDataSizer(POData):
2572            textJ = G2lat.textureIndex(POData[5])
2573            mainSizer.Add(wx.StaticText(dataDisplay,-1,' Spherical harmonic coefficients: '+'Texture index: %.3f'%(textJ)),0,wx.ALIGN_CENTER_VERTICAL)
2574            mainSizer.Add((0,5),0)
2575            ODFSizer = wx.FlexGridSizer(2,8,2,2)
2576            ODFIndx = {}
2577            ODFkeys = POData[5].keys()
2578            ODFkeys.sort()
2579            for odf in ODFkeys:
2580                ODFSizer.Add(wx.StaticText(dataDisplay,-1,odf),0,wx.ALIGN_CENTER_VERTICAL)
2581                ODFval = wx.TextCtrl(dataDisplay,wx.ID_ANY,'%8.3f'%(POData[5][odf]),style=wx.TE_PROCESS_ENTER)
2582                ODFIndx[ODFval.GetId()] = odf
2583#                ODFval.Bind(wx.EVT_TEXT_ENTER,OnODFValue)
2584#                ODFval.Bind(wx.EVT_KILL_FOCUS,OnODFValue)
2585                ODFSizer.Add(ODFval,0,wx.ALIGN_CENTER_VERTICAL)
2586            return ODFSizer
2587           
2588        def ExtSizer():           
2589            extSizer = wx.BoxSizer(wx.HORIZONTAL)
2590            extRef = wx.CheckBox(dataDisplay,-1,label=' Extinction: ')
2591            extRef.SetValue(UseList[item]['Extinction'][1])
2592            Indx[extRef.GetId()] = item
2593            extRef.Bind(wx.EVT_CHECKBOX, OnExtRef)
2594            extSizer.Add(extRef,0,wx.ALIGN_CENTER_VERTICAL)
2595            extVal = wx.TextCtrl(dataDisplay,wx.ID_ANY,
2596                '%.2f'%(UseList[item]['Extinction'][0]),style=wx.TE_PROCESS_ENTER)
2597            Indx[extVal.GetId()] = item
2598            extVal.Bind(wx.EVT_TEXT_ENTER,OnExtVal)
2599            extVal.Bind(wx.EVT_KILL_FOCUS,OnExtVal)
2600            extSizer.Add(extVal,0,wx.ALIGN_CENTER_VERTICAL)
2601            return extSizer
2602                                   
2603        DData.DestroyChildren()
2604        dataDisplay = wx.Panel(DData)
2605        mainSizer = wx.BoxSizer(wx.VERTICAL)
2606        mainSizer.Add(wx.StaticText(dataDisplay,-1,'Histogram data for '+PhaseName+':'),0,wx.ALIGN_CENTER_VERTICAL)
2607        mainSizer.Add(PlotSizer())           
2608           
2609        for item in keyList:
2610            histData = UseList[item]
2611            mainSizer.Add((5,5),0)
2612           
2613            showSizer = wx.BoxSizer(wx.HORIZONTAL)
2614            showData = wx.CheckBox(dataDisplay,-1,label=' Show '+item)
2615            showData.SetValue(UseList[item]['Show'])
2616            Indx[showData.GetId()] = item
2617            showData.Bind(wx.EVT_CHECKBOX, OnShowData)
2618            showSizer.Add(showData,0,wx.ALIGN_CENTER_VERTICAL)
2619            copyData = wx.Button(dataDisplay,-1,label=' Copy?')
2620            Indx[copyData.GetId()] = item
2621            copyData.Bind(wx.EVT_BUTTON,OnCopyData)
2622            showSizer.Add(copyData,wx.ALIGN_CENTER_VERTICAL)
2623            mainSizer.Add(showSizer,0,wx.ALIGN_CENTER_VERTICAL)
2624            mainSizer.Add((0,5),0)
2625           
2626            if UseList[item]['Show']:
2627                mainSizer.Add(ScaleSizer())
2628                mainSizer.Add((0,5),0)
2629               
2630            if item[:4] == 'PWDR' and UseList[item]['Show']:
2631                sizeSizer = wx.BoxSizer(wx.VERTICAL)
2632                if UseList[item]['Size'][0] == 'isotropic':
2633                    isoSizer = wx.BoxSizer(wx.HORIZONTAL)
2634                    isoSizer.Add(TopSizer(' Size model: ',['isotropic','uniaxial','ellipsoidal'],
2635                        'Size',OnSizeType),0,wx.ALIGN_CENTER_VERTICAL)
2636                    isoSizer.Add(IsoSizer(u' Cryst. size(\xb5m): ','Size','%.3f',
2637                        OnSizeVal,OnSizeRef),0,wx.ALIGN_CENTER_VERTICAL)
2638                    sizeSizer.Add(isoSizer)
2639                elif UseList[item]['Size'][0] == 'uniaxial':
2640                    uniSizer = wx.BoxSizer(wx.HORIZONTAL)
2641                    uniSizer.Add(TopSizer(' Size model: ',['isotropic','uniaxial','ellipsoidal'],
2642                        'Size',OnSizeType),0,wx.ALIGN_CENTER_VERTICAL)
2643                    uniSizer.Add(UniSizer('Size',OnSizeAxis),0,wx.ALIGN_CENTER_VERTICAL)
2644                    sizeSizer.Add(uniSizer)
2645                    sizeSizer.Add(UniDataSizer(u'size(\xb5m): ','Size','%.3f',OnSizeVal,OnSizeRef))
2646                elif UseList[item]['Size'][0] == 'ellipsoidal':
2647                    ellSizer = wx.BoxSizer(wx.HORIZONTAL)
2648                    ellSizer.Add(TopSizer(' Size model: ',['isotropic','uniaxial','ellipsoidal'],
2649                        'Size',OnSizeType),0,wx.ALIGN_CENTER_VERTICAL)
2650                    ellSizer.Add(wx.StaticText(dataDisplay,-1,u' Coefficients(\xb5m): '),0,wx.ALIGN_CENTER_VERTICAL)
2651                    sizeSizer.Add(ellSizer)
2652                    sizeSizer.Add(EllSizeDataSizer())
2653                mainSizer.Add(sizeSizer)
2654                mainSizer.Add((0,5),0)                   
2655               
2656                strainSizer = wx.BoxSizer(wx.VERTICAL)
2657                if UseList[item]['Mustrain'][0] == 'isotropic':
2658                    isoSizer = wx.BoxSizer(wx.HORIZONTAL)
2659                    isoSizer.Add(TopSizer(' Mustrain model: ',['isotropic','uniaxial','generalized',],
2660                        'Mustrain',OnStrainType),0,wx.ALIGN_CENTER_VERTICAL)
2661                    isoSizer.Add(IsoSizer(' microstrain: ','Mustrain','%.1f',
2662                        OnStrainVal,OnStrainRef),0,wx.ALIGN_CENTER_VERTICAL)                   
2663                    strainSizer.Add(isoSizer)
2664                elif UseList[item]['Mustrain'][0] == 'uniaxial':
2665                    uniSizer = wx.BoxSizer(wx.HORIZONTAL)
2666                    uniSizer.Add(TopSizer(' Mustrain model: ',['isotropic','uniaxial','generalized',],
2667                        'Mustrain',OnStrainType),0,wx.ALIGN_CENTER_VERTICAL)
2668                    uniSizer.Add(UniSizer('Mustrain',OnStrainAxis),0,wx.ALIGN_CENTER_VERTICAL)
2669                    sizeSizer.Add(uniSizer)
2670                    sizeSizer.Add(UniDataSizer('mustrain: ','Mustrain','%.1f',OnStrainVal,OnStrainRef))
2671                elif UseList[item]['Mustrain'][0] == 'generalized':
2672                    genSizer = wx.BoxSizer(wx.HORIZONTAL)
2673                    genSizer.Add(TopSizer(' Mustrain model: ',['isotropic','uniaxial','generalized',],
2674                        'Mustrain',OnStrainType),0,wx.ALIGN_CENTER_VERTICAL)
2675                    genSizer.Add(wx.StaticText(dataDisplay,-1,' Coefficients: '),0,wx.ALIGN_CENTER_VERTICAL)
2676                    strainSizer.Add(genSizer)
2677                    strainSizer.Add(GenStrainDataSizer())                       
2678                mainSizer.Add(strainSizer)
2679                mainSizer.Add((0,5),0)
2680               
2681                mainSizer.Add(wx.StaticText(dataDisplay,-1,' Hydrostatic/elastic strain:'))
2682                mainSizer.Add(HstrainSizer())
2683                   
2684                #texture  'Pref. Ori.':['MD',1.0,False,[0,0,1],0,[]] last two for 'SH' are SHorder & coeff
2685                poSizer = wx.BoxSizer(wx.VERTICAL)
2686                POData = UseList[item]['Pref.Ori.']
2687                poSizer.Add(PoTopSizer(POData))
2688                if POData[0] == 'MD':
2689                    poSizer.Add(MDDataSizer(POData))
2690                else:           #'SH'
2691                    if POData[4]:       #SH order > 0
2692                        poSizer.Add(SHDataSizer(POData))
2693                mainSizer.Add(poSizer)
2694                mainSizer.Add((0,5),0)               
2695                #Extinction  'Extinction':[0.0,False]
2696                mainSizer.Add(ExtSizer())
2697                mainSizer.Add((0,5),0)
2698            elif item[:4] == 'HKLF' and UseList[item]['Show']:
2699                pass
2700        mainSizer.Add((5,5),0)
2701
2702        dataDisplay.SetSizer(mainSizer,True)
2703        mainSizer.FitInside(self.dataFrame)
2704        Size = mainSizer.GetMinSize()
2705        Size[0] += 40
2706        Size[1] = max(Size[1],250) + 20
2707        dataDisplay.SetSize(Size)
2708        DData.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
2709        Size[1] = min(Size[1],450)
2710        self.dataFrame.setSizePosLeft(Size)
2711       
2712    def OnHklfAdd(event):
2713        UseList = data['Histograms']
2714        keyList = UseList.keys()
2715        TextList = []
2716        if self.PatternTree.GetCount():
2717            item, cookie = self.PatternTree.GetFirstChild(self.root)
2718            while item:
2719                name = self.PatternTree.GetItemText(item)
2720                if name not in keyList and 'HKLF' in name:
2721                    TextList.append(name)
2722                item, cookie = self.PatternTree.GetNextChild(self.root, cookie)                       
2723            dlg = wx.MultiChoiceDialog(self, 'Which new data to use?', 'Use data', TextList, wx.CHOICEDLG_STYLE)
2724            try:
2725                if dlg.ShowModal() == wx.ID_OK:
2726                    result = dlg.GetSelections()
2727                    for i in result:
2728                        histoName = TextList[i]
2729                        UseList[histoName] = {'Histogram':histoName,'Show':False,'Scale':[1.0,True],
2730                            'Extinction':['Lorentzian','Secondary Type I',{'Eg':[0.0,False]},]}                       
2731                    data['Histograms'] = UseList
2732                    UpdateDData()
2733            finally:
2734                dlg.Destroy()
2735       
2736    def OnPwdrAdd(event):
2737        generalData = data['General']
2738        SGData = generalData['SGData']
2739        UseList = data['Histograms']
2740        newList = []
2741        NShkl = len(G2spc.MustrainNames(SGData))
2742        NDij = len(G2spc.HStrainNames(SGData))
2743        keyList = UseList.keys()
2744        TextList = ['All PWDR']
2745        if self.PatternTree.GetCount():
2746            item, cookie = self.PatternTree.GetFirstChild(self.root)
2747            while item:
2748                name = self.PatternTree.GetItemText(item)
2749                if name not in keyList and 'PWDR' in name:
2750                    TextList.append(name)
2751                item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
2752            dlg = wx.MultiChoiceDialog(self, 'Which new data to use?', 'Use data', TextList, wx.CHOICEDLG_STYLE)
2753            try:
2754                if dlg.ShowModal() == wx.ID_OK:
2755                    result = dlg.GetSelections()
2756                    for i in result: newList.append(TextList[i])
2757                    if 'All PWDR' in newList:
2758                        newList = TextList[1:]
2759                    for histoName in newList:
2760                        pId = G2gd.GetPatternTreeItemId(self,self.root,histoName)
2761                        UseList[histoName] = {'Histogram':histoName,'Show':False,
2762                            'Scale':[1.0,False],'Pref.Ori.':['MD',1.0,False,[0,0,1],0,{}],
2763                            'Size':['isotropic',[4.,4.,],[False,False],[0,0,1],6*[0.0,],6*[False,]],
2764                            'Mustrain':['isotropic',[1000.0,1000.0],[False,False],[0,0,1],
2765                                NShkl*[0.01,],NShkl*[False,]],
2766                            'HStrain':[NDij*[0.0,],NDij*[False,]],                         
2767                            'Extinction':[0.0,False]}
2768                        refList = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,pId,'Reflection Lists'))
2769                        refList[generalData['Name']] = []                       
2770                    data['Histograms'] = UseList
2771                    UpdateDData()
2772            finally:
2773                dlg.Destroy()
2774       
2775    def OnDataDelete(event):
2776        UseList = data['Histograms']
2777        keyList = ['All',]+UseList.keys()
2778        keyList.sort()
2779        DelList = []
2780        if UseList:
2781            DelList = []
2782            dlg = wx.MultiChoiceDialog(self, 
2783                'Which histogram to delete from this phase?', 'Delete histogram', 
2784                keyList, wx.CHOICEDLG_STYLE)
2785            try:
2786                if dlg.ShowModal() == wx.ID_OK:
2787                    result = dlg.GetSelections()
2788                    for i in result: 
2789                        DelList.append(keyList[i])
2790                    if 'All' in DelList:
2791                        DelList = keyList[1:]
2792                    for i in DelList:
2793                        del UseList[i]
2794                    UpdateDData()
2795            finally:
2796                dlg.Destroy()
2797
2798    def FillPawleyReflectionsGrid():
2799                       
2800        def KeyEditPawleyGrid(event):
2801            colList = self.PawleyRefl.GetSelectedCols()
2802            PawleyPeaks = data['Pawley ref']
2803            if event.GetKeyCode() == wx.WXK_RETURN:
2804                event.Skip(True)
2805            elif event.GetKeyCode() == wx.WXK_CONTROL:
2806                event.Skip(True)
2807            elif event.GetKeyCode() == wx.WXK_SHIFT:
2808                event.Skip(True)
2809            elif colList:
2810                self.PawleyRefl.ClearSelection()
2811                key = event.GetKeyCode()
2812                for col in colList:
2813                    if PawleyTable.GetTypeName(0,col) == wg.GRID_VALUE_BOOL:
2814                        if key == 89: #'Y'
2815                            for row in range(PawleyTable.GetNumberRows()): PawleyPeaks[row][col]=True
2816                        elif key == 78:  #'N'
2817                            for row in range(PawleyTable.GetNumberRows()): PawleyPeaks[row][col]=False
2818                        FillPawleyReflectionsGrid()
2819           
2820        if 'Pawley ref' in data:
2821            PawleyPeaks = data['Pawley ref']                       
2822            rowLabels = []
2823            for i in range(len(PawleyPeaks)): rowLabels.append(str(i))
2824            colLabels = ['h','k','l','mul','d','refine','Fsq(hkl)','sig(Fsq)']
2825            Types = 4*[wg.GRID_VALUE_LONG,]+[wg.GRID_VALUE_FLOAT+':10,4',wg.GRID_VALUE_BOOL,]+ \
2826                2*[wg.GRID_VALUE_FLOAT+':10,2',]
2827            PawleyTable = G2gd.Table(PawleyPeaks,rowLabels=rowLabels,colLabels=colLabels,types=Types)
2828            self.PawleyRefl.SetTable(PawleyTable, True)
2829            self.PawleyRefl.Bind(wx.EVT_KEY_DOWN, KeyEditPawleyGrid)                 
2830            self.PawleyRefl.SetMargins(0,0)
2831            self.PawleyRefl.AutoSizeColumns(False)
2832            self.dataFrame.setSizePosLeft([500,300])
2833                   
2834    def OnPawleyLoad(event):
2835        generalData = data['General']
2836        dmin = generalData['Pawley dmin']
2837        cell = generalData['Cell'][1:7]
2838        A = G2lat.cell2A(cell)
2839        SGData = generalData['SGData']
2840        HKLd = np.array(G2lat.GenHLaue(dmin,SGData,A))
2841        PawleyPeaks = []
2842        wx.BeginBusyCursor()
2843        try:
2844            for h,k,l,d in HKLd:
2845                ext,mul = G2spc.GenHKLf([h,k,l],SGData)[:2]
2846                if not ext:
2847                    PawleyPeaks.append([h,k,l,mul,d,False,100.0,1.0])
2848        finally:
2849            wx.EndBusyCursor()
2850        data['Pawley ref'] = PawleyPeaks
2851        FillPawleyReflectionsGrid()
2852       
2853    def OnPawleyEstimate(event):
2854        try:
2855            Refs = data['Pawley ref']
2856            Histograms = data['Histograms']
2857        except KeyError:
2858            print '**** Error - no histograms defined for this phase ****'
2859            return
2860        HistoNames = Histograms.keys()
2861        PatternId = G2gd.GetPatternTreeItemId(self,self.root,HistoNames[0])
2862        xdata = self.PatternTree.GetItemPyData(PatternId)[1]
2863        Inst = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId,'Instrument Parameters'))
2864        Inst = dict(zip(Inst[3],Inst[1]))
2865        Sample = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId,'Sample Parameters'))
2866        if 'Lam' in Inst:
2867            wave = Inst['Lam']
2868        else:
2869            wave = Inst['Lam1']
2870       
2871        posCorr = Inst['Zero']
2872        print Sample
2873        const = 9.e-2/(np.pi*Sample['Gonio. radius'])                  #shifts in microns
2874       
2875        for ref in Refs:
2876            pos = 2.0*asind(wave/(2.0*ref[4]))
2877            if 'Bragg' in Sample['Type']:
2878                pos -= const*(4.*Sample['Shift'][0]*cosd(pos/2.0)+ \
2879                    Sample['Transparency'][0]*sind(pos)*100.0)            #trans(=1/mueff) in cm
2880            else:               #Debye-Scherrer - simple but maybe not right
2881                pos -= const*(Sample['DisplaceX'][0]*cosd(pos)+Sample['DisplaceY'][0]*sind(pos))
2882            indx = np.searchsorted(xdata[0],pos)
2883            try:
2884                ref[6] = xdata[1][indx]
2885                print ref[:7],indx,pos
2886            except IndexError:
2887                pass
2888        FillPawleyReflectionsGrid()
2889                           
2890    def OnPawleyDelete(event):
2891        dlg = wx.MessageDialog(self,'Do you really want to delete Pawley reflections?','Delete', 
2892            wx.YES_NO | wx.ICON_QUESTION)
2893        try:
2894            result = dlg.ShowModal()
2895        finally:
2896            dlg.Destroy()
2897        if result == wx.ID_YES: 
2898            data['Pawley ref'] = []
2899            FillPawleyReflectionsGrid()
2900           
2901    def OnTextureClear(event):
2902        event.Skip()
2903
2904    def OnPageChanged(event):
2905        page = event.GetSelection()
2906        text = self.dataDisplay.GetPageText(page)
2907        if text == 'Atoms':
2908            self.dataFrame.SetMenuBar(self.dataFrame.AtomsMenu)
2909            self.dataFrame.Bind(wx.EVT_MENU, OnAtomAdd, id=G2gd.wxID_ATOMSEDITADD)
2910            self.dataFrame.Bind(wx.EVT_MENU, OnAtomTestAdd, id=G2gd.wxID_ATOMSTESTADD)
2911            self.dataFrame.Bind(wx.EVT_MENU, OnAtomInsert, id=G2gd.wxID_ATOMSEDITINSERT)
2912            self.dataFrame.Bind(wx.EVT_MENU, OnAtomTestInsert, id=G2gd.wxID_ATONTESTINSERT)
2913            self.dataFrame.Bind(wx.EVT_MENU, AtomDelete, id=G2gd.wxID_ATOMSEDITDELETE)
2914            self.dataFrame.Bind(wx.EVT_MENU, AtomRefine, id=G2gd.wxID_ATOMSREFINE)
2915            self.dataFrame.Bind(wx.EVT_MENU, AtomModify, id=G2gd.wxID_ATOMSMODIFY)
2916            self.dataFrame.Bind(wx.EVT_MENU, AtomTransform, id=G2gd.wxID_ATOMSTRANSFORM)
2917            self.dataFrame.Bind(wx.EVT_MENU, OnReloadDrawAtoms, id=G2gd.wxID_RELOADDRAWATOMS)
2918            FillAtomsGrid()
2919        elif text == 'General':
2920            UpdateGeneral()
2921            self.dataFrame.SetMenuBar(self.dataFrame.BlankMenu)
2922        elif text == 'Data':
2923            self.dataFrame.SetMenuBar(self.dataFrame.DataMenu)
2924            self.dataFrame.Bind(wx.EVT_MENU, OnPwdrAdd, id=G2gd.wxID_PWDRADD)
2925            self.dataFrame.Bind(wx.EVT_MENU, OnHklfAdd, id=G2gd.wxID_HKLFADD)
2926            self.dataFrame.Bind(wx.EVT_MENU, OnDataDelete, id=G2gd.wxID_DATADELETE)
2927            UpdateDData()
2928            G2plt.PlotSizeStrainPO(self,data,Start=True)
2929        elif text == 'Draw Options':
2930            self.dataFrame.SetMenuBar(self.dataFrame.BlankMenu)
2931            UpdateDrawOptions()
2932            G2plt.PlotStructure(self,data)
2933        elif text == 'Draw Atoms':
2934            self.dataFrame.SetMenuBar(self.dataFrame.DrawAtomsMenu)
2935            self.dataFrame.Bind(wx.EVT_MENU, DrawAtomStyle, id=G2gd.wxID_DRAWATOMSTYLE)
2936            self.dataFrame.Bind(wx.EVT_MENU, DrawAtomLabel, id=G2gd.wxID_DRAWATOMLABEL)
2937            self.dataFrame.Bind(wx.EVT_MENU, DrawAtomColor, id=G2gd.wxID_DRAWATOMCOLOR)
2938            self.dataFrame.Bind(wx.EVT_MENU, ResetAtomColors, id=G2gd.wxID_DRAWATOMRESETCOLOR)
2939            self.dataFrame.Bind(wx.EVT_MENU, SetViewPoint, id=G2gd.wxID_DRAWVIEWPOINT)
2940            self.dataFrame.Bind(wx.EVT_MENU, AddSymEquiv, id=G2gd.wxID_DRAWADDEQUIV)
2941            self.dataFrame.Bind(wx.EVT_MENU, TransformSymEquiv, id=G2gd.wxID_DRAWTRANSFORM)
2942            self.dataFrame.Bind(wx.EVT_MENU, FillCoordSphere, id=G2gd.wxID_DRAWFILLCOORD)           
2943            self.dataFrame.Bind(wx.EVT_MENU, FillUnitCell, id=G2gd.wxID_DRAWFILLCELL)
2944            self.dataFrame.Bind(wx.EVT_MENU, DrawAtomsDelete, id=G2gd.wxID_DRAWDELETE)
2945            UpdateDrawAtoms()
2946            G2plt.PlotStructure(self,data)
2947        elif text == 'Pawley reflections':
2948            self.dataFrame.SetMenuBar(self.dataFrame.PawleyMenu)
2949            self.dataFrame.Bind(wx.EVT_MENU, OnPawleyLoad, id=G2gd.wxID_PAWLEYLOAD)
2950            self.dataFrame.Bind(wx.EVT_MENU, OnPawleyEstimate, id=G2gd.wxID_PAWLEYESTIMATE)
2951            self.dataFrame.Bind(wx.EVT_MENU, OnPawleyDelete, id=G2gd.wxID_PAWLEYDELETE)           
2952            FillPawleyReflectionsGrid()
2953        elif text == 'Texture':
2954            self.dataFrame.SetMenuBar(self.dataFrame.TextureMenu)
2955            self.dataFrame.Bind(wx.EVT_MENU, OnTextureClear, id=G2gd.wxID_CLEARTEXTURE)
2956            UpdateTexture()                       
2957            G2plt.PlotTexture(self,data,Start=True)
2958        else:
2959            self.dataFrame.SetMenuBar(self.dataFrame.BlankMenu)
2960        event.Skip()
2961       
2962    General = wx.Window(self.dataDisplay)
2963    self.dataDisplay.AddPage(General,'General')
2964    SetupGeneral()
2965    GeneralData = data['General']
2966    UpdateGeneral()
2967
2968    if GeneralData['Type'] == 'Pawley':
2969        DData = wx.ScrolledWindow(self.dataDisplay)
2970        self.dataDisplay.AddPage(DData,'Data')
2971        self.PawleyRefl = G2gd.GSGrid(self.dataDisplay)
2972        self.dataDisplay.AddPage(self.PawleyRefl,'Pawley reflections')
2973    else:
2974        DData = wx.ScrolledWindow(self.dataDisplay)
2975        self.dataDisplay.AddPage(DData,'Data')
2976        Texture = wx.ScrolledWindow(self.dataDisplay)
2977        self.dataDisplay.AddPage(Texture,'Texture')
2978        Atoms = G2gd.GSGrid(self.dataDisplay)
2979        self.dataDisplay.AddPage(Atoms,'Atoms')
2980        drawOptions = wx.Window(self.dataDisplay)
2981        self.dataDisplay.AddPage(drawOptions,'Draw Options')
2982        drawAtoms = G2gd.GSGrid(self.dataDisplay)
2983        self.dataDisplay.AddPage(drawAtoms,'Draw Atoms')
2984
2985    self.dataDisplay.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, OnPageChanged)
2986    self.dataDisplay.SetSelection(oldPage)
2987   
2988           
Note: See TracBrowser for help on using the repository browser.