source: trunk/GSASIIphsGUI.py @ 808

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

Add Babinet modification to form factors - works OK
Use atom Ids for restraints
add 'all' in atom constraint editing routines
New add routines for bond restraints (angle add not done yet)
FindAtomIndexByIDs, FillAtomLookUp?, GetAtomsByID, & GetAtomItemsById? all now in GSASIImath.py
removed from GSASIIphsGUI.py
change phase tick mark colors
get GSASIIstruct.py to recognize protein atoms & do a protein calc.

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