source: trunk/GSASIIphsGUI.py @ 264

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

begin implementation of pdf generation - work in progress
modify image to have azimuth=0 as vertical "up"
add textctrls for max and min image intensity
fix to some lattice parameter defaults for some Laue groups

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