source: trunk/GSASIIphsGUI.py @ 411

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

fix very old (!) bug in psvfcj.for
implement neutron scattering lengths in GSASII including the dozen anomalous scattering isotopes
isotope choice is in General
so GSASII will now do neutron CW Rietveld refinements
some cleanup of the constraints GUI
remove varyList from GSASIImapvars.py globals

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