source: trunk/GSASIIphsGUI.py @ 395

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

Add goniometer omega, chi & phi to sample data
put SH texture in General
fix phase delete to remove it from reflection lists as well
continue development of constraints/restraints GUI
fixes to texture computations, GUI & least squares refinement

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