source: trunk/GSASIIphsGUI.py @ 397

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

collect default settings for Sample in one routine
add recalibrate routine for images
azimuths from image integration are now the center angle of each azimuth bin
put in 1/2 pixel offset in image calibration/integration calcs

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