source: trunk/GSASIIphsGUI.py @ 303

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

Allow reading of xye (Topas style) files
Begin implementation of spherical harmonics texture
Refactor indexing; replace cell refinement from peak positions

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