source: trunk/GSASIIphsGUI.py @ 404

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

put error bars on seq refinement plots
add cubic elastic strain coeff
make sure results are saved from seq refinements

  • Property svn:keywords set to Date Author Revision URL Id
File size: 139.1 KB
Line 
1#GSASII - phase data display routines
2########### SVN repository information ###################
3# $Date: 2011-10-28 18:59:03 +0000 (Fri, 28 Oct 2011) $
4# $Author: vondreele $
5# $Revision: 404 $
6# $URL: trunk/GSASIIphsGUI.py $
7# $Id: GSASIIphsGUI.py 404 2011-10-28 18:59:03Z 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            Saxis = Obj.GetValue().split()
1943            if textureData['PlotType'] in ['Pole figure','Axial pole distribution']:               
1944                try:
1945                    hkl = [int(Saxis[i]) for i in range(3)]
1946                except (ValueError,IndexError):
1947                    hkl = textureData['PFhkl']
1948                if not np.any(np.array(hkl)):       #can't be all zeros!
1949                    hkl = textureData['PFhkl']
1950                Obj.SetValue('%d %d %d'%(hkl[0],hkl[1],hkl[2]))
1951                textureData['PFhkl'] = hkl
1952            else:
1953                try:
1954                    hkl = [float(Saxis[i]) for i in range(3)]
1955                except (ValueError,IndexError):
1956                    hkl = textureData['PFxyz']
1957                if not np.any(np.array(hkl)):       #can't be all zeros!
1958                    hkl = textureData['PFxyz']
1959                Obj.SetValue('%3.1f %3.1f %3.1f'%(xyz[0],xyz[1],xyz[2]))
1960                textureData['PFxyz'] = xyz
1961            G2plt.PlotTexture(self,data)
1962               
1963        Texture.DestroyChildren()
1964        dataDisplay = wx.Panel(Texture)
1965        mainSizer = wx.BoxSizer(wx.VERTICAL)
1966        titleSizer = wx.BoxSizer(wx.HORIZONTAL)
1967        titleSizer.Add(wx.StaticText(dataDisplay,-1,'Spherical harmonics texture data for '+PhaseName+':'),0,wx.ALIGN_CENTER_VERTICAL)
1968        titleSizer.Add(wx.StaticText(dataDisplay,-1,
1969            ' Texture Index J = %7.3f'%(G2lat.textureIndex(textureData['SH Coeff'][1]))),
1970            0,wx.ALIGN_CENTER_VERTICAL)
1971        mainSizer.Add(titleSizer,0)
1972        mainSizer.Add((0,5),0)
1973        shSizer = wx.FlexGridSizer(1,6,5,5)
1974        shSizer.Add(wx.StaticText(dataDisplay,-1,'Texture model: '),0,wx.ALIGN_CENTER_VERTICAL)
1975        shModel = wx.ComboBox(dataDisplay,-1,value=textureData['Model'],choices=shModels,
1976            style=wx.CB_READONLY|wx.CB_DROPDOWN)
1977        shModel.Bind(wx.EVT_COMBOBOX,OnShModel)
1978        shSizer.Add(shModel,0,wx.ALIGN_CENTER_VERTICAL)
1979        shSizer.Add(wx.StaticText(dataDisplay,-1,'  Harmonic order: '),0,wx.ALIGN_CENTER_VERTICAL)
1980        shOrder = wx.ComboBox(dataDisplay,-1,value=str(textureData['Order']),choices=[str(2*i) for i in range(18)],
1981            style=wx.CB_READONLY|wx.CB_DROPDOWN)
1982        shOrder.Bind(wx.EVT_COMBOBOX,OnShOrder)
1983        shSizer.Add(shOrder,0,wx.ALIGN_CENTER_VERTICAL)
1984        shRef = wx.CheckBox(dataDisplay,-1,label=' Refine texture?')
1985        shRef.SetValue(textureData['SH Coeff'][0])
1986        shRef.Bind(wx.EVT_CHECKBOX, OnSHRefine)
1987        shSizer.Add(shRef,0,wx.ALIGN_CENTER_VERTICAL)
1988        shShow = wx.CheckBox(dataDisplay,-1,label=' Show coeff.?')
1989        shShow.SetValue(textureData['SHShow'])
1990        shShow.Bind(wx.EVT_CHECKBOX, OnSHShow)
1991        shSizer.Add(shShow,0,wx.ALIGN_CENTER_VERTICAL)
1992        mainSizer.Add(shSizer,0,0)
1993        mainSizer.Add((0,5),0)
1994        PTSizer = wx.FlexGridSizer(2,4,5,5)
1995        PTSizer.Add(wx.StaticText(dataDisplay,-1,' Texture plot type: '),0,wx.ALIGN_CENTER_VERTICAL)
1996        choices = ['Axial pole distribution','Pole figure','Inverse pole figure']           
1997        pfType = wx.ComboBox(dataDisplay,-1,value=str(textureData['PlotType']),choices=choices,
1998            style=wx.CB_READONLY|wx.CB_DROPDOWN)
1999        pfType.Bind(wx.EVT_COMBOBOX,OnPfType)
2000        PTSizer.Add(pfType,0,wx.ALIGN_CENTER_VERTICAL)
2001        PTSizer.Add(wx.StaticText(dataDisplay,-1,' Projection type: '),0,wx.ALIGN_CENTER_VERTICAL)
2002        projSel = wx.ComboBox(dataDisplay,-1,value=self.Projection,choices=['equal area','stereographic'],
2003            style=wx.CB_READONLY|wx.CB_DROPDOWN)
2004        projSel.Bind(wx.EVT_COMBOBOX,OnProjSel)
2005        PTSizer.Add(projSel,0,wx.ALIGN_CENTER_VERTICAL)
2006        if textureData['PlotType'] in ['Pole figure','Axial pole distribution']:
2007            PTSizer.Add(wx.StaticText(dataDisplay,-1,' Pole figure HKL: '),0,wx.ALIGN_CENTER_VERTICAL)
2008            PH = textureData['PFhkl']
2009            pfVal = wx.TextCtrl(dataDisplay,-1,'%d %d %d'%(PH[0],PH[1],PH[2]),style=wx.TE_PROCESS_ENTER)
2010        else:
2011            PTSizer.Add(wx.StaticText(dataDisplay,-1,' Inverse pole figure XYZ: '),0,wx.ALIGN_CENTER_VERTICAL)
2012            PX = textureData['PFxyz']
2013            pfVal = wx.TextCtrl(dataDisplay,-1,'%3.1f %3.1f %3.1f'%(PX[0],PX[1],PX[2]),style=wx.TE_PROCESS_ENTER)
2014        pfVal.Bind(wx.EVT_TEXT_ENTER,OnPFValue)
2015        pfVal.Bind(wx.EVT_KILL_FOCUS,OnPFValue)
2016        PTSizer.Add(pfVal,0,wx.ALIGN_CENTER_VERTICAL)
2017        PTSizer.Add(wx.StaticText(dataDisplay,-1,' Color scheme'),0,wx.ALIGN_CENTER_VERTICAL)
2018        choice = [m for m in mpl.cm.datad.keys() if not m.endswith("_r")]
2019        choice.sort()
2020        colorSel = wx.ComboBox(dataDisplay,-1,value=self.ContourColor,choices=choice,
2021            style=wx.CB_READONLY|wx.CB_DROPDOWN)
2022        colorSel.Bind(wx.EVT_COMBOBOX,OnColorSel)
2023        PTSizer.Add(colorSel,0,wx.ALIGN_CENTER_VERTICAL)       
2024        mainSizer.Add(PTSizer,0,wx.ALIGN_CENTER_VERTICAL)
2025        mainSizer.Add((0,5),0)
2026        if textureData['SHShow']:
2027            mainSizer.Add(wx.StaticText(dataDisplay,-1,'Spherical harmonic coefficients: '),0,wx.ALIGN_CENTER_VERTICAL)
2028            mainSizer.Add((0,5),0)
2029            ODFSizer = wx.FlexGridSizer(2,8,2,2)
2030            ODFIndx = {}
2031            ODFkeys = textureData['SH Coeff'][1].keys()
2032            ODFkeys.sort()
2033            for item in ODFkeys:
2034                ODFSizer.Add(wx.StaticText(dataDisplay,-1,item),0,wx.ALIGN_CENTER_VERTICAL)
2035                ODFval = wx.TextCtrl(dataDisplay,wx.ID_ANY,'%8.3f'%(textureData['SH Coeff'][1][item]),style=wx.TE_PROCESS_ENTER)
2036                ODFIndx[ODFval.GetId()] = item
2037                ODFval.Bind(wx.EVT_TEXT_ENTER,OnODFValue)
2038                ODFval.Bind(wx.EVT_KILL_FOCUS,OnODFValue)
2039                ODFSizer.Add(ODFval,0,wx.ALIGN_CENTER_VERTICAL)
2040            mainSizer.Add(ODFSizer,0,wx.ALIGN_CENTER_VERTICAL)
2041            mainSizer.Add((0,5),0)
2042        mainSizer.Add((0,5),0)
2043        mainSizer.Add(wx.StaticText(dataDisplay,-1,'Sample orientation angles: '),0,wx.ALIGN_CENTER_VERTICAL)
2044        mainSizer.Add((0,5),0)
2045        angSizer = wx.BoxSizer(wx.HORIZONTAL)
2046        angIndx = {}
2047        valIndx = {}
2048        for item in ['Sample omega','Sample chi','Sample phi']:
2049            angRef = wx.CheckBox(dataDisplay,-1,label=item+': ')
2050            angRef.SetValue(textureData[item][0])
2051            angIndx[angRef.GetId()] = item
2052            angRef.Bind(wx.EVT_CHECKBOX, OnAngRef)
2053            angSizer.Add(angRef,0,wx.ALIGN_CENTER_VERTICAL)
2054            angVal = wx.TextCtrl(dataDisplay,wx.ID_ANY,'%8.2f'%(textureData[item][1]),style=wx.TE_PROCESS_ENTER)
2055            valIndx[angVal.GetId()] = item
2056            angVal.Bind(wx.EVT_TEXT_ENTER,OnAngValue)
2057            angVal.Bind(wx.EVT_KILL_FOCUS,OnAngValue)
2058            angSizer.Add(angVal,0,wx.ALIGN_CENTER_VERTICAL)
2059            angSizer.Add((5,0),0)
2060        mainSizer.Add(angSizer,0,wx.ALIGN_CENTER_VERTICAL)
2061        dataDisplay.SetSizer(mainSizer,True)
2062        mainSizer.Fit(self.dataFrame)
2063        Size = mainSizer.GetMinSize()
2064        Size[0] += 40
2065        Size[1] = max(Size[1],250) + 20
2066        dataDisplay.SetSize(Size)
2067        Texture.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
2068        Size[1] = min(Size[1],450)
2069        self.dataFrame.setSizePosLeft(Size)
2070       
2071    def UpdateDData():
2072        UseList = data['Histograms']
2073        if UseList:
2074            self.dataFrame.DataMenu.Enable(G2gd.wxID_DATADELETE,True)
2075            self.Refine.Enable(True)
2076        else:
2077            self.dataFrame.DataMenu.Enable(G2gd.wxID_DATADELETE,False)
2078            self.Refine.Enable(False)           
2079        generalData = data['General']       
2080        SGData = generalData['SGData']
2081        keyList = UseList.keys()
2082        keyList.sort()
2083        Indx = {}
2084       
2085        def OnShowData(event):
2086            Obj = event.GetEventObject()
2087            hist = Indx[Obj.GetId()]
2088            UseList[hist]['Show'] = Obj.GetValue()
2089            UpdateDData()
2090            G2plt.PlotStrain(self,data)
2091           
2092        def OnCopyData(event):
2093            #how about HKLF data? This is only for PWDR data
2094            Obj = event.GetEventObject()
2095            hist = Indx[Obj.GetId()]
2096            sourceDict = UseList[hist]
2097            copyNames = ['Scale','Pref.Ori.','Size','Mustrain','HStrain','Extinction']
2098            copyDict = {}
2099            for name in copyNames: 
2100                copyDict[name] = sourceDict[name]
2101            keyList = ['All',]+UseList.keys()
2102            if UseList:
2103                copyList = []
2104                dlg = wx.MultiChoiceDialog(self, 
2105                    'Copy parameters to which histograms?', 'Copy parameters', 
2106                    keyList, wx.CHOICEDLG_STYLE)
2107                try:
2108                    if dlg.ShowModal() == wx.ID_OK:
2109                        result = dlg.GetSelections()
2110                        for i in result: 
2111                            copyList.append(keyList[i])
2112                        if 'All' in copyList: 
2113                            copyList = keyList[1:]
2114                        for item in copyList:
2115                            UseList[item].update(copyDict)
2116                        UpdateDData()
2117                finally:
2118                    dlg.Destroy()
2119           
2120        def OnScaleRef(event):
2121            Obj = event.GetEventObject()
2122            UseList[Indx[Obj.GetId()]]['Scale'][1] = Obj.GetValue()
2123           
2124        def OnScaleVal(event):
2125            Obj = event.GetEventObject()
2126            try:
2127                scale = float(Obj.GetValue())
2128                if scale > 0:
2129                    UseList[Indx[Obj.GetId()]]['Scale'][0] = scale
2130            except ValueError:
2131                pass
2132            Obj.SetValue("%.4f"%(UseList[Indx[Obj.GetId()]]['Scale'][0]))          #reset in case of error
2133           
2134        def OnSizeType(event):
2135            Obj = event.GetEventObject()
2136            hist = Indx[Obj.GetId()]
2137            UseList[hist]['Size'][0] = Obj.GetValue()
2138            UpdateDData()
2139           
2140        def OnSizeRef(event):
2141            Obj = event.GetEventObject()
2142            hist,pid = Indx[Obj.GetId()]
2143            if UseList[hist]['Size'][0] == 'ellipsoidal':
2144                UseList[hist]['Size'][5][pid] = Obj.GetValue()               
2145            else:
2146                UseList[hist]['Size'][2][pid] = Obj.GetValue()
2147           
2148        def OnSizeVal(event):
2149            Obj = event.GetEventObject()
2150            hist,pid = Indx[Obj.GetId()]
2151            if UseList[hist]['Size'][0] == 'ellipsoidal':
2152                try:
2153                    size = float(Obj.GetValue())
2154                    if pid < 3 and size <= 0.01:            #10A lower limit!
2155                        raise ValueError                   
2156                except ValueError:
2157                    pass
2158            else:
2159                try:
2160                    size = float(Obj.GetValue())
2161                    if size <= 0.01:            #10A lower limit!
2162                        raise ValueError
2163                    UseList[hist]['Size'][1][pid] = size
2164                except ValueError:
2165                    pass
2166            Obj.SetValue("%.3f"%(UseList[hist]['Size'][1][pid]))          #reset in case of error
2167           
2168        def OnSizeAxis(event):           
2169            Obj = event.GetEventObject()
2170            hist = Indx[Obj.GetId()]
2171            Saxis = Obj.GetValue().split()
2172            try:
2173                hkl = [int(Saxis[i]) for i in range(3)]
2174            except (ValueError,IndexError):
2175                hkl = UseList[hist]['Size'][3]
2176            if not np.any(np.array(hkl)):
2177                hkl = UseList[hist]['Size'][3]
2178            UseList[hist]['Size'][3] = hkl
2179            h,k,l = hkl
2180            Obj.SetValue('%3d %3d %3d'%(h,k,l)) 
2181                       
2182        def OnStrainType(event):
2183            Obj = event.GetEventObject()
2184            hist = Indx[Obj.GetId()]
2185            UseList[hist]['Mustrain'][0] = Obj.GetValue()
2186            UpdateDData()
2187            G2plt.PlotStrain(self,data)
2188           
2189        def OnStrainRef(event):
2190            Obj = event.GetEventObject()
2191            hist,pid = Indx[Obj.GetId()]
2192            if UseList[hist]['Mustrain'][0] == 'generalized':
2193                UseList[hist]['Mustrain'][5][pid] = Obj.GetValue()
2194            else:
2195                UseList[hist]['Mustrain'][2][pid] = Obj.GetValue()
2196           
2197        def OnStrainVal(event):
2198            Snames = G2spc.MustrainNames(SGData)
2199            Obj = event.GetEventObject()
2200            hist,pid = Indx[Obj.GetId()]
2201            try:
2202                strain = float(Obj.GetValue())
2203                if UseList[hist]['Mustrain'][0] == 'generalized':
2204                    if '4' in Snames[pid] and strain < 0:
2205                        raise ValueError
2206                    UseList[hist]['Mustrain'][4][pid] = strain
2207                else:
2208                    if strain <= 0:
2209                        raise ValueError
2210                    UseList[hist]['Mustrain'][1][pid] = strain
2211            except ValueError:
2212                pass
2213            if UseList[hist]['Mustrain'][0] == 'generalized':
2214                Obj.SetValue("%.3f"%(UseList[hist]['Mustrain'][4][pid]))          #reset in case of error
2215            else:
2216                Obj.SetValue("%.1f"%(UseList[hist]['Mustrain'][1][pid]))          #reset in case of error
2217            G2plt.PlotStrain(self,data)
2218           
2219        def OnStrainAxis(event):
2220            Obj = event.GetEventObject()
2221            hist = Indx[Obj.GetId()]
2222            Saxis = Obj.GetValue().split()
2223            try:
2224                hkl = [int(Saxis[i]) for i in range(3)]
2225            except (ValueError,IndexError):
2226                hkl = UseList[hist]['Mustrain'][3]
2227            if not np.any(np.array(hkl)):
2228                hkl = UseList[hist]['Mustrain'][3]
2229            UseList[hist]['Mustrain'][3] = hkl
2230            h,k,l = hkl
2231            Obj.SetValue('%3d %3d %3d'%(h,k,l)) 
2232            G2plt.PlotStrain(self,data)
2233           
2234        def OnHstrainRef(event):
2235            Obj = event.GetEventObject()
2236            hist,pid = Indx[Obj.GetId()]
2237            UseList[hist]['HStrain'][1][pid] = Obj.GetValue()
2238           
2239        def OnHstrainVal(event):
2240            Snames = G2spc.HStrainNames(SGData)
2241            Obj = event.GetEventObject()
2242            hist,pid = Indx[Obj.GetId()]
2243            try:
2244                strain = float(Obj.GetValue())
2245                UseList[hist]['HStrain'][0][pid] = strain
2246            except ValueError:
2247                pass
2248            Obj.SetValue("%.5f"%(UseList[hist]['HStrain'][0][pid]))          #reset in case of error
2249
2250        def OnPOType(event):
2251            Obj = event.GetEventObject()
2252            hist = Indx[Obj.GetId()]
2253            if 'March' in POType.GetValue():
2254                UseList[hist]['Pref.Ori.'][0] = 'MD'
2255            else:
2256                UseList[hist]['Pref.Ori.'][0] = 'SH'
2257            UpdateDData()           
2258
2259        def OnPORef(event):
2260            Obj = event.GetEventObject()
2261            hist = Indx[Obj.GetId()]
2262            UseList[hist]['Pref.Ori.'][2] = Obj.GetValue()
2263           
2264        def OnPOVal(event):
2265            Obj = event.GetEventObject()
2266            hist = Indx[Obj.GetId()]
2267            try:
2268                mdVal = float(Obj.GetValue())
2269                if mdVal > 0:
2270                    UseList[hist]['Pref.Ori.'][1] = mdVal
2271            except ValueError:
2272                pass
2273            Obj.SetValue("%.3f"%(UseList[hist]['Pref.Ori.'][1]))          #reset in case of error
2274           
2275        def OnPOAxis(event):
2276            Obj = event.GetEventObject()
2277            hist = Indx[Obj.GetId()]
2278            Saxis = Obj.GetValue().split()
2279            try:
2280                hkl = [int(Saxis[i]) for i in range(3)]
2281            except (ValueError,IndexError):
2282                hkl = UseList[hist]['Pref.Ori.'][3]
2283            if not np.any(np.array(hkl)):
2284                hkl = UseList[hist]['Pref.Ori.'][3]
2285            UseList[hist]['Pref.Ori.'][3] = hkl
2286            h,k,l = hkl
2287            Obj.SetValue('%3d %3d %3d'%(h,k,l)) 
2288           
2289        def OnPOOrder(event):
2290            Obj = event.GetEventObject()
2291            hist = Indx[Obj.GetId()]
2292            Order = int(Obj.GetValue())
2293            UseList[hist]['Pref.Ori.'][4] = Order
2294            UseList[hist]['Pref.Ori.'][5] = SetPOCoef(Order,hist)
2295            UpdateDData()
2296
2297        def SetPOCoef(Order,hist):
2298            cofNames = G2lat.GenSHCoeff(SGData['SGLaue'],'0',Order,False)     #cylindrical & no M
2299            newPOCoef = dict(zip(cofNames,np.zeros(len(cofNames))))
2300            POCoeff = UseList[hist]['Pref.Ori.'][5]
2301            for cofName in POCoeff:
2302                if cofName in  cofNames:
2303                    newPOCoef[cofName] = POCoeff[cofName]
2304            return newPOCoef
2305       
2306        def OnExtRef(event):
2307            Obj = event.GetEventObject()
2308            UseList[Indx[Obj.GetId()]]['Extinction'][1] = Obj.GetValue()
2309           
2310        def OnExtVal(event):
2311            Obj = event.GetEventObject()
2312            try:
2313                ext = float(Obj.GetValue())
2314                if ext >= 0:
2315                    UseList[Indx[Obj.GetId()]]['Extinction'][0] = ext
2316            except ValueError:
2317                pass
2318            Obj.SetValue("%.2f"%(UseList[Indx[Obj.GetId()]]['Extinction'][0]))          #reset in case of error
2319           
2320        def checkAxis(axis):
2321            if not np.any(np.array(axis)):
2322                return False
2323            return axis
2324           
2325        def ScaleSizer():
2326            scaleSizer = wx.BoxSizer(wx.HORIZONTAL)
2327            scaleRef = wx.CheckBox(dataDisplay,-1,label=' Phase fraction: ')
2328            scaleRef.SetValue(UseList[item]['Scale'][1])
2329            Indx[scaleRef.GetId()] = item
2330            scaleRef.Bind(wx.EVT_CHECKBOX, OnScaleRef)
2331            scaleSizer.Add(scaleRef,0,wx.ALIGN_CENTER_VERTICAL)
2332            scaleVal = wx.TextCtrl(dataDisplay,wx.ID_ANY,
2333                '%.4f'%(UseList[item]['Scale'][0]),style=wx.TE_PROCESS_ENTER)
2334            Indx[scaleVal.GetId()] = item
2335            scaleVal.Bind(wx.EVT_TEXT_ENTER,OnScaleVal)
2336            scaleVal.Bind(wx.EVT_KILL_FOCUS,OnScaleVal)
2337            scaleSizer.Add(scaleVal,0,wx.ALIGN_CENTER_VERTICAL)
2338            return scaleSizer
2339           
2340        def TopSizer(name,choices,parm,OnType):
2341            topSizer = wx.BoxSizer(wx.HORIZONTAL)
2342            topSizer.Add(wx.StaticText(dataDisplay,-1,name),0,wx.ALIGN_CENTER_VERTICAL)
2343            sizeType = wx.ComboBox(dataDisplay,wx.ID_ANY,value=UseList[item][parm][0],choices=choices,
2344                style=wx.CB_READONLY|wx.CB_DROPDOWN)
2345            sizeType.Bind(wx.EVT_COMBOBOX, OnType)
2346            Indx[sizeType.GetId()] = item
2347            topSizer.Add(sizeType)
2348            topSizer.Add((5,0),0)
2349            return topSizer
2350           
2351        def IsoSizer(name,parm,fmt,OnVal,OnRef):
2352            isoSizer = wx.BoxSizer(wx.HORIZONTAL)
2353            sizeRef = wx.CheckBox(dataDisplay,-1,label=name)
2354            sizeRef.thisown = False
2355            sizeRef.SetValue(UseList[item][parm][2][0])
2356            Indx[sizeRef.GetId()] = [item,0]
2357            sizeRef.Bind(wx.EVT_CHECKBOX, OnRef)
2358            isoSizer.Add(sizeRef,0,wx.ALIGN_CENTER_VERTICAL)
2359            sizeVal = wx.TextCtrl(dataDisplay,wx.ID_ANY,
2360                fmt%(UseList[item][parm][1][0]),style=wx.TE_PROCESS_ENTER)
2361            Indx[sizeVal.GetId()] = [item,0]
2362            sizeVal.Bind(wx.EVT_TEXT_ENTER,OnVal)
2363            sizeVal.Bind(wx.EVT_KILL_FOCUS,OnVal)
2364            isoSizer.Add(sizeVal,0,wx.ALIGN_CENTER_VERTICAL)
2365            return isoSizer
2366           
2367        def UniSizer(parm,OnAxis):
2368            uniSizer = wx.BoxSizer(wx.HORIZONTAL)
2369            uniSizer.Add(wx.StaticText(dataDisplay,-1,' Unique axis, H K L: '),0,wx.ALIGN_CENTER_VERTICAL)
2370            h,k,l = UseList[item][parm][3]
2371            Axis = wx.TextCtrl(dataDisplay,-1,'%3d %3d %3d'%(h,k,l),style=wx.TE_PROCESS_ENTER)
2372            Indx[Axis.GetId()] = item
2373            Axis.Bind(wx.EVT_TEXT_ENTER,OnAxis)
2374            Axis.Bind(wx.EVT_KILL_FOCUS,OnAxis)
2375            uniSizer.Add(Axis,0,wx.ALIGN_CENTER_VERTICAL)
2376            return uniSizer
2377           
2378        def UniDataSizer(parmName,parm,fmt,OnVal,OnRef):
2379            dataSizer = wx.BoxSizer(wx.HORIZONTAL)
2380            parms = zip([' Equatorial '+parmName,' Axial '+parmName],
2381                UseList[item][parm][1],UseList[item][parm][2],range(2))
2382            for Pa,val,ref,id in parms:
2383                sizeRef = wx.CheckBox(dataDisplay,-1,label=Pa)
2384                sizeRef.thisown = False
2385                sizeRef.SetValue(ref)
2386                Indx[sizeRef.GetId()] = [item,id]
2387                sizeRef.Bind(wx.EVT_CHECKBOX, OnRef)
2388                dataSizer.Add(sizeRef,0,wx.ALIGN_CENTER_VERTICAL)
2389                sizeVal = wx.TextCtrl(dataDisplay,wx.ID_ANY,fmt%(val),style=wx.TE_PROCESS_ENTER)
2390                Indx[sizeVal.GetId()] = [item,id]
2391                sizeVal.Bind(wx.EVT_TEXT_ENTER,OnVal)
2392                sizeVal.Bind(wx.EVT_KILL_FOCUS,OnVal)
2393                dataSizer.Add(sizeVal,0,wx.ALIGN_CENTER_VERTICAL)
2394                dataSizer.Add((5,0),0)
2395            return dataSizer
2396           
2397        def EllSizeDataSizer():
2398            parms = zip(['S11','S22','S33','S12','S13','S23'],UseList[item]['Size'][4],
2399                UseList[item]['Size'][5],range(6))
2400            dataSizer = wx.FlexGridSizer(2,6,5,5)
2401            for Pa,val,ref,id in parms:
2402                sizeRef = wx.CheckBox(dataDisplay,-1,label=Pa)
2403                sizeRef.thisown = False
2404                sizeRef.SetValue(ref)
2405                Indx[sizeRef.GetId()] = [item,id]
2406                sizeRef.Bind(wx.EVT_CHECKBOX, OnSizeRef)
2407                dataSizer.Add(sizeRef,0,wx.ALIGN_CENTER_VERTICAL)
2408                sizeVal = wx.TextCtrl(dataDisplay,wx.ID_ANY,'%.3f'%(val),style=wx.TE_PROCESS_ENTER)
2409                Indx[sizeVal.GetId()] = [item,id]
2410                sizeVal.Bind(wx.EVT_TEXT_ENTER,OnSizeVal)
2411                sizeVal.Bind(wx.EVT_KILL_FOCUS,OnSizeVal)
2412                dataSizer.Add(sizeVal,0,wx.ALIGN_CENTER_VERTICAL)
2413            return dataSizer
2414           
2415        def GenStrainDataSizer():
2416            Snames = G2spc.MustrainNames(SGData)
2417            numb = len(Snames)
2418            if len(UseList[item]['Mustrain'][4]) < numb:
2419                UseList[item]['Mustrain'][4] = numb*[0.0,]
2420                UseList[item]['Mustrain'][5] = numb*[False,]
2421            parms = zip(Snames,UseList[item]['Mustrain'][4],UseList[item]['Mustrain'][5],range(numb))
2422            dataSizer = wx.FlexGridSizer(1,6,5,5)
2423            for Pa,val,ref,id in parms:
2424                strainRef = wx.CheckBox(dataDisplay,-1,label=Pa)
2425                strainRef.thisown = False
2426                strainRef.SetValue(ref)
2427                Indx[strainRef.GetId()] = [item,id]
2428                strainRef.Bind(wx.EVT_CHECKBOX, OnStrainRef)
2429                dataSizer.Add(strainRef,0,wx.ALIGN_CENTER_VERTICAL)
2430                strainVal = wx.TextCtrl(dataDisplay,wx.ID_ANY,'%.5f'%(val),style=wx.TE_PROCESS_ENTER)
2431                Indx[strainVal.GetId()] = [item,id]
2432                strainVal.Bind(wx.EVT_TEXT_ENTER,OnStrainVal)
2433                strainVal.Bind(wx.EVT_KILL_FOCUS,OnStrainVal)
2434                dataSizer.Add(strainVal,0,wx.ALIGN_CENTER_VERTICAL)
2435            return dataSizer
2436           
2437        def HstrainSizer():
2438            hstrainSizer = wx.FlexGridSizer(1,6,5,5)
2439            Hsnames = G2spc.HStrainNames(SGData)
2440            parms = zip(Hsnames,UseList[item]['HStrain'][0],UseList[item]['HStrain'][1],range(len(Hsnames)))
2441            for Pa,val,ref,id in parms:
2442                hstrainRef = wx.CheckBox(dataDisplay,-1,label=Pa)
2443                hstrainRef.thisown = False
2444                hstrainRef.SetValue(ref)
2445                Indx[hstrainRef.GetId()] = [item,id]
2446                hstrainRef.Bind(wx.EVT_CHECKBOX, OnHstrainRef)
2447                hstrainSizer.Add(hstrainRef,0,wx.ALIGN_CENTER_VERTICAL)
2448                hstrainVal = wx.TextCtrl(dataDisplay,wx.ID_ANY,'%.5f'%(val),style=wx.TE_PROCESS_ENTER)
2449                Indx[hstrainVal.GetId()] = [item,id]
2450                hstrainVal.Bind(wx.EVT_TEXT_ENTER,OnHstrainVal)
2451                hstrainVal.Bind(wx.EVT_KILL_FOCUS,OnHstrainVal)
2452                hstrainSizer.Add(hstrainVal,0,wx.ALIGN_CENTER_VERTICAL)
2453            return hstrainSizer
2454           
2455                                   
2456        DData.DestroyChildren()
2457        dataDisplay = wx.Panel(DData)
2458        mainSizer = wx.BoxSizer(wx.VERTICAL)
2459        mainSizer.Add(wx.StaticText(dataDisplay,-1,'Histogram data for '+PhaseName+':'),0,wx.ALIGN_CENTER_VERTICAL)
2460        for item in keyList:
2461            histData = UseList[item]
2462            mainSizer.Add((5,5),0)
2463           
2464            showSizer = wx.BoxSizer(wx.HORIZONTAL)
2465            showData = wx.CheckBox(dataDisplay,-1,label=' Show '+item)
2466            showData.SetValue(UseList[item]['Show'])
2467            Indx[showData.GetId()] = item
2468            showData.Bind(wx.EVT_CHECKBOX, OnShowData)
2469            showSizer.Add(showData,0,wx.ALIGN_CENTER_VERTICAL)
2470            copyData = wx.Button(dataDisplay,-1,label=' Copy?')
2471            Indx[copyData.GetId()] = item
2472            copyData.Bind(wx.EVT_BUTTON,OnCopyData)
2473            showSizer.Add(copyData,wx.ALIGN_CENTER_VERTICAL)
2474            mainSizer.Add(showSizer,0,wx.ALIGN_CENTER_VERTICAL)
2475            mainSizer.Add((0,5),0)
2476           
2477            if UseList[item]['Show']:
2478                mainSizer.Add(ScaleSizer())
2479                mainSizer.Add((0,5),0)
2480               
2481            if item[:4] == 'PWDR' and UseList[item]['Show']:
2482                sizeSizer = wx.BoxSizer(wx.VERTICAL)
2483                if UseList[item]['Size'][0] == 'isotropic':
2484                    isoSizer = wx.BoxSizer(wx.HORIZONTAL)
2485                    isoSizer.Add(TopSizer(' Size model: ',['isotropic','uniaxial','ellipsoidal'],
2486                        'Size',OnSizeType),0,wx.ALIGN_CENTER_VERTICAL)
2487                    isoSizer.Add(IsoSizer(' Cryst. size(\xb5m): ','Size','%.3f',
2488                        OnSizeVal,OnSizeRef),0,wx.ALIGN_CENTER_VERTICAL)
2489                    sizeSizer.Add(isoSizer)
2490                elif UseList[item]['Size'][0] == 'uniaxial':
2491                    uniSizer = wx.BoxSizer(wx.HORIZONTAL)
2492                    uniSizer.Add(TopSizer(' Size model: ',['isotropic','uniaxial','ellipsoidal'],
2493                        'Size',OnSizeType),0,wx.ALIGN_CENTER_VERTICAL)
2494                    uniSizer.Add(UniSizer('Size',OnSizeAxis),0,wx.ALIGN_CENTER_VERTICAL)
2495                    sizeSizer.Add(uniSizer)
2496                    sizeSizer.Add(UniDataSizer('size(\xb5m): ','Size','%.3f',OnSizeVal,OnSizeRef))
2497                elif UseList[item]['Size'][0] == 'ellipsoidal':
2498                    ellSizer = wx.BoxSizer(wx.HORIZONTAL)
2499                    ellSizer.Add(TopSizer(' Size model: ',['isotropic','uniaxial','ellipsoidal'],
2500                        'Size',OnSizeType),0,wx.ALIGN_CENTER_VERTICAL)
2501                    ellSizer.Add(wx.StaticText(dataDisplay,-1,' Coefficients(\xb5m): '),0,wx.ALIGN_CENTER_VERTICAL)
2502                    sizeSizer.Add(ellSizer)
2503                    sizeSizer.Add(EllSizeDataSizer())
2504                mainSizer.Add(sizeSizer)
2505                mainSizer.Add((0,5),0)                   
2506               
2507                strainSizer = wx.BoxSizer(wx.VERTICAL)
2508                if UseList[item]['Mustrain'][0] == 'isotropic':
2509                    isoSizer = wx.BoxSizer(wx.HORIZONTAL)
2510                    isoSizer.Add(TopSizer(' Mustrain model: ',['isotropic','uniaxial','generalized',],
2511                        'Mustrain',OnStrainType),0,wx.ALIGN_CENTER_VERTICAL)
2512                    isoSizer.Add(IsoSizer(' microstrain: ','Mustrain','%.1f',
2513                        OnStrainVal,OnStrainRef),0,wx.ALIGN_CENTER_VERTICAL)                   
2514                    strainSizer.Add(isoSizer)
2515                elif UseList[item]['Mustrain'][0] == 'uniaxial':
2516                    uniSizer = wx.BoxSizer(wx.HORIZONTAL)
2517                    uniSizer.Add(TopSizer(' Mustrain model: ',['isotropic','uniaxial','generalized',],
2518                        'Mustrain',OnStrainType),0,wx.ALIGN_CENTER_VERTICAL)
2519                    uniSizer.Add(UniSizer('Mustrain',OnStrainAxis),0,wx.ALIGN_CENTER_VERTICAL)
2520                    sizeSizer.Add(uniSizer)
2521                    sizeSizer.Add(UniDataSizer('mustrain: ','Mustrain','%.1f',OnStrainVal,OnStrainRef))
2522                elif UseList[item]['Mustrain'][0] == 'generalized':
2523                    genSizer = wx.BoxSizer(wx.HORIZONTAL)
2524                    genSizer.Add(TopSizer(' Mustrain model: ',['isotropic','uniaxial','generalized',],
2525                        'Mustrain',OnStrainType),0,wx.ALIGN_CENTER_VERTICAL)
2526                    genSizer.Add(wx.StaticText(dataDisplay,-1,' Coefficients: '),0,wx.ALIGN_CENTER_VERTICAL)
2527                    strainSizer.Add(genSizer)
2528                    strainSizer.Add(GenStrainDataSizer())                       
2529                mainSizer.Add(strainSizer)
2530                mainSizer.Add((0,5),0)
2531               
2532                mainSizer.Add(wx.StaticText(dataDisplay,-1,' Hydrostatic/elastic strain:'))
2533                mainSizer.Add(HstrainSizer())
2534                   
2535                #texture  'Pref. Ori.':['MD',1.0,False,[0,0,1],0,[]] last two for 'SH' are SHorder & coeff
2536                poSizer = wx.FlexGridSizer(1,6,5,5)
2537                POData = UseList[item]['Pref.Ori.']
2538                choice = ['March-Dollase','Spherical harmonics']
2539                POtype = choice[['MD','SH'].index(POData[0])]
2540                poSizer.Add(wx.StaticText(dataDisplay,-1,' Preferred orientation model '),0,wx.ALIGN_CENTER_VERTICAL)
2541                POType = wx.ComboBox(dataDisplay,wx.ID_ANY,value=POtype,choices=choice,
2542                    style=wx.CB_READONLY|wx.CB_DROPDOWN)
2543                Indx[POType.GetId()] = item
2544                POType.Bind(wx.EVT_COMBOBOX, OnPOType)
2545                poSizer.Add(POType)
2546                if POData[0] == 'MD':
2547                    mainSizer.Add(poSizer)
2548                    poSizer = wx.BoxSizer(wx.HORIZONTAL)
2549                    poRef = wx.CheckBox(dataDisplay,-1,label=' March-Dollase ratio: ')
2550                    poRef.SetValue(POData[2])
2551                    Indx[poRef.GetId()] = item
2552                    poRef.Bind(wx.EVT_CHECKBOX,OnPORef)
2553                    poSizer.Add(poRef,0,wx.ALIGN_CENTER_VERTICAL)
2554                    poVal = wx.TextCtrl(dataDisplay,wx.ID_ANY,
2555                        '%.3f'%(POData[1]),style=wx.TE_PROCESS_ENTER)
2556                    Indx[poVal.GetId()] = item
2557                    poVal.Bind(wx.EVT_TEXT_ENTER,OnPOVal)
2558                    poVal.Bind(wx.EVT_KILL_FOCUS,OnPOVal)
2559                    poSizer.Add(poVal,0,wx.ALIGN_CENTER_VERTICAL)
2560                    poSizer.Add(wx.StaticText(dataDisplay,-1,' Unique axis, H K L: '),0,wx.ALIGN_CENTER_VERTICAL)
2561                    h,k,l =POData[3]
2562                    poAxis = wx.TextCtrl(dataDisplay,-1,'%3d %3d %3d'%(h,k,l),style=wx.TE_PROCESS_ENTER)
2563                    Indx[poAxis.GetId()] = item
2564                    poAxis.Bind(wx.EVT_TEXT_ENTER,OnPOAxis)
2565                    poAxis.Bind(wx.EVT_KILL_FOCUS,OnPOAxis)
2566                    poSizer.Add(poAxis,0,wx.ALIGN_CENTER_VERTICAL)
2567                    mainSizer.Add(poSizer)
2568                else:           #'SH'
2569                    poSizer.Add(wx.StaticText(dataDisplay,-1,' Harmonic order: '),0,wx.ALIGN_CENTER_VERTICAL)
2570                    poOrder = wx.ComboBox(dataDisplay,wx.ID_ANY,value=str(POData[4]),choices=[str(2*i) for i in range(18)],
2571                        style=wx.CB_READONLY|wx.CB_DROPDOWN)
2572                    Indx[poOrder.GetId()] = item
2573                    poOrder.Bind(wx.EVT_COMBOBOX,OnPOOrder)
2574                    poSizer.Add(poOrder,0,wx.ALIGN_CENTER_VERTICAL)
2575                    poRef = wx.CheckBox(dataDisplay,-1,label=' Refine? ')
2576                    poRef.SetValue(POData[2])
2577                    Indx[poRef.GetId()] = item
2578                    poRef.Bind(wx.EVT_CHECKBOX,OnPORef)
2579                    poSizer.Add(poRef,0,wx.ALIGN_CENTER_VERTICAL)
2580                    mainSizer.Add(poSizer)
2581                    if POData[4]:
2582                        textJ = G2lat.textureIndex(POData[5])
2583                        mainSizer.Add(wx.StaticText(dataDisplay,-1,' Spherical harmonic coefficients: '+'Texture index: %.3f'%(textJ)),0,wx.ALIGN_CENTER_VERTICAL)
2584                        mainSizer.Add((0,5),0)
2585                        ODFSizer = wx.FlexGridSizer(2,8,2,2)
2586                        ODFIndx = {}
2587                        ODFkeys = POData[5].keys()
2588                        ODFkeys.sort()
2589                        for odf in ODFkeys:
2590                            ODFSizer.Add(wx.StaticText(dataDisplay,-1,odf),0,wx.ALIGN_CENTER_VERTICAL)
2591                            ODFval = wx.TextCtrl(dataDisplay,wx.ID_ANY,'%8.3f'%(POData[5][odf]),style=wx.TE_PROCESS_ENTER)
2592                            ODFIndx[ODFval.GetId()] = odf
2593    #                        ODFval.Bind(wx.EVT_TEXT_ENTER,OnODFValue)
2594    #                        ODFval.Bind(wx.EVT_KILL_FOCUS,OnODFValue)
2595                            ODFSizer.Add(ODFval,0,wx.ALIGN_CENTER_VERTICAL)
2596                        mainSizer.Add(ODFSizer,0,wx.ALIGN_CENTER_VERTICAL)
2597                        mainSizer.Add((0,5),0)
2598                mainSizer.Add((0,5),0)               
2599                #Extinction  'Extinction':[0.0,False]
2600                extSizer = wx.BoxSizer(wx.HORIZONTAL)
2601                extRef = wx.CheckBox(dataDisplay,-1,label=' Extinction: ')
2602                extRef.SetValue(UseList[item]['Extinction'][1])
2603                Indx[extRef.GetId()] = item
2604                extRef.Bind(wx.EVT_CHECKBOX, OnExtRef)
2605                extSizer.Add(extRef,0,wx.ALIGN_CENTER_VERTICAL)
2606                extVal = wx.TextCtrl(dataDisplay,wx.ID_ANY,
2607                    '%.2f'%(UseList[item]['Extinction'][0]),style=wx.TE_PROCESS_ENTER)
2608                Indx[extVal.GetId()] = item
2609                extVal.Bind(wx.EVT_TEXT_ENTER,OnExtVal)
2610                extVal.Bind(wx.EVT_KILL_FOCUS,OnExtVal)
2611                extSizer.Add(extVal,0,wx.ALIGN_CENTER_VERTICAL)
2612                mainSizer.Add(extSizer)
2613                mainSizer.Add((0,5),0)
2614            elif item[:4] == 'HKLF' and UseList[item]['Show']:
2615                pass
2616        mainSizer.Add((5,5),0)
2617
2618        dataDisplay.SetSizer(mainSizer,True)
2619        mainSizer.Fit(self.dataFrame)
2620        Size = mainSizer.GetMinSize()
2621        Size[0] += 40
2622        Size[1] = max(Size[1],250) + 20
2623        dataDisplay.SetSize(Size)
2624        DData.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
2625        Size[1] = min(Size[1],450)
2626        self.dataFrame.setSizePosLeft(Size)
2627       
2628    def OnHklfAdd(event):
2629        UseList = data['Histograms']
2630        keyList = UseList.keys()
2631        TextList = []
2632        if self.PatternTree.GetCount():
2633            item, cookie = self.PatternTree.GetFirstChild(self.root)
2634            while item:
2635                name = self.PatternTree.GetItemText(item)
2636                if name not in keyList and 'HKLF' in name:
2637                    TextList.append(name)
2638                item, cookie = self.PatternTree.GetNextChild(self.root, cookie)                       
2639            dlg = wx.MultiChoiceDialog(self, 'Which new data to use?', 'Use data', TextList, wx.CHOICEDLG_STYLE)
2640            try:
2641                if dlg.ShowModal() == wx.ID_OK:
2642                    result = dlg.GetSelections()
2643                    for i in result:
2644                        histoName = TextList[i]
2645                        UseList[histoName] = {'Histogram':histoName,'Show':False,'Scale':[1.0,True],
2646                            'Extinction':['Lorentzian','Secondary Type I',{'Eg':[0.0,False]},]}                       
2647                    data['Histograms'] = UseList
2648                    UpdateDData()
2649            finally:
2650                dlg.Destroy()
2651       
2652    def OnPwdrAdd(event):
2653        generalData = data['General']
2654        SGData = generalData['SGData']
2655        UseList = data['Histograms']
2656        newList = []
2657        NShkl = len(G2spc.MustrainNames(SGData))
2658        NDij = len(G2spc.HStrainNames(SGData))
2659        keyList = UseList.keys()
2660        TextList = ['All PWDR']
2661        if self.PatternTree.GetCount():
2662            item, cookie = self.PatternTree.GetFirstChild(self.root)
2663            while item:
2664                name = self.PatternTree.GetItemText(item)
2665                if name not in keyList and 'PWDR' in name:
2666                    TextList.append(name)
2667                item, cookie = self.PatternTree.GetNextChild(self.root, cookie)
2668            dlg = wx.MultiChoiceDialog(self, 'Which new data to use?', 'Use data', TextList, wx.CHOICEDLG_STYLE)
2669            try:
2670                if dlg.ShowModal() == wx.ID_OK:
2671                    result = dlg.GetSelections()
2672                    for i in result: newList.append(TextList[i])
2673                    if 'All PWDR' in newList:
2674                        newList = TextList[1:]
2675                    for histoName in newList:
2676                        pId = G2gd.GetPatternTreeItemId(self,self.root,histoName)
2677                        UseList[histoName] = {'Histogram':histoName,'Show':False,
2678                            'Scale':[1.0,False],'Pref.Ori.':['MD',1.0,False,[0,0,1],0,{}],
2679                            'Size':['isotropic',[4.,4.,],[False,False],[0,0,1],6*[0.0,],6*[False,]],
2680                            'Mustrain':['isotropic',[1000.0,1000.0],[False,False],[0,0,1],
2681                                NShkl*[0.01,],NShkl*[False,]],
2682                            'HStrain':[NDij*[0.0,],NDij*[False,]],                         
2683                            'Extinction':[0.0,False]}
2684                        refList = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,pId,'Reflection Lists'))
2685                        refList[generalData['Name']] = []                       
2686                    data['Histograms'] = UseList
2687                    UpdateDData()
2688            finally:
2689                dlg.Destroy()
2690       
2691    def OnDataDelete(event):
2692        UseList = data['Histograms']
2693        keyList = ['All',]+UseList.keys()
2694        keyList.sort()
2695        DelList = []
2696        if UseList:
2697            DelList = []
2698            dlg = wx.MultiChoiceDialog(self, 
2699                'Which histogram to delete from this phase?', 'Delete histogram', 
2700                keyList, wx.CHOICEDLG_STYLE)
2701            try:
2702                if dlg.ShowModal() == wx.ID_OK:
2703                    result = dlg.GetSelections()
2704                    for i in result: 
2705                        DelList.append(keyList[i])
2706                    if 'All' in DelList:
2707                        DelList = keyList[1:]
2708                    for i in DelList:
2709                        del UseList[i]
2710                    UpdateDData()
2711            finally:
2712                dlg.Destroy()
2713
2714    def FillPawleyReflectionsGrid():
2715                       
2716        def KeyEditPawleyGrid(event):
2717            colList = self.PawleyRefl.GetSelectedCols()
2718            PawleyPeaks = data['Pawley ref']
2719            if event.GetKeyCode() == wx.WXK_RETURN:
2720                event.Skip(True)
2721            elif event.GetKeyCode() == wx.WXK_CONTROL:
2722                event.Skip(True)
2723            elif event.GetKeyCode() == wx.WXK_SHIFT:
2724                event.Skip(True)
2725            elif colList:
2726                self.PawleyRefl.ClearSelection()
2727                key = event.GetKeyCode()
2728                for col in colList:
2729                    if PawleyTable.GetTypeName(0,col) == wg.GRID_VALUE_BOOL:
2730                        if key == 89: #'Y'
2731                            for row in range(PawleyTable.GetNumberRows()): PawleyPeaks[row][col]=True
2732                        elif key == 78:  #'N'
2733                            for row in range(PawleyTable.GetNumberRows()): PawleyPeaks[row][col]=False
2734                        FillPawleyReflectionsGrid()
2735           
2736        if 'Pawley ref' in data:
2737            PawleyPeaks = data['Pawley ref']                       
2738            rowLabels = []
2739            for i in range(len(PawleyPeaks)): rowLabels.append(str(i))
2740            colLabels = ['h','k','l','mul','d','refine','Fsq(hkl)','sig(Fsq)']
2741            Types = 4*[wg.GRID_VALUE_LONG,]+[wg.GRID_VALUE_FLOAT+':10,4',wg.GRID_VALUE_BOOL,]+ \
2742                2*[wg.GRID_VALUE_FLOAT+':10,2',]
2743            PawleyTable = G2gd.Table(PawleyPeaks,rowLabels=rowLabels,colLabels=colLabels,types=Types)
2744            self.PawleyRefl.SetTable(PawleyTable, True)
2745            self.PawleyRefl.Bind(wx.EVT_KEY_DOWN, KeyEditPawleyGrid)                 
2746            self.PawleyRefl.SetMargins(0,0)
2747            self.PawleyRefl.AutoSizeColumns(False)
2748            self.dataFrame.setSizePosLeft([500,300])
2749                   
2750    def OnPawleyLoad(event):
2751        generalData = data['General']
2752        dmin = generalData['Pawley dmin']
2753        cell = generalData['Cell'][1:7]
2754        A = G2lat.cell2A(cell)
2755        SGData = generalData['SGData']
2756        HKLd = np.array(G2lat.GenHLaue(dmin,SGData,A))
2757        PawleyPeaks = []
2758        wx.BeginBusyCursor()
2759        try:
2760            for h,k,l,d in HKLd:
2761                ext,mul = G2spc.GenHKLf([h,k,l],SGData)[:2]
2762                if not ext:
2763                    PawleyPeaks.append([h,k,l,mul,d,False,100.0,1.0])
2764        finally:
2765            wx.EndBusyCursor()
2766        data['Pawley ref'] = PawleyPeaks
2767        FillPawleyReflectionsGrid()
2768       
2769    def OnPawleyEstimate(event):
2770        try:
2771            Refs = data['Pawley ref']
2772            Histograms = data['Histograms']
2773        except KeyError:
2774            print '**** Error - no histograms defined for this phase ****'
2775            return
2776        HistoNames = Histograms.keys()
2777        PatternId = G2gd.GetPatternTreeItemId(self,self.root,HistoNames[0])
2778        xdata = self.PatternTree.GetItemPyData(PatternId)[1]
2779        Inst = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId,'Instrument Parameters'))
2780        Inst = dict(zip(Inst[3],Inst[1]))
2781        Sample = self.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(self,PatternId,'Sample Parameters'))
2782        if 'Lam' in Inst:
2783            wave = Inst['Lam']
2784        else:
2785            wave = Inst['Lam1']
2786       
2787        posCorr = Inst['Zero']
2788        print Sample
2789        const = 9.e-2/(np.pi*Sample['Gonio. radius'])                  #shifts in microns
2790       
2791        for ref in Refs:
2792            pos = 2.0*asind(wave/(2.0*ref[4]))
2793            if 'Bragg' in Sample['Type']:
2794                pos -= const*(4.*Sample['Shift'][0]*cosd(pos/2.0)+ \
2795                    Sample['Transparency'][0]*sind(pos)*100.0)            #trans(=1/mueff) in cm
2796            else:               #Debye-Scherrer - simple but maybe not right
2797                pos -= const*(Sample['DisplaceX'][0]*cosd(pos)+Sample['DisplaceY'][0]*sind(pos))
2798            indx = np.searchsorted(xdata[0],pos)
2799            try:
2800                ref[6] = xdata[1][indx]
2801                print ref[:7],indx,pos
2802            except IndexError:
2803                pass
2804        FillPawleyReflectionsGrid()
2805                           
2806    def OnPawleyDelete(event):
2807        dlg = wx.MessageDialog(self,'Do you really want to delete Pawley reflections?','Delete', 
2808            wx.YES_NO | wx.ICON_QUESTION)
2809        try:
2810            result = dlg.ShowModal()
2811        finally:
2812            dlg.Destroy()
2813        if result == wx.ID_YES: 
2814            data['Pawley ref'] = []
2815            FillPawleyReflectionsGrid()
2816           
2817    def OnTextureClear(event):
2818        event.Skip()
2819
2820    def OnPageChanged(event):
2821        page = event.GetSelection()
2822        text = self.dataDisplay.GetPageText(page)
2823        if text == 'Atoms':
2824            self.dataFrame.SetMenuBar(self.dataFrame.AtomsMenu)
2825            self.dataFrame.Bind(wx.EVT_MENU, OnAtomAdd, id=G2gd.wxID_ATOMSEDITADD)
2826            self.dataFrame.Bind(wx.EVT_MENU, OnAtomTestAdd, id=G2gd.wxID_ATOMSTESTADD)
2827            self.dataFrame.Bind(wx.EVT_MENU, OnAtomInsert, id=G2gd.wxID_ATOMSEDITINSERT)
2828            self.dataFrame.Bind(wx.EVT_MENU, OnAtomTestInsert, id=G2gd.wxID_ATONTESTINSERT)
2829            self.dataFrame.Bind(wx.EVT_MENU, AtomDelete, id=G2gd.wxID_ATOMSEDITDELETE)
2830            self.dataFrame.Bind(wx.EVT_MENU, AtomRefine, id=G2gd.wxID_ATOMSREFINE)
2831            self.dataFrame.Bind(wx.EVT_MENU, AtomModify, id=G2gd.wxID_ATOMSMODIFY)
2832            self.dataFrame.Bind(wx.EVT_MENU, AtomTransform, id=G2gd.wxID_ATOMSTRANSFORM)
2833            self.dataFrame.Bind(wx.EVT_MENU, OnReloadDrawAtoms, id=G2gd.wxID_RELOADDRAWATOMS)
2834            FillAtomsGrid()
2835        elif text == 'General':
2836            UpdateGeneral()
2837            self.dataFrame.SetMenuBar(self.dataFrame.BlankMenu)
2838        elif text == 'Data':
2839            self.dataFrame.SetMenuBar(self.dataFrame.DataMenu)
2840            self.dataFrame.Bind(wx.EVT_MENU, OnPwdrAdd, id=G2gd.wxID_PWDRADD)
2841            self.dataFrame.Bind(wx.EVT_MENU, OnHklfAdd, id=G2gd.wxID_HKLFADD)
2842            self.dataFrame.Bind(wx.EVT_MENU, OnDataDelete, id=G2gd.wxID_DATADELETE)
2843            UpdateDData()
2844            G2plt.PlotStrain(self,data)
2845        elif text == 'Draw Options':
2846            self.dataFrame.SetMenuBar(self.dataFrame.BlankMenu)
2847            UpdateDrawOptions()
2848            G2plt.PlotStructure(self,data)
2849        elif text == 'Draw Atoms':
2850            self.dataFrame.SetMenuBar(self.dataFrame.DrawAtomsMenu)
2851            self.dataFrame.Bind(wx.EVT_MENU, DrawAtomStyle, id=G2gd.wxID_DRAWATOMSTYLE)
2852            self.dataFrame.Bind(wx.EVT_MENU, DrawAtomLabel, id=G2gd.wxID_DRAWATOMLABEL)
2853            self.dataFrame.Bind(wx.EVT_MENU, DrawAtomColor, id=G2gd.wxID_DRAWATOMCOLOR)
2854            self.dataFrame.Bind(wx.EVT_MENU, ResetAtomColors, id=G2gd.wxID_DRAWATOMRESETCOLOR)
2855            self.dataFrame.Bind(wx.EVT_MENU, SetViewPoint, id=G2gd.wxID_DRAWVIEWPOINT)
2856            self.dataFrame.Bind(wx.EVT_MENU, AddSymEquiv, id=G2gd.wxID_DRAWADDEQUIV)
2857            self.dataFrame.Bind(wx.EVT_MENU, TransformSymEquiv, id=G2gd.wxID_DRAWTRANSFORM)
2858            self.dataFrame.Bind(wx.EVT_MENU, FillCoordSphere, id=G2gd.wxID_DRAWFILLCOORD)           
2859            self.dataFrame.Bind(wx.EVT_MENU, FillUnitCell, id=G2gd.wxID_DRAWFILLCELL)
2860            self.dataFrame.Bind(wx.EVT_MENU, DrawAtomsDelete, id=G2gd.wxID_DRAWDELETE)
2861            UpdateDrawAtoms()
2862            G2plt.PlotStructure(self,data)
2863        elif text == 'Pawley reflections':
2864            self.dataFrame.SetMenuBar(self.dataFrame.PawleyMenu)
2865            self.dataFrame.Bind(wx.EVT_MENU, OnPawleyLoad, id=G2gd.wxID_PAWLEYLOAD)
2866            self.dataFrame.Bind(wx.EVT_MENU, OnPawleyEstimate, id=G2gd.wxID_PAWLEYESTIMATE)
2867            self.dataFrame.Bind(wx.EVT_MENU, OnPawleyDelete, id=G2gd.wxID_PAWLEYDELETE)           
2868            FillPawleyReflectionsGrid()
2869        elif text == 'Texture':
2870            self.dataFrame.SetMenuBar(self.dataFrame.TextureMenu)
2871            self.dataFrame.Bind(wx.EVT_MENU, OnTextureClear, id=G2gd.wxID_CLEARTEXTURE)
2872            UpdateTexture()                       
2873            G2plt.PlotTexture(self,data,Start=True)
2874        else:
2875            self.dataFrame.SetMenuBar(self.dataFrame.BlankMenu)
2876        event.Skip()
2877       
2878    General = wx.Window(self.dataDisplay)
2879    self.dataDisplay.AddPage(General,'General')
2880    SetupGeneral()
2881    GeneralData = data['General']
2882    UpdateGeneral()
2883
2884    if GeneralData['Type'] == 'Pawley':
2885        DData = wx.ScrolledWindow(self.dataDisplay)
2886        self.dataDisplay.AddPage(DData,'Data')
2887        self.PawleyRefl = G2gd.GSGrid(self.dataDisplay)
2888        self.dataDisplay.AddPage(self.PawleyRefl,'Pawley reflections')
2889    else:
2890        DData = wx.ScrolledWindow(self.dataDisplay)
2891        self.dataDisplay.AddPage(DData,'Data')
2892        Texture = wx.ScrolledWindow(self.dataDisplay)
2893        self.dataDisplay.AddPage(Texture,'Texture')
2894        Atoms = G2gd.GSGrid(self.dataDisplay)
2895        self.dataDisplay.AddPage(Atoms,'Atoms')
2896        drawOptions = wx.Window(self.dataDisplay)
2897        self.dataDisplay.AddPage(drawOptions,'Draw Options')
2898        drawAtoms = G2gd.GSGrid(self.dataDisplay)
2899        self.dataDisplay.AddPage(drawAtoms,'Draw Atoms')
2900
2901    self.dataDisplay.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, OnPageChanged)
2902    self.dataDisplay.SetSelection(oldPage)
2903   
2904           
Note: See TracBrowser for help on using the repository browser.