source: trunk/GSASIIphsGUI.py @ 690

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

use wx.CallAfter? in UpdateGeneral?; maybe now OSX will work.

  • Property svn:keywords set to Date Author Revision URL Id
File size: 195.0 KB
Line 
1# -*- coding: utf-8 -*-
2#GSASII - phase data display routines
3########### SVN repository information ###################
4# $Date: 2012-07-19 14:56:42 +0000 (Thu, 19 Jul 2012) $
5# $Author: vondreele $
6# $Revision: 690 $
7# $URL: trunk/GSASIIphsGUI.py $
8# $Id: GSASIIphsGUI.py 690 2012-07-19 14:56:42Z vondreele $
9########### SVN repository information ###################
10import wx
11import wx.grid as wg
12import matplotlib as mpl
13import math
14import copy
15import time
16import sys
17import random as ran
18import cPickle
19import GSASIIpath
20GSASIIpath.SetVersionNumber("$Revision: 690 $")
21import GSASIIlattice as G2lat
22import GSASIIspc as G2spc
23import GSASIIElem as G2elem
24import GSASIIElemGUI as G2elemGUI
25import GSASIIplot as G2plt
26import GSASIIgrid as G2gd
27import GSASIIIO as G2IO
28import GSASIIstruct as G2str
29import GSASIImath as G2mth
30import GSASIIpwd as G2pwd
31import numpy as np
32import numpy.linalg as nl
33import numpy.ma as ma
34
35VERY_LIGHT_GREY = wx.Colour(235,235,235)
36WHITE = wx.Colour(255,255,255)
37BLACK = wx.Colour(0,0,0)
38
39# trig functions in degrees
40sind = lambda x: math.sin(x*math.pi/180.)
41tand = lambda x: math.tan(x*math.pi/180.)
42cosd = lambda x: math.cos(x*math.pi/180.)
43asind = lambda x: 180.*math.asin(x)/math.pi
44
45class SymOpDialog(wx.Dialog):
46    def __init__(self,parent,SGData,New=True):
47        wx.Dialog.__init__(self,parent,-1,'Select symmetry operator',
48            pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE)
49        panel = wx.Panel(self)
50        self.SGData = SGData
51        self.New = New
52        self.OpSelected = [0,0,0,[0,0,0],False]
53        mainSizer = wx.BoxSizer(wx.VERTICAL)
54        mainSizer.Add((5,5),0)
55        if SGData['SGInv']:
56            choice = ['No','Yes']
57            self.inv = wx.RadioBox(panel,-1,'Choose inversion?',choices=choice)
58            self.inv.Bind(wx.EVT_RADIOBOX, self.OnOpSelect)
59            mainSizer.Add(self.inv,0,wx.ALIGN_CENTER_VERTICAL)
60        mainSizer.Add((5,5),0)
61        if SGData['SGLatt'] != 'P':
62            LattOp = G2spc.Latt2text(SGData['SGLatt']).split(';')
63            self.latt = wx.RadioBox(panel,-1,'Choose cell centering?',choices=LattOp)
64            self.latt.Bind(wx.EVT_RADIOBOX, self.OnOpSelect)
65            mainSizer.Add(self.latt,0,wx.ALIGN_CENTER_VERTICAL)
66        mainSizer.Add((5,5),0)
67        if SGData['SGLaue'] in ['-1','2/m','mmm','4/m','4/mmm']:
68            Ncol = 2
69        else:
70            Ncol = 3
71        OpList = []
72        for M,T in SGData['SGOps']:
73            OpList.append(G2spc.MT2text(M,T))
74        self.oprs = wx.RadioBox(panel,-1,'Choose space group operator?',choices=OpList,
75            majorDimension=Ncol)
76        self.oprs.Bind(wx.EVT_RADIOBOX, self.OnOpSelect)
77        mainSizer.Add(self.oprs,0,wx.ALIGN_CENTER_VERTICAL)
78        mainSizer.Add((5,5),0)
79        mainSizer.Add(wx.StaticText(panel,-1,"   Choose unit cell?"),0,wx.ALIGN_CENTER_VERTICAL)
80        mainSizer.Add((5,5),0)
81        cellSizer = wx.BoxSizer(wx.HORIZONTAL)
82        cellSizer.Add((5,0),0)
83        cellName = ['X','Y','Z']
84        self.cell = []
85        for i in range(3):
86            self.cell.append(wx.SpinCtrl(panel,-1,cellName[i],size=wx.Size(50,20)))
87            self.cell[-1].SetRange(-3,3)
88            self.cell[-1].SetValue(0)
89            self.cell[-1].Bind(wx.EVT_SPINCTRL, self.OnOpSelect)
90            cellSizer.Add(self.cell[-1],0,wx.ALIGN_CENTER_VERTICAL)
91        mainSizer.Add(cellSizer,0,)
92        if self.New:
93            choice = ['No','Yes']
94            self.new = wx.RadioBox(panel,-1,'Generate new positions?',choices=choice)
95            self.new.Bind(wx.EVT_RADIOBOX, self.OnOpSelect)
96            mainSizer.Add(self.new,0,wx.ALIGN_CENTER_VERTICAL)
97        mainSizer.Add((5,5),0)
98
99        OkBtn = wx.Button(panel,-1,"Ok")
100        OkBtn.Bind(wx.EVT_BUTTON, self.OnOk)
101        cancelBtn = wx.Button(panel,-1,"Cancel")
102        cancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel)
103        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
104        btnSizer.Add((20,20),1)
105        btnSizer.Add(OkBtn)
106        btnSizer.Add((20,20),1)
107        btnSizer.Add(cancelBtn)
108        btnSizer.Add((20,20),1)
109
110        mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
111        panel.SetSizer(mainSizer)
112        panel.Fit()
113        self.Fit()
114
115    def OnOpSelect(self,event):
116        if self.SGData['SGInv']:
117            self.OpSelected[0] = self.inv.GetSelection()
118        if self.SGData['SGLatt'] != 'P':
119            self.OpSelected[1] = self.latt.GetSelection()
120        self.OpSelected[2] = self.oprs.GetSelection()
121        for i in range(3):
122            self.OpSelected[3][i] = float(self.cell[i].GetValue())
123        if self.New:
124            self.OpSelected[4] = self.new.GetSelection()
125
126    def GetSelection(self):
127        return self.OpSelected
128
129    def OnOk(self,event):
130        parent = self.GetParent()
131        parent.Raise()
132        self.EndModal(wx.ID_OK)
133
134    def OnCancel(self,event):
135        parent = self.GetParent()
136        parent.Raise()
137        self.EndModal(wx.ID_CANCEL)
138
139class DisAglDialog(wx.Dialog):
140   
141    def __default__(self,data,default):
142        if data:
143            self.data = data
144        else:
145            self.data = {}
146            self.data['Name'] = default['Name']
147            self.data['Factors'] = [0.85,0.85]
148            self.data['AtomTypes'] = default['AtomTypes']
149            self.data['BondRadii'] = default['BondRadii']
150            self.data['AngleRadii'] = default['AngleRadii']
151       
152    def __init__(self,parent,data,default):
153        wx.Dialog.__init__(self,parent,-1,'Distance Angle Controls', 
154            pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE)
155        self.default = default
156        self.panel = wx.Panel(self)         #just a dummy - gets destroyed in Draw!
157        self.__default__(data,self.default)
158        self.Draw(self.data)
159               
160    def Draw(self,data):
161        self.panel.Destroy()
162        self.panel = wx.Panel(self)
163        mainSizer = wx.BoxSizer(wx.VERTICAL)
164        mainSizer.Add(wx.StaticText(self.panel,-1,'Controls for phase '+data['Name']),
165            0,wx.ALIGN_CENTER_VERTICAL|wx.LEFT,10)
166        mainSizer.Add((10,10),1)
167       
168        radiiSizer = wx.FlexGridSizer(2,3,5,5)
169        radiiSizer.Add(wx.StaticText(self.panel,-1,' Type'),0,wx.ALIGN_CENTER_VERTICAL)
170        radiiSizer.Add(wx.StaticText(self.panel,-1,'Bond radii'),0,wx.ALIGN_CENTER_VERTICAL)
171        radiiSizer.Add(wx.StaticText(self.panel,-1,'Angle radii'),0,wx.ALIGN_CENTER_VERTICAL)
172        self.objList = {}
173        for id,item in enumerate(self.data['AtomTypes']):
174            radiiSizer.Add(wx.StaticText(self.panel,-1,' '+item),0,wx.ALIGN_CENTER_VERTICAL)
175            bRadii = wx.TextCtrl(self.panel,-1,value='%.3f'%(data['BondRadii'][id]),style=wx.TE_PROCESS_ENTER)
176            self.objList[bRadii.GetId()] = ['BondRadii',id]
177            bRadii.Bind(wx.EVT_TEXT_ENTER,self.OnRadiiVal)
178            bRadii.Bind(wx.EVT_KILL_FOCUS,self.OnRadiiVal)
179            radiiSizer.Add(bRadii,0,wx.ALIGN_CENTER_VERTICAL)
180            aRadii = wx.TextCtrl(self.panel,-1,value='%.3f'%(data['AngleRadii'][id]),style=wx.TE_PROCESS_ENTER)
181            self.objList[aRadii.GetId()] = ['AngleRadii',id]
182            aRadii.Bind(wx.EVT_TEXT_ENTER,self.OnRadiiVal)
183            aRadii.Bind(wx.EVT_KILL_FOCUS,self.OnRadiiVal)
184            radiiSizer.Add(aRadii,0,wx.ALIGN_CENTER_VERTICAL)
185        mainSizer.Add(radiiSizer,0,wx.EXPAND)
186        factorSizer = wx.FlexGridSizer(2,2,5,5)
187        Names = ['Bond','Angle']
188        for i,name in enumerate(Names):
189            factorSizer.Add(wx.StaticText(self.panel,-1,name+' search factor'),0,wx.ALIGN_CENTER_VERTICAL)
190            bondFact = wx.TextCtrl(self.panel,-1,value='%.3f'%(data['Factors'][i]),style=wx.TE_PROCESS_ENTER)
191            self.objList[bondFact.GetId()] = ['Factors',i]
192            bondFact.Bind(wx.EVT_TEXT_ENTER,self.OnRadiiVal)
193            bondFact.Bind(wx.EVT_KILL_FOCUS,self.OnRadiiVal)
194            factorSizer.Add(bondFact)
195        mainSizer.Add(factorSizer,0,wx.EXPAND)
196       
197        OkBtn = wx.Button(self.panel,-1,"Ok")
198        OkBtn.Bind(wx.EVT_BUTTON, self.OnOk)
199        ResetBtn = wx.Button(self.panel,-1,'Reset')
200        ResetBtn.Bind(wx.EVT_BUTTON, self.OnReset)
201        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
202        btnSizer.Add((20,20),1)
203        btnSizer.Add(OkBtn)
204        btnSizer.Add(ResetBtn)
205        btnSizer.Add((20,20),1)
206        mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
207        self.panel.SetSizer(mainSizer)
208        self.panel.Fit()
209        self.Fit()
210   
211    def OnRadiiVal(self,event):
212        Obj = event.GetEventObject()
213        item = self.objList[Obj.GetId()]
214        try:
215            self.data[item[0]][item[1]] = float(Obj.GetValue())
216        except ValueError:
217            pass
218        Obj.SetValue("%.3f"%(self.data[item[0]][item[1]]))          #reset in case of error
219       
220    def GetData(self):
221        return self.data
222       
223    def OnOk(self,event):
224        parent = self.GetParent()
225        parent.Raise()
226        self.EndModal(wx.ID_OK)             
227       
228    def OnReset(self,event):
229        data = {}
230        self.__default__(data,self.default)
231        self.Draw(self.data)
232       
233class SingleFloatDialog(wx.Dialog):
234   
235    def __init__(self,parent,title,prompt,value,limits=[0.,1.]):
236        wx.Dialog.__init__(self,parent,-1,title, 
237            pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE)
238        self.panel = wx.Panel(self)         #just a dummy - gets destroyed in Draw!
239        self.limits = limits
240        self.value = value
241        self.prompt = prompt
242        self.Draw()
243       
244    def Draw(self):
245       
246        def OnValItem(event):
247            try:
248                val = float(valItem.GetValue())
249                if val < self.limits[0] or val > self.limits[1]:
250                    raise ValueError
251            except ValueError:
252                val = self.value
253            self.value = val
254            valItem.SetValue('%.5g'%(self.value))
255           
256        self.panel.Destroy()
257        self.panel = wx.Panel(self)
258        mainSizer = wx.BoxSizer(wx.VERTICAL)
259        mainSizer.Add(wx.StaticText(self.panel,-1,self.prompt),0,wx.ALIGN_CENTER)
260        valItem = wx.TextCtrl(self.panel,-1,value='%.5g'%(self.value),style=wx.TE_PROCESS_ENTER)
261        mainSizer.Add(valItem,0,wx.ALIGN_CENTER)
262        valItem.Bind(wx.EVT_TEXT_ENTER,OnValItem)
263        valItem.Bind(wx.EVT_KILL_FOCUS,OnValItem)
264        OkBtn = wx.Button(self.panel,-1,"Ok")
265        OkBtn.Bind(wx.EVT_BUTTON, self.OnOk)
266        CancelBtn = wx.Button(self.panel,-1,'Cancel')
267        CancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel)
268        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
269        btnSizer.Add((20,20),1)
270        btnSizer.Add(OkBtn)
271        btnSizer.Add(CancelBtn)
272        btnSizer.Add((20,20),1)
273        mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
274        self.panel.SetSizer(mainSizer)
275        self.panel.Fit()
276        self.Fit()
277
278    def GetValue(self):
279        return self.value
280       
281    def OnOk(self,event):
282        parent = self.GetParent()
283        parent.Raise()
284        self.EndModal(wx.ID_OK)             
285       
286    def OnCancel(self,event):
287        parent = self.GetParent()
288        parent.Raise()
289        self.EndModal(wx.ID_CANCEL)             
290       
291def FindAtomIndexByIDs(atomData,IDs,Draw=True):
292    indx = []
293    for i,atom in enumerate(atomData):
294        if Draw and atom[-3] in IDs:
295            indx.append(i)
296        elif atom[-1] in IDs:
297            indx.append(i)
298    return indx
299       
300def UpdatePhaseData(G2frame,Item,data,oldPage):
301
302    Atoms = []
303    if G2frame.dataDisplay:
304        G2frame.dataDisplay.Destroy()
305    PhaseName = G2frame.PatternTree.GetItemText(Item)
306    G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.BlankMenu)
307    G2frame.dataFrame.SetLabel('Phase Data for '+PhaseName)
308    G2frame.dataFrame.CreateStatusBar()
309    G2frame.dataDisplay = G2gd.GSNoteBook(parent=G2frame.dataFrame,size=G2frame.dataFrame.GetClientSize())
310
311    def SetupGeneral():
312        generalData = data['General']
313        atomData = data['Atoms']
314        generalData['AtomTypes'] = []
315        generalData['Isotopes'] = {}
316# various patches
317        if 'Isotope' not in generalData:
318            generalData['Isotope'] = {}
319        if 'Data plot type' not in generalData:
320            generalData['Data plot type'] = 'Mustrain'
321        if 'POhkl' not in generalData:
322            generalData['POhkl'] = [0,0,1]
323        if 'Map' not in generalData:
324            generalData['Map'] = {'MapType':'','RefList':'','Resolution':0.5,
325                'rho':[],'rhoMax':0.,'mapSize':10.0,'cutOff':50.,'Flip':False}
326        if 'Flip' not in generalData:
327            generalData['Flip'] = {'RefList':'','Resolution':0.5,'Norm element':'None',
328                'k-factor':0.1}
329        if 'doPawley' not in generalData:
330            generalData['doPawley'] = False
331        if 'Pawley dmin' not in generalData:
332            generalData['Pawley dmin'] = 1.0
333           
334#        if 'SH Texture' not in generalData:
335#            generalData['SH Texture'] = data['SH Texture']
336        generalData['NoAtoms'] = {}
337        generalData['BondRadii'] = []
338        generalData['AngleRadii'] = []
339        generalData['vdWRadii'] = []
340        generalData['AtomMass'] = []
341        generalData['Color'] = []
342        generalData['Mydir'] = G2frame.dirname
343        cx,ct,cs,cia = [3,1,7,9]
344        generalData['AtomPtrs'] = [cx,ct,cs,cia]
345        if generalData['Type'] =='macromolecular':
346            cx,ct,cs,cia = [6,4,10,12]
347            generalData['AtomPtrs'] = [cx,ct,cs,cia]
348        for atom in atomData:
349            atom[ct] = atom[ct].lower().capitalize()              #force to standard form
350            if generalData['AtomTypes'].count(atom[ct]):
351                generalData['NoAtoms'][atom[ct]] += atom[cs-1]*float(atom[cs+1])
352            elif atom[ct] != 'UNK':
353                Info = G2elem.GetAtomInfo(atom[ct])
354                generalData['AtomTypes'].append(atom[ct])
355                generalData['Z'] = Info['Z']
356                generalData['Isotopes'][atom[ct]] = Info['Isotopes']
357                generalData['BondRadii'].append(Info['Drad'])
358                generalData['AngleRadii'].append(Info['Arad'])
359                generalData['vdWRadii'].append(Info['Vdrad'])
360                if atom[ct] in generalData['Isotope']:
361                    generalData['AtomMass'].append(Info['Isotopes'][generalData['Isotope'][atom[ct]]][0])
362                else:
363                    generalData['Isotope'][atom[ct]] = 'Nat. Abund.'
364                    generalData['AtomMass'].append(Info['Mass'])
365                generalData['NoAtoms'][atom[ct]] = atom[cs-1]*float(atom[cs+1])
366                generalData['Color'].append(Info['Color'])
367        F000X = 0.
368        F000N = 0.
369        for i,elem in enumerate(generalData['AtomTypes']):
370            F000X += generalData['NoAtoms'][elem]*generalData['Z']
371            isotope = generalData['Isotope'][elem]
372            F000N += generalData['NoAtoms'][elem]*generalData['Isotopes'][elem][isotope][1]
373        generalData['F000X'] = F000X
374        generalData['F000N'] = F000N
375       
376
377################################################################################
378##### General phase routines
379################################################################################
380
381    def UpdateGeneral():
382       
383        ''' default dictionary structure for phase data: (taken from GSASII.py)
384        'General':{
385            'Name':PhaseName
386            'Type':'nuclear'
387            'SGData':SGData
388            'Cell':[False,10.,10.,10.,90.,90.,90,1000.]
389            'AtomPtrs':[]
390            'Histogram list':['',]
391            'Pawley dmin':1.0}
392        'Atoms':[]
393        'Drawing':{}
394        '''
395       
396        phaseTypes = ['nuclear','modulated','magnetic','macromolecular']
397        SetupGeneral()
398        generalData = data['General']
399        Map = generalData['Map']
400        Flip = generalData['Flip'] 
401        PWDR = any(['PWDR' in item for item in data['Histograms'].keys()])
402       
403        def NameSizer():
404                   
405            def OnPhaseName(event):
406                oldName = generalData['Name']
407                generalData['Name'] = NameTxt.GetValue()
408                G2frame.G2plotNB.Rename(oldName,generalData['Name'])
409                G2frame.dataFrame.SetLabel('Phase Data for '+generalData['Name'])
410                G2frame.PatternTree.SetItemText(Item,generalData['Name'])
411                #Hmm, need to change phase name key in Reflection Lists for each histogram
412                           
413            def OnPhaseType(event):
414                if not generalData['AtomTypes']:             #can change only if no atoms!
415                    generalData['Type'] = TypeTxt.GetValue()
416                    dataDisplay.DestroyChildren()           #needed to clear away bad cellSizer, etc.
417                    wx.CallAfter(UpdateGeneral)
418                else:
419                    TypeTxt.SetValue(generalData['Type'])               
420               
421            def OnSpaceGroup(event):
422                SpcGp = SGTxt.GetValue()
423                SGErr,SGData = G2spc.SpcGroup(SpcGp)
424                if SGErr:
425                    text = [G2spc.SGErrors(SGErr)+'\nSpace Group set to previous']
426                    SGTxt.SetValue(generalData['SGData']['SpGrp'])
427                    msg = 'Space Group Error'
428                    Style = wx.ICON_EXCLAMATION
429                else:
430                    text = G2spc.SGPrint(SGData)
431                    generalData['SGData'] = SGData
432                    msg = 'Space Group Information'
433                    Style = wx.ICON_INFORMATION
434                Text = ''
435                for line in text:
436                    Text += line+'\n'
437                wx.MessageBox(Text,caption=msg,style=Style)
438                dataDisplay.DestroyChildren()           #needed to clear away bad cellSizer, etc.
439                wx.CallAfter(UpdateGeneral)
440               
441            nameSizer = wx.BoxSizer(wx.HORIZONTAL)
442            nameSizer.Add(wx.StaticText(dataDisplay,-1,' Phase name: '),0,wx.ALIGN_CENTER_VERTICAL)
443            NameTxt = wx.TextCtrl(dataDisplay,-1,value=generalData['Name'],style=wx.TE_PROCESS_ENTER)
444            NameTxt.Bind(wx.EVT_TEXT_ENTER,OnPhaseName)
445            NameTxt.Bind(wx.EVT_KILL_FOCUS,OnPhaseName)
446            nameSizer.Add(NameTxt,0,wx.ALIGN_CENTER_VERTICAL)
447            nameSizer.Add(wx.StaticText(dataDisplay,-1,'  Phase type: '),0,wx.ALIGN_CENTER_VERTICAL)
448            if len(data['Atoms']):
449                choices = phaseTypes[:-1]
450            else:
451                choices = phaseTypes           
452            TypeTxt = wx.ComboBox(dataDisplay,-1,value=generalData['Type'],choices=choices,
453                style=wx.CB_READONLY|wx.CB_DROPDOWN)
454            TypeTxt.Bind(wx.EVT_COMBOBOX, OnPhaseType)
455            nameSizer.Add(TypeTxt,0,wx.ALIGN_CENTER_VERTICAL)
456            nameSizer.Add(wx.StaticText(dataDisplay,-1,'  Space group: '),0,wx.ALIGN_CENTER_VERTICAL)
457            SGTxt = wx.TextCtrl(dataDisplay,-1,value=generalData['SGData']['SpGrp'],style=wx.TE_PROCESS_ENTER)
458            SGTxt.Bind(wx.EVT_TEXT_ENTER,OnSpaceGroup)
459            nameSizer.Add(SGTxt,0,wx.ALIGN_CENTER_VERTICAL)
460            return nameSizer
461           
462        def CellSizer():
463           
464            cellGUIlist = [[['m3','m3m'],4,zip([" Unit cell: a = "," Vol = "],["%.5f","%.3f"],[True,False],[0,0])],
465            [['3R','3mR'],6,zip([" a = "," alpha = "," Vol = "],["%.5f","%.3f","%.3f"],[True,True,False],[0,2,0])],
466            [['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])],
467            [['mmm'],8,zip([" a = "," b = "," c = "," Vol = "],["%.5f","%.5f","%.5f","%.3f"],
468                [True,True,True,False],[0,1,2,0])],
469            [['2/m'+'a'],10,zip([" a = "," b = "," c = "," alpha = "," Vol = "],
470                ["%.5f","%.5f","%.5f","%.3f","%.3f"],[True,True,True,True,False],[0,1,2,4,0])],
471            [['2/m'+'b'],10,zip([" a = "," b = "," c = "," beta = "," Vol = "],
472                ["%.5f","%.5f","%.5f","%.3f","%.3f"],[True,True,True,True,False],[0,1,2,4,0])],
473            [['2/m'+'c'],10,zip([" a = "," b = "," c = "," gamma = "," Vol = "],
474                ["%.5f","%.5f","%.5f","%.3f","%.3f"],[True,True,True,True,False],[0,1,2,4,0])],
475            [['-1'],8,zip([" a = "," b = "," c = "," Vol = "," alpha = "," beta = "," gamma = "],
476                ["%.5f","%.5f","%.5f","%.3f","%.3f","%.3f","%.3f"],
477                [True,True,True,False,True,True,True],[0,1,2,0,3,4,5])]]
478               
479            def OnCellRef(event):
480                generalData['Cell'][0] = cellRef.GetValue()
481               
482            def OnCellChange(event):
483                SGData = generalData['SGData']
484                laue = SGData['SGLaue']
485                if laue == '2/m':
486                    laue += SGData['SGUniq']
487                cell = generalData['Cell']
488                Obj = event.GetEventObject()
489                ObjId = cellList.index(Obj.GetId())
490                try:
491                    value = max(1.0,float(Obj.GetValue()))
492                except ValueError:
493                    if ObjId < 3:               #bad cell edge - reset
494                        value = controls[6+ObjId]
495                    else:                       #bad angle
496                        value = 90.
497                if laue in ['m3','m3m']:
498                    cell[1] = cell[2] = cell[3] = value
499                    cell[4] = cell[5] = cell[6] = 90.0
500                    Obj.SetValue("%.5f"%(cell[1]))
501                elif laue in ['3R','3mR']:
502                    if ObjId == 0:
503                        cell[1] = cell[2] = cell[3] = value
504                        Obj.SetValue("%.5f"%(cell[1]))
505                    else:
506                        cell[4] = cell[5] = cell[6] = value
507                        Obj.SetValue("%.5f"%(cell[4]))
508                elif laue in ['3','3m1','31m','6/m','6/mmm','4/m','4/mmm']:                   
509                    cell[4] = cell[5] = 90.
510                    cell[6] = 120.
511                    if laue in ['4/m','4/mmm']:
512                        cell[6] = 90.
513                    if ObjId == 0:
514                        cell[1] = cell[2] = value
515                        Obj.SetValue("%.5f"%(cell[1]))
516                    else:
517                        cell[3] = value
518                        Obj.SetValue("%.5f"%(cell[3]))
519                elif laue in ['mmm']:
520                    cell[ObjId+1] = value
521                    cell[4] = cell[5] = cell[6] = 90.
522                    Obj.SetValue("%.5f"%(cell[ObjId+1]))
523                elif laue in ['2/m'+'a']:
524                    cell[5] = cell[6] = 90.
525                    if ObjId != 3:
526                        cell[ObjId+1] = value
527                        Obj.SetValue("%.5f"%(cell[ObjId+1]))
528                    else:
529                        cell[4] = value
530                        Obj.SetValue("%.3f"%(cell[4]))
531                elif laue in ['2/m'+'b']:
532                    cell[4] = cell[6] = 90.
533                    if ObjId != 3:
534                        cell[ObjId+1] = value
535                        Obj.SetValue("%.5f"%(cell[ObjId+1]))
536                    else:
537                        cell[5] = value
538                        Obj.SetValue("%.3f"%(cell[5]))
539                elif laue in ['2/m'+'c']:
540                    cell[5] = cell[6] = 90.
541                    if ObjId != 3:
542                        cell[ObjId+1] = value
543                        Obj.SetValue("%.5f"%(cell[ObjId+1]))
544                    else:
545                        cell[6] = value
546                        Obj.SetValue("%.3f"%(cell[6]))
547                else:
548                    cell[ObjId+1] = value
549                    if ObjId < 3:
550                        Obj.SetValue("%.5f"%(cell[1+ObjId]))
551                    else:
552                        Obj.SetValue("%.3f"%(cell[1+ObjId]))                       
553                cell[7] = G2lat.calc_V(G2lat.cell2A(cell[1:7]))
554                volVal.SetValue("%.3f"%(cell[7]))
555                generalData['Cell'] = cell
556                dataDisplay.DestroyChildren()           #needed to clear away bad cellSizer, etc.
557                wx.CallAfter(UpdateGeneral)
558           
559            cell = generalData['Cell']
560            laue = generalData['SGData']['SGLaue']
561            if laue == '2/m':
562                laue += generalData['SGData']['SGUniq']
563            for cellGUI in cellGUIlist:
564                if laue in cellGUI[0]:
565                    useGUI = cellGUI
566            cellSizer = wx.FlexGridSizer(2,useGUI[1]+1,5,5)
567            if PWDR:
568                cellRef = wx.CheckBox(dataDisplay,-1,label='Refine unit cell:')
569                cellSizer.Add(cellRef,0,wx.ALIGN_CENTER_VERTICAL)
570                cellRef.Bind(wx.EVT_CHECKBOX, OnCellRef)
571                cellRef.SetValue(cell[0])
572            cellList = []
573            for txt,fmt,ifEdit,Id in useGUI[2]:
574                cellSizer.Add(wx.StaticText(dataDisplay,label=txt),0,wx.ALIGN_CENTER_VERTICAL)
575                if ifEdit:          #a,b,c,etc.
576                    cellVal = wx.TextCtrl(dataDisplay,value=(fmt%(cell[Id+1])),
577                        style=wx.TE_PROCESS_ENTER)
578                    cellVal.Bind(wx.EVT_TEXT_ENTER,OnCellChange)       
579                    cellVal.Bind(wx.EVT_KILL_FOCUS,OnCellChange)
580                    cellSizer.Add(cellVal,0,wx.ALIGN_CENTER_VERTICAL)
581                    cellList.append(cellVal.GetId())
582                else:               #volume
583                    volVal = wx.TextCtrl(dataDisplay,value=(fmt%(cell[7])),style=wx.TE_READONLY)
584                    volVal.SetBackgroundColour(VERY_LIGHT_GREY)
585                    cellSizer.Add(volVal,0,wx.ALIGN_CENTER_VERTICAL)
586            return cellSizer
587           
588        def ElemSizer():
589           
590            def OnIsotope(event):
591                Obj = event.GetEventObject()
592                item = Indx[Obj.GetId()]
593                isotope = Obj.GetValue()
594                generalData['Isotope'][item] = isotope
595                indx = generalData['AtomTypes'].index(item)
596                data['General']['AtomMass'][indx] = generalData['Isotopes'][item][isotope][0]
597                dataDisplay.DestroyChildren()           #needed to clear away bad cellSizer, etc.
598                wx.CallAfter(UpdateGeneral)
599               
600            elemSizer = wx.FlexGridSizer(8,len(generalData['AtomTypes'])+1,1,1)
601            elemSizer.Add(wx.StaticText(dataDisplay,label=' Elements'),0,wx.ALIGN_CENTER_VERTICAL)
602            for elem in generalData['AtomTypes']:
603                typTxt = wx.TextCtrl(dataDisplay,value=elem,style=wx.TE_READONLY)
604                typTxt.SetBackgroundColour(VERY_LIGHT_GREY)
605                elemSizer.Add(typTxt,0,wx.ALIGN_CENTER_VERTICAL)
606            elemSizer.Add(wx.StaticText(dataDisplay,label=' Isotope'),0,wx.ALIGN_CENTER_VERTICAL)
607            for elem in generalData['AtomTypes']:
608                choices = generalData['Isotopes'][elem].keys()
609                isoSel = wx.ComboBox(dataDisplay,-1,value=generalData['Isotope'][elem],choices=choices,
610                    style=wx.CB_READONLY|wx.CB_DROPDOWN)
611                isoSel.Bind(wx.EVT_COMBOBOX,OnIsotope)
612                Indx[isoSel.GetId()] = elem
613                elemSizer.Add(isoSel,1,wx.ALIGN_CENTER_VERTICAL|wx.EXPAND)
614            elemSizer.Add(wx.StaticText(dataDisplay,label=' No. per cell'),0,wx.ALIGN_CENTER_VERTICAL)
615            for elem in generalData['AtomTypes']:
616                numbTxt = wx.TextCtrl(dataDisplay,value='%.1f'%(generalData['NoAtoms'][elem]),
617                    style=wx.TE_READONLY)
618                numbTxt.SetBackgroundColour(VERY_LIGHT_GREY)
619                elemSizer.Add(numbTxt,0,wx.ALIGN_CENTER_VERTICAL)
620            elemSizer.Add(wx.StaticText(dataDisplay,label=' Atom weight'),0,wx.ALIGN_CENTER_VERTICAL)
621            for wt in generalData['AtomMass']:
622                wtTxt = wx.TextCtrl(dataDisplay,value='%.3f'%(wt),style=wx.TE_READONLY)
623                wtTxt.SetBackgroundColour(VERY_LIGHT_GREY)
624                elemSizer.Add(wtTxt,0,wx.ALIGN_CENTER_VERTICAL)
625            elemSizer.Add(wx.StaticText(dataDisplay,label=' Bond radii'),0,wx.ALIGN_CENTER_VERTICAL)
626            for rad in generalData['BondRadii']:
627                bondRadii = wx.TextCtrl(dataDisplay,value='%.2f'%(rad),style=wx.TE_READONLY)
628                bondRadii.SetBackgroundColour(VERY_LIGHT_GREY)
629                elemSizer.Add(bondRadii,0,wx.ALIGN_CENTER_VERTICAL)
630            elemSizer.Add(wx.StaticText(dataDisplay,label=' Angle radii'),0,wx.ALIGN_CENTER_VERTICAL)
631            for rad in generalData['AngleRadii']:
632                elemTxt = wx.TextCtrl(dataDisplay,value='%.2f'%(rad),style=wx.TE_READONLY)
633                elemTxt.SetBackgroundColour(VERY_LIGHT_GREY)
634                elemSizer.Add(elemTxt,0,wx.ALIGN_CENTER_VERTICAL)
635            elemSizer.Add(wx.StaticText(dataDisplay,label=' van der Waals radii'),0,wx.ALIGN_CENTER_VERTICAL)
636            for rad in generalData['vdWRadii']:
637                elemTxt = wx.TextCtrl(dataDisplay,value='%.2f'%(rad),style=wx.TE_READONLY)
638                elemTxt.SetBackgroundColour(VERY_LIGHT_GREY)
639                elemSizer.Add(elemTxt,0,wx.ALIGN_CENTER_VERTICAL)
640            elemSizer.Add(wx.StaticText(dataDisplay,label=' Default color'),0,wx.ALIGN_CENTER_VERTICAL)
641            for R,G,B in generalData['Color']:
642                colorTxt = wx.TextCtrl(dataDisplay,value='',style=wx.TE_READONLY)
643                colorTxt.SetBackgroundColour(wx.Colour(R,G,B))
644                elemSizer.Add(colorTxt,0,wx.ALIGN_CENTER_VERTICAL)
645            return elemSizer
646           
647        def DenSizer():
648           
649            mass = 0.
650            for i,elem in enumerate(generalData['AtomTypes']):
651                mass += generalData['NoAtoms'][elem]*generalData['AtomMass'][i]
652            denSizer = wx.BoxSizer(wx.HORIZONTAL)
653            denSizer.Add(wx.StaticText(dataDisplay,-1,' Density: '),0,wx.ALIGN_CENTER_VERTICAL)
654            Volume = generalData['Cell'][7]
655            density = mass/(0.6022137*Volume)
656            denTxt = wx.TextCtrl(dataDisplay,-1,'%.3f'%(density),style=wx.TE_READONLY)
657            denTxt.SetBackgroundColour(VERY_LIGHT_GREY)
658            denSizer.Add(denTxt,0,wx.ALIGN_CENTER_VERTICAL)       
659            if generalData['Type'] == 'macromolecular' and mass > 0.0:
660                denSizer.Add(wx.StaticText(dataDisplay,-1,' Matthews coeff.: '),
661                    0,wx.ALIGN_CENTER_VERTICAL)
662                mattTxt = wx.TextCtrl(dataDisplay,-1,'%.3f'%(Volume/mass),style=wx.TE_READONLY)
663                mattTxt.SetBackgroundColour(VERY_LIGHT_GREY)
664                denSizer.Add(mattTxt,0,wx.ALIGN_CENTER_VERTICAL)
665            return denSizer
666           
667        def PawleySizer():
668           
669            def OnPawleyRef(event):
670                generalData['doPawley'] = pawlRef.GetValue()
671           
672            def OnPawleyVal(event):
673                try:
674                    dmin = float(pawlVal.GetValue())
675                    if 0.25 <= dmin <= 20.:
676                        generalData['Pawley dmin'] = dmin
677                except ValueError:
678                    pass
679                pawlVal.SetValue("%.3f"%(generalData['Pawley dmin']))          #reset in case of error               
680           
681            pawleySizer = wx.BoxSizer(wx.HORIZONTAL)
682            pawleySizer.Add(wx.StaticText(dataDisplay,label=' Pawley controls: '),0,wx.ALIGN_CENTER_VERTICAL)
683            pawlRef = wx.CheckBox(dataDisplay,-1,label=' Do Pawley refinement?')
684            pawlRef.SetValue(generalData['doPawley'])
685            pawlRef.Bind(wx.EVT_CHECKBOX,OnPawleyRef)
686            pawleySizer.Add(pawlRef,0,wx.ALIGN_CENTER_VERTICAL)
687            pawleySizer.Add(wx.StaticText(dataDisplay,label=' Pawley dmin: '),0,wx.ALIGN_CENTER_VERTICAL)
688            pawlVal = wx.TextCtrl(dataDisplay,value='%.3f'%(generalData['Pawley dmin']),style=wx.TE_PROCESS_ENTER)
689            pawlVal.Bind(wx.EVT_TEXT_ENTER,OnPawleyVal)       
690            pawlVal.Bind(wx.EVT_KILL_FOCUS,OnPawleyVal)
691            pawleySizer.Add(pawlVal,0,wx.ALIGN_CENTER_VERTICAL)
692            return pawleySizer
693           
694        def MapSizer():
695           
696            def OnMapType(event):
697                Map['MapType'] = mapType.GetValue()
698               
699            def OnRefList(event):
700                Map['RefList'] = refList.GetValue()
701               
702            def OnResVal(event):
703                try:
704                    res = float(mapRes.GetValue())
705                    if 0.25 <= res <= 20.:
706                        Map['Resolution'] = res
707                except ValueError:
708                    pass
709                mapRes.SetValue("%.2f"%(Map['Resolution']))          #reset in case of error
710           
711            def OnCutOff(event):
712                try:
713                    res = float(cutOff.GetValue())
714                    if 1.0 <= res <= 100.:
715                        Map['cutOff'] = res
716                except ValueError:
717                    pass
718                cutOff.SetValue("%.1f"%(Map['cutOff']))          #reset in case of error
719           
720            #patch
721            if 'cutOff' not in Map:
722                Map['cutOff'] = 100.0
723            mapTypes = ['Fobs','Fcalc','delt-F','2*Fo-Fc','Patterson']
724            refList = data['Histograms'].keys()
725            if not generalData['AtomTypes']:
726                 mapTypes = ['Patterson',]
727                 Map['MapType'] = 'Patterson'
728            mapSizer = wx.BoxSizer(wx.VERTICAL)
729            lineSizer = wx.BoxSizer(wx.HORIZONTAL)
730            lineSizer.Add(wx.StaticText(dataDisplay,label=' Fourier map controls: Map type: '),0,wx.ALIGN_CENTER_VERTICAL)
731            mapType = wx.ComboBox(dataDisplay,-1,value=Map['MapType'],choices=mapTypes,
732                style=wx.CB_READONLY|wx.CB_DROPDOWN)
733            mapType.Bind(wx.EVT_COMBOBOX,OnMapType)
734            lineSizer.Add(mapType,0,wx.ALIGN_CENTER_VERTICAL)
735            lineSizer.Add(wx.StaticText(dataDisplay,label=' Reflection set from: '),0,wx.ALIGN_CENTER_VERTICAL)
736            refList = wx.ComboBox(dataDisplay,-1,value=Map['RefList'],choices=refList,
737                style=wx.CB_READONLY|wx.CB_DROPDOWN)
738            refList.Bind(wx.EVT_COMBOBOX,OnRefList)
739            lineSizer.Add(refList,0,wx.ALIGN_CENTER_VERTICAL)
740            mapSizer.Add(lineSizer,0,wx.ALIGN_CENTER_VERTICAL)
741            line2Sizer = wx.BoxSizer(wx.HORIZONTAL)
742            line2Sizer.Add(wx.StaticText(dataDisplay,label=' Resolution: '),0,wx.ALIGN_CENTER_VERTICAL)
743            mapRes =  wx.TextCtrl(dataDisplay,value='%.2f'%(Map['Resolution']),style=wx.TE_PROCESS_ENTER)
744            mapRes.Bind(wx.EVT_TEXT_ENTER,OnResVal)       
745            mapRes.Bind(wx.EVT_KILL_FOCUS,OnResVal)
746            line2Sizer.Add(mapRes,0,wx.ALIGN_CENTER_VERTICAL)
747            line2Sizer.Add(wx.StaticText(dataDisplay,label=' Peak cutoff %: '),0,wx.ALIGN_CENTER_VERTICAL)
748            cutOff =  wx.TextCtrl(dataDisplay,value='%.1f'%(Map['cutOff']),style=wx.TE_PROCESS_ENTER)
749            cutOff.Bind(wx.EVT_TEXT_ENTER,OnCutOff)       
750            cutOff.Bind(wx.EVT_KILL_FOCUS,OnCutOff)
751            line2Sizer.Add(cutOff,0,wx.ALIGN_CENTER_VERTICAL)
752            mapSizer.Add(line2Sizer,0,wx.ALIGN_CENTER_VERTICAL)
753            return mapSizer
754               
755        def FlipSizer():
756           
757            def OnRefList(event):
758                Flip['RefList'] = refList.GetValue()
759               
760            def OnNormElem(event):
761                PE = G2elemGUI.PickElement(G2frame,ifNone=True)
762                if PE.ShowModal() == wx.ID_OK:
763                    Flip['Norm element'] = PE.Elem.strip()
764                    normElem.SetLabel(Flip['Norm element'])
765                PE.Destroy()               
766               
767            def OnResVal(event):
768                try:
769                    res = float(flipRes.GetValue())
770                    if 0.25 <= res <= 20.:
771                        Flip['Resolution'] = res
772                except ValueError:
773                    pass
774                flipRes.SetValue("%.2f"%(Flip['Resolution']))          #reset in case of error
775           
776            def OnkFactor(event):
777                try:
778                    res = float(kFactor.GetValue())
779                    if 0.1 <= res <= 1.2:
780                        Flip['k-factor'] = res
781                except ValueError:
782                    pass
783                kFactor.SetValue("%.3f"%(Flip['k-factor']))          #reset in case of error
784           
785            refList = data['Histograms'].keys()
786            flipSizer = wx.BoxSizer(wx.VERTICAL)
787            lineSizer = wx.BoxSizer(wx.HORIZONTAL)
788            lineSizer.Add(wx.StaticText(dataDisplay,label=' Charge flip controls: Reflection set from: '),0,wx.ALIGN_CENTER_VERTICAL)
789            refList = wx.ComboBox(dataDisplay,-1,value=Flip['RefList'],choices=refList,
790                style=wx.CB_READONLY|wx.CB_DROPDOWN)
791            refList.Bind(wx.EVT_COMBOBOX,OnRefList)
792            lineSizer.Add(refList,0,wx.ALIGN_CENTER_VERTICAL)
793            flipSizer.Add(lineSizer,0,wx.ALIGN_CENTER_VERTICAL)
794            line2Sizer = wx.BoxSizer(wx.HORIZONTAL)
795            line2Sizer.Add(wx.StaticText(dataDisplay,label=' Normalizing element: '),0,wx.ALIGN_CENTER_VERTICAL)
796            normElem = wx.Button(dataDisplay,label=Flip['Norm element'],style=wx.TE_READONLY)
797            normElem.Bind(wx.EVT_BUTTON,OnNormElem)
798            line2Sizer.Add(normElem,0,wx.ALIGN_CENTER_VERTICAL)
799            line2Sizer.Add(wx.StaticText(dataDisplay,label=' Resolution: '),0,wx.ALIGN_CENTER_VERTICAL)
800            flipRes =  wx.TextCtrl(dataDisplay,value='%.2f'%(Flip['Resolution']),style=wx.TE_PROCESS_ENTER)
801            flipRes.Bind(wx.EVT_TEXT_ENTER,OnResVal)       
802            flipRes.Bind(wx.EVT_KILL_FOCUS,OnResVal)
803            line2Sizer.Add(flipRes,0,wx.ALIGN_CENTER_VERTICAL)
804            line2Sizer.Add(wx.StaticText(dataDisplay,label=' k-Factor (0.1-1.2): '),0,wx.ALIGN_CENTER_VERTICAL)
805            kFactor =  wx.TextCtrl(dataDisplay,value='%.3f'%(Flip['k-factor']),style=wx.TE_PROCESS_ENTER)
806            kFactor.Bind(wx.EVT_TEXT_ENTER,OnkFactor)       
807            kFactor.Bind(wx.EVT_KILL_FOCUS,OnkFactor)
808            line2Sizer.Add(kFactor,0,wx.ALIGN_CENTER_VERTICAL)
809            flipSizer.Add(line2Sizer,0,wx.ALIGN_CENTER_VERTICAL)
810            return flipSizer
811               
812        General.DestroyChildren()
813        dataDisplay = wx.Panel(General)
814        mainSizer = wx.BoxSizer(wx.VERTICAL)
815        mainSizer.Add((5,5),0)
816        mainSizer.Add(NameSizer(),0)
817        mainSizer.Add((5,5),0)       
818        mainSizer.Add(CellSizer(),0)
819        mainSizer.Add((5,5),0)
820       
821        Indx = {}
822        if len(generalData['AtomTypes']):
823            mainSizer.Add(DenSizer())
824            mainSizer.Add((5,5),0)           
825            mainSizer.Add(ElemSizer())
826           
827        mainSizer.Add((5,5),0)
828        mainSizer.Add(PawleySizer())
829
830        mainSizer.Add((5,5),0)
831        mainSizer.Add(MapSizer())
832
833        mainSizer.Add((5,5),0)
834        mainSizer.Add(FlipSizer())
835
836        dataDisplay.SetSizer(mainSizer)
837        Size = mainSizer.Fit(G2frame.dataFrame)
838        Size[1] += 26                           #compensate for status bar
839        dataDisplay.SetSize(Size)
840        G2frame.dataFrame.setSizePosLeft(Size)
841
842################################################################################
843#####  Atom routines
844################################################################################
845
846    def FillAtomsGrid():
847
848        G2frame.dataFrame.setSizePosLeft([700,300])
849        generalData = data['General']
850        atomData = data['Atoms']
851        Items = [G2gd.wxID_ATOMSEDITINSERT, G2gd.wxID_ATOMSEDITDELETE, G2gd.wxID_ATOMSREFINE, 
852            G2gd.wxID_ATOMSMODIFY, G2gd.wxID_ATOMSTRANSFORM, G2gd.wxID_ATONTESTINSERT]
853        if atomData:
854            for item in Items:   
855                G2frame.dataFrame.AtomsMenu.Enable(item,True)
856        else:
857            for item in Items:
858                G2frame.dataFrame.AtomsMenu.Enable(item,False)           
859           
860        AAchoice = ": ,ALA,ARG,ASN,ASP,CYS,GLN,GLU,GLY,HIS,ILE,LEU,LYS,MET,PHE,PRO,SER,THR,TRP,TYR,VAL,MSE,HOH,UNK"
861        Types = [wg.GRID_VALUE_STRING,wg.GRID_VALUE_STRING,wg.GRID_VALUE_CHOICE+": ,X,XU,U,F,FX,FXU,FU",]+ \
862            3*[wg.GRID_VALUE_FLOAT+':10,5',]+[wg.GRID_VALUE_FLOAT+':10,4', #x,y,z,frac
863            wg.GRID_VALUE_STRING,wg.GRID_VALUE_STRING,wg.GRID_VALUE_CHOICE+":I,A",]
864        Types += 7*[wg.GRID_VALUE_FLOAT+':10,5',]
865        colLabels = ['Name','Type','refine','x','y','z','frac','site sym','mult','I/A','Uiso','U11','U22','U33','U12','U13','U23']
866        if generalData['Type'] == 'magnetic':
867            colLabels += ['Mx','My','Mz']
868            Types[2] = wg.GRID_VALUE_CHOICE+": ,X,XU,U,M,MX,MXU,MU,F,FX,FXU,FU,FM,FMX,FMU,"
869            Types += 3*[wg.GRID_VALUE_FLOAT+':10,4',]
870        elif generalData['Type'] == 'macromolecular':
871            colLabels = ['res no','residue','chain'] + colLabels
872            Types = [wg.GRID_VALUE_STRING,
873                wg.GRID_VALUE_CHOICE+AAchoice,
874                wg.GRID_VALUE_STRING] + Types
875        elif generalData['Type'] == 'modulated':
876            Types += []
877            colLabels += []
878
879        def RefreshAtomGrid(event):
880
881            r,c =  event.GetRow(),event.GetCol()
882            if r < 0 and c < 0:
883                for row in range(Atoms.GetNumberRows()):
884                    Atoms.SelectRow(row,True)                   
885            if r < 0:                          #double click on col label! Change all atoms!
886                sel = -1
887                noSkip = True
888                if Atoms.GetColLabelValue(c) == 'refine':
889                    Type = generalData['Type']
890                    if Type in ['nuclear','macromolecular']:
891                        choice = ['F - site fraction','X - coordinates','U - thermal parameters']
892                    elif Type in ['magnetic',]:
893                        choice = ['F - site fraction','X - coordinates','U - thermal parameters','M - magnetic moment']
894                    dlg = wx.MultiChoiceDialog(G2frame,'Select','Refinement controls',choice)
895                    if dlg.ShowModal() == wx.ID_OK:
896                        sel = dlg.GetSelections()
897                        parms = ''
898                        for x in sel:
899                            parms += choice[x][0]
900                    dlg.Destroy()
901                elif Atoms.GetColLabelValue(c) == 'I/A':
902                    choice = ['Isotropic','Anisotropic']
903                    dlg = wx.SingleChoiceDialog(G2frame,'Select','Thermal Motion',choice)
904                    if dlg.ShowModal() == wx.ID_OK:
905                        sel = dlg.GetSelection()
906                        parms = choice[sel][0]
907                    dlg.Destroy()
908                elif Atoms.GetColLabelValue(c) == 'Type':
909                    choice = generalData['AtomTypes']
910                    dlg = wx.SingleChoiceDialog(G2frame,'Select','Atom types',choice)
911                    if dlg.ShowModal() == wx.ID_OK:
912                        sel = dlg.GetSelection()
913                        parms = choice[sel]
914                        noSkip = False
915                        Atoms.ClearSelection()
916                        for row in range(Atoms.GetNumberRows()):
917                            if parms == atomData[row][c]:
918                                Atoms.SelectRow(row,True)
919                    dlg.Destroy()
920                    SetupGeneral()
921                elif Atoms.GetColLabelValue(c) == 'residue':
922                    choice = []
923                    for r in range(Atoms.GetNumberRows()):
924                        if str(atomData[r][c]) not in choice:
925                            choice.append(str(atomData[r][c]))
926                    choice.sort()
927                    dlg = wx.SingleChoiceDialog(G2frame,'Select','Residue',choice)
928                    if dlg.ShowModal() == wx.ID_OK:
929                        sel = dlg.GetSelection()
930                        parms = choice[sel]
931                        noSkip = False
932                        Atoms.ClearSelection()
933                        for row in range(Atoms.GetNumberRows()):
934                            if parms == atomData[row][c]:
935                                Atoms.SelectRow(row,True)
936                    dlg.Destroy()
937                elif Atoms.GetColLabelValue(c) == 'res no':
938                    choice = []
939                    for r in range(Atoms.GetNumberRows()):
940                        if str(atomData[r][c]) not in choice:
941                            choice.append(str(atomData[r][c]))
942                    dlg = wx.SingleChoiceDialog(G2frame,'Select','Residue no.',choice)
943                    if dlg.ShowModal() == wx.ID_OK:
944                        sel = dlg.GetSelection()
945                        parms = choice[sel]
946                        noSkip = False
947                        Atoms.ClearSelection()
948                        for row in range(Atoms.GetNumberRows()):
949                            if int(parms) == atomData[row][c]:
950                                Atoms.SelectRow(row,True)
951                    dlg.Destroy()
952                elif Atoms.GetColLabelValue(c) == 'chain':
953                    choice = []
954                    for r in range(Atoms.GetNumberRows()):
955                        if atomData[r][c] not in choice:
956                            choice.append(atomData[r][c])
957                    dlg = wx.SingleChoiceDialog(G2frame,'Select','Chain',choice)
958                    if dlg.ShowModal() == wx.ID_OK:
959                        sel = dlg.GetSelection()
960                        parms = choice[sel]
961                        noSkip = False
962                        Atoms.ClearSelection()
963                        for row in range(Atoms.GetNumberRows()):
964                            if parms == atomData[row][c]:
965                                Atoms.SelectRow(row,True)
966                    dlg.Destroy()
967                elif Atoms.GetColLabelValue(c) == 'Uiso':       #this needs to ask for value
968                    pass                                        #& then change all 'I' atoms
969                if sel >= 0 and noSkip:
970                    ui = colLabels.index('U11')
971                    us = colLabels.index('Uiso')
972                    ss = colLabels.index('site sym')
973                    for r in range(Atoms.GetNumberRows()):
974                        ID = atomData[r][-1]
975                        if parms != atomData[r][c] and Atoms.GetColLabelValue(c) == 'I/A':
976                            if parms == 'A':                #'I' --> 'A'
977                                Uiso = float(Atoms.GetCellValue(r,us))
978                                sytsym = atomData[r][ss]
979                                CSI = G2spc.GetCSuinel(sytsym)
980                                atomData[r][ui:ui+6] = Uiso*np.array(CSI[3])
981                                atomData[r][us] = 0.0
982                                Atoms.SetCellStyle(r,us,VERY_LIGHT_GREY,True)
983                                for i in range(6):
984                                    ci = ui+i
985                                    Atoms.SetCellStyle(r,ci,VERY_LIGHT_GREY,True)
986                                    if CSI[2][i]:
987                                        Atoms.SetCellStyle(r,ci,WHITE,False)
988                            else:                           #'A' --> 'I'
989                                Uij = atomData[r][ui:ui+6]
990                                Uiso = (Uij[0]+Uij[1]+Uij[2])/3.0
991                                atomData[r][us] = Uiso
992                                Atoms.SetCellStyle(r,us,WHITE,False)
993                                for i in range(6):
994                                    ci = ui+i
995                                    atomData[r][ci] = 0.0
996                                    Atoms.SetCellStyle(r,ci,VERY_LIGHT_GREY,True)
997                        atomData[r][c] = parms
998                        if 'Atoms' in data['Drawing']:
999                            DrawAtomsReplaceByID(data['Drawing'],atomData[r],ID)
1000                    FillAtomsGrid()
1001                   
1002        def ChangeAtomCell(event):
1003           
1004            def chkUij(Uij,CSI): #needs to do something!!!
1005                return Uij
1006
1007            r,c =  event.GetRow(),event.GetCol()
1008            if r >= 0 and c >= 0:
1009                ID = atomData[r][-1]
1010                if Atoms.GetColLabelValue(c) in ['x','y','z']:
1011                    ci = colLabels.index('x')
1012                    XYZ = atomData[r][ci:ci+3]
1013                    if None in XYZ:
1014                        XYZ = [0,0,0]
1015                    SScol = colLabels.index('site sym')
1016                    Mulcol = colLabels.index('mult')
1017                    E,SGData = G2spc.SpcGroup(generalData['SGData']['SpGrp'])
1018                    Sytsym,Mult = G2spc.SytSym(XYZ,SGData)
1019                    atomData[r][SScol] = Sytsym
1020                    atomData[r][Mulcol] = Mult
1021                    if atomData[r][colLabels.index('I/A')] == 'A':
1022                        ui = colLabels.index('U11')
1023                        CSI = G2spc.GetCSuinel(Sytsym)
1024                        atomData[r][ui:ui+6] = chkUij(atomData[r][ui:ui+6],Sytsym)
1025                        for i in range(6):
1026                            ci = i+ui
1027                            Atoms.SetCellStyle(r,ci,VERY_LIGHT_GREY,True)
1028                            if CSI[2][i]:
1029                                Atoms.SetCellStyle(r,ci,WHITE,False)
1030                    SetupGeneral()
1031                elif Atoms.GetColLabelValue(c) == 'I/A':            #note use of text color to make it vanish!
1032                    if atomData[r][c] == 'I':
1033                        Uij = atomData[r][c+2:c+8]
1034                        atomData[r][c+1] = (Uij[0]+Uij[1]+Uij[2])/3.0
1035                        Atoms.SetCellStyle(r,c+1,WHITE,False)
1036                        Atoms.SetCellTextColour(r,c+1,BLACK)
1037                        for i in range(6):
1038                            ci = i+colLabels.index('U11')
1039                            Atoms.SetCellStyle(r,ci,VERY_LIGHT_GREY,True)
1040                            Atoms.SetCellTextColour(r,ci,VERY_LIGHT_GREY)
1041                            atomData[r][ci] = 0.0
1042                    else:
1043                        value = atomData[r][c+1]
1044                        CSI = G2spc.GetCSuinel(atomData[r][colLabels.index('site sym')])
1045                        atomData[r][c+1] =  0.0
1046                        Atoms.SetCellStyle(r,c+1,VERY_LIGHT_GREY,True)
1047                        Atoms.SetCellTextColour(r,c+1,VERY_LIGHT_GREY)
1048                        for i in range(6):
1049                            ci = i+colLabels.index('U11')
1050                            atomData[r][ci] = value*CSI[3][i]
1051                            Atoms.SetCellStyle(r,ci,VERY_LIGHT_GREY,True)
1052                            Atoms.SetCellTextColour(r,ci,BLACK)
1053                            if CSI[2][i]:
1054                                Atoms.SetCellStyle(r,ci,WHITE,False)
1055                elif Atoms.GetColLabelValue(c) in ['U11','U22','U33','U12','U13','U23']:
1056                    value = atomData[r][c]
1057                    CSI = G2spc.GetCSuinel(atomData[r][colLabels.index('site sym')])
1058                    iUij = CSI[0][c-colLabels.index('U11')]
1059                    for i in range(6):
1060                        if iUij == CSI[0][i]:
1061                            atomData[r][i+colLabels.index('U11')] = value*CSI[1][i]
1062                if 'Atoms' in data['Drawing']:
1063                    DrawAtomsReplaceByID(data['Drawing'],atomData[r],ID)
1064                    FindBondsDraw()
1065                   
1066        def AtomTypeSelect(event):
1067            r,c =  event.GetRow(),event.GetCol()
1068            if Atoms.GetColLabelValue(c) == 'Type':
1069                PE = G2elemGUI.PickElement(G2frame)
1070                if PE.ShowModal() == wx.ID_OK:
1071                    if PE.Elem not in 'None':                       
1072                        atomData[r][c] = PE.Elem.strip()
1073                        name = atomData[r][c]
1074                        if len(name) in [2,4]:
1075                            atomData[r][c-1] = name[:2]+'(%d)'%(r+1)
1076                        else:
1077                            atomData[r][c-1] = name[:1]+'(%d)'%(r+1)
1078                PE.Destroy()
1079                SetupGeneral()
1080                FillAtomsGrid()
1081                value = Atoms.GetCellValue(r,c)
1082                atomData[r][c] = value
1083                ID = atomData[r][-1]
1084                if 'Atoms' in data['Drawing']:
1085                    DrawAtomsReplaceByID(data['Drawing'],atomData[r],ID)
1086                SetupGeneral()
1087            else:
1088                event.Skip()
1089
1090        def RowSelect(event):
1091            r,c =  event.GetRow(),event.GetCol()
1092            if r < 0 and c < 0:
1093                if Atoms.IsSelection():
1094                    Atoms.ClearSelection()
1095            elif c < 0:                   #only row clicks
1096                if event.ControlDown():                   
1097                    if r in Atoms.GetSelectedRows():
1098                        Atoms.DeselectRow(r)
1099                    else:
1100                        Atoms.SelectRow(r,True)
1101                elif event.ShiftDown():
1102                    for row in range(r+1):
1103                        Atoms.SelectRow(row,True)
1104                else:
1105                    Atoms.ClearSelection()
1106                    Atoms.SelectRow(r,True)               
1107               
1108        def ChangeSelection(event):
1109            r,c =  event.GetRow(),event.GetCol()
1110            if r < 0 and c < 0:
1111                Atoms.ClearSelection()
1112            if c < 0:
1113                if r in Atoms.GetSelectedRows():
1114                    Atoms.DeselectRow(r)
1115                else:
1116                    Atoms.SelectRow(r,True)
1117            if r < 0:
1118                if c in Atoms.GetSelectedCols():
1119                    Atoms.DeselectCol(c)
1120                else:
1121                    Atoms.SelectCol(c,True)
1122       
1123        SGData = data['General']['SGData']
1124        if SGData['SGPolax']:
1125            G2frame.dataFrame.SetStatusText('Warning: The location of the origin is arbitrary in '+SGData['SGPolax'])
1126        table = []
1127        rowLabels = []
1128        for i,atom in enumerate(atomData):
1129            table.append(atom)
1130            rowLabels.append(str(i))
1131        atomTable = G2gd.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
1132        Atoms.SetTable(atomTable, True)
1133        Atoms.Bind(wg.EVT_GRID_CELL_CHANGE, ChangeAtomCell)
1134        Atoms.Bind(wg.EVT_GRID_CELL_LEFT_DCLICK, AtomTypeSelect)
1135        Atoms.Bind(wg.EVT_GRID_LABEL_LEFT_DCLICK, RefreshAtomGrid)
1136        Atoms.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK, RowSelect)
1137        Atoms.Bind(wg.EVT_GRID_LABEL_RIGHT_CLICK, ChangeSelection)
1138        Atoms.SetMargins(0,0)
1139        Atoms.AutoSizeColumns(False)
1140        colType = colLabels.index('Type')
1141        colSS = colLabels.index('site sym')
1142        colIA = colLabels.index('I/A')
1143        colU11 = colLabels.index('U11')
1144        colUiso = colLabels.index('Uiso')
1145        for i in range(colU11-1,colU11+6):
1146            Atoms.SetColSize(i,50)           
1147        for row in range(Atoms.GetNumberRows()):
1148            Atoms.SetReadOnly(row,colType,True)
1149            Atoms.SetReadOnly(row,colSS,True)                         #site sym
1150            Atoms.SetReadOnly(row,colSS+1,True)                       #Mult
1151            if Atoms.GetCellValue(row,colIA) == 'A':
1152                CSI = G2spc.GetCSuinel(atomData[row][colLabels.index('site sym')])
1153                Atoms.SetCellStyle(row,colUiso,VERY_LIGHT_GREY,True)
1154                Atoms.SetCellTextColour(row,colUiso,VERY_LIGHT_GREY)
1155                for i in range(6):
1156                    ci = colU11+i
1157                    Atoms.SetCellTextColour(row,ci,BLACK)
1158                    Atoms.SetCellStyle(row,ci,VERY_LIGHT_GREY,True)
1159                    if CSI[2][i]:
1160                        Atoms.SetCellStyle(row,ci,WHITE,False)
1161            else:
1162                Atoms.SetCellStyle(row,colUiso,WHITE,False)
1163                Atoms.SetCellTextColour(row,colUiso,BLACK)
1164                for i in range(6):
1165                    ci = colU11+i
1166                    Atoms.SetCellStyle(row,ci,VERY_LIGHT_GREY,True)
1167                    Atoms.SetCellTextColour(row,ci,VERY_LIGHT_GREY)
1168
1169    def OnAtomAdd(event):
1170        AtomAdd(0,0,0)
1171        FillAtomsGrid()
1172        event.StopPropagation()
1173       
1174    def OnAtomTestAdd(event):
1175        try:
1176            drawData = data['Drawing']
1177            x,y,z = drawData['testPos'][0]
1178            AtomAdd(x,y,z)
1179        except:
1180            AtomAdd(0,0,0)
1181        FillAtomsGrid()
1182        event.StopPropagation()
1183               
1184    def AtomAdd(x,y,z,El='H'):
1185        atomData = data['Atoms']
1186        generalData = data['General']
1187        Ncol = Atoms.GetNumberCols()
1188        atId = ran.randint(0,sys.maxint)
1189        E,SGData = G2spc.SpcGroup(generalData['SGData']['SpGrp'])
1190        Sytsym,Mult = G2spc.SytSym([x,y,z],SGData)
1191        if generalData['Type'] == 'macromolecular':
1192            atomData.append([0,'UNK','','UNK',El,'',x,y,z,1,Sytsym,Mult,'I',0.10,0,0,0,0,0,0,atId])
1193        elif generalData['Type'] == 'nuclear':
1194            atomData.append(['UNK',El,'',x,y,z,1,Sytsym,Mult,'I',0.01,0,0,0,0,0,0,atId])
1195        elif generalData['Type'] == 'magnetic':
1196            atomData.append(['UNK',El,'',x,y,z,1,Sytsym,Mult,0,'I',0.01,0,0,0,0,0,0,0,0,0,atId])
1197        SetupGeneral()
1198        if 'Atoms' in data['Drawing']:           
1199            DrawAtomAdd(data['Drawing'],atomData[-1])
1200            G2plt.PlotStructure(G2frame,data)
1201
1202    def OnAtomInsert(event):
1203        AtomInsert(0,0,0)
1204        FillAtomsGrid()
1205        event.StopPropagation()
1206       
1207    def OnAtomTestInsert(event):
1208        if 'Drawing' in data:
1209            drawData = data['Drawing']
1210            x,y,z = drawData['testPos'][0]
1211            AtomAdd(x,y,z)
1212            FillAtomsGrid()
1213        event.StopPropagation()
1214           
1215    def AtomInsert(x,y,z):
1216        indx = Atoms.GetSelectedRows()
1217        if indx:
1218            indx = indx[0]
1219            atomData = data['Atoms']
1220            generalData = data['General']
1221            Ncol = Atoms.GetNumberCols()
1222            E,SGData = G2spc.SpcGroup(generalData['SGData']['SpGrp'])
1223            Sytsym,Mult = G2spc.SytSym([0,0,0],SGData)
1224            atId = ran.randint(0,sys.maxint)
1225            if generalData['Type'] == 'macromolecular':
1226                atomData.insert(indx,[0,'UNK','','UNK','UNK','',x,y,z,1,Sytsym,Mult,'I',0.10,0,0,0,0,0,0,atId])
1227            elif generalData['Type'] == 'nuclear':
1228                atomData.insert(indx,['UNK','UNK','',x,y,z,1,Sytsym,Mult,'I',0.01,0,0,0,0,0,0,atId])
1229            elif generalData['Type'] == 'magnetic':
1230                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])
1231            SetupGeneral()
1232
1233    def AtomDelete(event):
1234        indx = Atoms.GetSelectedRows()
1235        IDs = []
1236        if indx:
1237            atomData = data['Atoms']
1238            indx.reverse()
1239            for ind in indx:
1240                atom = atomData[ind]
1241                IDs.append(atom[-1])
1242                del atomData[ind]
1243            if 'Atoms' in data['Drawing']:
1244                DrawAtomsDeleteByIDs(IDs)
1245                FillAtomsGrid()
1246                G2plt.PlotStructure(G2frame,data)
1247            SetupGeneral()
1248        event.StopPropagation()
1249
1250    def AtomRefine(event):
1251        colLabels = [Atoms.GetColLabelValue(c) for c in range(Atoms.GetNumberCols())]
1252        c = colLabels.index('refine')
1253        indx = Atoms.GetSelectedRows()
1254        if indx:
1255            atomData = data['Atoms']
1256            generalData = data['General']
1257            Type = generalData['Type']
1258            if Type in ['nuclear','macromolecular']:
1259                choice = ['F - site fraction','X - coordinates','U - thermal parameters']
1260            elif Type == 'magnetic':
1261                choice = ['F - site fraction','X - coordinates','U - thermal parameters','M - magnetic moment']
1262            dlg = wx.MultiChoiceDialog(G2frame,'Select','Refinement controls',choice)
1263            if dlg.ShowModal() == wx.ID_OK:
1264                sel = dlg.GetSelections()
1265                parms = ''
1266                for x in sel:
1267                    parms += choice[x][0]
1268                for r in indx:
1269                    atomData[r][c] = parms
1270                Atoms.ForceRefresh()
1271            dlg.Destroy()
1272
1273    def AtomModify(event):                  #intent to implement global modifications (+,-,*,/, etc.)?
1274        indx = Atoms.GetSelectedRows()
1275        if indx:
1276            atomData = data['Atoms']
1277            generalData = data['General']
1278            colLabels = [Atoms.GetColLabelValue(c) for c in range(Atoms.GetNumberCols())]
1279            choices = ['Type','x','y','z','frac','I/A','Uiso']
1280            dlg = wx.SingleChoiceDialog(G2frame,'Select','Atom parameter',choices)
1281            if dlg.ShowModal() == wx.ID_OK:
1282                sel = dlg.GetSelection()
1283                parm = choices[sel]
1284                cid = colLabels.index(parm)
1285            dlg.Destroy()
1286            if parm in ['Type']:
1287                dlg = G2elemGUI.PickElement(G2frame)
1288                if dlg.ShowModal() == wx.ID_OK:
1289                    if dlg.Elem not in ['None']:
1290                        El = dlg.Elem.strip()
1291                        for r in indx:                       
1292                            atomData[r][cid] = El
1293                            if len(El) in [2,4]:
1294                                atomData[r][cid-1] = El[:2]+'(%d)'%(r+1)
1295                            else:
1296                                atomData[r][cid-1] = El[:1]+'(%d)'%(r+1)
1297                        SetupGeneral()
1298                        if 'Atoms' in data['Drawing']:
1299                            for r in indx:
1300                                ID = atomData[r][-1]
1301                                DrawAtomsReplaceByID(data['Drawing'],atomData[r],ID)
1302                    FillAtomsGrid()
1303                dlg.Destroy()
1304            elif parm in ['I/A']:
1305                choices = ['Isotropic','Anisotropic']
1306                dlg = wx.SingleChoiceDialog(G2frame,'Select','Thermal parameter model',choices)
1307                if dlg.ShowModal() == wx.ID_OK:
1308                    sel = dlg.GetSelection()
1309                    parm = choices[sel][0]
1310                    for r in indx:                       
1311                        atomData[r][cid] = parm
1312                    FillAtomsGrid()
1313                dlg.Destroy()
1314            elif parm in ['frac','Uiso']:
1315                limits = [0.,1.]
1316                val = 1.0
1317                if  parm in ['Uiso']:
1318                    limits = [0.,0.25]
1319                    val = 0.01
1320                dlg = SingleFloatDialog(G2frame,'New value','Enter new value for '+parm,val,limits)
1321                if dlg.ShowModal() == wx.ID_OK:
1322                    parm = dlg.GetValue()
1323                    for r in indx:                       
1324                        atomData[r][cid] = parm
1325                    SetupGeneral()
1326                    FillAtomsGrid()
1327                dlg.Destroy()
1328            elif parm in ['x','y','z']:
1329                limits = [-1.,1.]
1330                val = 0.
1331                dlg = SingleFloatDialog(G2frame,'Atom shift','Enter shift for '+parm,val,limits)
1332                if dlg.ShowModal() == wx.ID_OK:
1333                    parm = dlg.GetValue()
1334                    for r in indx:                       
1335                        atomData[r][cid] += parm
1336                    SetupGeneral()
1337                    FillAtomsGrid()
1338                dlg.Destroy()
1339
1340    def AtomTransform(event):
1341        indx = Atoms.GetSelectedRows()
1342        if indx:
1343            generalData = data['General']
1344            colLabels = [Atoms.GetColLabelValue(c) for c in range(Atoms.GetNumberCols())]
1345            cx = colLabels.index('x')
1346            cuia = colLabels.index('I/A')
1347            cuij = colLabels.index('U11')
1348            css = colLabels.index('site sym')
1349            atomData = data['Atoms']
1350            generalData = data['General']
1351            SGData = generalData['SGData']
1352            dlg = SymOpDialog(G2frame,SGData,True)
1353            try:
1354                if dlg.ShowModal() == wx.ID_OK:
1355                    Inv,Cent,Opr,Cell,New = dlg.GetSelection()
1356                    Cell = np.array(Cell)
1357                    cent = SGData['SGCen'][Cent]
1358                    M,T = SGData['SGOps'][Opr]
1359                    for ind in indx:
1360                        XYZ = np.array(atomData[ind][cx:cx+3])
1361                        XYZ = np.inner(M,XYZ)+T
1362                        if Inv:
1363                            XYZ = -XYZ
1364                        XYZ = XYZ+cent+Cell
1365                        if New:
1366                            atom = copy.copy(atomData[ind])
1367                        else:
1368                            atom = atomData[ind]
1369                        atom[cx:cx+3] = XYZ
1370                        atom[css:css+2] = G2spc.SytSym(XYZ,SGData)
1371                        if atom[cuia] == 'A':
1372                            Uij = atom[cuij:cuij+6]
1373                            U = G2spc.Uij2U(Uij)
1374                            U = np.inner(np.inner(M,U),M)
1375                            Uij = G2spc.U2Uij(U)
1376                            atom[cuij:cuij+6] = Uij
1377                        if New:
1378                            atomData.append(atom)
1379            finally:
1380                dlg.Destroy()
1381            Atoms.ClearSelection()
1382            if New:
1383                FillAtomsGrid()
1384            else:
1385                Atoms.ForceRefresh()
1386
1387    def OnDistAngle(event):
1388        indx = Atoms.GetSelectedRows()
1389        Oxyz = []
1390        xyz = []
1391        DisAglData = {}
1392        DisAglCtls = {}
1393        if indx:
1394            generalData = data['General']
1395            DisAglData['OrigIndx'] = indx
1396            if 'DisAglCtls' in generalData:
1397                DisAglCtls = generalData['DisAglCtls']
1398            dlg = DisAglDialog(G2frame,DisAglCtls,generalData)
1399            if dlg.ShowModal() == wx.ID_OK:
1400                DisAglCtls = dlg.GetData()
1401            dlg.Destroy()
1402            generalData['DisAglCtls'] = DisAglCtls
1403            atomData = data['Atoms']
1404            colLabels = [Atoms.GetColLabelValue(c) for c in range(Atoms.GetNumberCols())]
1405            cx = colLabels.index('x')
1406            cn = colLabels.index('Name')
1407            for i,atom in enumerate(atomData):
1408                xyz.append([i,]+atom[cn:cn+2]+atom[cx:cx+3])
1409                if i in indx:
1410                    Oxyz.append([i,]+atom[cn:cn+2]+atom[cx:cx+3])
1411            DisAglData['OrigAtoms'] = Oxyz
1412            DisAglData['TargAtoms'] = xyz
1413            generalData = data['General']
1414            DisAglData['SGData'] = generalData['SGData']
1415            DisAglData['Cell'] = generalData['Cell'][1:] #+ volume
1416            if 'pId' in data:
1417                DisAglData['pId'] = data['pId']
1418                DisAglData['covData'] = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.root, 'Covariance'))
1419            G2str.DistAngle(DisAglCtls,DisAglData)
1420                       
1421################################################################################
1422#Structure drawing GUI stuff               
1423################################################################################
1424
1425    def SetupDrawingData():
1426        generalData = data['General']
1427        atomData = data['Atoms']
1428        AA3letter = ['ALA','ARG','ASN','ASP','CYS','GLN','GLU','GLY','HIS','ILE',
1429            'LEU','LYS','MET','PHE','PRO','SER','THR','TRP','TYR','VAL','MSE','HOH','WAT','UNK']
1430        AA1letter = ['A','R','N','D','C','Q','E','G','H','I',
1431            'L','K','M','F','P','S','T','W','Y','V','M',' ',' ',' ']
1432        defaultDrawing = {'Atoms':[],'viewPoint':[[0.5,0.5,0.5],[]],'showHydrogen':True,
1433            'backColor':[0,0,0],'depthFog':False,'Zclip':50.0,'cameraPos':50.,
1434            'radiusFactor':0.85,'contourLevel':1.,'bondRadius':0.1,'ballScale':0.33,
1435            'vdwScale':0.67,'ellipseProb':50,'sizeH':0.50,'unitCellBox':False,
1436            'showABC':True,'selectedAtoms':[],'Atoms':[],'Rotation':[0.0,0.0,0.0,[]],
1437            'bondList':{},'testPos':[[-.1,-.1,-.1],[0.0,0.0,0.0],[0,0]]}
1438        try:
1439            drawingData = data['Drawing']
1440        except KeyError:
1441            data['Drawing'] = {}
1442            drawingData = data['Drawing']
1443        if not drawingData:                 #fill with defaults if empty
1444            drawingData.update(defaultDrawing)
1445        if 'contourLevel' not in drawingData:
1446            drawingData['contourLevel'] = 1.
1447        cx,ct,cs,ci = [0,0,0,0]
1448        if generalData['Type'] == 'nuclear':
1449            cx,ct,cs,ci = [2,1,6,17]         #x, type, style & index
1450        elif generalData['Type'] == 'macromolecular':
1451            cx,ct,cs,ci = [5,4,9,20]         #x, type, style & index
1452        elif generalData['Type'] == 'magnetic':
1453            cx,ct,cs,ci = [2,1,6,20]         #x, type, style & index
1454#        elif generalData['Type'] == 'modulated':
1455#           ?????   for future
1456        drawingData['atomPtrs'] = [cx,ct,cs,ci]
1457        if not drawingData.get('Atoms'):
1458            for atom in atomData:
1459                DrawAtomAdd(drawingData,atom)
1460            data['Drawing'] = drawingData
1461           
1462    def MakeDrawAtom(atom,oldatom=None):
1463        AA3letter = ['ALA','ARG','ASN','ASP','CYS','GLN','GLU','GLY','HIS','ILE',
1464            'LEU','LYS','MET','PHE','PRO','SER','THR','TRP','TYR','VAL','MSE','HOH','WAT','UNK']
1465        AA1letter = ['A','R','N','D','C','Q','E','G','H','I',
1466            'L','K','M','F','P','S','T','W','Y','V','M',' ',' ',' ']
1467        generalData = data['General']
1468        SGData = generalData['SGData']
1469        if generalData['Type'] == 'nuclear':
1470            if oldatom:
1471                opr = oldatom[5]
1472                if atom[9] == 'A':                   
1473                    X,U = G2spc.ApplyStringOps(opr,SGData,atom[3:6],atom[11:17])
1474                    atomInfo = [atom[:2]+list(X)+oldatom[5:9]+atom[9:11]+list(U)+oldatom[17:]][0]
1475                else:
1476                    X = G2spc.ApplyStringOps(opr,SGData,atom[3:6])
1477                    atomInfo = [atom[:2]+list(X)+oldatom[5:9]+atom[9:]+[oldatom[-1]]][0]
1478            else:
1479                atomInfo = [atom[:2]+atom[3:6]+['1',]+['vdW balls',]+
1480                    ['',]+[[255,255,255],]+atom[9:]+[[],[]]][0]
1481            ct,cs = [1,8]         #type & color
1482        elif generalData['Type'] == 'macromolecular':
1483            try:
1484                oneLetter = AA3letter.index(atom[1])
1485            except ValueError:
1486                oneLetter = -1
1487            atomInfo = [[atom[1].strip()+atom[0],]+
1488                [AA1letter[oneLetter]+atom[0],]+atom[2:5]+
1489                atom[6:9]+['1',]+['sticks',]+['',]+[[255,255,255],]+atom[12:]+[[],[]]][0]
1490            ct,cs = [4,11]         #type & color
1491        elif generalData['Type'] == 'magnetic':
1492            if oldatom:
1493                atomInfo = [atom[:2]+oldatom[3:]][0]
1494            else:
1495                atomInfo = [atom[:2]+atom[3:6]+['vdW balls',]+['',]+atom[9:]+[[],[]]][0]
1496            ct,cs = [1,8]         #type & color
1497#        elif generalData['Type'] == 'modulated':
1498#           ?????   for future
1499        atNum = generalData['AtomTypes'].index(atom[ct])
1500        atomInfo[cs] = list(generalData['Color'][atNum])
1501        return atomInfo
1502           
1503    def DrawAtomAdd(drawingData,atom):
1504        drawingData['Atoms'].append(MakeDrawAtom(atom))
1505       
1506    def DrawAtomsReplaceByID(drawingData,atom,ID):
1507        IDs = [ID,]
1508        atomData = drawingData['Atoms']
1509        indx = FindAtomIndexByIDs(atomData,IDs)
1510        for ind in indx:
1511            atomData[ind] = MakeDrawAtom(atom,atomData[ind])
1512           
1513    def OnRestraint(event):       
1514        indx = drawAtoms.GetSelectedRows()
1515        restData = G2frame.PatternTree.GetItemPyData(   
1516            G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Restraints'))
1517        drawingData = data['Drawing']
1518        generalData = data['General']
1519        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])           
1520        cx,ct,cs,ci = drawingData['atomPtrs']
1521        atomData = drawingData['Atoms']
1522        atNames = []
1523        atXYZ = []
1524        atSymOp = []
1525        atIndx = []
1526        for item in indx:
1527            atNames.append(atomData[item][ct-1])
1528            atXYZ.append(np.array(atomData[item][cx:cx+3]))
1529            atSymOp.append(atomData[item][cs-1])
1530            atIndx.append(atomData[item][ci])
1531        if event.GetId() == G2gd.wxID_DRAWRESTRBOND and len(indx) == 2:
1532            try:
1533                bondData = restData[PhaseName]['Bond']
1534            except KeyError:
1535                bondData = {'wtFactor':1.0,'Bonds':[]}
1536                restData[PhaseName] = {}
1537                restData[PhaseName]['Bond'] = bondData
1538            dist = G2mth.getRestDist(atXYZ,Amat)
1539            bondData['Bonds'].append([atNames,atSymOp,atIndx,dist,1.54,0.01])
1540        elif event.GetId() == G2gd.wxID_DRAWRESTRANGLE and len(indx) == 3:
1541            try:
1542                angleData = restData[PhaseName]['Angle']
1543            except KeyError:
1544                angleData = {'wtFactor':1.0,'Angles':[]}
1545                restData[PhaseName] = {}
1546                restData[PhaseName]['Angle'] = angleData
1547            angle = G2mth.getRestAngle(atXYZ,Amat)
1548            angleData['Angles'].append([atNames,atSymOp,atIndx,angle,109.5,1.0])           
1549        elif event.GetId() == G2gd.wxID_DRAWRESTRPLANE and len(indx) > 3:
1550            try:
1551                planeData = restData[PhaseName]['Plane']
1552            except KeyError:
1553                planeData = {'wtFactor':1.0,'Planes':[]}
1554                restData[PhaseName] = {}
1555                restData[PhaseName]['Plane'] = planeData
1556            plane = G2mth.getRestPlane(atXYZ,Amat)
1557            planeData['Planes'].append([atNames,atSymOp,atIndx,plane,0.0,0.01])           
1558        elif event.GetId() == G2gd.wxID_DRAWRESTRCHIRAL and len(indx) == 4:
1559            try:
1560                chiralData = restData[PhaseName]['Chiral']
1561            except KeyError:
1562                chiralData = {'wtFactor':1.0,'Volumes':[]}
1563                restData[PhaseName] = {}
1564                restData[PhaseName]['Chiral'] = chiralData
1565            volume = G2mth.getRestChiral(atXYZ,Amat)
1566            chiralData['Volumes'].append([atNames,atSymOp,atIndx,volume,2.5,0.1])           
1567        else:
1568            print '**** ERROR wrong number of atoms selected for this restraint'
1569            return
1570        G2frame.PatternTree.SetItemPyData(   
1571            G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Restraints'),restData)
1572
1573################################################################################
1574##### Atom draw routines
1575################################################################################
1576           
1577    def UpdateDrawAtoms():
1578        generalData = data['General']
1579        SetupDrawingData()
1580        drawingData = data['Drawing']
1581        cx,ct,cs,ci = drawingData['atomPtrs']
1582        atomData = drawingData['Atoms']
1583        Types = [wg.GRID_VALUE_STRING,wg.GRID_VALUE_STRING,]+3*[wg.GRID_VALUE_FLOAT+':10,5',]+ \
1584            [wg.GRID_VALUE_STRING,wg.GRID_VALUE_CHOICE+": ,lines,vdW balls,sticks,balls & sticks,ellipsoids,polyhedra",
1585            wg.GRID_VALUE_CHOICE+": ,type,name,number",wg.GRID_VALUE_STRING,wg.GRID_VALUE_STRING,]
1586        styleChoice = [' ','lines','vdW balls','sticks','balls & sticks','ellipsoids','polyhedra']
1587        labelChoice = [' ','type','name','number']
1588        colLabels = ['Name','Type','x','y','z','Sym Op','Style','Label','Color','I/A']
1589        if generalData['Type'] == 'macromolecular':
1590            colLabels = ['Residue','1-letter','Chain'] + colLabels
1591            Types = 3*[wg.GRID_VALUE_STRING,]+Types
1592            Types[8] = wg.GRID_VALUE_CHOICE+": ,lines,vdW balls,sticks,balls & sticks,ellipsoids,backbone,ribbons,schematic"
1593            styleChoice = [' ','lines','vdW balls','sticks','balls & sticks','ellipsoids','backbone','ribbons','schematic']
1594            labelChoice = [' ','type','name','number','residue','1-letter','chain']
1595            Types[9] = wg.GRID_VALUE_CHOICE+": ,type,name,number,residue,1-letter,chain"
1596#        elif generalData['Type'] == 'modulated':
1597#            Types += []
1598#            colLabels += []
1599
1600        def RefreshAtomGrid(event):
1601
1602            def SetChoice(name,c,n=0):
1603                choice = []
1604                for r in range(len(atomData)):
1605                    if n:
1606                        srchStr = str(atomData[r][c][:n])
1607                    else:
1608                        srchStr = str(atomData[r][c])
1609                    if srchStr not in choice:
1610                        if n:
1611                            choice.append(str(atomData[r][c][:n]))
1612                        else:
1613                            choice.append(str(atomData[r][c]))
1614                choice.sort()
1615
1616                dlg = wx.MultiChoiceDialog(G2frame,'Select',name,choice)
1617                if dlg.ShowModal() == wx.ID_OK:
1618                    sel = dlg.GetSelections()
1619                    parms = []
1620                    for x in sel:
1621                        parms.append(choice[x])
1622                    noSkip = False
1623                    drawAtoms.ClearSelection()
1624                    drawingData['selectedAtoms'] = []
1625                    for row in range(len(atomData)):
1626                        test = atomData[row][c]
1627                        if n:
1628                            test = test[:n]
1629                        if  test in parms:
1630                            drawAtoms.SelectRow(row,True)
1631                            drawingData['selectedAtoms'].append(row)
1632                    G2plt.PlotStructure(G2frame,data)                   
1633                dlg.Destroy()
1634               
1635            r,c =  event.GetRow(),event.GetCol()
1636            if r < 0 and c < 0:
1637                for row in range(drawAtoms.GetNumberRows()):
1638                    drawingData['selectedAtoms'].append(row)
1639                    drawAtoms.SelectRow(row,True)                   
1640            elif r < 0:                          #dclick on col label
1641                sel = -1
1642                Parms = False
1643                noSkip = True
1644                if drawAtoms.GetColLabelValue(c) == 'Style':
1645                    dlg = wx.SingleChoiceDialog(G2frame,'Select','Atom drawing style',styleChoice)
1646                    if dlg.ShowModal() == wx.ID_OK:
1647                        sel = dlg.GetSelection()
1648                        parms = styleChoice[sel]
1649                        for r in range(len(atomData)):
1650                            atomData[r][c] = parms
1651                            drawAtoms.SetCellValue(r,c,parms)
1652                        FindBondsDraw()
1653                        G2plt.PlotStructure(G2frame,data)
1654                    dlg.Destroy()
1655                elif drawAtoms.GetColLabelValue(c) == 'Label':
1656                    dlg = wx.SingleChoiceDialog(G2frame,'Select','Atom labelling style',labelChoice)
1657                    if dlg.ShowModal() == wx.ID_OK:
1658                        sel = dlg.GetSelection()
1659                        parms = labelChoice[sel]
1660                        for r in range(len(atomData)):
1661                            atomData[r][c] = parms
1662                            drawAtoms.SetCellValue(r,c,parms)
1663                    dlg.Destroy()                   
1664                elif drawAtoms.GetColLabelValue(c) == 'Color':
1665                    dlg = wx.ColourDialog(G2frame)
1666                    if dlg.ShowModal() == wx.ID_OK:
1667                        color = dlg.GetColourData().GetColour()
1668                        attr = wg.GridCellAttr()                #needs to be here - gets lost if outside loop!
1669                        attr.SetReadOnly(True)
1670                        attr.SetBackgroundColour(color)
1671                        for r in range(len(atomData)):
1672                            atomData[r][c] = color
1673                            drawingData['Atoms'][r][c] = color
1674                            drawAtoms.SetAttr(r,c,attr)
1675                        UpdateDrawAtoms()
1676                    dlg.Destroy()
1677                elif drawAtoms.GetColLabelValue(c) == 'Residue':
1678                    SetChoice('Residue',c,3)
1679                elif drawAtoms.GetColLabelValue(c) == '1-letter':
1680                    SetChoice('1-letter',c,1)
1681                elif drawAtoms.GetColLabelValue(c) == 'Chain':
1682                    SetChoice('Chain',c)
1683                elif drawAtoms.GetColLabelValue(c) == 'Name':
1684                    SetChoice('Name',c)
1685                elif drawAtoms.GetColLabelValue(c) == 'Sym Op':
1686                    SetChoice('Name',c)
1687                elif drawAtoms.GetColLabelValue(c) == 'Type':
1688                    SetChoice('Type',c)
1689                elif drawAtoms.GetColLabelValue(c) in ['x','y','z','I/A']:
1690                    drawAtoms.ClearSelection()
1691            else:
1692                if drawAtoms.GetColLabelValue(c) in ['Style','Label']:
1693                    atomData[r][c] = drawAtoms.GetCellValue(r,c)
1694                    FindBondsDraw()
1695                elif drawAtoms.GetColLabelValue(c) == 'Color':
1696                    color = atomData[r][c]
1697                    colors = wx.ColourData()
1698                    colors.SetChooseFull(True)
1699                    colors.SetCustomColour(0,color)
1700                    colors.SetColour(color)
1701                    dlg = wx.ColourDialog(G2frame,colors)
1702                    dlg.GetColourData().SetCustomColour(0,color)
1703                    if dlg.ShowModal() == wx.ID_OK:
1704                        color = dlg.GetColourData().GetColour()
1705                        attr = wg.GridCellAttr()                #needs to be here - gets lost if outside loop!
1706                        attr.SetReadOnly(True)
1707                        attr.SetBackgroundColour(color)
1708                        atomData[r][c] = color
1709                        drawingData['Atoms'][r][c] = color
1710                        drawAtoms.SetAttr(i,cs+2,attr)
1711                    dlg.Destroy()
1712                    event.StopPropagation()
1713                    UpdateDrawAtoms()
1714            G2plt.PlotStructure(G2frame,data)
1715                   
1716        def RowSelect(event):
1717            r,c =  event.GetRow(),event.GetCol()
1718            if r < 0 and c < 0:
1719                if drawAtoms.IsSelection():
1720                    drawAtoms.ClearSelection()
1721            elif c < 0:                   #only row clicks
1722                if event.ControlDown():                   
1723                    if r in drawAtoms.GetSelectedRows():
1724                        drawAtoms.DeselectRow(r)
1725                    else:
1726                        drawAtoms.SelectRow(r,True)
1727                elif event.ShiftDown():
1728                    for row in range(r+1):
1729                        drawAtoms.SelectRow(row,True)
1730                else:
1731                    drawAtoms.ClearSelection()
1732                    drawAtoms.SelectRow(r,True)               
1733            drawingData['selectedAtoms'] = []
1734            drawingData['selectedAtoms'] = drawAtoms.GetSelectedRows()
1735            G2plt.PlotStructure(G2frame,data)                   
1736               
1737        table = []
1738        rowLabels = []
1739        for i,atom in enumerate(drawingData['Atoms']):
1740            table.append(atom[:colLabels.index('I/A')+1])
1741            rowLabels.append(str(i))
1742
1743        atomTable = G2gd.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
1744        drawAtoms.SetTable(atomTable, True)
1745        drawAtoms.SetMargins(0,0)
1746        drawAtoms.AutoSizeColumns(True)
1747        drawAtoms.SetColSize(colLabels.index('Style'),80)
1748        drawAtoms.SetColSize(colLabels.index('Color'),50)
1749        drawAtoms.Bind(wg.EVT_GRID_CELL_CHANGE, RefreshAtomGrid)
1750        drawAtoms.Bind(wg.EVT_GRID_LABEL_LEFT_DCLICK, RefreshAtomGrid)
1751        drawAtoms.Bind(wg.EVT_GRID_CELL_LEFT_DCLICK, RefreshAtomGrid)
1752        drawAtoms.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK, RowSelect)
1753        for i,atom in enumerate(drawingData['Atoms']):
1754            attr = wg.GridCellAttr()                #needs to be here - gets lost if outside loop!
1755            attr.SetReadOnly(True)
1756            attr.SetBackgroundColour(atom[cs+2])
1757            drawAtoms.SetAttr(i,cs+2,attr)
1758            drawAtoms.SetCellValue(i,cs+2,'')
1759        indx = drawingData['selectedAtoms']
1760        if indx:
1761            for r in range(len(atomData)):
1762                if r in indx:
1763                    drawAtoms.SelectRow(r)
1764        for c in range(len(colLabels)):
1765           attr = wg.GridCellAttr()                #needs to be here - gets lost if outside loop!
1766           attr.SetReadOnly(True)
1767           attr.SetBackgroundColour(VERY_LIGHT_GREY)
1768           if colLabels[c] not in ['Style','Label','Color']:
1769                drawAtoms.SetColAttr(c,attr)
1770        G2frame.dataFrame.setSizePosLeft([600,300])
1771       
1772        FindBondsDraw()
1773        drawAtoms.ClearSelection()
1774        G2plt.PlotStructure(G2frame,data)
1775
1776    def DrawAtomStyle(event):
1777        indx = drawAtoms.GetSelectedRows()
1778        if indx:
1779            generalData = data['General']
1780            atomData = data['Drawing']['Atoms']
1781            cx,ct,cs,ci = data['Drawing']['atomPtrs']
1782            styleChoice = [' ','lines','vdW balls','sticks','balls & sticks','ellipsoids','polyhedra']
1783            if generalData['Type'] == 'macromolecular':
1784                styleChoice = [' ','lines','vdW balls','sticks','balls & sticks','ellipsoids',
1785                'backbone','ribbons','schematic']
1786            dlg = wx.SingleChoiceDialog(G2frame,'Select','Atom drawing style',styleChoice)
1787            if dlg.ShowModal() == wx.ID_OK:
1788                sel = dlg.GetSelection()
1789                parms = styleChoice[sel]
1790                for r in indx:
1791                    atomData[r][cs] = parms
1792                    drawAtoms.SetCellValue(r,cs,parms)
1793            dlg.Destroy()
1794            FindBondsDraw()
1795            drawAtoms.ClearSelection()
1796            G2plt.PlotStructure(G2frame,data)
1797
1798    def DrawAtomLabel(event):
1799        indx = drawAtoms.GetSelectedRows()
1800        if indx:
1801            generalData = data['General']
1802            atomData = data['Drawing']['Atoms']
1803            cx,ct,cs,ci = data['Drawing']['atomPtrs']
1804            styleChoice = [' ','type','name','number']
1805            if generalData['Type'] == 'macromolecular':
1806                styleChoice = [' ','type','name','number','residue','1-letter','chain']
1807            dlg = wx.SingleChoiceDialog(G2frame,'Select','Atom label style',styleChoice)
1808            if dlg.ShowModal() == wx.ID_OK:
1809                sel = dlg.GetSelection()
1810                parms = styleChoice[sel]
1811                for r in indx:
1812                    atomData[r][cs+1] = parms
1813                    drawAtoms.SetCellValue(r,cs+1,parms)
1814            dlg.Destroy()
1815            drawAtoms.ClearSelection()
1816            G2plt.PlotStructure(G2frame,data)
1817           
1818    def DrawAtomColor(event):
1819
1820        indx = drawAtoms.GetSelectedRows()
1821        if indx:
1822            if len(indx) > 1:
1823                G2frame.dataFrame.SetStatusText('Select Custom Color, change color, Add to Custom Colors, then OK')
1824            else:
1825                G2frame.dataFrame.SetStatusText('Change color, Add to Custom Colors, then OK')
1826            generalData = data['General']
1827            atomData = data['Drawing']['Atoms']
1828            cx,ct,cs,ci = data['Drawing']['atomPtrs']
1829            atmColors = []
1830            atmTypes = []
1831            for r in indx:
1832                if atomData[r][cs+2] not in atmColors:
1833                    atmColors.append(atomData[r][cs+2])
1834                    atmTypes.append(atomData[r][ct])
1835                    if len(atmColors) > 16:
1836                        break
1837            colors = wx.ColourData()
1838            colors.SetChooseFull(True)
1839            for i,color in enumerate(atmColors):
1840                colors.SetCustomColour(i,color)
1841            dlg = wx.ColourDialog(G2frame,colors)
1842            if dlg.ShowModal() == wx.ID_OK:
1843                for i in range(len(atmColors)):                   
1844                    atmColors[i] = dlg.GetColourData().GetCustomColour(i)
1845                colorDict = dict(zip(atmTypes,atmColors))
1846                for r in indx:
1847                    color = colorDict[atomData[r][ct]]
1848                    atomData[r][cs+2] = color
1849                    attr = wg.GridCellAttr()                #needs to be here - gets lost if outside loop!
1850                    attr.SetBackgroundColour(color)
1851                    drawAtoms.SetAttr(r,cs+2,attr)
1852                    data['Drawing']['Atoms'][r][cs+2] = color
1853            drawAtoms.ClearSelection()
1854            dlg.Destroy()
1855            G2frame.dataFrame.SetStatusText('')
1856            G2plt.PlotStructure(G2frame,data)
1857           
1858    def ResetAtomColors(event):
1859        generalData = data['General']
1860        atomData = data['Drawing']['Atoms']
1861        cx,ct,cs,ci = data['Drawing']['atomPtrs']
1862        for atom in atomData:           
1863            atNum = generalData['AtomTypes'].index(atom[ct])
1864            atom[cs+2] = list(generalData['Color'][atNum])
1865        UpdateDrawAtoms()
1866        drawAtoms.ClearSelection()
1867        G2plt.PlotStructure(G2frame,data)       
1868       
1869    def SetViewPoint(event):
1870        indx = drawAtoms.GetSelectedRows()
1871        if indx:
1872            atomData = data['Drawing']['Atoms']
1873            cx = data['Drawing']['atomPtrs'][0]
1874            data['Drawing']['viewPoint'] = [atomData[indx[0]][cx:cx+3],[indx[0],0]]
1875            drawAtoms.ClearSelection()                                  #do I really want to do this?
1876            G2plt.PlotStructure(G2frame,data)
1877           
1878    def noDuplicate(xyz,atomData):                  #be careful where this is used - it's slow
1879        cx = data['Drawing']['atomPtrs'][0]
1880        if True in [np.allclose(np.array(xyz),np.array(atom[cx:cx+3]),atol=0.0002) for atom in atomData]:
1881            return False
1882        else:
1883            return True
1884               
1885    def AddSymEquiv(event):
1886        indx = drawAtoms.GetSelectedRows()
1887        indx.sort()
1888        if indx:
1889            colLabels = [drawAtoms.GetColLabelValue(c) for c in range(drawAtoms.GetNumberCols())]
1890            cx = colLabels.index('x')
1891            cuia = colLabels.index('I/A')
1892            cuij = cuia+2
1893            atomData = data['Drawing']['Atoms']
1894            generalData = data['General']
1895            SGData = generalData['SGData']
1896            dlg = SymOpDialog(G2frame,SGData,False)
1897            try:
1898                if dlg.ShowModal() == wx.ID_OK:
1899                    Inv,Cent,Opr,Cell,New = dlg.GetSelection()
1900                    Cell = np.array(Cell)
1901                    cent = SGData['SGCen'][Cent]
1902                    M,T = SGData['SGOps'][Opr]
1903                    for ind in indx:
1904                        XYZ = np.array(atomData[ind][cx:cx+3])
1905                        XYZ = np.inner(M,XYZ)+T
1906                        if Inv:
1907                            XYZ = -XYZ
1908                        XYZ = XYZ+cent+Cell
1909                        if noDuplicate(XYZ,atomData):
1910                            atom = copy.copy(atomData[ind])
1911                            atom[cx:cx+3] = XYZ
1912                            atomOp = atom[cx+3]
1913                            newOp = str(((Opr+1)+100*Cent)*(1-2*Inv))+'+'+ \
1914                                str(int(Cell[0]))+','+str(int(Cell[1]))+','+str(int(Cell[2]))                           
1915                            atom[cx+3] = G2spc.StringOpsProd(atomOp,newOp,SGData)
1916                            if atom[cuia] == 'A':
1917                                Uij = atom[cuij:cuij+6]
1918                                U = G2spc.Uij2U(Uij)
1919                                U = np.inner(np.inner(M,U),M)
1920                                Uij = G2spc.U2Uij(U)
1921                                atom[cuij:cuij+6] = Uij
1922                            atomData.append(atom)
1923            finally:
1924                dlg.Destroy()
1925            UpdateDrawAtoms()
1926            drawAtoms.ClearSelection()
1927            G2plt.PlotStructure(G2frame,data)
1928           
1929    def TransformSymEquiv(event):
1930        indx = drawAtoms.GetSelectedRows()
1931        indx.sort()
1932        if indx:
1933            atomData = data['Drawing']['Atoms']
1934            colLabels = [drawAtoms.GetColLabelValue(c) for c in range(drawAtoms.GetNumberCols())]
1935            cx = colLabels.index('x')
1936            cuia = colLabels.index('I/A')
1937            cuij = cuia+2
1938            atomData = data['Drawing']['Atoms']
1939            generalData = data['General']
1940            SGData = generalData['SGData']
1941            dlg = SymOpDialog(G2frame,SGData,False)
1942            try:
1943                if dlg.ShowModal() == wx.ID_OK:
1944                    Inv,Cent,Opr,Cell,New = dlg.GetSelection()
1945                    Cell = np.array(Cell)
1946                    cent = SGData['SGCen'][Cent]
1947                    M,T = SGData['SGOps'][Opr]
1948                    for ind in indx:
1949                        XYZ = np.array(atomData[ind][cx:cx+3])
1950                        XYZ = np.inner(M,XYZ)+T
1951                        if Inv:
1952                            XYZ = -XYZ
1953                        XYZ = XYZ+cent+Cell
1954                        atom = atomData[ind]
1955                        atom[cx:cx+3] = XYZ
1956                        atomOp = atom[cx+3]
1957                        newOp = str(((Opr+1)+100*Cent)*(1-2*Inv))+'+'+ \
1958                            str(int(Cell[0]))+','+str(int(Cell[1]))+','+str(int(Cell[2]))
1959                        atom[cx+3] = G2spc.StringOpsProd(atomOp,newOp,SGData)
1960                        if atom[cuia] == 'A':
1961                            Uij = atom[cuij:cuij+6]
1962                            U = G2spc.Uij2U(Uij)
1963                            U = np.inner(np.inner(M,U),M)
1964                            Uij = G2spc.U2Uij(U)
1965                            atom[cuij:cuij+6] = Uij
1966                    data['Drawing']['Atoms'] = atomData
1967            finally:
1968                dlg.Destroy()
1969            UpdateDrawAtoms()
1970            drawAtoms.ClearSelection()
1971            G2plt.PlotStructure(G2frame,data)
1972           
1973    def FillCoordSphere(event):
1974        generalData = data['General']
1975        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])
1976        radii = generalData['BondRadii']
1977        atomTypes = generalData['AtomTypes']
1978        try:
1979            indH = atomTypes.index('H')
1980            radii[indH] = 0.5
1981        except:
1982            pass           
1983        indx = drawAtoms.GetSelectedRows()
1984        if indx:
1985            indx.sort()
1986            atomData = data['Drawing']['Atoms']
1987            numAtoms = len(atomData)
1988            cx,ct,cs,ci = data['Drawing']['atomPtrs']
1989            generalData = data['General']
1990            SGData = generalData['SGData']
1991            cellArray = G2lat.CellBlock(1)
1992            for ind in indx:
1993                atomA = atomData[ind]
1994                xyzA = np.array(atomA[cx:cx+3])
1995                indA = atomTypes.index(atomA[ct])
1996                for atomB in atomData[:numAtoms]:
1997                    indB = atomTypes.index(atomB[ct])
1998                    sumR = radii[indA]+radii[indB]
1999                    xyzB = np.array(atomB[cx:cx+3])
2000                    for xyz in cellArray+xyzB:
2001                        dist = np.sqrt(np.sum(np.inner(Amat,xyz-xyzA)**2))
2002                        if 0 < dist <= data['Drawing']['radiusFactor']*sumR:
2003                            if noDuplicate(xyz,atomData):
2004                                oprB = atomB[cx+3]
2005                                C = xyz-xyzB
2006                                newOp = '1+'+str(int(round(C[0])))+','+str(int(round(C[1])))+','+str(int(round(C[2])))
2007                                newAtom = atomB[:]
2008                                newAtom[cx:cx+3] = xyz
2009                                newAtom[cx+3] = G2spc.StringOpsProd(oprB,newOp,SGData)
2010                                atomData.append(newAtom)
2011            data['Drawing']['Atoms'] = atomData
2012            UpdateDrawAtoms()
2013            drawAtoms.ClearSelection()
2014            G2plt.PlotStructure(G2frame,data)
2015           
2016    def FillUnitCell(event):
2017        indx = drawAtoms.GetSelectedRows()
2018        indx.sort()
2019        if indx:
2020            atomData = data['Drawing']['Atoms']
2021            colLabels = [drawAtoms.GetColLabelValue(c) for c in range(drawAtoms.GetNumberCols())]
2022            cx = colLabels.index('x')
2023            cuia = colLabels.index('I/A')
2024            cuij = cuia+2
2025            generalData = data['General']
2026            SGData = generalData['SGData']
2027            for ind in indx:
2028                atom = atomData[ind]
2029                XYZ = np.array(atom[cx:cx+3])
2030                if atom[cuia] == 'A':
2031                    Uij = atom[cuij:cuij+6]
2032                    result = G2spc.GenAtom(XYZ,SGData,False,Uij,False)
2033                    for item in result:
2034                        atom = copy.copy(atomData[ind])
2035                        atom[cx:cx+3] = item[0]
2036                        atom[cx+3] = str(item[2])+'+' \
2037                            +str(item[3][0])+','+str(item[3][1])+','+str(item[3][2])
2038                        atom[cuij:cuij+6] = item[1]
2039                        Opp = G2spc.Opposite(item[0])
2040                        for xyz in Opp:
2041                            if noDuplicate(xyz,atomData):
2042                                cell = np.asarray(np.rint(xyz-atom[cx:cx+3]),dtype=np.int32)
2043                                cell = '1'+'+'+ \
2044                                    str(cell[0])+','+str(cell[1])+','+str(cell[2])
2045                                atom[cx:cx+3] = xyz
2046                                atom[cx+3] = G2spc.StringOpsProd(cell,atom[cx+3],SGData)
2047                                atomData.append(atom[:])
2048                else:
2049                    result = G2spc.GenAtom(XYZ,SGData,False,Move=False)
2050                    for item in result:
2051                        atom = copy.copy(atomData[ind])
2052                        atom[cx:cx+3] = item[0]
2053                        atom[cx+3] = str(item[1])+'+' \
2054                            +str(item[2][0])+','+str(item[2][1])+','+str(item[2][2])
2055                        Opp = G2spc.Opposite(item[0])
2056                        for xyz in Opp:
2057                            if noDuplicate(xyz,atomData):
2058                                cell = np.asarray(np.rint(xyz-atom[cx:cx+3]),dtype=np.int32)
2059                                cell = '1'+'+'+ \
2060                                    str(cell[0])+','+str(cell[1])+','+str(cell[2])
2061                                atom[cx:cx+3] = xyz
2062                                atom[cx+3] = G2spc.StringOpsProd(cell,atom[cx+3],SGData)
2063                                atomData.append(atom[:])               
2064                data['Drawing']['Atoms'] = atomData
2065            UpdateDrawAtoms()
2066            drawAtoms.ClearSelection()
2067            G2plt.PlotStructure(G2frame,data)
2068           
2069    def FindBondsToo():                         #works but slow for large structures - keep as reference
2070        cx,ct,cs,ci = data['Drawing']['atomPtrs']
2071        atomData = data['Drawing']['Atoms']
2072        generalData = data['General']
2073        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])
2074        radii = generalData['BondRadii']
2075        atomTypes = generalData['AtomTypes']
2076        try:
2077            indH = atomTypes.index('H')
2078            radii[indH] = 0.5
2079        except:
2080            pass           
2081        for atom in atomData:
2082            atom[-1] = []
2083        Atoms = []
2084        for i,atom in enumerate(atomData):
2085            Atoms.append([i,np.array(atom[cx:cx+3]),atom[cs],radii[atomTypes.index(atom[ct])]])
2086        for atomA in Atoms:
2087            if atomA[2] in ['lines','sticks','ellipsoids','balls & sticks','polyhedra']:
2088                for atomB in Atoms:                   
2089                    Dx = atomB[1]-atomA[1]
2090                    DX = np.inner(Amat,Dx)
2091                    dist = np.sqrt(np.sum(DX**2))
2092                    sumR = atomA[3]+atomB[3]
2093                    if 0.5 < dist <= 0.85*sumR:
2094                        i = atomA[0]
2095                        if atomA[2] == 'polyhedra':
2096                            atomData[i][-1].append(DX)
2097                        elif atomB[1] != 'polyhedra':
2098                            j = atomB[0]
2099                            atomData[i][-1].append(Dx*atomA[3]/sumR)
2100                            atomData[j][-1].append(-Dx*atomB[3]/sumR)
2101                   
2102    def FindBondsDraw():                    #uses numpy & masks - very fast even for proteins!
2103        import numpy.ma as ma
2104        cx,ct,cs,ci = data['Drawing']['atomPtrs']
2105        hydro = data['Drawing']['showHydrogen']
2106        atomData = data['Drawing']['Atoms']
2107        generalData = data['General']
2108        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])
2109        radii = generalData['BondRadii']
2110        atomTypes = generalData['AtomTypes']
2111        try:
2112            indH = atomTypes.index('H')
2113            radii[indH] = 0.5
2114        except:
2115            pass           
2116        for atom in atomData:
2117            atom[-2] = []               #clear out old bonds/polyhedra
2118            atom[-1] = []
2119        Indx = range(len(atomData))
2120        Atoms = []
2121        Styles = []
2122        Radii = []
2123        for atom in atomData:
2124            Atoms.append(np.array(atom[cx:cx+3]))
2125            Styles.append(atom[cs])
2126            try:
2127                if not hydro and atom[ct] == 'H':
2128                    Radii.append(0.0)
2129                else:
2130                    Radii.append(radii[atomTypes.index(atom[ct])])
2131            except ValueError:          #changed atom type!
2132                Radii.append(0.20)
2133        Atoms = np.array(Atoms)
2134        Radii = np.array(Radii)
2135        IASR = zip(Indx,Atoms,Styles,Radii)
2136        for atomA in IASR:
2137            if atomA[2] in ['lines','sticks','ellipsoids','balls & sticks','polyhedra']:
2138                Dx = Atoms-atomA[1]
2139                dist = ma.masked_less(np.sqrt(np.sum(np.inner(Amat,Dx)**2,axis=0)),0.5) #gets rid of G2frame & disorder "bonds" < 0.5A
2140                sumR = atomA[3]+Radii
2141                IndB = ma.nonzero(ma.masked_greater(dist-data['Drawing']['radiusFactor']*sumR,0.))                 #get indices of bonded atoms
2142                i = atomA[0]
2143                for j in IndB[0]:
2144                    if Styles[i] == 'polyhedra':
2145                        atomData[i][-2].append(np.inner(Amat,Dx[j]))
2146                    elif Styles[j] != 'polyhedra' and j > i:
2147                        atomData[i][-2].append(Dx[j]*Radii[i]/sumR[j])
2148                        atomData[j][-2].append(-Dx[j]*Radii[j]/sumR[j])
2149                if Styles[i] == 'polyhedra':
2150                    Bonds = atomData[i][-2]
2151                    Faces = []
2152                    if len(Bonds) > 2:
2153                        FaceGen = G2lat.uniqueCombinations(Bonds,3)     #N.B. this is a generator
2154                        for face in FaceGen:
2155                            vol = nl.det(face)
2156                            if abs(vol) > 1. or len(Bonds) == 3:
2157                                if vol < 0.:
2158                                    face = [face[0],face[2],face[1]]
2159                                face = np.array(face)
2160                                if not np.array([np.array(nl.det(face-bond))+0.0001 < 0 for bond in Bonds]).any():
2161                                    norm = np.cross(face[1]-face[0],face[2]-face[0])
2162                                    norm /= np.sqrt(np.sum(norm**2))
2163                                    Faces.append([face,norm])
2164                        atomData[i][-1] = Faces
2165                       
2166    def DrawAtomsDelete(event):   
2167        indx = drawAtoms.GetSelectedRows()
2168        indx.sort()
2169        if indx:
2170            atomData = data['Drawing']['Atoms']
2171            indx.reverse()
2172            for ind in indx:
2173                del atomData[ind]
2174            UpdateDrawAtoms()
2175            drawAtoms.ClearSelection()
2176            G2plt.PlotStructure(G2frame,data)
2177        event.StopPropagation()
2178       
2179    def OnReloadDrawAtoms(event):
2180        data['Drawing']['Atoms'] = []
2181        UpdateDrawAtoms()
2182        drawAtoms.ClearSelection()
2183        G2plt.PlotStructure(G2frame,data)
2184        event.StopPropagation()
2185       
2186    def FindAtomIndexByIDs(atomData,IDs,Draw=True):
2187        indx = []
2188        for i,atom in enumerate(atomData):
2189            if Draw and atom[-3] in IDs:
2190                indx.append(i)
2191            elif atom[-1] in IDs:
2192                indx.append(i)
2193        return indx
2194       
2195    def DrawAtomsDeleteByIDs(IDs):
2196        atomData = data['Drawing']['Atoms']
2197        indx = FindAtomIndexByIDs(atomData,IDs)
2198        indx.reverse()
2199        for ind in indx:
2200            del atomData[ind]
2201           
2202    def ChangeDrawAtomsByIDs(colName,IDs,value):
2203        atomData = data['Drawing']['Atoms']
2204        cx,ct,cs,ci = data['Drawing']['atomPtrs']
2205        if colName == 'Name':
2206            col = ct-1
2207        elif colName == 'Type':
2208            col = ct
2209        elif colName == 'I/A':
2210            col = cs
2211        indx = FindAtomIndexByIDs(atomData,IDs)
2212        for ind in indx:
2213            atomData[ind][col] = value
2214               
2215    def OnDrawPlane(event):
2216        indx = drawAtoms.GetSelectedRows()
2217        if len(indx) < 4:
2218            print '**** ERROR - need 4+ atoms for plane calculation'
2219            return
2220        PlaneData = {}
2221        drawingData = data['Drawing']
2222        atomData = drawingData['Atoms']
2223        colLabels = [drawAtoms.GetColLabelValue(c) for c in range(drawAtoms.GetNumberCols())]
2224        cx = colLabels.index('x')
2225        cn = colLabels.index('Name')
2226        xyz = []
2227        for i,atom in enumerate(atomData):
2228            if i in indx:
2229                xyz.append([i,]+atom[cn:cn+2]+atom[cx:cx+3])
2230        generalData = data['General']
2231        PlaneData['Name'] = generalData['Name']
2232        PlaneData['Atoms'] = xyz
2233        PlaneData['Cell'] = generalData['Cell'][1:] #+ volume
2234        G2str.BestPlane(PlaneData)
2235   
2236    def OnDrawDAT(event):
2237        #distance, angle, torsion
2238        indx = drawAtoms.GetSelectedRows()
2239        if len(indx) not in [2,3,4]:
2240            print '**** ERROR - wrong number of atoms for distance, angle or torsion calculation'
2241            return
2242        DATData = {}
2243        ocx,oct,ocs,cia = data['General']['AtomPtrs']
2244        drawingData = data['Drawing']
2245        atomData = data['Atoms']
2246        atomDData = drawingData['Atoms']
2247        colLabels = [drawAtoms.GetColLabelValue(c) for c in range(drawAtoms.GetNumberCols())]
2248        cx = colLabels.index('x')
2249        cn = colLabels.index('Name')
2250        cid = colLabels.index('I/A')+8
2251        xyz = []
2252        Oxyz = []
2253        DATData['Natoms'] = len(indx)
2254        for i in indx:
2255            atom = atomDData[i]
2256            xyz.append([i,]+atom[cn:cn+2]+atom[cx:cx+4]) #also gets Sym Op
2257            id = FindAtomIndexByIDs(atomData,[atom[cid],],False)[0]
2258            Oxyz.append([id,]+atomData[id][cx+1:cx+4])
2259        DATData['Datoms'] = xyz
2260        DATData['Oatoms'] = Oxyz
2261        generalData = data['General']
2262        DATData['Name'] = generalData['Name']
2263        DATData['SGData'] = generalData['SGData']
2264        DATData['Cell'] = generalData['Cell'][1:] #+ volume
2265        if 'pId' in data:
2266            DATData['pId'] = data['pId']
2267            DATData['covData'] = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.root, 'Covariance'))
2268        G2str.DisAglTor(DATData)
2269               
2270################################################################################
2271#### Draw Options page
2272################################################################################
2273
2274    def UpdateDrawOptions():
2275        import copy
2276        import wx.lib.colourselect as wcs
2277        generalData = data['General']
2278        SetupDrawingData()
2279        drawingData = data['Drawing']
2280        if generalData['Type'] == 'nuclear':
2281            pickChoice = ['Atoms','Bonds','Torsions','Planes']
2282        elif generalData['Type'] == 'macromolecular':
2283            pickChoice = ['Atoms','Residues','Chains','Bonds','Torsions','Planes','phi/psi']
2284
2285        def SlopSizer():
2286           
2287            def OnCameraPos(event):
2288                drawingData['cameraPos'] = cameraPos.GetValue()
2289                cameraPosTxt.SetLabel(' Camera Distance: '+'%.2f'%(drawingData['cameraPos']))
2290                ZclipTxt.SetLabel(' Z clipping: '+'%.2fA'%(drawingData['Zclip']*drawingData['cameraPos']/100.))
2291                G2plt.PlotStructure(G2frame,data)
2292
2293            def OnZclip(event):
2294                drawingData['Zclip'] = Zclip.GetValue()
2295                ZclipTxt.SetLabel(' Z clipping: '+'%.2fA'%(drawingData['Zclip']*drawingData['cameraPos']/100.))
2296                G2plt.PlotStructure(G2frame,data)
2297               
2298            def OnVdWScale(event):
2299                drawingData['vdwScale'] = vdwScale.GetValue()/100.
2300                vdwScaleTxt.SetLabel(' van der Waals scale: '+'%.2f'%(drawingData['vdwScale']))
2301                G2plt.PlotStructure(G2frame,data)
2302   
2303            def OnEllipseProb(event):
2304                drawingData['ellipseProb'] = ellipseProb.GetValue()
2305                ellipseProbTxt.SetLabel(' Ellipsoid probability: '+'%d%%'%(drawingData['ellipseProb']))
2306                G2plt.PlotStructure(G2frame,data)
2307   
2308            def OnBallScale(event):
2309                drawingData['ballScale'] = ballScale.GetValue()/100.
2310                ballScaleTxt.SetLabel(' Ball scale: '+'%.2f'%(drawingData['ballScale']))
2311                G2plt.PlotStructure(G2frame,data)
2312
2313            def OnBondRadius(event):
2314                drawingData['bondRadius'] = bondRadius.GetValue()/100.
2315                bondRadiusTxt.SetLabel(' Bond radius, A: '+'%.2f'%(drawingData['bondRadius']))
2316                G2plt.PlotStructure(G2frame,data)
2317               
2318            def OnContourLevel(event):
2319                drawingData['contourLevel'] = contourLevel.GetValue()/100.
2320                contourLevelTxt.SetLabel(' Contour level: '+'%.2f'%(drawingData['contourLevel']*generalData['Map']['rhoMax']))
2321                G2plt.PlotStructure(G2frame,data)
2322
2323            def OnMapSize(event):
2324                drawingData['mapSize'] = mapSize.GetValue()/10.
2325                mapSizeTxt.SetLabel(' Map radius, A: '+'%.1f'%(drawingData['mapSize']))
2326                G2plt.PlotStructure(G2frame,data)
2327
2328           
2329            slopSizer = wx.BoxSizer(wx.HORIZONTAL)
2330            slideSizer = wx.FlexGridSizer(7,2)
2331            slideSizer.AddGrowableCol(1,1)
2332   
2333            cameraPosTxt = wx.StaticText(dataDisplay,-1,
2334                ' Camera Distance: '+'%.2f'%(drawingData['cameraPos']),name='cameraPos')
2335            slideSizer.Add(cameraPosTxt,0,wx.ALIGN_CENTER_VERTICAL)
2336            cameraPos = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=drawingData['cameraPos'],name='cameraSlider')
2337            cameraPos.SetRange(10,500)
2338            cameraPos.Bind(wx.EVT_SLIDER, OnCameraPos)
2339            slideSizer.Add(cameraPos,1,wx.EXPAND|wx.RIGHT)
2340           
2341            ZclipTxt = wx.StaticText(dataDisplay,-1,' Z clipping: '+'%.2fA'%(drawingData['Zclip']*drawingData['cameraPos']/100.))
2342            slideSizer.Add(ZclipTxt,0,wx.ALIGN_CENTER_VERTICAL)
2343            Zclip = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=drawingData['Zclip'])
2344            Zclip.SetRange(1,99)
2345            Zclip.Bind(wx.EVT_SLIDER, OnZclip)
2346            slideSizer.Add(Zclip,1,wx.EXPAND|wx.RIGHT)
2347           
2348            vdwScaleTxt = wx.StaticText(dataDisplay,-1,' van der Waals scale: '+'%.2f'%(drawingData['vdwScale']))
2349            slideSizer.Add(vdwScaleTxt,0,wx.ALIGN_CENTER_VERTICAL)
2350            vdwScale = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=int(100*drawingData['vdwScale']))
2351            vdwScale.Bind(wx.EVT_SLIDER, OnVdWScale)
2352            slideSizer.Add(vdwScale,1,wx.EXPAND|wx.RIGHT)
2353   
2354            ellipseProbTxt = wx.StaticText(dataDisplay,-1,' Ellipsoid probability: '+'%d%%'%(drawingData['ellipseProb']))
2355            slideSizer.Add(ellipseProbTxt,0,wx.ALIGN_CENTER_VERTICAL)
2356            ellipseProb = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=drawingData['ellipseProb'])
2357            ellipseProb.SetRange(1,99)
2358            ellipseProb.Bind(wx.EVT_SLIDER, OnEllipseProb)
2359            slideSizer.Add(ellipseProb,1,wx.EXPAND|wx.RIGHT)
2360   
2361            ballScaleTxt = wx.StaticText(dataDisplay,-1,' Ball scale: '+'%.2f'%(drawingData['ballScale']))
2362            slideSizer.Add(ballScaleTxt,0,wx.ALIGN_CENTER_VERTICAL)
2363            ballScale = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=int(100*drawingData['ballScale']))
2364            ballScale.Bind(wx.EVT_SLIDER, OnBallScale)
2365            slideSizer.Add(ballScale,1,wx.EXPAND|wx.RIGHT)
2366   
2367            bondRadiusTxt = wx.StaticText(dataDisplay,-1,' Bond radius, A: '+'%.2f'%(drawingData['bondRadius']))
2368            slideSizer.Add(bondRadiusTxt,0,wx.ALIGN_CENTER_VERTICAL)
2369            bondRadius = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=int(100*drawingData['bondRadius']))
2370            bondRadius.SetRange(1,25)
2371            bondRadius.Bind(wx.EVT_SLIDER, OnBondRadius)
2372            slideSizer.Add(bondRadius,1,wx.EXPAND|wx.RIGHT)
2373           
2374            if generalData['Map']['rhoMax']:
2375                contourLevelTxt = wx.StaticText(dataDisplay,-1,' Contour level: '+'%.2f'%(drawingData['contourLevel']*generalData['Map']['rhoMax']))
2376                slideSizer.Add(contourLevelTxt,0,wx.ALIGN_CENTER_VERTICAL)
2377                contourLevel = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=int(100*drawingData['contourLevel']))
2378                contourLevel.SetRange(1,100)
2379                contourLevel.Bind(wx.EVT_SLIDER, OnContourLevel)
2380                slideSizer.Add(contourLevel,1,wx.EXPAND|wx.RIGHT)
2381                mapSizeTxt = wx.StaticText(dataDisplay,-1,' Map radius, A: '+'%.1f'%(drawingData['mapSize']))
2382                slideSizer.Add(mapSizeTxt,0,wx.ALIGN_CENTER_VERTICAL)
2383                mapSize = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=int(10*drawingData['mapSize']))
2384                mapSize.SetRange(1,100)
2385                mapSize.Bind(wx.EVT_SLIDER, OnMapSize)
2386                slideSizer.Add(mapSize,1,wx.EXPAND|wx.RIGHT)
2387           
2388            slopSizer.Add(slideSizer,1,wx.EXPAND|wx.RIGHT)
2389            slopSizer.Add((10,5),0)
2390            slopSizer.SetMinSize(wx.Size(350,10))
2391            return slopSizer
2392           
2393        def ShowSizer():
2394           
2395            def OnBackColor(event):
2396                drawingData['backColor'] = event.GetValue()
2397                G2plt.PlotStructure(G2frame,data)
2398   
2399            def OnShowABC(event):
2400                drawingData['showABC'] = showABC.GetValue()
2401                G2plt.PlotStructure(G2frame,data)
2402   
2403            def OnShowUnitCell(event):
2404                drawingData['unitCellBox'] = unitCellBox.GetValue()
2405                G2plt.PlotStructure(G2frame,data)
2406   
2407            def OnShowHyd(event):
2408                drawingData['showHydrogen'] = showHydrogen.GetValue()
2409                FindBondsDraw()
2410                G2plt.PlotStructure(G2frame,data)
2411               
2412            showSizer = wx.FlexGridSizer(5,3,5,0)           
2413            lineSizer = wx.BoxSizer(wx.HORIZONTAL)
2414            lineSizer.Add(wx.StaticText(dataDisplay,-1,' Background color:'),0,wx.ALIGN_CENTER_VERTICAL)
2415            backColor = wcs.ColourSelect(dataDisplay, -1,colour=drawingData['backColor'],size=wx.Size(25,25))
2416            backColor.Bind(wcs.EVT_COLOURSELECT, OnBackColor)
2417            lineSizer.Add(backColor,0,wx.ALIGN_CENTER_VERTICAL)
2418            showSizer.Add(lineSizer,0,)
2419           
2420            showSizer.Add(wx.StaticText(dataDisplay,-1,' View Point:  '),0,wx.ALIGN_CENTER_VERTICAL)
2421            VP = drawingData['viewPoint'][0]
2422            viewPoint = wx.TextCtrl(dataDisplay,value='%.3f, %.3f, %.3f'%(VP[0],VP[1],VP[2]),
2423                style=wx.TE_READONLY,size=wx.Size(120,20),name='viewPoint')
2424            viewPoint.SetBackgroundColour(VERY_LIGHT_GREY)
2425            showSizer.Add(viewPoint,0,wx.ALIGN_CENTER_VERTICAL)
2426           
2427            showABC = wx.CheckBox(dataDisplay,-1,label=' Show test point?')
2428            showABC.Bind(wx.EVT_CHECKBOX, OnShowABC)
2429            showABC.SetValue(drawingData['showABC'])
2430            showSizer.Add(showABC,0,wx.ALIGN_CENTER_VERTICAL)
2431   
2432            unitCellBox = wx.CheckBox(dataDisplay,-1,label=' Show unit cell?')
2433            unitCellBox.Bind(wx.EVT_CHECKBOX, OnShowUnitCell)
2434            unitCellBox.SetValue(drawingData['unitCellBox'])
2435            showSizer.Add(unitCellBox,0,wx.ALIGN_CENTER_VERTICAL)
2436   
2437            showHydrogen = wx.CheckBox(dataDisplay,-1,label=' Show hydrogens?')
2438            showHydrogen.Bind(wx.EVT_CHECKBOX, OnShowHyd)
2439            showHydrogen.SetValue(drawingData['showHydrogen'])
2440            showSizer.Add(showHydrogen,0,wx.ALIGN_CENTER_VERTICAL)
2441            return showSizer
2442           
2443        def RadSizer():
2444           
2445            def OnSizeHatoms(event):
2446                try:
2447                    value = max(0.1,min(1.2,float(sizeH.GetValue())))
2448                except ValueError:
2449                    value = 0.5
2450                drawingData['sizeH'] = value
2451                sizeH.SetValue("%.2f"%(value))
2452                G2plt.PlotStructure(G2frame,data)
2453               
2454            def OnRadFactor(event):
2455                try:
2456                    value = max(0.1,min(1.2,float(radFactor.GetValue())))
2457                except ValueError:
2458                    value = 0.85
2459                drawingData['radiusFactor'] = value
2460                radFactor.SetValue("%.2f"%(value))
2461                FindBondsDraw()
2462                G2plt.PlotStructure(G2frame,data)
2463           
2464            radSizer = wx.BoxSizer(wx.HORIZONTAL)
2465            radSizer.Add(wx.StaticText(dataDisplay,-1,' Hydrogen radius, A:  '),0,wx.ALIGN_CENTER_VERTICAL)
2466            sizeH = wx.TextCtrl(dataDisplay,-1,value='%.2f'%(drawingData['sizeH']),size=wx.Size(60,20),style=wx.TE_PROCESS_ENTER)
2467            sizeH.Bind(wx.EVT_TEXT_ENTER,OnSizeHatoms)
2468            sizeH.Bind(wx.EVT_KILL_FOCUS,OnSizeHatoms)
2469            radSizer.Add(sizeH,0,wx.ALIGN_CENTER_VERTICAL)
2470   
2471            radSizer.Add(wx.StaticText(dataDisplay,-1,' Bond search factor:  '),0,wx.ALIGN_CENTER_VERTICAL)
2472            radFactor = wx.TextCtrl(dataDisplay,value='%.2f'%(drawingData['radiusFactor']),size=wx.Size(60,20),style=wx.TE_PROCESS_ENTER)
2473            radFactor.Bind(wx.EVT_TEXT_ENTER,OnRadFactor)
2474            radFactor.Bind(wx.EVT_KILL_FOCUS,OnRadFactor)
2475            radSizer.Add(radFactor,0,wx.ALIGN_CENTER_VERTICAL)
2476            return radSizer
2477
2478        drawOptions.DestroyChildren()
2479        dataDisplay = wx.Panel(drawOptions)
2480        mainSizer = wx.BoxSizer(wx.VERTICAL)
2481        mainSizer.Add((5,5),0)
2482        mainSizer.Add(wx.StaticText(dataDisplay,-1,' Drawing controls:'),0,wx.ALIGN_CENTER_VERTICAL)
2483        mainSizer.Add((5,5),0)       
2484        mainSizer.Add(SlopSizer(),0)
2485        mainSizer.Add((5,5),0)
2486        mainSizer.Add(ShowSizer(),0,)
2487        mainSizer.Add((5,5),0)
2488        mainSizer.Add(RadSizer(),0,)
2489
2490        dataDisplay.SetSizer(mainSizer)
2491        Size = mainSizer.Fit(G2frame.dataFrame)
2492        Size[1] += 26                           #compensate for status bar
2493        dataDisplay.SetSize(Size)
2494        G2frame.dataFrame.setSizePosLeft(Size)
2495
2496################################################################################
2497####  Texture routines
2498################################################################################
2499       
2500    def UpdateTexture():
2501        generalData = data['General']       
2502        SGData = generalData['SGData']
2503        try:
2504            textureData = generalData['SH Texture']
2505        except KeyError:            #fix old files!
2506            textureData = generalData['SH Texture'] = {'Order':0,'Model':'cylindrical',
2507                'Sample omega':[False,0.0],'Sample chi':[False,0.0],'Sample phi':[False,0.0],
2508                'SH Coeff':[False,{}],'SHShow':False,'PFhkl':[0,0,1],
2509                'PFxyz':[0,0,1.],'PlotType':'Pole figure'}
2510        if 'SHShow' not in textureData:     #another fix
2511            textureData.update({'SHShow':False,'PFhkl':[0,0,1],'PFxyz':[0,0,1.],'PlotType':'Pole figure'})
2512        try:                        #another fix!
2513            x = textureData['PlotType']
2514        except KeyError:
2515            textureData.update({'PFxyz':[0,0,1.],'PlotType':'Pole figure'})
2516        shModels = ['cylindrical','none','shear - 2/m','rolling - mmm']
2517        SamSym = dict(zip(shModels,['0','-1','2/m','mmm']))
2518        if generalData['doPawley'] and G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Sequental results'):
2519            G2frame.dataFrame.RefineTexture.Enable(True)
2520        shAngles = ['omega','chi','phi']
2521       
2522        def SetSHCoef():
2523            cofNames = G2lat.GenSHCoeff(SGData['SGLaue'],SamSym[textureData['Model']],textureData['Order'])
2524            newSHCoef = dict(zip(cofNames,np.zeros(len(cofNames))))
2525            SHCoeff = textureData['SH Coeff'][1]
2526            for cofName in SHCoeff:
2527                if cofName in  cofNames:
2528                    newSHCoef[cofName] = SHCoeff[cofName]
2529            return newSHCoef
2530       
2531        def OnShOrder(event):
2532            Obj = event.GetEventObject()
2533            textureData['Order'] = int(Obj.GetValue())
2534            textureData['SH Coeff'][1] = SetSHCoef()
2535            wx.CallAfter(UpdateTexture)
2536            G2plt.PlotTexture(G2frame,data)
2537                       
2538        def OnShModel(event):
2539            Obj = event.GetEventObject()
2540            textureData['Model'] = Obj.GetValue()
2541            textureData['SH Coeff'][1] = SetSHCoef()
2542            wx.CallAfter(UpdateTexture)
2543            G2plt.PlotTexture(G2frame,data)
2544           
2545        def OnSHRefine(event):
2546            Obj = event.GetEventObject()
2547            textureData['SH Coeff'][0] = Obj.GetValue()
2548           
2549        def OnSHShow(event):
2550            Obj = event.GetEventObject()
2551            textureData['SHShow'] = Obj.GetValue()
2552            wx.CallAfter(UpdateTexture)
2553           
2554        def OnProjSel(event):
2555            Obj = event.GetEventObject()
2556            G2frame.Projection = Obj.GetValue()
2557            G2plt.PlotTexture(G2frame,data)
2558           
2559        def OnColorSel(event):
2560            Obj = event.GetEventObject()
2561            G2frame.ContourColor = Obj.GetValue()
2562            G2plt.PlotTexture(G2frame,data)
2563           
2564        def OnAngRef(event):
2565            Obj = event.GetEventObject()
2566            textureData[angIndx[Obj.GetId()]][0] = Obj.GetValue()
2567           
2568        def OnAngValue(event):
2569            Obj = event.GetEventObject()
2570            try:
2571                value =  float(Obj.GetValue())
2572            except ValueError:
2573                value = textureData[valIndx[Obj.GetId()]][1]
2574            Obj.SetValue('%8.2f'%(value))
2575            textureData[valIndx[Obj.GetId()]][1] = value
2576           
2577        def OnODFValue(event): 
2578            Obj = event.GetEventObject()
2579            try:
2580                value =  float(Obj.GetValue())
2581            except ValueError:
2582                value = textureData['SH Coeff'][1][ODFIndx[Obj.GetId()]]
2583            Obj.SetValue('%8.3f'%(value))
2584            textureData['SH Coeff'][1][ODFIndx[Obj.GetId()]] = value
2585            G2plt.PlotTexture(G2frame,data)
2586           
2587        def OnPfType(event):
2588            Obj = event.GetEventObject()
2589            textureData['PlotType'] = Obj.GetValue()
2590            wx.CallAfter(UpdateTexture)
2591            G2plt.PlotTexture(G2frame,data)
2592           
2593        def OnPFValue(event):
2594            Obj = event.GetEventObject()
2595            Saxis = Obj.GetValue().split()
2596            if textureData['PlotType'] in ['Pole figure','Axial pole distribution']:               
2597                try:
2598                    hkl = [int(Saxis[i]) for i in range(3)]
2599                except (ValueError,IndexError):
2600                    hkl = textureData['PFhkl']
2601                if not np.any(np.array(hkl)):       #can't be all zeros!
2602                    hkl = textureData['PFhkl']
2603                Obj.SetValue('%d %d %d'%(hkl[0],hkl[1],hkl[2]))
2604                textureData['PFhkl'] = hkl
2605            else:
2606                try:
2607                    xyz = [float(Saxis[i]) for i in range(3)]
2608                except (ValueError,IndexError):
2609                    xyz = textureData['PFxyz']
2610                if not np.any(np.array(xyz)):       #can't be all zeros!
2611                    xyz = textureData['PFxyz']
2612                Obj.SetValue('%3.1f %3.1f %3.1f'%(xyz[0],xyz[1],xyz[2]))
2613                textureData['PFxyz'] = xyz
2614            G2plt.PlotTexture(G2frame,data)
2615
2616        if Texture.GetSizer():
2617            Texture.GetSizer().Clear(True)
2618        mainSizer = wx.BoxSizer(wx.VERTICAL)
2619        titleSizer = wx.BoxSizer(wx.HORIZONTAL)
2620        titleSizer.Add(wx.StaticText(Texture,-1,'Spherical harmonics texture data for '+PhaseName+':'),0,wx.ALIGN_CENTER_VERTICAL)
2621        titleSizer.Add(wx.StaticText(Texture,-1,
2622            ' Texture Index J = %7.3f'%(G2lat.textureIndex(textureData['SH Coeff'][1]))),
2623            0,wx.ALIGN_CENTER_VERTICAL)
2624        mainSizer.Add(titleSizer,0)
2625        mainSizer.Add((0,5),0)
2626        shSizer = wx.FlexGridSizer(1,6,5,5)
2627        shSizer.Add(wx.StaticText(Texture,-1,'Texture model: '),0,wx.ALIGN_CENTER_VERTICAL)
2628        shModel = wx.ComboBox(Texture,-1,value=textureData['Model'],choices=shModels,
2629            style=wx.CB_READONLY|wx.CB_DROPDOWN)
2630        shModel.Bind(wx.EVT_COMBOBOX,OnShModel)
2631        shSizer.Add(shModel,0,wx.ALIGN_CENTER_VERTICAL)
2632        shSizer.Add(wx.StaticText(Texture,-1,'  Harmonic order: '),0,wx.ALIGN_CENTER_VERTICAL)
2633        shOrder = wx.ComboBox(Texture,-1,value=str(textureData['Order']),choices=[str(2*i) for i in range(18)],
2634            style=wx.CB_READONLY|wx.CB_DROPDOWN)
2635        shOrder.Bind(wx.EVT_COMBOBOX,OnShOrder)
2636        shSizer.Add(shOrder,0,wx.ALIGN_CENTER_VERTICAL)
2637        shRef = wx.CheckBox(Texture,-1,label=' Refine texture?')
2638        shRef.SetValue(textureData['SH Coeff'][0])
2639        shRef.Bind(wx.EVT_CHECKBOX, OnSHRefine)
2640        shSizer.Add(shRef,0,wx.ALIGN_CENTER_VERTICAL)
2641        shShow = wx.CheckBox(Texture,-1,label=' Show coeff.?')
2642        shShow.SetValue(textureData['SHShow'])
2643        shShow.Bind(wx.EVT_CHECKBOX, OnSHShow)
2644        shSizer.Add(shShow,0,wx.ALIGN_CENTER_VERTICAL)
2645        mainSizer.Add(shSizer,0,0)
2646        mainSizer.Add((0,5),0)
2647        PTSizer = wx.FlexGridSizer(2,4,5,5)
2648        PTSizer.Add(wx.StaticText(Texture,-1,' Texture plot type: '),0,wx.ALIGN_CENTER_VERTICAL)
2649        choices = ['Axial pole distribution','Pole figure','Inverse pole figure']           
2650        pfType = wx.ComboBox(Texture,-1,value=str(textureData['PlotType']),choices=choices,
2651            style=wx.CB_READONLY|wx.CB_DROPDOWN)
2652        pfType.Bind(wx.EVT_COMBOBOX,OnPfType)
2653        PTSizer.Add(pfType,0,wx.ALIGN_CENTER_VERTICAL)
2654        if 'Axial' not in textureData['PlotType']:
2655            PTSizer.Add(wx.StaticText(Texture,-1,' Projection type: '),0,wx.ALIGN_CENTER_VERTICAL)
2656            projSel = wx.ComboBox(Texture,-1,value=G2frame.Projection,choices=['equal area','stereographic','3D display'],
2657                style=wx.CB_READONLY|wx.CB_DROPDOWN)
2658            projSel.Bind(wx.EVT_COMBOBOX,OnProjSel)
2659            PTSizer.Add(projSel,0,wx.ALIGN_CENTER_VERTICAL)
2660        if textureData['PlotType'] in ['Pole figure','Axial pole distribution']:
2661            PTSizer.Add(wx.StaticText(Texture,-1,' Pole figure HKL: '),0,wx.ALIGN_CENTER_VERTICAL)
2662            PH = textureData['PFhkl']
2663            pfVal = wx.TextCtrl(Texture,-1,'%d %d %d'%(PH[0],PH[1],PH[2]),style=wx.TE_PROCESS_ENTER)
2664        else:
2665            PTSizer.Add(wx.StaticText(Texture,-1,' Inverse pole figure XYZ: '),0,wx.ALIGN_CENTER_VERTICAL)
2666            PX = textureData['PFxyz']
2667            pfVal = wx.TextCtrl(Texture,-1,'%3.1f %3.1f %3.1f'%(PX[0],PX[1],PX[2]),style=wx.TE_PROCESS_ENTER)
2668        pfVal.Bind(wx.EVT_TEXT_ENTER,OnPFValue)
2669        pfVal.Bind(wx.EVT_KILL_FOCUS,OnPFValue)
2670        PTSizer.Add(pfVal,0,wx.ALIGN_CENTER_VERTICAL)
2671        if 'Axial' not in textureData['PlotType']:
2672            PTSizer.Add(wx.StaticText(Texture,-1,' Color scheme'),0,wx.ALIGN_CENTER_VERTICAL)
2673            choice = [m for m in mpl.cm.datad.keys() if not m.endswith("_r")]
2674            choice.sort()
2675            colorSel = wx.ComboBox(Texture,-1,value=G2frame.ContourColor,choices=choice,
2676                style=wx.CB_READONLY|wx.CB_DROPDOWN)
2677            colorSel.Bind(wx.EVT_COMBOBOX,OnColorSel)
2678            PTSizer.Add(colorSel,0,wx.ALIGN_CENTER_VERTICAL)       
2679        mainSizer.Add(PTSizer,0,wx.ALIGN_CENTER_VERTICAL)
2680        mainSizer.Add((0,5),0)
2681        if textureData['SHShow']:
2682            mainSizer.Add(wx.StaticText(Texture,-1,'Spherical harmonic coefficients: '),0,wx.ALIGN_CENTER_VERTICAL)
2683            mainSizer.Add((0,5),0)
2684            ODFSizer = wx.FlexGridSizer(2,8,2,2)
2685            ODFIndx = {}
2686            ODFkeys = textureData['SH Coeff'][1].keys()
2687            ODFkeys.sort()
2688            for item in ODFkeys:
2689                ODFSizer.Add(wx.StaticText(Texture,-1,item),0,wx.ALIGN_CENTER_VERTICAL)
2690                ODFval = wx.TextCtrl(Texture,wx.ID_ANY,'%8.3f'%(textureData['SH Coeff'][1][item]),style=wx.TE_PROCESS_ENTER)
2691                ODFIndx[ODFval.GetId()] = item
2692                ODFval.Bind(wx.EVT_TEXT_ENTER,OnODFValue)
2693                ODFval.Bind(wx.EVT_KILL_FOCUS,OnODFValue)
2694                ODFSizer.Add(ODFval,0,wx.ALIGN_CENTER_VERTICAL)
2695            mainSizer.Add(ODFSizer,0,wx.ALIGN_CENTER_VERTICAL)
2696            mainSizer.Add((0,5),0)
2697        mainSizer.Add((0,5),0)
2698        mainSizer.Add(wx.StaticText(Texture,-1,'Sample orientation angles: '),0,wx.ALIGN_CENTER_VERTICAL)
2699        mainSizer.Add((0,5),0)
2700        angSizer = wx.BoxSizer(wx.HORIZONTAL)
2701        angIndx = {}
2702        valIndx = {}
2703        for item in ['Sample omega','Sample chi','Sample phi']:
2704            angRef = wx.CheckBox(Texture,-1,label=item+': ')
2705            angRef.SetValue(textureData[item][0])
2706            angIndx[angRef.GetId()] = item
2707            angRef.Bind(wx.EVT_CHECKBOX, OnAngRef)
2708            angSizer.Add(angRef,0,wx.ALIGN_CENTER_VERTICAL)
2709            angVal = wx.TextCtrl(Texture,wx.ID_ANY,'%8.2f'%(textureData[item][1]),style=wx.TE_PROCESS_ENTER)
2710            valIndx[angVal.GetId()] = item
2711            angVal.Bind(wx.EVT_TEXT_ENTER,OnAngValue)
2712            angVal.Bind(wx.EVT_KILL_FOCUS,OnAngValue)
2713            angSizer.Add(angVal,0,wx.ALIGN_CENTER_VERTICAL)
2714            angSizer.Add((5,0),0)
2715        mainSizer.Add(angSizer,0,wx.ALIGN_CENTER_VERTICAL)
2716        Texture.SetSizer(mainSizer,True)
2717        mainSizer.Fit(G2frame.dataFrame)
2718        Size = mainSizer.GetMinSize()
2719        Size[0] += 40
2720        Size[1] = max(Size[1],250) + 20
2721        Texture.SetSize(Size)
2722        Texture.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
2723        Size[1] = min(Size[1],450)
2724        G2frame.dataFrame.setSizePosLeft(Size)
2725
2726################################################################################
2727##### DData routines
2728################################################################################
2729       
2730    def UpdateDData():
2731        UseList = data['Histograms']
2732        if UseList:
2733            G2frame.dataFrame.DataMenu.Enable(G2gd.wxID_DATADELETE,True)
2734            G2frame.Refine.Enable(True)
2735        else:
2736            G2frame.dataFrame.DataMenu.Enable(G2gd.wxID_DATADELETE,False)
2737            G2frame.Refine.Enable(False)           
2738        generalData = data['General']       
2739        SGData = generalData['SGData']
2740        keyList = UseList.keys()
2741        keyList.sort()
2742        PWDR = any(['PWDR' in item for item in keyList])
2743        Indx = {}
2744       
2745        def PlotSizer():
2746
2747            def OnPlotSel(event):
2748                Obj = event.GetEventObject()
2749                generalData['Data plot type'] = Obj.GetStringSelection()
2750                wx.CallAfter(UpdateDData)
2751                G2plt.PlotSizeStrainPO(G2frame,data)
2752               
2753            def OnPOhkl(event):
2754                Obj = event.GetEventObject()
2755                Saxis = Obj.GetValue().split()
2756                try:
2757                    hkl = [int(Saxis[i]) for i in range(3)]
2758                except (ValueError,IndexError):
2759                    hkl = generalData['POhkl']
2760                if not np.any(np.array(hkl)):
2761                    hkl = generalData['POhkl']
2762                generalData['POhkl'] = hkl
2763                h,k,l = hkl
2764                Obj.SetValue('%3d %3d %3d'%(h,k,l)) 
2765                G2plt.PlotSizeStrainPO(G2frame,data)
2766           
2767            plotSizer = wx.BoxSizer(wx.VERTICAL)
2768            choice = ['None','Mustrain','Size','Preferred orientation']
2769            plotSel = wx.RadioBox(DData,-1,'Select plot type:',choices=choice,
2770                majorDimension=2,style=wx.RA_SPECIFY_COLS)
2771            plotSel.SetStringSelection(generalData['Data plot type'])
2772            plotSel.Bind(wx.EVT_RADIOBOX,OnPlotSel)   
2773            plotSizer.Add(plotSel)
2774            if generalData['Data plot type'] == 'Preferred orientation':
2775                POhklSizer = wx.BoxSizer(wx.HORIZONTAL)
2776                POhklSizer.Add(wx.StaticText(DData,-1,' Plot preferred orientation for H K L: '),0,wx.ALIGN_CENTER_VERTICAL)
2777                h,k,l = generalData['POhkl']
2778                poAxis = wx.TextCtrl(DData,-1,'%3d %3d %3d'%(h,k,l),style=wx.TE_PROCESS_ENTER)
2779                poAxis.Bind(wx.EVT_TEXT_ENTER,OnPOhkl)
2780                poAxis.Bind(wx.EVT_KILL_FOCUS,OnPOhkl)
2781                POhklSizer.Add(poAxis,0,wx.ALIGN_CENTER_VERTICAL)
2782                plotSizer.Add(POhklSizer)           
2783            return plotSizer
2784           
2785        def ScaleSizer():
2786           
2787            def OnScaleRef(event):
2788                Obj = event.GetEventObject()
2789                UseList[Indx[Obj.GetId()]]['Scale'][1] = Obj.GetValue()
2790               
2791            def OnScaleVal(event):
2792                Obj = event.GetEventObject()
2793                try:
2794                    scale = float(Obj.GetValue())
2795                    if scale > 0:
2796                        UseList[Indx[Obj.GetId()]]['Scale'][0] = scale
2797                except ValueError:
2798                    pass
2799                Obj.SetValue("%.4f"%(UseList[Indx[Obj.GetId()]]['Scale'][0]))          #reset in case of error
2800                           
2801            scaleSizer = wx.BoxSizer(wx.HORIZONTAL)
2802            if 'PWDR' in item:
2803                scaleRef = wx.CheckBox(DData,-1,label=' Phase fraction: ')
2804            elif 'HKLF' in item:
2805                scaleRef = wx.CheckBox(DData,-1,label=' Scale factor: ')               
2806            scaleRef.SetValue(UseList[item]['Scale'][1])
2807            Indx[scaleRef.GetId()] = item
2808            scaleRef.Bind(wx.EVT_CHECKBOX, OnScaleRef)
2809            scaleSizer.Add(scaleRef,0,wx.ALIGN_CENTER_VERTICAL)
2810            scaleVal = wx.TextCtrl(DData,wx.ID_ANY,
2811                '%.4f'%(UseList[item]['Scale'][0]),style=wx.TE_PROCESS_ENTER)
2812            Indx[scaleVal.GetId()] = item
2813            scaleVal.Bind(wx.EVT_TEXT_ENTER,OnScaleVal)
2814            scaleVal.Bind(wx.EVT_KILL_FOCUS,OnScaleVal)
2815            scaleSizer.Add(scaleVal,0,wx.ALIGN_CENTER_VERTICAL)
2816            return scaleSizer
2817           
2818        def OnShowData(event):
2819            Obj = event.GetEventObject()
2820            hist = Indx[Obj.GetId()]
2821            UseList[hist]['Show'] = Obj.GetValue()
2822            wx.CallAfter(UpdateDData)
2823            G2plt.PlotSizeStrainPO(G2frame,data)
2824           
2825        def OnCopyData(event):
2826            #how about HKLF data? This is only for PWDR data
2827            Obj = event.GetEventObject()
2828            hist = Indx[Obj.GetId()]
2829            sourceDict = UseList[hist]
2830            copyNames = ['Scale','Pref.Ori.','Size','Mustrain','HStrain','Extinction']
2831            copyDict = {}
2832            for name in copyNames: 
2833                copyDict[name] = copy.deepcopy(sourceDict[name])        #force copy
2834            keyList = ['All',]+UseList.keys()
2835            if UseList:
2836                copyList = []
2837                dlg = wx.MultiChoiceDialog(G2frame, 
2838                    'Copy parameters to which histograms?', 'Copy parameters', 
2839                    keyList, wx.CHOICEDLG_STYLE)
2840                try:
2841                    if dlg.ShowModal() == wx.ID_OK:
2842                        result = dlg.GetSelections()
2843                        for i in result: 
2844                            copyList.append(keyList[i])
2845                        if 'All' in copyList: 
2846                            copyList = keyList[1:]
2847                        for item in copyList:
2848                            UseList[item].update(copy.deepcopy(copyDict))
2849                        wx.CallAfter(UpdateDData)
2850                finally:
2851                    dlg.Destroy()
2852                   
2853        def OnCopyFlags(event):
2854            Obj = event.GetEventObject()
2855            hist = Indx[Obj.GetId()]
2856            sourceDict = UseList[hist]
2857            copyDict = {}
2858            copyNames = ['Scale','Pref.Ori.','Size','Mustrain','HStrain','Extinction']
2859            for name in copyNames:
2860                if name in ['Scale','Extinction','HStrain']:
2861                    copyDict[name] = sourceDict[name][1]
2862                elif name in ['Size','Mustrain']:
2863                    copyDict[name] = [sourceDict[name][0],sourceDict[name][2],sourceDict[name][4]]
2864                elif name == 'Pref.Ori.':
2865                    copyDict[name] = [sourceDict[name][0],sourceDict[name][2]]
2866                    if sourceDict[name][0] == 'SH':
2867                        SHterms = sourceDict[name][5]
2868                        SHflags = {}
2869                        for item in SHterms:
2870                            SHflags[item] = SHterms[item][1]
2871                        copyDict[name].append(SHflags)                       
2872            keyList = ['All',]+UseList.keys()
2873            if UseList:
2874                copyList = []
2875                dlg = wx.MultiChoiceDialog(G2frame, 
2876                    'Copy parameters to which histograms?', 'Copy parameters', 
2877                    keyList, wx.CHOICEDLG_STYLE)
2878                try:
2879                    if dlg.ShowModal() == wx.ID_OK:
2880                        result = dlg.GetSelections()
2881                        for i in result: 
2882                            copyList.append(keyList[i])
2883                        if 'All' in copyList: 
2884                            copyList = keyList[1:]
2885                        for item in copyList:
2886                            UseList[item]                           
2887                            for name in copyNames:
2888                                if name in ['Scale','Extinction','HStrain']:
2889                                    UseList[item][name][1] = copy.copy(copyDict[name])
2890                                elif name in ['Size','Mustrain']:
2891                                    UseList[item][name][0] = copy.copy(copyDict[name][0])
2892                                    UseList[item][name][2] = copy.copy(copyDict[name][1])
2893                                    UseList[item][name][4] = copy.copy(copyDict[name][2])
2894                                elif name == 'Pref.Ori.':
2895                                    UseList[item][name][0] = copy.copy(copyDict[name][0])
2896                                    UseList[item][name][2] = copy.copy(copyDict[name][1])
2897                                    if sourceDict[name][0] == 'SH':
2898                                        SHflags = copy.copy(copyDict[name][2])
2899                                        SHterms = copy.copy(sourceDict[name][5])
2900                                        for item in SHflags:
2901                                            SHterms[item][1] = copy.copy(SHflags[item])                                             
2902                        wx.CallAfter(UpdateDData)
2903                finally:
2904                    dlg.Destroy()
2905           
2906           
2907        def OnLGmixRef(event):
2908            Obj = event.GetEventObject()
2909            hist,name = Indx[Obj.GetId()]
2910            UseList[hist][name][2][2] = Obj.GetValue()
2911           
2912        def OnLGmixVal(event):
2913            Obj = event.GetEventObject()
2914            hist,name = Indx[Obj.GetId()]
2915            try:
2916                value = float(Obj.GetValue())
2917                if 0.1 <= value <= 1:
2918                    UseList[hist][name][1][2] = value
2919                else:
2920                    raise ValueError
2921            except ValueError:
2922                pass
2923            Obj.SetValue("%.4f"%(UseList[hist][name][1][2]))          #reset in case of error
2924
2925        def OnSizeType(event):
2926            Obj = event.GetEventObject()
2927            hist = Indx[Obj.GetId()]
2928            UseList[hist]['Size'][0] = Obj.GetValue()
2929            G2plt.PlotSizeStrainPO(G2frame,data)
2930            wx.CallAfter(UpdateDData)
2931           
2932        def OnSizeRef(event):
2933            Obj = event.GetEventObject()
2934            hist,pid = Indx[Obj.GetId()]
2935            if UseList[hist]['Size'][0] == 'ellipsoidal':
2936                UseList[hist]['Size'][5][pid] = Obj.GetValue()               
2937            else:
2938                UseList[hist]['Size'][2][pid] = Obj.GetValue()
2939           
2940        def OnSizeVal(event):
2941            Obj = event.GetEventObject()
2942            hist,pid = Indx[Obj.GetId()]
2943            if UseList[hist]['Size'][0] == 'ellipsoidal':
2944                try:
2945                    size = float(Obj.GetValue())
2946                    if pid < 3 and size <= 0.001:            #10A lower limit!
2947                        raise ValueError
2948                    UseList[hist]['Size'][4][pid] = size                   
2949                except ValueError:
2950                    pass
2951                Obj.SetValue("%.3f"%(UseList[hist]['Size'][4][pid]))          #reset in case of error
2952            else:
2953                try:
2954                    size = float(Obj.GetValue())
2955                    if size <= 0.001:            #10A lower limit!
2956                        raise ValueError
2957                    UseList[hist]['Size'][1][pid] = size
2958                except ValueError:
2959                    pass
2960                Obj.SetValue("%.3f"%(UseList[hist]['Size'][1][pid]))          #reset in case of error
2961            G2plt.PlotSizeStrainPO(G2frame,data)
2962           
2963        def OnSizeAxis(event):           
2964            Obj = event.GetEventObject()
2965            hist = Indx[Obj.GetId()]
2966            Saxis = Obj.GetValue().split()
2967            try:
2968                hkl = [int(Saxis[i]) for i in range(3)]
2969            except (ValueError,IndexError):
2970                hkl = UseList[hist]['Size'][3]
2971            if not np.any(np.array(hkl)):
2972                hkl = UseList[hist]['Size'][3]
2973            UseList[hist]['Size'][3] = hkl
2974            h,k,l = hkl
2975            Obj.SetValue('%3d %3d %3d'%(h,k,l)) 
2976                       
2977        def OnStrainType(event):
2978            Obj = event.GetEventObject()
2979            hist = Indx[Obj.GetId()]
2980            UseList[hist]['Mustrain'][0] = Obj.GetValue()
2981            wx.CallAfter(UpdateDData)
2982            G2plt.PlotSizeStrainPO(G2frame,data)
2983           
2984        def OnStrainRef(event):
2985            Obj = event.GetEventObject()
2986            hist,pid = Indx[Obj.GetId()]
2987            if UseList[hist]['Mustrain'][0] == 'generalized':
2988                UseList[hist]['Mustrain'][5][pid] = Obj.GetValue()
2989            else:
2990                UseList[hist]['Mustrain'][2][pid] = Obj.GetValue()
2991           
2992        def OnStrainVal(event):
2993            Snames = G2spc.MustrainNames(SGData)
2994            Obj = event.GetEventObject()
2995            hist,pid = Indx[Obj.GetId()]
2996            try:
2997                strain = float(Obj.GetValue())
2998                if UseList[hist]['Mustrain'][0] == 'generalized':
2999                    if '4' in Snames[pid] and strain < 0:
3000                        raise ValueError
3001                    UseList[hist]['Mustrain'][4][pid] = strain
3002                else:
3003                    if strain <= 0:
3004                        raise ValueError
3005                    UseList[hist]['Mustrain'][1][pid] = strain
3006            except ValueError:
3007                pass
3008            if UseList[hist]['Mustrain'][0] == 'generalized':
3009                Obj.SetValue("%.3f"%(UseList[hist]['Mustrain'][4][pid]))          #reset in case of error
3010            else:
3011                Obj.SetValue("%.1f"%(UseList[hist]['Mustrain'][1][pid]))          #reset in case of error
3012            G2plt.PlotSizeStrainPO(G2frame,data)
3013           
3014        def OnStrainAxis(event):
3015            Obj = event.GetEventObject()
3016            hist = Indx[Obj.GetId()]
3017            Saxis = Obj.GetValue().split()
3018            try:
3019                hkl = [int(Saxis[i]) for i in range(3)]
3020            except (ValueError,IndexError):
3021                hkl = UseList[hist]['Mustrain'][3]
3022            if not np.any(np.array(hkl)):
3023                hkl = UseList[hist]['Mustrain'][3]
3024            UseList[hist]['Mustrain'][3] = hkl
3025            h,k,l = hkl
3026            Obj.SetValue('%3d %3d %3d'%(h,k,l)) 
3027            G2plt.PlotSizeStrainPO(G2frame,data)
3028           
3029        def OnHstrainRef(event):
3030            Obj = event.GetEventObject()
3031            hist,pid = Indx[Obj.GetId()]
3032            UseList[hist]['HStrain'][1][pid] = Obj.GetValue()
3033           
3034        def OnHstrainVal(event):
3035            Snames = G2spc.HStrainNames(SGData)
3036            Obj = event.GetEventObject()
3037            hist,pid = Indx[Obj.GetId()]
3038            try:
3039                strain = float(Obj.GetValue())
3040                UseList[hist]['HStrain'][0][pid] = strain
3041            except ValueError:
3042                pass
3043            Obj.SetValue("%.5f"%(UseList[hist]['HStrain'][0][pid]))          #reset in case of error
3044
3045        def OnPOVal(event):
3046            Obj = event.GetEventObject()
3047            hist = Indx[Obj.GetId()]
3048            try:
3049                mdVal = float(Obj.GetValue())
3050                if mdVal > 0:
3051                    UseList[hist]['Pref.Ori.'][1] = mdVal
3052            except ValueError:
3053                pass
3054            Obj.SetValue("%.3f"%(UseList[hist]['Pref.Ori.'][1]))          #reset in case of error
3055           
3056        def OnPOAxis(event):
3057            Obj = event.GetEventObject()
3058            hist = Indx[Obj.GetId()]
3059            Saxis = Obj.GetValue().split()
3060            try:
3061                hkl = [int(Saxis[i]) for i in range(3)]
3062            except (ValueError,IndexError):
3063                hkl = UseList[hist]['Pref.Ori.'][3]
3064            if not np.any(np.array(hkl)):
3065                hkl = UseList[hist]['Pref.Ori.'][3]
3066            UseList[hist]['Pref.Ori.'][3] = hkl
3067            h,k,l = hkl
3068            Obj.SetValue('%3d %3d %3d'%(h,k,l)) 
3069           
3070        def OnPOOrder(event):
3071            Obj = event.GetEventObject()
3072            hist = Indx[Obj.GetId()]
3073            Order = int(Obj.GetValue())
3074            UseList[hist]['Pref.Ori.'][4] = Order
3075            UseList[hist]['Pref.Ori.'][5] = SetPOCoef(Order,hist)
3076            wx.CallAfter(UpdateDData)
3077
3078        def OnPOType(event):
3079            Obj = event.GetEventObject()
3080            hist = Indx[Obj.GetId()]
3081            if 'March' in Obj.GetValue():
3082                UseList[hist]['Pref.Ori.'][0] = 'MD'
3083            else:
3084                UseList[hist]['Pref.Ori.'][0] = 'SH'
3085            wx.CallAfter(UpdateDData)           
3086   
3087        def OnPORef(event):
3088            Obj = event.GetEventObject()
3089            hist = Indx[Obj.GetId()]
3090            UseList[hist]['Pref.Ori.'][2] = Obj.GetValue()
3091               
3092        def SetPOCoef(Order,hist):
3093            cofNames = G2lat.GenSHCoeff(SGData['SGLaue'],'0',Order,False)     #cylindrical & no M
3094            newPOCoef = dict(zip(cofNames,np.zeros(len(cofNames))))
3095            POCoeff = UseList[hist]['Pref.Ori.'][5]
3096            for cofName in POCoeff:
3097                if cofName in  cofNames:
3098                    newPOCoef[cofName] = POCoeff[cofName]
3099            return newPOCoef
3100       
3101        def OnExtRef(event):
3102            Obj = event.GetEventObject()
3103            UseList[Indx[Obj.GetId()]]['Extinction'][1] = Obj.GetValue()
3104           
3105        def OnExtVal(event):
3106            Obj = event.GetEventObject()
3107            try:
3108                ext = float(Obj.GetValue())
3109                if ext >= 0:
3110                    UseList[Indx[Obj.GetId()]]['Extinction'][0] = ext
3111            except ValueError:
3112                pass
3113            Obj.SetValue("%.2f"%(UseList[Indx[Obj.GetId()]]['Extinction'][0]))
3114           
3115        def OnTbarVal(event):
3116            Obj = event.GetEventObject()
3117            try:
3118                tbar = float(Obj.GetValue())
3119                if tbar >= 0:
3120                    UseList[Indx[Obj.GetId()]]['Extinction'][2]['Tbar'] = tbar
3121            except ValueError:
3122                pass
3123            Obj.SetValue("%.2f"%(UseList[Indx[Obj.GetId()]]['Extinction'][2]['Tbar']))
3124           
3125        def OnEval(event):
3126            Obj = event.GetEventObject()
3127            item = Indx[Obj.GetId()]
3128            try:
3129                val = float(Obj.GetValue())
3130                if val >= 0:
3131                    UseList[item[0]]['Extinction'][2][item[1]][0] = val
3132            except ValueError:
3133                pass
3134            Obj.SetValue("%9.3g"%(UseList[item[0]]['Extinction'][2][item[1]][0]))
3135           
3136        def OnEref(event):
3137            Obj = event.GetEventObject()
3138            item = Indx[Obj.GetId()]
3139            UseList[item[0]]['Extinction'][2][item[1]][1] = Obj.GetValue()
3140
3141        def OnSCExtType(event):
3142            Obj = event.GetEventObject()
3143            item = Indx[Obj.GetId()]
3144            UseList[item[0]]['Extinction'][item[1]] = Obj.GetValue()
3145            wx.CallAfter(UpdateDData)
3146               
3147        def checkAxis(axis):
3148            if not np.any(np.array(axis)):
3149                return False
3150            return axis
3151           
3152        def TopSizer(name,choices,parm,OnType):
3153            topSizer = wx.BoxSizer(wx.HORIZONTAL)
3154            topSizer.Add(wx.StaticText(DData,-1,name),0,wx.ALIGN_CENTER_VERTICAL)
3155            sizeType = wx.ComboBox(DData,wx.ID_ANY,value=UseList[item][parm][0],choices=choices,
3156                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3157            sizeType.Bind(wx.EVT_COMBOBOX, OnType)
3158            Indx[sizeType.GetId()] = item
3159            topSizer.Add(sizeType)
3160            topSizer.Add((5,0),0)
3161            return topSizer
3162           
3163        def LGmixSizer(name,OnVal,OnRef):
3164            lgmixSizer = wx.BoxSizer(wx.HORIZONTAL)
3165            lgmixRef = wx.CheckBox(DData,-1,label='LGmix')
3166            lgmixRef.thisown = False
3167            lgmixRef.SetValue(UseList[item][name][2][2])
3168            Indx[lgmixRef.GetId()] = [item,name]
3169            lgmixRef.Bind(wx.EVT_CHECKBOX, OnRef)
3170            lgmixSizer.Add(lgmixRef,0,wx.ALIGN_CENTER_VERTICAL)
3171            lgmixVal = wx.TextCtrl(DData,wx.ID_ANY,
3172                '%.4f'%(UseList[item][name][1][2]),style=wx.TE_PROCESS_ENTER)
3173            Indx[lgmixVal.GetId()] = [item,name]
3174            lgmixVal.Bind(wx.EVT_TEXT_ENTER,OnVal)
3175            lgmixVal.Bind(wx.EVT_KILL_FOCUS,OnVal)
3176            lgmixSizer.Add(lgmixVal,0,wx.ALIGN_CENTER_VERTICAL)
3177            return lgmixSizer
3178                       
3179        def IsoSizer(name,parm,fmt,OnVal,OnRef):
3180            isoSizer = wx.BoxSizer(wx.HORIZONTAL)
3181            sizeRef = wx.CheckBox(DData,-1,label=name)
3182            sizeRef.thisown = False
3183            sizeRef.SetValue(UseList[item][parm][2][0])
3184            Indx[sizeRef.GetId()] = [item,0]
3185            sizeRef.Bind(wx.EVT_CHECKBOX, OnRef)
3186            isoSizer.Add(sizeRef,0,wx.ALIGN_CENTER_VERTICAL)
3187            sizeVal = wx.TextCtrl(DData,wx.ID_ANY,
3188                fmt%(UseList[item][parm][1][0]),style=wx.TE_PROCESS_ENTER)
3189            Indx[sizeVal.GetId()] = [item,0]
3190            sizeVal.Bind(wx.EVT_TEXT_ENTER,OnVal)
3191            sizeVal.Bind(wx.EVT_KILL_FOCUS,OnVal)
3192            isoSizer.Add(sizeVal,0,wx.ALIGN_CENTER_VERTICAL)
3193            return isoSizer
3194           
3195        def UniSizer(parm,OnAxis):
3196            uniSizer = wx.BoxSizer(wx.HORIZONTAL)
3197            uniSizer.Add(wx.StaticText(DData,-1,' Unique axis, H K L: '),0,wx.ALIGN_CENTER_VERTICAL)
3198            h,k,l = UseList[item][parm][3]
3199            Axis = wx.TextCtrl(DData,-1,'%3d %3d %3d'%(h,k,l),style=wx.TE_PROCESS_ENTER)
3200            Indx[Axis.GetId()] = item
3201            Axis.Bind(wx.EVT_TEXT_ENTER,OnAxis)
3202            Axis.Bind(wx.EVT_KILL_FOCUS,OnAxis)
3203            uniSizer.Add(Axis,0,wx.ALIGN_CENTER_VERTICAL)
3204            return uniSizer
3205           
3206        def UniDataSizer(parmName,parm,fmt,OnVal,OnRef):
3207            dataSizer = wx.BoxSizer(wx.HORIZONTAL)
3208            parms = zip([' Equatorial '+parmName,' Axial '+parmName],
3209                UseList[item][parm][1],UseList[item][parm][2],range(2))
3210            for Pa,val,ref,id in parms:
3211                sizeRef = wx.CheckBox(DData,-1,label=Pa)
3212                sizeRef.thisown = False
3213                sizeRef.SetValue(ref)
3214                Indx[sizeRef.GetId()] = [item,id]
3215                sizeRef.Bind(wx.EVT_CHECKBOX, OnRef)
3216                dataSizer.Add(sizeRef,0,wx.ALIGN_CENTER_VERTICAL)
3217                sizeVal = wx.TextCtrl(DData,wx.ID_ANY,fmt%(val),style=wx.TE_PROCESS_ENTER)
3218                Indx[sizeVal.GetId()] = [item,id]
3219                sizeVal.Bind(wx.EVT_TEXT_ENTER,OnVal)
3220                sizeVal.Bind(wx.EVT_KILL_FOCUS,OnVal)
3221                dataSizer.Add(sizeVal,0,wx.ALIGN_CENTER_VERTICAL)
3222                dataSizer.Add((5,0),0)
3223            return dataSizer
3224           
3225        def EllSizeDataSizer():
3226            parms = zip(['S11','S22','S33','S12','S13','S23'],UseList[item]['Size'][4],
3227                UseList[item]['Size'][5],range(6))
3228            dataSizer = wx.FlexGridSizer(1,6,5,5)
3229            for Pa,val,ref,id in parms:
3230                sizeRef = wx.CheckBox(DData,-1,label=Pa)
3231                sizeRef.thisown = False
3232                sizeRef.SetValue(ref)
3233                Indx[sizeRef.GetId()] = [item,id]
3234                sizeRef.Bind(wx.EVT_CHECKBOX, OnSizeRef)
3235                dataSizer.Add(sizeRef,0,wx.ALIGN_CENTER_VERTICAL)
3236                sizeVal = wx.TextCtrl(DData,wx.ID_ANY,'%.3f'%(val),style=wx.TE_PROCESS_ENTER)
3237                Indx[sizeVal.GetId()] = [item,id]
3238                sizeVal.Bind(wx.EVT_TEXT_ENTER,OnSizeVal)
3239                sizeVal.Bind(wx.EVT_KILL_FOCUS,OnSizeVal)
3240                dataSizer.Add(sizeVal,0,wx.ALIGN_CENTER_VERTICAL)
3241            return dataSizer
3242           
3243        def GenStrainDataSizer():
3244            Snames = G2spc.MustrainNames(SGData)
3245            numb = len(Snames)
3246            if len(UseList[item]['Mustrain'][4]) < numb:
3247                UseList[item]['Mustrain'][4] = numb*[0.0,]
3248                UseList[item]['Mustrain'][5] = numb*[False,]
3249            parms = zip(Snames,UseList[item]['Mustrain'][4],UseList[item]['Mustrain'][5],range(numb))
3250            dataSizer = wx.FlexGridSizer(1,6,5,5)
3251            for Pa,val,ref,id in parms:
3252                strainRef = wx.CheckBox(DData,-1,label=Pa)
3253                strainRef.thisown = False
3254                strainRef.SetValue(ref)
3255                Indx[strainRef.GetId()] = [item,id]
3256                strainRef.Bind(wx.EVT_CHECKBOX, OnStrainRef)
3257                dataSizer.Add(strainRef,0,wx.ALIGN_CENTER_VERTICAL)
3258                strainVal = wx.TextCtrl(DData,wx.ID_ANY,'%.5f'%(val),style=wx.TE_PROCESS_ENTER)
3259                Indx[strainVal.GetId()] = [item,id]
3260                strainVal.Bind(wx.EVT_TEXT_ENTER,OnStrainVal)
3261                strainVal.Bind(wx.EVT_KILL_FOCUS,OnStrainVal)
3262                dataSizer.Add(strainVal,0,wx.ALIGN_CENTER_VERTICAL)
3263            return dataSizer
3264           
3265        def HstrainSizer():
3266            hstrainSizer = wx.FlexGridSizer(1,6,5,5)
3267            Hsnames = G2spc.HStrainNames(SGData)
3268            parms = zip(Hsnames,UseList[item]['HStrain'][0],UseList[item]['HStrain'][1],range(len(Hsnames)))
3269            for Pa,val,ref,id in parms:
3270                hstrainRef = wx.CheckBox(DData,-1,label=Pa)
3271                hstrainRef.thisown = False
3272                hstrainRef.SetValue(ref)
3273                Indx[hstrainRef.GetId()] = [item,id]
3274                hstrainRef.Bind(wx.EVT_CHECKBOX, OnHstrainRef)
3275                hstrainSizer.Add(hstrainRef,0,wx.ALIGN_CENTER_VERTICAL)
3276                hstrainVal = wx.TextCtrl(DData,wx.ID_ANY,'%.5f'%(val),style=wx.TE_PROCESS_ENTER)
3277                Indx[hstrainVal.GetId()] = [item,id]
3278                hstrainVal.Bind(wx.EVT_TEXT_ENTER,OnHstrainVal)
3279                hstrainVal.Bind(wx.EVT_KILL_FOCUS,OnHstrainVal)
3280                hstrainSizer.Add(hstrainVal,0,wx.ALIGN_CENTER_VERTICAL)
3281            return hstrainSizer
3282           
3283        def PoTopSizer(POData):
3284            poSizer = wx.FlexGridSizer(1,6,5,5)
3285            choice = ['March-Dollase','Spherical harmonics']
3286            POtype = choice[['MD','SH'].index(POData[0])]
3287            poSizer.Add(wx.StaticText(DData,-1,' Preferred orientation model '),0,wx.ALIGN_CENTER_VERTICAL)
3288            POType = wx.ComboBox(DData,wx.ID_ANY,value=POtype,choices=choice,
3289                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3290            Indx[POType.GetId()] = item
3291            POType.Bind(wx.EVT_COMBOBOX, OnPOType)
3292            poSizer.Add(POType)
3293            if POData[0] == 'SH':
3294                poSizer.Add(wx.StaticText(DData,-1,' Harmonic order: '),0,wx.ALIGN_CENTER_VERTICAL)
3295                poOrder = wx.ComboBox(DData,wx.ID_ANY,value=str(POData[4]),choices=[str(2*i) for i in range(18)],
3296                    style=wx.CB_READONLY|wx.CB_DROPDOWN)
3297                Indx[poOrder.GetId()] = item
3298                poOrder.Bind(wx.EVT_COMBOBOX,OnPOOrder)
3299                poSizer.Add(poOrder,0,wx.ALIGN_CENTER_VERTICAL)
3300                poRef = wx.CheckBox(DData,-1,label=' Refine? ')
3301                poRef.SetValue(POData[2])
3302                Indx[poRef.GetId()] = item
3303                poRef.Bind(wx.EVT_CHECKBOX,OnPORef)
3304                poSizer.Add(poRef,0,wx.ALIGN_CENTER_VERTICAL)
3305            return poSizer
3306           
3307        def MDDataSizer(POData):
3308            poSizer = wx.BoxSizer(wx.HORIZONTAL)
3309            poRef = wx.CheckBox(DData,-1,label=' March-Dollase ratio: ')
3310            poRef.SetValue(POData[2])
3311            Indx[poRef.GetId()] = item
3312            poRef.Bind(wx.EVT_CHECKBOX,OnPORef)
3313            poSizer.Add(poRef,0,wx.ALIGN_CENTER_VERTICAL)
3314            poVal = wx.TextCtrl(DData,wx.ID_ANY,
3315                '%.3f'%(POData[1]),style=wx.TE_PROCESS_ENTER)
3316            Indx[poVal.GetId()] = item
3317            poVal.Bind(wx.EVT_TEXT_ENTER,OnPOVal)
3318            poVal.Bind(wx.EVT_KILL_FOCUS,OnPOVal)
3319            poSizer.Add(poVal,0,wx.ALIGN_CENTER_VERTICAL)
3320            poSizer.Add(wx.StaticText(DData,-1,' Unique axis, H K L: '),0,wx.ALIGN_CENTER_VERTICAL)
3321            h,k,l =POData[3]
3322            poAxis = wx.TextCtrl(DData,-1,'%3d %3d %3d'%(h,k,l),style=wx.TE_PROCESS_ENTER)
3323            Indx[poAxis.GetId()] = item
3324            poAxis.Bind(wx.EVT_TEXT_ENTER,OnPOAxis)
3325            poAxis.Bind(wx.EVT_KILL_FOCUS,OnPOAxis)
3326            poSizer.Add(poAxis,0,wx.ALIGN_CENTER_VERTICAL)
3327            return poSizer
3328           
3329        def SHDataSizer(POData):
3330            textJ = G2lat.textureIndex(POData[5])
3331            mainSizer.Add(wx.StaticText(DData,-1,' Spherical harmonic coefficients: '+'Texture index: %.3f'%(textJ)),0,wx.ALIGN_CENTER_VERTICAL)
3332            mainSizer.Add((0,5),0)
3333            ODFSizer = wx.FlexGridSizer(2,8,2,2)
3334            ODFIndx = {}
3335            ODFkeys = POData[5].keys()
3336            ODFkeys.sort()
3337            for odf in ODFkeys:
3338                ODFSizer.Add(wx.StaticText(DData,-1,odf),0,wx.ALIGN_CENTER_VERTICAL)
3339                ODFval = wx.TextCtrl(DData,wx.ID_ANY,'%8.3f'%(POData[5][odf]),style=wx.TE_PROCESS_ENTER)
3340                ODFIndx[ODFval.GetId()] = odf
3341#                ODFval.Bind(wx.EVT_TEXT_ENTER,OnODFValue)
3342#                ODFval.Bind(wx.EVT_KILL_FOCUS,OnODFValue)
3343                ODFSizer.Add(ODFval,0,wx.ALIGN_CENTER_VERTICAL)
3344            return ODFSizer
3345           
3346        def ExtSizer():           
3347            extSizer = wx.BoxSizer(wx.HORIZONTAL)
3348            extRef = wx.CheckBox(DData,-1,label=' Extinction: ')
3349            extRef.SetValue(UseList[item]['Extinction'][1])
3350            Indx[extRef.GetId()] = item
3351            extRef.Bind(wx.EVT_CHECKBOX, OnExtRef)
3352            extSizer.Add(extRef,0,wx.ALIGN_CENTER_VERTICAL)
3353            extVal = wx.TextCtrl(DData,wx.ID_ANY,
3354                '%.2f'%(UseList[item]['Extinction'][0]),style=wx.TE_PROCESS_ENTER)
3355            Indx[extVal.GetId()] = item
3356            extVal.Bind(wx.EVT_TEXT_ENTER,OnExtVal)
3357            extVal.Bind(wx.EVT_KILL_FOCUS,OnExtVal)
3358            extSizer.Add(extVal,0,wx.ALIGN_CENTER_VERTICAL)
3359            return extSizer
3360       
3361        def SCExtSizer():
3362            extSizer = wx.BoxSizer(wx.VERTICAL)
3363            typeSizer = wx.BoxSizer(wx.HORIZONTAL)           
3364            typeSizer.Add(wx.StaticText(DData,-1,' Extinction type: '),0,wx.ALIGN_CENTER_VERTICAL)
3365            Choices = ['Primary','Secondary Type I','Secondary Type II','Secondary Type I & II']
3366            typeTxt = wx.ComboBox(DData,-1,choices=Choices,value=UseList[item]['Extinction'][1],
3367                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3368            Indx[typeTxt.GetId()] = [item,1]
3369            typeTxt.Bind(wx.EVT_COMBOBOX,OnSCExtType)
3370            typeSizer.Add(typeTxt)
3371            typeSizer.Add(wx.StaticText(DData,-1,' Approx: '),0,wx.ALIGN_CENTER_VERTICAL)
3372            Choices=['Lorentzian','Gaussian']
3373            approxTxT = wx.ComboBox(DData,-1,choices=Choices,value=UseList[item]['Extinction'][0],
3374                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3375            Indx[approxTxT.GetId()] = [item,0]
3376            approxTxT.Bind(wx.EVT_COMBOBOX,OnSCExtType)
3377            typeSizer.Add(approxTxT)
3378            extSizer.Add(typeSizer,0,wx.ALIGN_CENTER_VERTICAL)
3379            extSizer.Add((0,5),)
3380            valSizer =wx.BoxSizer(wx.HORIZONTAL)
3381            valSizer.Add(wx.StaticText(DData,-1,' Tbar(mm):'),0,wx.ALIGN_CENTER_VERTICAL)
3382            tbarVal = wx.TextCtrl(DData,wx.ID_ANY,
3383                '%.3f'%(UseList[item]['Extinction'][2]['Tbar']),style=wx.TE_PROCESS_ENTER)
3384            Indx[tbarVal.GetId()] = item
3385            tbarVal.Bind(wx.EVT_TEXT_ENTER,OnTbarVal)
3386            tbarVal.Bind(wx.EVT_KILL_FOCUS,OnTbarVal)
3387            valSizer.Add(tbarVal,0,wx.ALIGN_CENTER_VERTICAL)
3388            if 'Primary' in UseList[item]['Extinction'][1]:
3389                Ekey = ['Ep',]
3390            elif 'Secondary Type II' == UseList[item]['Extinction'][1]:
3391                Ekey = ['Es',]
3392            elif 'Secondary Type I' == UseList[item]['Extinction'][1]:
3393                Ekey = ['Eg',]
3394            else:
3395                Ekey = ['Eg','Es']
3396            for ekey in Ekey:
3397                Eref = wx.CheckBox(DData,-1,label=ekey+' : ')
3398                Eref.SetValue(UseList[item]['Extinction'][2][ekey][1])
3399                Indx[Eref.GetId()] = [item,ekey]
3400                Eref.Bind(wx.EVT_CHECKBOX, OnEref)
3401                valSizer.Add(Eref,0,wx.ALIGN_CENTER_VERTICAL)
3402                Eval = wx.TextCtrl(DData,wx.ID_ANY,
3403                    '%9.3g'%(UseList[item]['Extinction'][2][ekey][0]),style=wx.TE_PROCESS_ENTER)
3404                Indx[Eval.GetId()] = [item,ekey]
3405                Eval.Bind(wx.EVT_TEXT_ENTER,OnEval)
3406                Eval.Bind(wx.EVT_KILL_FOCUS,OnEval)
3407                valSizer.Add(Eval,0,wx.ALIGN_CENTER_VERTICAL)
3408
3409            extSizer.Add(valSizer,0,wx.ALIGN_CENTER_VERTICAL)
3410            return extSizer
3411           
3412        if DData.GetSizer():
3413            DData.GetSizer().Clear(True)
3414        mainSizer = wx.BoxSizer(wx.VERTICAL)
3415        mainSizer.Add(wx.StaticText(DData,-1,'Histogram data for '+PhaseName+':'),0,wx.ALIGN_CENTER_VERTICAL)
3416        if PWDR:
3417            mainSizer.Add(PlotSizer())           
3418           
3419        for item in keyList:
3420            histData = UseList[item]
3421            showSizer = wx.BoxSizer(wx.HORIZONTAL)
3422            showData = wx.CheckBox(DData,-1,label=' Show '+item)
3423            showData.SetValue(UseList[item]['Show'])
3424            Indx[showData.GetId()] = item
3425            showData.Bind(wx.EVT_CHECKBOX, OnShowData)
3426            showSizer.Add(showData,0,wx.ALIGN_CENTER_VERTICAL)
3427            copyData = wx.Button(DData,-1,label=' Copy?')
3428            Indx[copyData.GetId()] = item
3429            copyData.Bind(wx.EVT_BUTTON,OnCopyData)
3430            showSizer.Add(copyData,wx.ALIGN_CENTER_VERTICAL)
3431            copyFlags = wx.Button(DData,-1,label=' Copy flags?')
3432            Indx[copyFlags.GetId()] = item
3433            copyFlags.Bind(wx.EVT_BUTTON,OnCopyFlags)
3434            showSizer.Add(copyFlags,wx.ALIGN_CENTER_VERTICAL)
3435            mainSizer.Add((5,5),0)
3436            mainSizer.Add(showSizer,0,wx.ALIGN_CENTER_VERTICAL)
3437            mainSizer.Add((0,5),0)
3438           
3439            if UseList[item]['Show']:
3440                mainSizer.Add(ScaleSizer())
3441                mainSizer.Add((0,5),0)
3442               
3443            if item[:4] == 'PWDR' and UseList[item]['Show']:
3444                if UseList[item]['Size'][0] == 'isotropic':
3445                    isoSizer = wx.BoxSizer(wx.HORIZONTAL)
3446                    isoSizer.Add(TopSizer(' Size model: ',['isotropic','uniaxial','ellipsoidal'],
3447                        'Size',OnSizeType),0,wx.ALIGN_CENTER_VERTICAL)
3448                    isoSizer.Add(LGmixSizer('Size',OnLGmixVal,OnLGmixRef))
3449                    mainSizer.Add(isoSizer)
3450                    mainSizer.Add(IsoSizer(u' Cryst. size(\xb5m): ','Size','%.3f',
3451                        OnSizeVal,OnSizeRef),0,wx.ALIGN_CENTER_VERTICAL)
3452                elif UseList[item]['Size'][0] == 'uniaxial':
3453                    uniSizer = wx.BoxSizer(wx.HORIZONTAL)
3454                    uniSizer.Add(TopSizer(' Size model: ',['isotropic','uniaxial','ellipsoidal'],
3455                        'Size',OnSizeType),0,wx.ALIGN_CENTER_VERTICAL)
3456                    uniSizer.Add(LGmixSizer('Size',OnLGmixVal,OnLGmixRef))
3457                    uniSizer.Add(UniSizer('Size',OnSizeAxis),0,wx.ALIGN_CENTER_VERTICAL)
3458                    mainSizer.Add(uniSizer)
3459                    mainSizer.Add(UniDataSizer(u'size(\xb5m): ','Size','%.3f',OnSizeVal,OnSizeRef))
3460                elif UseList[item]['Size'][0] == 'ellipsoidal':
3461                    ellSizer = wx.BoxSizer(wx.HORIZONTAL)
3462                    ellSizer.Add(TopSizer(' Size model: ',['isotropic','uniaxial','ellipsoidal'],
3463                        'Size',OnSizeType),0,wx.ALIGN_CENTER_VERTICAL)
3464                    ellSizer.Add(LGmixSizer('Size',OnLGmixVal,OnLGmixRef))
3465                    mainSizer.Add(ellSizer)
3466                    mainSizer.Add(EllSizeDataSizer())
3467                mainSizer.Add((0,5),0)                   
3468               
3469                if UseList[item]['Mustrain'][0] == 'isotropic':
3470                    isoSizer = wx.BoxSizer(wx.HORIZONTAL)
3471                    isoSizer.Add(TopSizer(' Mustrain model: ',['isotropic','uniaxial','generalized',],
3472                        'Mustrain',OnStrainType),0,wx.ALIGN_CENTER_VERTICAL)
3473                    isoSizer.Add(LGmixSizer('Mustrain',OnLGmixVal,OnLGmixRef))
3474                    mainSizer.Add(isoSizer)
3475                    mainSizer.Add(IsoSizer(' microstrain: ','Mustrain','%.1f',
3476                        OnStrainVal,OnStrainRef),0,wx.ALIGN_CENTER_VERTICAL)                   
3477                    mainSizer.Add((0,5),0)
3478                elif UseList[item]['Mustrain'][0] == 'uniaxial':
3479                    uniSizer = wx.BoxSizer(wx.HORIZONTAL)
3480                    uniSizer.Add(TopSizer(' Mustrain model: ',['isotropic','uniaxial','generalized',],
3481                        'Mustrain',OnStrainType),0,wx.ALIGN_CENTER_VERTICAL)
3482                    uniSizer.Add(LGmixSizer('Mustrain',OnLGmixVal,OnLGmixRef))
3483                    uniSizer.Add(UniSizer('Mustrain',OnStrainAxis),0,wx.ALIGN_CENTER_VERTICAL)
3484                    mainSizer.Add(uniSizer)
3485                    mainSizer.Add(UniDataSizer('mustrain: ','Mustrain','%.1f',OnStrainVal,OnStrainRef))
3486                elif UseList[item]['Mustrain'][0] == 'generalized':
3487                    genSizer = wx.BoxSizer(wx.HORIZONTAL)
3488                    genSizer.Add(TopSizer(' Mustrain model: ',['isotropic','uniaxial','generalized',],
3489                        'Mustrain',OnStrainType),0,wx.ALIGN_CENTER_VERTICAL)
3490                    genSizer.Add(LGmixSizer('Mustrain',OnLGmixVal,OnLGmixRef))
3491                    mainSizer.Add(genSizer)
3492                    mainSizer.Add(GenStrainDataSizer())                       
3493                mainSizer.Add((0,5),0)
3494               
3495                mainSizer.Add(wx.StaticText(DData,-1,' Hydrostatic/elastic strain:'))
3496                mainSizer.Add(HstrainSizer())
3497                   
3498                #texture  'Pref. Ori.':['MD',1.0,False,[0,0,1],0,[]] last two for 'SH' are SHorder & coeff
3499                poSizer = wx.BoxSizer(wx.VERTICAL)
3500                POData = UseList[item]['Pref.Ori.']
3501                poSizer.Add(PoTopSizer(POData))
3502                if POData[0] == 'MD':
3503                    poSizer.Add(MDDataSizer(POData))
3504                else:           #'SH'
3505                    if POData[4]:       #SH order > 0
3506                        poSizer.Add(SHDataSizer(POData))
3507                       
3508                mainSizer.Add(poSizer)
3509                mainSizer.Add((0,5),0)               
3510                #Extinction  'Extinction':[0.0,False]
3511                mainSizer.Add(ExtSizer())
3512                mainSizer.Add((0,5),0)
3513            elif item[:4] == 'HKLF' and UseList[item]['Show']:
3514                mainSizer.Add((0,5),0)               
3515                mainSizer.Add(SCExtSizer())
3516                mainSizer.Add((0,5),0)
3517                pass
3518        mainSizer.Add((5,5),0)
3519
3520        DData.SetSizer(mainSizer,True)
3521        mainSizer.FitInside(G2frame.dataFrame)
3522        Size = mainSizer.GetMinSize()
3523        Size[0] += 40
3524        Size[1] = max(Size[1],290) + 20
3525        DData.SetSize(Size)
3526        DData.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
3527        Size[1] = min(Size[1],450)
3528        G2frame.dataFrame.setSizePosLeft(Size)
3529       
3530    def OnHklfAdd(event):
3531        UseList = data['Histograms']
3532        keyList = UseList.keys()
3533        TextList = []
3534        if G2frame.PatternTree.GetCount():
3535            item, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
3536            while item:
3537                name = G2frame.PatternTree.GetItemText(item)
3538                if name not in keyList and 'HKLF' in name:
3539                    TextList.append(name)
3540                item, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)                       
3541            dlg = wx.MultiChoiceDialog(G2frame, 'Which new data to use?', 'Use data', TextList, wx.CHOICEDLG_STYLE)
3542            try:
3543                if dlg.ShowModal() == wx.ID_OK:
3544                    result = dlg.GetSelections()
3545                    for i in result:
3546                        histoName = TextList[i]
3547                        UseList[histoName] = {'Histogram':histoName,'Show':False,'Scale':[1.0,True],
3548                            'Extinction':['Lorentzian','Secondary Type I',
3549                            {'Tbar':0.0,'Eg':[0.0,False],'Es':[0.0,False],'Ep':[0.0,False]},]}                       
3550                    data['Histograms'] = UseList
3551                    wx.BeginBusyCursor()
3552                    UpdateHKLFdata(histoName)
3553                    wx.EndBusyCursor()
3554                    wx.CallAfter(UpdateDData)
3555            finally:
3556                dlg.Destroy()
3557               
3558    def UpdateHKLFdata(histoName):
3559        generalData = data['General']
3560        Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,histoName)
3561        reflData = G2frame.PatternTree.GetItemPyData(Id)[1]
3562        SGData = generalData['SGData']
3563        Cell = generalData['Cell'][1:7]
3564        G,g = G2lat.cell2Gmat(Cell)
3565        for ref in reflData:
3566            H = ref[:3]
3567            ref[4] = np.sqrt(1./G2lat.calc_rDsq2(H,G))
3568            iabsnt,ref[3],ref[11],ref[12] = G2spc.GenHKLf(H,SGData)
3569        G2frame.PatternTree.SetItemPyData(Id,[histoName,reflData])
3570       
3571    def OnPwdrAdd(event):
3572        generalData = data['General']
3573        SGData = generalData['SGData']
3574        UseList = data['Histograms']
3575        newList = []
3576        NShkl = len(G2spc.MustrainNames(SGData))
3577        NDij = len(G2spc.HStrainNames(SGData))
3578        keyList = UseList.keys()
3579        TextList = ['All PWDR']
3580        if G2frame.PatternTree.GetCount():
3581            item, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
3582            while item:
3583                name = G2frame.PatternTree.GetItemText(item)
3584                if name not in keyList and 'PWDR' in name:
3585                    TextList.append(name)
3586                item, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
3587            dlg = wx.MultiChoiceDialog(G2frame, 'Which new data to use?', 'Use data', TextList, wx.CHOICEDLG_STYLE)
3588            try:
3589                if dlg.ShowModal() == wx.ID_OK:
3590                    result = dlg.GetSelections()
3591                    for i in result: newList.append(TextList[i])
3592                    if 'All PWDR' in newList:
3593                        newList = TextList[1:]
3594                    for histoName in newList:
3595                        pId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,histoName)
3596                        UseList[histoName] = {'Histogram':histoName,'Show':False,
3597                            'Scale':[1.0,False],'Pref.Ori.':['MD',1.0,False,[0,0,1],0,{}],
3598                            'Size':['isotropic',[4.,4.,1.0],[False,False,False],[0,0,1],
3599                                [4.,4.,4.,0.,0.,0.],6*[False,]],
3600                            'Mustrain':['isotropic',[1000.0,1000.0,1.0],[False,False,False],[0,0,1],
3601                                NShkl*[0.01,],NShkl*[False,]],
3602                            'HStrain':[NDij*[0.0,],NDij*[False,]],                         
3603                            'Extinction':[0.0,False]}
3604                        refList = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,pId,'Reflection Lists'))
3605                        refList[generalData['Name']] = []                       
3606                    data['Histograms'] = UseList
3607                    wx.CallAfter(UpdateDData)
3608            finally:
3609                dlg.Destroy()
3610       
3611    def OnDataDelete(event):
3612        UseList = data['Histograms']
3613        keyList = ['All',]+UseList.keys()
3614        keyList.sort()
3615        DelList = []
3616        if UseList:
3617            DelList = []
3618            dlg = wx.MultiChoiceDialog(G2frame, 
3619                'Which histogram to delete from this phase?', 'Delete histogram', 
3620                keyList, wx.CHOICEDLG_STYLE)
3621            try:
3622                if dlg.ShowModal() == wx.ID_OK:
3623                    result = dlg.GetSelections()
3624                    for i in result: 
3625                        DelList.append(keyList[i])
3626                    if 'All' in DelList:
3627                        DelList = keyList[1:]
3628                    for i in DelList:
3629                        del UseList[i]
3630                    wx.CallAfter(UpdateDData)
3631            finally:
3632                dlg.Destroy()
3633
3634################################################################################
3635##### Pawley routines
3636################################################################################
3637
3638    def FillPawleyReflectionsGrid():
3639                       
3640        def KeyEditPawleyGrid(event):
3641            colList = G2frame.PawleyRefl.GetSelectedCols()
3642            PawleyPeaks = data['Pawley ref']
3643            if event.GetKeyCode() == wx.WXK_RETURN:
3644                event.Skip(True)
3645            elif event.GetKeyCode() == wx.WXK_CONTROL:
3646                event.Skip(True)
3647            elif event.GetKeyCode() == wx.WXK_SHIFT:
3648                event.Skip(True)
3649            elif colList:
3650                G2frame.PawleyRefl.ClearSelection()
3651                key = event.GetKeyCode()
3652                for col in colList:
3653                    if PawleyTable.GetTypeName(0,col) == wg.GRID_VALUE_BOOL:
3654                        if key == 89: #'Y'
3655                            for row in range(PawleyTable.GetNumberRows()): PawleyPeaks[row][col]=True
3656                        elif key == 78:  #'N'
3657                            for row in range(PawleyTable.GetNumberRows()): PawleyPeaks[row][col]=False
3658                        FillPawleyReflectionsGrid()
3659           
3660        if 'Pawley ref' in data:
3661            PawleyPeaks = data['Pawley ref']                       
3662            rowLabels = []
3663            for i in range(len(PawleyPeaks)): rowLabels.append(str(i))
3664            colLabels = ['h','k','l','mul','d','refine','Fsq(hkl)','sig(Fsq)']
3665            Types = 4*[wg.GRID_VALUE_LONG,]+[wg.GRID_VALUE_FLOAT+':10,4',wg.GRID_VALUE_BOOL,]+ \
3666                2*[wg.GRID_VALUE_FLOAT+':10,2',]
3667            PawleyTable = G2gd.Table(PawleyPeaks,rowLabels=rowLabels,colLabels=colLabels,types=Types)
3668            G2frame.PawleyRefl.SetTable(PawleyTable, True)
3669            G2frame.PawleyRefl.Bind(wx.EVT_KEY_DOWN, KeyEditPawleyGrid)                 
3670            for r in range(G2frame.PawleyRefl.GetNumberRows()):
3671                for c in range(G2frame.PawleyRefl.GetNumberCols()):
3672                    if c in [5,6]:
3673                        G2frame.PawleyRefl.SetReadOnly(r,c,isReadOnly=False)
3674                    else:
3675                        G2frame.PawleyRefl.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
3676            G2frame.PawleyRefl.SetMargins(0,0)
3677            G2frame.PawleyRefl.AutoSizeColumns(False)
3678            G2frame.dataFrame.setSizePosLeft([500,300])
3679                   
3680    def OnPawleyLoad(event):
3681        generalData = data['General']
3682        dmin = generalData['Pawley dmin']
3683        cell = generalData['Cell'][1:7]
3684        A = G2lat.cell2A(cell)
3685        SGData = generalData['SGData']
3686        HKLd = np.array(G2lat.GenHLaue(dmin,SGData,A))
3687        PawleyPeaks = []
3688        wx.BeginBusyCursor()
3689        try:
3690            for h,k,l,d in HKLd:
3691                ext,mul = G2spc.GenHKLf([h,k,l],SGData)[:2]
3692                if not ext:
3693                    mul *= 2        #for powder multiplicity
3694                    PawleyPeaks.append([h,k,l,mul,d,False,100.0,1.0])
3695        finally:
3696            wx.EndBusyCursor()
3697        data['Pawley ref'] = PawleyPeaks
3698        FillPawleyReflectionsGrid()
3699       
3700    def OnPawleyEstimate(event):
3701        try:
3702            Refs = data['Pawley ref']
3703            Histograms = data['Histograms']
3704        except KeyError:
3705            print '**** Error - no histograms defined for this phase ****'
3706            return
3707        HistoNames = Histograms.keys()
3708        PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,HistoNames[0])
3709        xdata = G2frame.PatternTree.GetItemPyData(PatternId)[1]
3710        Inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Instrument Parameters'))
3711        Inst = dict(zip(Inst[3],Inst[1]))
3712        Sample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Sample Parameters'))
3713        if 'Lam' in Inst:
3714            wave = Inst['Lam']
3715        else:
3716            wave = Inst['Lam1']
3717        posCorr = Inst['Zero']
3718        const = 9.e-2/(np.pi*Sample['Gonio. radius'])                  #shifts in microns
3719       
3720        for ref in Refs:
3721            pos = 2.0*asind(wave/(2.0*ref[4]))
3722            if 'Bragg' in Sample['Type']:
3723                pos -= const*(4.*Sample['Shift'][0]*cosd(pos/2.0)+ \
3724                    Sample['Transparency'][0]*sind(pos)*100.0)            #trans(=1/mueff) in cm
3725            else:               #Debye-Scherrer - simple but maybe not right
3726                pos -= const*(Sample['DisplaceX'][0]*cosd(pos)+Sample['DisplaceY'][0]*sind(pos))
3727            indx = np.searchsorted(xdata[0],pos)
3728            try:
3729                FWHM = max(0.001,G2pwd.getFWHM(pos,Inst))/2.
3730                dx = xdata[0][indx+1]-xdata[0][indx]
3731                ref[6] = FWHM*xdata[1][indx]/dx
3732                Lorenz = 1./(2.*sind(xdata[0][indx]/2.)**2*cosd(xdata[0][indx]/2.))           #Lorentz correction
3733                pola,dIdPola = G2pwd.Polarization(Inst['Polariz.'],xdata[0][indx],Inst['Azimuth'])
3734                ref[6] /= (Lorenz*pola*ref[3])
3735            except IndexError:
3736                pass
3737        FillPawleyReflectionsGrid()
3738                           
3739    def OnPawleyDelete(event):
3740        dlg = wx.MessageDialog(G2frame,'Do you really want to delete Pawley reflections?','Delete', 
3741            wx.YES_NO | wx.ICON_QUESTION)
3742        try:
3743            result = dlg.ShowModal()
3744        finally:
3745            dlg.Destroy()
3746        if result == wx.ID_YES: 
3747            data['Pawley ref'] = []
3748            FillPawleyReflectionsGrid()
3749
3750################################################################################
3751##### Fourier routines
3752################################################################################
3753
3754    def FillMapPeaksGrid():
3755                       
3756        def RowSelect(event):
3757            r,c =  event.GetRow(),event.GetCol()
3758            if r < 0 and c < 0:
3759                if MapPeaks.IsSelection():
3760                    MapPeaks.ClearSelection()
3761                else:
3762                    for row in range(MapPeaks.GetNumberRows()):
3763                        MapPeaks.SelectRow(row,True)
3764                   
3765            elif c < 0:                   #only row clicks
3766                if event.ControlDown():                   
3767                    if r in MapPeaks.GetSelectedRows():
3768                        MapPeaks.DeselectRow(r)
3769                    else:
3770                        MapPeaks.SelectRow(r,True)
3771                elif event.ShiftDown():
3772                    for row in range(r+1):
3773                        MapPeaks.SelectRow(row,True)
3774                else:
3775                    MapPeaks.ClearSelection()
3776                    MapPeaks.SelectRow(r,True)               
3777            G2plt.PlotStructure(G2frame,data)                   
3778           
3779        G2frame.dataFrame.setSizePosLeft([450,300])
3780        if 'Map Peaks' in data:
3781            mapPeaks = data['Map Peaks']                       
3782            rowLabels = []
3783            for i in range(len(mapPeaks)): rowLabels.append(str(i))
3784            colLabels = ['mag','x','y','z']
3785            Types = 4*[wg.GRID_VALUE_FLOAT+':10,4',]
3786            MapPeaksTable = G2gd.Table(mapPeaks,rowLabels=rowLabels,colLabels=colLabels,types=Types)
3787            MapPeaks.SetTable(MapPeaksTable, True)
3788            MapPeaks.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK, RowSelect)
3789            for r in range(MapPeaks.GetNumberRows()):
3790                for c in range(MapPeaks.GetNumberCols()):
3791                    MapPeaks.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
3792            MapPeaks.SetMargins(0,0)
3793            MapPeaks.AutoSizeColumns(False)
3794                   
3795    def OnPeaksMove(event):
3796        if 'Map Peaks' in data:
3797            mapPeaks = data['Map Peaks']                       
3798            Ind = MapPeaks.GetSelectedRows()
3799            for ind in Ind:
3800                x,y,z = mapPeaks[ind][1:]
3801                AtomAdd(x,y,z,'C')
3802   
3803    def OnPeaksClear(event):
3804        data['Map Peaks'] = []
3805        FillMapPeaksGrid()
3806        G2plt.PlotStructure(G2frame,data)
3807       
3808    def OnPeaksDelete(event):
3809        if 'Map Peaks' in data:
3810            mapPeaks = data['Map Peaks']
3811            Ind = MapPeaks.GetSelectedRows()
3812            Ind.sort()
3813            Ind.reverse()
3814            for ind in Ind:
3815                mapPeaks = np.delete(mapPeaks,ind,0)
3816            data['Map Peaks'] = mapPeaks
3817        FillMapPeaksGrid()
3818        G2plt.PlotStructure(G2frame,data)
3819               
3820    def OnPeaksUnique(event):
3821        if 'Map Peaks' in data:
3822            mapPeaks = data['Map Peaks']
3823            Ind = MapPeaks.GetSelectedRows()
3824            if Ind:
3825                G2mth.PeaksUnique(data,Ind)
3826                FillMapPeaksGrid()
3827                G2plt.PlotStructure(G2frame,data)
3828   
3829    def OnFourierMaps(event):
3830        generalData = data['General']
3831        mapData = generalData['Map']
3832        reflName = mapData['RefList']
3833        phaseName = generalData['Name']
3834        if 'PWDR' in reflName:
3835            PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, reflName)
3836            reflSets = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Reflection Lists'))
3837            reflData = reflSets[phaseName]
3838        elif 'HKLF' in reflName:
3839            PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, reflName)
3840            reflData = G2frame.PatternTree.GetItemPyData(PatternId)[1]
3841        mapData.update(G2mth.FourierMap(data,reflData))
3842        mapData['Flip'] = False
3843        mapSig = np.std(mapData['rho'])
3844        if not data['Drawing']:                 #if new drawing - no drawing data!
3845            SetupDrawingData()
3846        data['Drawing']['contourLevel'] = 1.
3847        data['Drawing']['mapSize'] = 10.
3848        print mapData['MapType']+' computed: rhomax = %.3f rhomin = %.3f sigma = %.3f'%(np.max(mapData['rho']),np.min(mapData['rho']),mapSig)
3849        UpdateDrawAtoms()
3850        G2plt.PlotStructure(G2frame,data)
3851       
3852    def printRho(SGLaue,rho,rhoMax):                         
3853# map printing for testing purposes
3854        dim = len(rho.shape)
3855        if dim == 2:
3856            ix,jy = rho.shape
3857            for j in range(jy):
3858                line = ''
3859                if SGLaue in ['3','3m1','31m','6/m','6/mmm']:
3860                    line += (jy-j)*'  '
3861                for i in range(ix):
3862                    r = int(100*rho[i,j]/rhoMax)
3863                    line += '%4d'%(r)
3864                print line+'\n'
3865        else:
3866            ix,jy,kz = rho.shape
3867            for k in range(kz):
3868                print 'k = ',k
3869                for j in range(jy):
3870                    line = ''
3871                    if SGLaue in ['3','3m1','31m','6/m','6/mmm']:
3872                        line += (jy-j)*'  '
3873                    for i in range(ix):
3874                        r = int(100*rho[i,j,k]/rhoMax)
3875                        line += '%4d'%(r)
3876                    print line+'\n'
3877## keep this               
3878   
3879    def OnSearchMaps(event):
3880       
3881        peaks = []
3882        mags = []
3883        print ' Begin fourier map search - can take some time'
3884        time0 = time.time()
3885
3886        pgbar = wx.ProgressDialog('Map search','No. Peaks found =',301.0, 
3887            style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_CAN_ABORT)
3888        screenSize = wx.ClientDisplayRect()
3889        Size = pgbar.GetSize()
3890        Size = (int(Size[0]*1.2),Size[1]) # increase size a bit along x
3891        pgbar.SetPosition(wx.Point(screenSize[2]-Size[0]-305,screenSize[1]+5))
3892        pgbar.SetSize(Size)
3893        try:
3894            peaks,mags = G2mth.SearchMap(data,keepDup=True,Pgbar=pgbar)
3895        finally:
3896            pgbar.Destroy()
3897        sortIdx = np.argsort(mags.flatten())
3898        if len(peaks):
3899            data['Map Peaks'] = np.concatenate((mags,peaks),axis=1)           
3900            print ' Map search finished, time = %.2fs'%(time.time()-time0)
3901        Page = G2frame.dataDisplay.FindPage('Map peaks')
3902        G2frame.dataDisplay.ChangeSelection(Page)
3903        G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.MapPeaksMenu)
3904        G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksMove, id=G2gd.wxID_PEAKSMOVE)
3905        G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksUnique, id=G2gd.wxID_PEAKSUNIQUE)
3906        G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksDelete, id=G2gd.wxID_PEAKSDELETE)
3907        G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksClear, id=G2gd.wxID_PEAKSCLEAR)
3908        UpdateDrawAtoms()
3909        FillMapPeaksGrid()
3910        G2plt.PlotStructure(G2frame,data)
3911       
3912    def OnChargeFlip(event):
3913        generalData = data['General']
3914        mapData = generalData['Map']
3915        flipData = generalData['Flip']
3916        reflName = flipData['RefList']
3917        phaseName = generalData['Name']
3918        if 'PWDR' in reflName:
3919            PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, reflName)
3920            reflSets = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Reflection Lists'))
3921            reflData = reflSets[phaseName]
3922        elif 'HKLF' in reflName:
3923            PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, reflName)
3924            reflData = G2frame.PatternTree.GetItemPyData(PatternId)[1]
3925        else:
3926            print '**** ERROR - No data defined for charge flipping'
3927            return
3928        pgbar = wx.ProgressDialog('Charge flipping','Residual Rcf =',101.0, 
3929            style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_CAN_ABORT)
3930        screenSize = wx.ClientDisplayRect()
3931        Size = pgbar.GetSize()
3932        Size = (int(Size[0]*1.2),Size[1]) # increase size a bit along x
3933        pgbar.SetPosition(wx.Point(screenSize[2]-Size[0]-305,screenSize[1]+5))
3934        pgbar.SetSize(Size)
3935        try:
3936            mapData.update(G2mth.ChargeFlip(data,reflData,pgbar))
3937        finally:
3938            pgbar.Destroy()
3939        mapData['Flip'] = True       
3940        mapSig = np.std(mapData['rho'])
3941        if not data['Drawing']:                 #if new drawing - no drawing data!
3942            SetupDrawingData()
3943        data['Drawing']['contourLevel'] = 1.
3944        data['Drawing']['mapSize'] = 10.
3945        print ' Charge flip map computed: rhomax = %.3f rhomin = %.3f sigma = %.3f'%(np.max(mapData['rho']),np.min(mapData['rho']),mapSig)
3946        if mapData['Rcf'] < 99.:
3947            OnSearchMaps(event)             #does a plot structure at end
3948        else:
3949            print 'Bad charge flip map - no peak search done'
3950               
3951    def OnTextureRefine(event):
3952        print 'refine texture?'
3953        event.Skip()       
3954           
3955    def OnTextureClear(event):
3956        print 'clear texture?'
3957        event.Skip()
3958
3959    def OnPageChanged(event):
3960        page = event.GetSelection()
3961        text = G2frame.dataDisplay.GetPageText(page)
3962        if text == 'Atoms':
3963            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.AtomsMenu)
3964            G2frame.dataFrame.Bind(wx.EVT_MENU, OnAtomAdd, id=G2gd.wxID_ATOMSEDITADD)
3965            G2frame.dataFrame.Bind(wx.EVT_MENU, OnAtomTestAdd, id=G2gd.wxID_ATOMSTESTADD)
3966            G2frame.dataFrame.Bind(wx.EVT_MENU, OnAtomInsert, id=G2gd.wxID_ATOMSEDITINSERT)
3967            G2frame.dataFrame.Bind(wx.EVT_MENU, OnAtomTestInsert, id=G2gd.wxID_ATONTESTINSERT)
3968            G2frame.dataFrame.Bind(wx.EVT_MENU, AtomDelete, id=G2gd.wxID_ATOMSEDITDELETE)
3969            G2frame.dataFrame.Bind(wx.EVT_MENU, AtomRefine, id=G2gd.wxID_ATOMSREFINE)
3970            G2frame.dataFrame.Bind(wx.EVT_MENU, AtomModify, id=G2gd.wxID_ATOMSMODIFY)
3971            G2frame.dataFrame.Bind(wx.EVT_MENU, AtomTransform, id=G2gd.wxID_ATOMSTRANSFORM)
3972            G2frame.dataFrame.Bind(wx.EVT_MENU, OnReloadDrawAtoms, id=G2gd.wxID_RELOADDRAWATOMS)
3973            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDistAngle, id=G2gd.wxID_ATOMSDISAGL)
3974            FillAtomsGrid()
3975        elif text == 'General':
3976            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.DataGeneral)
3977            G2frame.dataFrame.Bind(wx.EVT_MENU, OnFourierMaps, id=G2gd.wxID_FOURCALC)
3978            G2frame.dataFrame.Bind(wx.EVT_MENU, OnSearchMaps, id=G2gd.wxID_FOURSEARCH)
3979            G2frame.dataFrame.Bind(wx.EVT_MENU, OnChargeFlip, id=G2gd.wxID_CHARGEFLIP)
3980            UpdateGeneral()
3981        elif text == 'Data':
3982            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.DataMenu)
3983            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPwdrAdd, id=G2gd.wxID_PWDRADD)
3984            G2frame.dataFrame.Bind(wx.EVT_MENU, OnHklfAdd, id=G2gd.wxID_HKLFADD)
3985            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDataDelete, id=G2gd.wxID_DATADELETE)
3986            UpdateDData()
3987            G2plt.PlotSizeStrainPO(G2frame,data,Start=True)
3988        elif text == 'Draw Options':
3989            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.DataDrawOptions)
3990            UpdateDrawOptions()
3991            G2plt.PlotStructure(G2frame,data)
3992        elif text == 'Draw Atoms':
3993            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.DrawAtomsMenu)
3994            G2frame.dataFrame.Bind(wx.EVT_MENU, DrawAtomStyle, id=G2gd.wxID_DRAWATOMSTYLE)
3995            G2frame.dataFrame.Bind(wx.EVT_MENU, DrawAtomLabel, id=G2gd.wxID_DRAWATOMLABEL)
3996            G2frame.dataFrame.Bind(wx.EVT_MENU, DrawAtomColor, id=G2gd.wxID_DRAWATOMCOLOR)
3997            G2frame.dataFrame.Bind(wx.EVT_MENU, ResetAtomColors, id=G2gd.wxID_DRAWATOMRESETCOLOR)
3998            G2frame.dataFrame.Bind(wx.EVT_MENU, SetViewPoint, id=G2gd.wxID_DRAWVIEWPOINT)
3999            G2frame.dataFrame.Bind(wx.EVT_MENU, AddSymEquiv, id=G2gd.wxID_DRAWADDEQUIV)
4000            G2frame.dataFrame.Bind(wx.EVT_MENU, TransformSymEquiv, id=G2gd.wxID_DRAWTRANSFORM)
4001            G2frame.dataFrame.Bind(wx.EVT_MENU, FillCoordSphere, id=G2gd.wxID_DRAWFILLCOORD)           
4002            G2frame.dataFrame.Bind(wx.EVT_MENU, FillUnitCell, id=G2gd.wxID_DRAWFILLCELL)
4003            G2frame.dataFrame.Bind(wx.EVT_MENU, DrawAtomsDelete, id=G2gd.wxID_DRAWDELETE)
4004            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDrawDAT, id=G2gd.wxID_DRAWDISAGLTOR)
4005            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDrawPlane, id=G2gd.wxID_DRAWPLANE)
4006            G2frame.dataFrame.Bind(wx.EVT_MENU, OnRestraint, id=G2gd.wxID_DRAWRESTRBOND)
4007            G2frame.dataFrame.Bind(wx.EVT_MENU, OnRestraint, id=G2gd.wxID_DRAWRESTRANGLE)
4008            G2frame.dataFrame.Bind(wx.EVT_MENU, OnRestraint, id=G2gd.wxID_DRAWRESTRPLANE)
4009            G2frame.dataFrame.Bind(wx.EVT_MENU, OnRestraint, id=G2gd.wxID_DRAWRESTRCHIRAL)
4010            UpdateDrawAtoms()
4011            G2plt.PlotStructure(G2frame,data)
4012        elif text == 'Pawley reflections':
4013            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.PawleyMenu)
4014            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPawleyLoad, id=G2gd.wxID_PAWLEYLOAD)
4015            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPawleyEstimate, id=G2gd.wxID_PAWLEYESTIMATE)
4016            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPawleyDelete, id=G2gd.wxID_PAWLEYDELETE)           
4017            FillPawleyReflectionsGrid()
4018        elif text == 'Texture':
4019            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.TextureMenu)
4020            G2frame.dataFrame.Bind(wx.EVT_MENU, OnTextureRefine, id=G2gd.wxID_REFINETEXTURE)
4021            G2frame.dataFrame.Bind(wx.EVT_MENU, OnTextureClear, id=G2gd.wxID_CLEARTEXTURE)
4022            UpdateTexture()                       
4023            G2plt.PlotTexture(G2frame,data,Start=True)
4024        elif text == 'Map peaks':
4025            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.MapPeaksMenu)
4026            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksMove, id=G2gd.wxID_PEAKSMOVE)
4027            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksUnique, id=G2gd.wxID_PEAKSUNIQUE)
4028            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksDelete, id=G2gd.wxID_PEAKSDELETE)
4029            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksClear, id=G2gd.wxID_PEAKSCLEAR)
4030            FillMapPeaksGrid()
4031            G2plt.PlotStructure(G2frame,data)
4032           
4033        else:
4034            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.BlankMenu)
4035        event.Skip()
4036       
4037    General = wx.Window(G2frame.dataDisplay)
4038    G2frame.dataDisplay.AddPage(General,'General')
4039    G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.DataGeneral)
4040    G2frame.dataFrame.Bind(wx.EVT_MENU, OnFourierMaps, id=G2gd.wxID_FOURCALC)
4041    G2frame.dataFrame.Bind(wx.EVT_MENU, OnSearchMaps, id=G2gd.wxID_FOURSEARCH)
4042    G2frame.dataFrame.Bind(wx.EVT_MENU, OnChargeFlip, id=G2gd.wxID_CHARGEFLIP)
4043    SetupGeneral()
4044    GeneralData = data['General']
4045    UpdateGeneral()
4046
4047    DData = wx.ScrolledWindow(G2frame.dataDisplay)
4048    G2frame.dataDisplay.AddPage(DData,'Data')
4049    Atoms = G2gd.GSGrid(G2frame.dataDisplay)
4050    G2frame.dataDisplay.AddPage(Atoms,'Atoms')
4051    drawOptions = wx.Window(G2frame.dataDisplay)
4052    G2frame.dataDisplay.AddPage(drawOptions,'Draw Options')
4053    drawAtoms = G2gd.GSGrid(G2frame.dataDisplay)
4054    G2frame.dataDisplay.AddPage(drawAtoms,'Draw Atoms')
4055    Texture = wx.ScrolledWindow(G2frame.dataDisplay)
4056    G2frame.dataDisplay.AddPage(Texture,'Texture')
4057    MapPeaks = G2gd.GSGrid(G2frame.dataDisplay)
4058    G2frame.dataDisplay.AddPage(MapPeaks,'Map peaks')
4059    G2frame.PawleyRefl = G2gd.GSGrid(G2frame.dataDisplay)
4060    G2frame.dataDisplay.AddPage(G2frame.PawleyRefl,'Pawley reflections')
4061           
4062    G2frame.dataDisplay.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, OnPageChanged)
4063    G2frame.dataDisplay.SetSelection(oldPage)
4064   
4065           
Note: See TracBrowser for help on using the repository browser.