source: trunk/GSASIIphsGUI.py @ 445

Last change on this file since 445 was 445, checked in by toby, 10 years ago

1st stop on help fixes

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