source: trunk/GSASIIphsGUI.py @ 814

Last change on this file since 814 was 814, checked in by vondreele, 9 years ago

implement hot keys for some main menu & menu items
fix crash in general
put a status item in as a reminder for peak fitting options
continue restraint development

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