source: trunk/GSASIIphsGUI.py @ 436

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

remove a stray print from psvfcj.for
add the wx inspector tool (commented out) at top of GSASII.py
use wx.CallAfter? - fixes the crash in UpdateDData & maybe UpdateTexture?
copy command in SampleData? now copies phi,chi & omega

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