source: trunk/GSASIIphsGUI.py @ 388

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

add SGPolax to SGData dictionary - marks arbitrary axes in polar space groups
remove plotting of #2 from instrument parameter plots

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