source: trunk/GSASIIphsGUI.py @ 439

Last change on this file since 439 was 439, checked in by toby, 11 years ago

do not destroy contents of scrolledwindow, as this deletes the scrollbars on Mac. Instead destroy the sizer.

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