source: trunk/GSASIIphsGUI.py @ 797

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

some fixes to TOF stuff
some fixes to SXC stuff

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