source: trunk/GSASIIphsGUI.py @ 399

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

Implement sequential refinement
remove print "load" & "save" for each item in Tree
revise application of azimuth offset - azimuths are now all "true" with correction

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