source: trunk/GSASIIphsGUI.py @ 428

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

begin something for plotting size & PO figures as well as mustrain
allow sorting of the indexing result by volume
fix weights for "STD" GSAS powder data files

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