source: trunk/GSASIIphsGUI.py @ 738

Last change on this file since 738 was 738, checked in by vondreele, 11 years ago

put wx.BusyCursor? in various places

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