source: trunk/GSASIIphsGUI.py @ 409

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

make it do CW neutrons - 1st pass at it

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