source: trunk/GSASIIphsGUI.py @ 242

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

refactor polygon search & rendering to eliminate internal "faces". Polygon search now in FindBonds? and Faces put at end of drawAtom array. Much faster rendering of complex polygons

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