source: trunk/GSASIIphsGUI.py @ 736

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

add space group choice to cell indexing page

  • Property svn:keywords set to Date Author Revision URL Id
File size: 202.9 KB
Line 
1# -*- coding: utf-8 -*-
2#GSASII - phase data display routines
3########### SVN repository information ###################
4# $Date: 2012-08-25 17:27:08 +0000 (Sat, 25 Aug 2012) $
5# $Author: vondreele $
6# $Revision: 736 $
7# $URL: trunk/GSASIIphsGUI.py $
8# $Id: GSASIIphsGUI.py 736 2012-08-25 17:27:08Z 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: 736 $")
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            for ind in indx:
2078                atomA = atomData[ind]
2079                xyzA = np.array(atomA[cx:cx+3])
2080                indA = atomTypes.index(atomA[ct])
2081                for atomB in atomData[:numAtoms]:
2082                    indB = atomTypes.index(atomB[ct])
2083                    sumR = radii[indA]+radii[indB]
2084                    xyzB = np.array(atomB[cx:cx+3])
2085                    for xyz in cellArray+xyzB:
2086                        dist = np.sqrt(np.sum(np.inner(Amat,xyz-xyzA)**2))
2087                        if 0 < dist <= data['Drawing']['radiusFactor']*sumR:
2088                            if noDuplicate(xyz,atomData):
2089                                oprB = atomB[cx+3]
2090                                C = xyz-xyzB
2091                                newOp = '1+'+str(int(round(C[0])))+','+str(int(round(C[1])))+','+str(int(round(C[2])))
2092                                newAtom = atomB[:]
2093                                newAtom[cx:cx+3] = xyz
2094                                newAtom[cx+3] = G2spc.StringOpsProd(oprB,newOp,SGData)
2095                                atomData.append(newAtom)
2096            data['Drawing']['Atoms'] = atomData
2097            UpdateDrawAtoms()
2098            drawAtoms.ClearSelection()
2099            G2plt.PlotStructure(G2frame,data)
2100           
2101    def FillUnitCell(event):
2102        indx = drawAtoms.GetSelectedRows()
2103        indx.sort()
2104        if indx:
2105            atomData = data['Drawing']['Atoms']
2106            colLabels = [drawAtoms.GetColLabelValue(c) for c in range(drawAtoms.GetNumberCols())]
2107            cx = colLabels.index('x')
2108            cuia = colLabels.index('I/A')
2109            cuij = cuia+2
2110            generalData = data['General']
2111            SGData = generalData['SGData']
2112            for ind in indx:
2113                atom = atomData[ind]
2114                XYZ = np.array(atom[cx:cx+3])
2115                if atom[cuia] == 'A':
2116                    Uij = atom[cuij:cuij+6]
2117                    result = G2spc.GenAtom(XYZ,SGData,False,Uij,False)
2118                    for item in result:
2119                        atom = copy.copy(atomData[ind])
2120                        atom[cx:cx+3] = item[0]
2121                        atom[cx+3] = str(item[2])+'+' \
2122                            +str(item[3][0])+','+str(item[3][1])+','+str(item[3][2])
2123                        atom[cuij:cuij+6] = item[1]
2124                        Opp = G2spc.Opposite(item[0])
2125                        for xyz in Opp:
2126                            if noDuplicate(xyz,atomData):
2127                                cell = np.asarray(np.rint(xyz-atom[cx:cx+3]),dtype=np.int32)
2128                                cell = '1'+'+'+ \
2129                                    str(cell[0])+','+str(cell[1])+','+str(cell[2])
2130                                atom[cx:cx+3] = xyz
2131                                atom[cx+3] = G2spc.StringOpsProd(cell,atom[cx+3],SGData)
2132                                atomData.append(atom[:])
2133                else:
2134                    result = G2spc.GenAtom(XYZ,SGData,False,Move=False)
2135                    for item in result:
2136                        atom = copy.copy(atomData[ind])
2137                        atom[cx:cx+3] = item[0]
2138                        atom[cx+3] = str(item[1])+'+' \
2139                            +str(item[2][0])+','+str(item[2][1])+','+str(item[2][2])
2140                        Opp = G2spc.Opposite(item[0])
2141                        for xyz in Opp:
2142                            if noDuplicate(xyz,atomData):
2143                                cell = np.asarray(np.rint(xyz-atom[cx:cx+3]),dtype=np.int32)
2144                                cell = '1'+'+'+ \
2145                                    str(cell[0])+','+str(cell[1])+','+str(cell[2])
2146                                atom[cx:cx+3] = xyz
2147                                atom[cx+3] = G2spc.StringOpsProd(cell,atom[cx+3],SGData)
2148                                atomData.append(atom[:])               
2149                data['Drawing']['Atoms'] = atomData
2150            UpdateDrawAtoms()
2151            drawAtoms.ClearSelection()
2152            G2plt.PlotStructure(G2frame,data)
2153           
2154    def FindBondsToo():                         #works but slow for large structures - keep as reference
2155        cx,ct,cs,ci = data['Drawing']['atomPtrs']
2156        atomData = data['Drawing']['Atoms']
2157        generalData = data['General']
2158        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])
2159        radii = generalData['BondRadii']
2160        atomTypes = generalData['AtomTypes']
2161        try:
2162            indH = atomTypes.index('H')
2163            radii[indH] = 0.5
2164        except:
2165            pass           
2166        for atom in atomData:
2167            atom[-1] = []
2168        Atoms = []
2169        for i,atom in enumerate(atomData):
2170            Atoms.append([i,np.array(atom[cx:cx+3]),atom[cs],radii[atomTypes.index(atom[ct])]])
2171        for atomA in Atoms:
2172            if atomA[2] in ['lines','sticks','ellipsoids','balls & sticks','polyhedra']:
2173                for atomB in Atoms:                   
2174                    Dx = atomB[1]-atomA[1]
2175                    DX = np.inner(Amat,Dx)
2176                    dist = np.sqrt(np.sum(DX**2))
2177                    sumR = atomA[3]+atomB[3]
2178                    if 0.5 < dist <= 0.85*sumR:
2179                        i = atomA[0]
2180                        if atomA[2] == 'polyhedra':
2181                            atomData[i][-1].append(DX)
2182                        elif atomB[1] != 'polyhedra':
2183                            j = atomB[0]
2184                            atomData[i][-1].append(Dx*atomA[3]/sumR)
2185                            atomData[j][-1].append(-Dx*atomB[3]/sumR)
2186                   
2187    def FindBondsDraw():                    #uses numpy & masks - very fast even for proteins!
2188        import numpy.ma as ma
2189        cx,ct,cs,ci = data['Drawing']['atomPtrs']
2190        hydro = data['Drawing']['showHydrogen']
2191        atomData = data['Drawing']['Atoms']
2192        generalData = data['General']
2193        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])
2194        radii = generalData['BondRadii']
2195        atomTypes = generalData['AtomTypes']
2196        try:
2197            indH = atomTypes.index('H')
2198            radii[indH] = 0.5
2199        except:
2200            pass           
2201        for atom in atomData:
2202            atom[-2] = []               #clear out old bonds/polyhedra
2203            atom[-1] = []
2204        Indx = range(len(atomData))
2205        Atoms = []
2206        Styles = []
2207        Radii = []
2208        for atom in atomData:
2209            Atoms.append(np.array(atom[cx:cx+3]))
2210            Styles.append(atom[cs])
2211            try:
2212                if not hydro and atom[ct] == 'H':
2213                    Radii.append(0.0)
2214                else:
2215                    Radii.append(radii[atomTypes.index(atom[ct])])
2216            except ValueError:          #changed atom type!
2217                Radii.append(0.20)
2218        Atoms = np.array(Atoms)
2219        Radii = np.array(Radii)
2220        IASR = zip(Indx,Atoms,Styles,Radii)
2221        for atomA in IASR:
2222            if atomA[2] in ['lines','sticks','ellipsoids','balls & sticks','polyhedra']:
2223                Dx = Atoms-atomA[1]
2224                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
2225                sumR = atomA[3]+Radii
2226                IndB = ma.nonzero(ma.masked_greater(dist-data['Drawing']['radiusFactor']*sumR,0.))                 #get indices of bonded atoms
2227                i = atomA[0]
2228                for j in IndB[0]:
2229                    if Styles[i] == 'polyhedra':
2230                        atomData[i][-2].append(np.inner(Amat,Dx[j]))
2231                    elif Styles[j] != 'polyhedra' and j > i:
2232                        atomData[i][-2].append(Dx[j]*Radii[i]/sumR[j])
2233                        atomData[j][-2].append(-Dx[j]*Radii[j]/sumR[j])
2234                if Styles[i] == 'polyhedra':
2235                    Bonds = atomData[i][-2]
2236                    Faces = []
2237                    if len(Bonds) > 2:
2238                        FaceGen = G2lat.uniqueCombinations(Bonds,3)     #N.B. this is a generator
2239                        for face in FaceGen:
2240                            vol = nl.det(face)
2241                            if abs(vol) > 1. or len(Bonds) == 3:
2242                                if vol < 0.:
2243                                    face = [face[0],face[2],face[1]]
2244                                face = np.array(face)
2245                                if not np.array([np.array(nl.det(face-bond))+0.0001 < 0 for bond in Bonds]).any():
2246                                    norm = np.cross(face[1]-face[0],face[2]-face[0])
2247                                    norm /= np.sqrt(np.sum(norm**2))
2248                                    Faces.append([face,norm])
2249                        atomData[i][-1] = Faces
2250                       
2251    def DrawAtomsDelete(event):   
2252        indx = drawAtoms.GetSelectedRows()
2253        indx.sort()
2254        if indx:
2255            atomData = data['Drawing']['Atoms']
2256            indx.reverse()
2257            for ind in indx:
2258                del atomData[ind]
2259            UpdateDrawAtoms()
2260            drawAtoms.ClearSelection()
2261            G2plt.PlotStructure(G2frame,data)
2262        event.StopPropagation()
2263       
2264    def OnReloadDrawAtoms(event):
2265        data['Drawing']['Atoms'] = []
2266        UpdateDrawAtoms()
2267        drawAtoms.ClearSelection()
2268        G2plt.PlotStructure(G2frame,data)
2269        event.StopPropagation()
2270       
2271    def FindAtomIndexByIDs(atomData,IDs,Draw=True):
2272        indx = []
2273        for i,atom in enumerate(atomData):
2274            if Draw and atom[-3] in IDs:
2275                indx.append(i)
2276            elif atom[-1] in IDs:
2277                indx.append(i)
2278        return indx
2279       
2280    def DrawAtomsDeleteByIDs(IDs):
2281        atomData = data['Drawing']['Atoms']
2282        indx = FindAtomIndexByIDs(atomData,IDs)
2283        indx.reverse()
2284        for ind in indx:
2285            del atomData[ind]
2286           
2287    def ChangeDrawAtomsByIDs(colName,IDs,value):
2288        atomData = data['Drawing']['Atoms']
2289        cx,ct,cs,ci = data['Drawing']['atomPtrs']
2290        if colName == 'Name':
2291            col = ct-1
2292        elif colName == 'Type':
2293            col = ct
2294        elif colName == 'I/A':
2295            col = cs
2296        indx = FindAtomIndexByIDs(atomData,IDs)
2297        for ind in indx:
2298            atomData[ind][col] = value
2299               
2300    def OnDrawPlane(event):
2301        indx = drawAtoms.GetSelectedRows()
2302        if len(indx) < 4:
2303            print '**** ERROR - need 4+ atoms for plane calculation'
2304            return
2305        PlaneData = {}
2306        drawingData = data['Drawing']
2307        atomData = drawingData['Atoms']
2308        colLabels = [drawAtoms.GetColLabelValue(c) for c in range(drawAtoms.GetNumberCols())]
2309        cx = colLabels.index('x')
2310        cn = colLabels.index('Name')
2311        xyz = []
2312        for i,atom in enumerate(atomData):
2313            if i in indx:
2314                xyz.append([i,]+atom[cn:cn+2]+atom[cx:cx+3])
2315        generalData = data['General']
2316        PlaneData['Name'] = generalData['Name']
2317        PlaneData['Atoms'] = xyz
2318        PlaneData['Cell'] = generalData['Cell'][1:] #+ volume
2319        G2str.BestPlane(PlaneData)
2320   
2321    def OnDrawDAT(event):
2322        #distance, angle, torsion
2323        indx = drawAtoms.GetSelectedRows()
2324        if len(indx) not in [2,3,4]:
2325            print '**** ERROR - wrong number of atoms for distance, angle or torsion calculation'
2326            return
2327        DATData = {}
2328        ocx,oct,ocs,cia = data['General']['AtomPtrs']
2329        drawingData = data['Drawing']
2330        atomData = data['Atoms']
2331        atomDData = drawingData['Atoms']
2332        colLabels = [drawAtoms.GetColLabelValue(c) for c in range(drawAtoms.GetNumberCols())]
2333        cx = colLabels.index('x')
2334        cn = colLabels.index('Name')
2335        cid = colLabels.index('I/A')+8
2336        xyz = []
2337        Oxyz = []
2338        DATData['Natoms'] = len(indx)
2339        for i in indx:
2340            atom = atomDData[i]
2341            xyz.append([i,]+atom[cn:cn+2]+atom[cx:cx+4]) #also gets Sym Op
2342            id = FindAtomIndexByIDs(atomData,[atom[cid],],False)[0]
2343            Oxyz.append([id,]+atomData[id][cx+1:cx+4])
2344        DATData['Datoms'] = xyz
2345        DATData['Oatoms'] = Oxyz
2346        generalData = data['General']
2347        DATData['Name'] = generalData['Name']
2348        DATData['SGData'] = generalData['SGData']
2349        DATData['Cell'] = generalData['Cell'][1:] #+ volume
2350        if 'pId' in data:
2351            DATData['pId'] = data['pId']
2352            DATData['covData'] = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.root, 'Covariance'))
2353        G2str.DisAglTor(DATData)
2354               
2355################################################################################
2356#### Draw Options page
2357################################################################################
2358
2359    def UpdateDrawOptions():
2360        import copy
2361        import wx.lib.colourselect as wcs
2362        generalData = data['General']
2363        SetupDrawingData()
2364        drawingData = data['Drawing']
2365        if generalData['Type'] == 'nuclear':
2366            pickChoice = ['Atoms','Bonds','Torsions','Planes']
2367        elif generalData['Type'] == 'macromolecular':
2368            pickChoice = ['Atoms','Residues','Chains','Bonds','Torsions','Planes','phi/psi']
2369
2370        def SlopSizer():
2371           
2372            def OnCameraPos(event):
2373                drawingData['cameraPos'] = cameraPos.GetValue()
2374                cameraPosTxt.SetLabel(' Camera Distance: '+'%.2f'%(drawingData['cameraPos']))
2375                ZclipTxt.SetLabel(' Z clipping: '+'%.2fA'%(drawingData['Zclip']*drawingData['cameraPos']/100.))
2376                G2plt.PlotStructure(G2frame,data)
2377
2378            def OnZclip(event):
2379                drawingData['Zclip'] = Zclip.GetValue()
2380                ZclipTxt.SetLabel(' Z clipping: '+'%.2fA'%(drawingData['Zclip']*drawingData['cameraPos']/100.))
2381                G2plt.PlotStructure(G2frame,data)
2382               
2383            def OnVdWScale(event):
2384                drawingData['vdwScale'] = vdwScale.GetValue()/100.
2385                vdwScaleTxt.SetLabel(' van der Waals scale: '+'%.2f'%(drawingData['vdwScale']))
2386                G2plt.PlotStructure(G2frame,data)
2387   
2388            def OnEllipseProb(event):
2389                drawingData['ellipseProb'] = ellipseProb.GetValue()
2390                ellipseProbTxt.SetLabel(' Ellipsoid probability: '+'%d%%'%(drawingData['ellipseProb']))
2391                G2plt.PlotStructure(G2frame,data)
2392   
2393            def OnBallScale(event):
2394                drawingData['ballScale'] = ballScale.GetValue()/100.
2395                ballScaleTxt.SetLabel(' Ball scale: '+'%.2f'%(drawingData['ballScale']))
2396                G2plt.PlotStructure(G2frame,data)
2397
2398            def OnBondRadius(event):
2399                drawingData['bondRadius'] = bondRadius.GetValue()/100.
2400                bondRadiusTxt.SetLabel(' Bond radius, A: '+'%.2f'%(drawingData['bondRadius']))
2401                G2plt.PlotStructure(G2frame,data)
2402               
2403            def OnContourLevel(event):
2404                drawingData['contourLevel'] = contourLevel.GetValue()/100.
2405                contourLevelTxt.SetLabel(' Contour level: '+'%.2f'%(drawingData['contourLevel']*generalData['Map']['rhoMax']))
2406                G2plt.PlotStructure(G2frame,data)
2407
2408            def OnMapSize(event):
2409                drawingData['mapSize'] = mapSize.GetValue()/10.
2410                mapSizeTxt.SetLabel(' Map radius, A: '+'%.1f'%(drawingData['mapSize']))
2411                G2plt.PlotStructure(G2frame,data)
2412
2413           
2414            slopSizer = wx.BoxSizer(wx.HORIZONTAL)
2415            slideSizer = wx.FlexGridSizer(7,2)
2416            slideSizer.AddGrowableCol(1,1)
2417   
2418            cameraPosTxt = wx.StaticText(dataDisplay,-1,
2419                ' Camera Distance: '+'%.2f'%(drawingData['cameraPos']),name='cameraPos')
2420            slideSizer.Add(cameraPosTxt,0,wx.ALIGN_CENTER_VERTICAL)
2421            cameraPos = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=drawingData['cameraPos'],name='cameraSlider')
2422            cameraPos.SetRange(10,500)
2423            cameraPos.Bind(wx.EVT_SLIDER, OnCameraPos)
2424            slideSizer.Add(cameraPos,1,wx.EXPAND|wx.RIGHT)
2425           
2426            ZclipTxt = wx.StaticText(dataDisplay,-1,' Z clipping: '+'%.2fA'%(drawingData['Zclip']*drawingData['cameraPos']/100.))
2427            slideSizer.Add(ZclipTxt,0,wx.ALIGN_CENTER_VERTICAL)
2428            Zclip = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=drawingData['Zclip'])
2429            Zclip.SetRange(1,99)
2430            Zclip.Bind(wx.EVT_SLIDER, OnZclip)
2431            slideSizer.Add(Zclip,1,wx.EXPAND|wx.RIGHT)
2432           
2433            vdwScaleTxt = wx.StaticText(dataDisplay,-1,' van der Waals scale: '+'%.2f'%(drawingData['vdwScale']))
2434            slideSizer.Add(vdwScaleTxt,0,wx.ALIGN_CENTER_VERTICAL)
2435            vdwScale = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=int(100*drawingData['vdwScale']))
2436            vdwScale.Bind(wx.EVT_SLIDER, OnVdWScale)
2437            slideSizer.Add(vdwScale,1,wx.EXPAND|wx.RIGHT)
2438   
2439            ellipseProbTxt = wx.StaticText(dataDisplay,-1,' Ellipsoid probability: '+'%d%%'%(drawingData['ellipseProb']))
2440            slideSizer.Add(ellipseProbTxt,0,wx.ALIGN_CENTER_VERTICAL)
2441            ellipseProb = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=drawingData['ellipseProb'])
2442            ellipseProb.SetRange(1,99)
2443            ellipseProb.Bind(wx.EVT_SLIDER, OnEllipseProb)
2444            slideSizer.Add(ellipseProb,1,wx.EXPAND|wx.RIGHT)
2445   
2446            ballScaleTxt = wx.StaticText(dataDisplay,-1,' Ball scale: '+'%.2f'%(drawingData['ballScale']))
2447            slideSizer.Add(ballScaleTxt,0,wx.ALIGN_CENTER_VERTICAL)
2448            ballScale = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=int(100*drawingData['ballScale']))
2449            ballScale.Bind(wx.EVT_SLIDER, OnBallScale)
2450            slideSizer.Add(ballScale,1,wx.EXPAND|wx.RIGHT)
2451   
2452            bondRadiusTxt = wx.StaticText(dataDisplay,-1,' Bond radius, A: '+'%.2f'%(drawingData['bondRadius']))
2453            slideSizer.Add(bondRadiusTxt,0,wx.ALIGN_CENTER_VERTICAL)
2454            bondRadius = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=int(100*drawingData['bondRadius']))
2455            bondRadius.SetRange(1,25)
2456            bondRadius.Bind(wx.EVT_SLIDER, OnBondRadius)
2457            slideSizer.Add(bondRadius,1,wx.EXPAND|wx.RIGHT)
2458           
2459            if generalData['Map']['rhoMax']:
2460                contourLevelTxt = wx.StaticText(dataDisplay,-1,' Contour level: '+'%.2f'%(drawingData['contourLevel']*generalData['Map']['rhoMax']))
2461                slideSizer.Add(contourLevelTxt,0,wx.ALIGN_CENTER_VERTICAL)
2462                contourLevel = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=int(100*drawingData['contourLevel']))
2463                contourLevel.SetRange(1,100)
2464                contourLevel.Bind(wx.EVT_SLIDER, OnContourLevel)
2465                slideSizer.Add(contourLevel,1,wx.EXPAND|wx.RIGHT)
2466                mapSizeTxt = wx.StaticText(dataDisplay,-1,' Map radius, A: '+'%.1f'%(drawingData['mapSize']))
2467                slideSizer.Add(mapSizeTxt,0,wx.ALIGN_CENTER_VERTICAL)
2468                mapSize = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=int(10*drawingData['mapSize']))
2469                mapSize.SetRange(1,100)
2470                mapSize.Bind(wx.EVT_SLIDER, OnMapSize)
2471                slideSizer.Add(mapSize,1,wx.EXPAND|wx.RIGHT)
2472           
2473            slopSizer.Add(slideSizer,1,wx.EXPAND|wx.RIGHT)
2474            slopSizer.Add((10,5),0)
2475            slopSizer.SetMinSize(wx.Size(350,10))
2476            return slopSizer
2477           
2478        def ShowSizer():
2479           
2480            def OnBackColor(event):
2481                drawingData['backColor'] = event.GetValue()
2482                G2plt.PlotStructure(G2frame,data)
2483   
2484            def OnShowABC(event):
2485                drawingData['showABC'] = showABC.GetValue()
2486                G2plt.PlotStructure(G2frame,data)
2487   
2488            def OnShowUnitCell(event):
2489                drawingData['unitCellBox'] = unitCellBox.GetValue()
2490                G2plt.PlotStructure(G2frame,data)
2491   
2492            def OnShowHyd(event):
2493                drawingData['showHydrogen'] = showHydrogen.GetValue()
2494                FindBondsDraw()
2495                G2plt.PlotStructure(G2frame,data)
2496               
2497            showSizer = wx.BoxSizer(wx.VERTICAL)           
2498            lineSizer = wx.BoxSizer(wx.HORIZONTAL)
2499            lineSizer.Add(wx.StaticText(dataDisplay,-1,' Background color:'),0,wx.ALIGN_CENTER_VERTICAL)
2500            backColor = wcs.ColourSelect(dataDisplay, -1,colour=drawingData['backColor'],size=wx.Size(25,25))
2501            backColor.Bind(wcs.EVT_COLOURSELECT, OnBackColor)
2502            lineSizer.Add(backColor,0,wx.ALIGN_CENTER_VERTICAL)
2503           
2504            lineSizer.Add(wx.StaticText(dataDisplay,-1,' View Point:'),0,wx.ALIGN_CENTER_VERTICAL)
2505            VP = drawingData['viewPoint'][0]
2506            viewPoint = wx.TextCtrl(dataDisplay,value='%.3f, %.3f, %.3f'%(VP[0],VP[1],VP[2]),
2507                style=wx.TE_READONLY,size=wx.Size(140,20),name='viewPoint')
2508            viewPoint.SetBackgroundColour(VERY_LIGHT_GREY)
2509            lineSizer.Add(viewPoint,0,wx.ALIGN_CENTER_VERTICAL)
2510            showSizer.Add(lineSizer)
2511            showSizer.Add((0,5),0)
2512           
2513            line2Sizer = wx.BoxSizer(wx.HORIZONTAL)
2514            showABC = wx.CheckBox(dataDisplay,-1,label=' Show test point?')
2515            showABC.Bind(wx.EVT_CHECKBOX, OnShowABC)
2516            showABC.SetValue(drawingData['showABC'])
2517            line2Sizer.Add(showABC,0,wx.ALIGN_CENTER_VERTICAL)
2518   
2519            unitCellBox = wx.CheckBox(dataDisplay,-1,label=' Show unit cell?')
2520            unitCellBox.Bind(wx.EVT_CHECKBOX, OnShowUnitCell)
2521            unitCellBox.SetValue(drawingData['unitCellBox'])
2522            line2Sizer.Add(unitCellBox,0,wx.ALIGN_CENTER_VERTICAL)
2523   
2524            showHydrogen = wx.CheckBox(dataDisplay,-1,label=' Show hydrogens?')
2525            showHydrogen.Bind(wx.EVT_CHECKBOX, OnShowHyd)
2526            showHydrogen.SetValue(drawingData['showHydrogen'])
2527            line2Sizer.Add(showHydrogen,0,wx.ALIGN_CENTER_VERTICAL)
2528            showSizer.Add(line2Sizer)
2529            return showSizer
2530           
2531        def RadSizer():
2532           
2533            def OnSizeHatoms(event):
2534                try:
2535                    value = max(0.1,min(1.2,float(sizeH.GetValue())))
2536                except ValueError:
2537                    value = 0.5
2538                drawingData['sizeH'] = value
2539                sizeH.SetValue("%.2f"%(value))
2540                G2plt.PlotStructure(G2frame,data)
2541               
2542            def OnRadFactor(event):
2543                try:
2544                    value = max(0.1,min(1.2,float(radFactor.GetValue())))
2545                except ValueError:
2546                    value = 0.85
2547                drawingData['radiusFactor'] = value
2548                radFactor.SetValue("%.2f"%(value))
2549                FindBondsDraw()
2550                G2plt.PlotStructure(G2frame,data)
2551           
2552            radSizer = wx.BoxSizer(wx.HORIZONTAL)
2553            radSizer.Add(wx.StaticText(dataDisplay,-1,' Hydrogen radius, A:  '),0,wx.ALIGN_CENTER_VERTICAL)
2554            sizeH = wx.TextCtrl(dataDisplay,-1,value='%.2f'%(drawingData['sizeH']),size=wx.Size(60,20),style=wx.TE_PROCESS_ENTER)
2555            sizeH.Bind(wx.EVT_TEXT_ENTER,OnSizeHatoms)
2556            sizeH.Bind(wx.EVT_KILL_FOCUS,OnSizeHatoms)
2557            radSizer.Add(sizeH,0,wx.ALIGN_CENTER_VERTICAL)
2558   
2559            radSizer.Add(wx.StaticText(dataDisplay,-1,' Bond search factor:  '),0,wx.ALIGN_CENTER_VERTICAL)
2560            radFactor = wx.TextCtrl(dataDisplay,value='%.2f'%(drawingData['radiusFactor']),size=wx.Size(60,20),style=wx.TE_PROCESS_ENTER)
2561            radFactor.Bind(wx.EVT_TEXT_ENTER,OnRadFactor)
2562            radFactor.Bind(wx.EVT_KILL_FOCUS,OnRadFactor)
2563            radSizer.Add(radFactor,0,wx.ALIGN_CENTER_VERTICAL)
2564            return radSizer
2565
2566        G2frame.dataFrame.SetStatusText('')
2567        drawOptions.DestroyChildren()
2568        dataDisplay = wx.Panel(drawOptions)
2569        mainSizer = wx.BoxSizer(wx.VERTICAL)
2570        mainSizer.Add((5,5),0)
2571        mainSizer.Add(wx.StaticText(dataDisplay,-1,' Drawing controls:'),0,wx.ALIGN_CENTER_VERTICAL)
2572        mainSizer.Add((5,5),0)       
2573        mainSizer.Add(SlopSizer(),0)
2574        mainSizer.Add((5,5),0)
2575        mainSizer.Add(ShowSizer(),0,)
2576        mainSizer.Add((5,5),0)
2577        mainSizer.Add(RadSizer(),0,)
2578
2579        dataDisplay.SetSizer(mainSizer)
2580        Size = mainSizer.Fit(G2frame.dataFrame)
2581        Size[1] += 35                           #compensate for status bar
2582        dataDisplay.SetSize(Size)
2583        G2frame.dataFrame.setSizePosLeft(Size)
2584
2585################################################################################
2586####  Texture routines
2587################################################################################
2588       
2589    def UpdateTexture():
2590        G2frame.dataFrame.SetStatusText('')
2591        generalData = data['General']       
2592        SGData = generalData['SGData']
2593        try:
2594            textureData = generalData['SH Texture']
2595        except KeyError:            #fix old files!
2596            textureData = generalData['SH Texture'] = {'Order':0,'Model':'cylindrical',
2597                'Sample omega':[False,0.0],'Sample chi':[False,0.0],'Sample phi':[False,0.0],
2598                'SH Coeff':[False,{}],'SHShow':False,'PFhkl':[0,0,1],
2599                'PFxyz':[0,0,1.],'PlotType':'Pole figure'}
2600        if 'SHShow' not in textureData:     #another fix
2601            textureData.update({'SHShow':False,'PFhkl':[0,0,1],'PFxyz':[0,0,1.],'PlotType':'Pole figure'})
2602        try:                        #another fix!
2603            x = textureData['PlotType']
2604        except KeyError:
2605            textureData.update({'PFxyz':[0,0,1.],'PlotType':'Pole figure'})
2606        shModels = ['cylindrical','none','shear - 2/m','rolling - mmm']
2607        SamSym = dict(zip(shModels,['0','-1','2/m','mmm']))
2608        if generalData['doPawley'] and G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Sequental results'):
2609            G2frame.dataFrame.RefineTexture.Enable(True)
2610        shAngles = ['omega','chi','phi']
2611       
2612        def SetSHCoef():
2613            cofNames = G2lat.GenSHCoeff(SGData['SGLaue'],SamSym[textureData['Model']],textureData['Order'])
2614            newSHCoef = dict(zip(cofNames,np.zeros(len(cofNames))))
2615            SHCoeff = textureData['SH Coeff'][1]
2616            for cofName in SHCoeff:
2617                if cofName in  cofNames:
2618                    newSHCoef[cofName] = SHCoeff[cofName]
2619            return newSHCoef
2620       
2621        def OnShOrder(event):
2622            Obj = event.GetEventObject()
2623            textureData['Order'] = int(Obj.GetValue())
2624            textureData['SH Coeff'][1] = SetSHCoef()
2625            wx.CallAfter(UpdateTexture)
2626            G2plt.PlotTexture(G2frame,data)
2627                       
2628        def OnShModel(event):
2629            Obj = event.GetEventObject()
2630            textureData['Model'] = Obj.GetValue()
2631            textureData['SH Coeff'][1] = SetSHCoef()
2632            wx.CallAfter(UpdateTexture)
2633            G2plt.PlotTexture(G2frame,data)
2634           
2635        def OnSHRefine(event):
2636            Obj = event.GetEventObject()
2637            textureData['SH Coeff'][0] = Obj.GetValue()
2638           
2639        def OnSHShow(event):
2640            Obj = event.GetEventObject()
2641            textureData['SHShow'] = Obj.GetValue()
2642            wx.CallAfter(UpdateTexture)
2643           
2644        def OnProjSel(event):
2645            Obj = event.GetEventObject()
2646            G2frame.Projection = Obj.GetValue()
2647            G2plt.PlotTexture(G2frame,data)
2648           
2649        def OnColorSel(event):
2650            Obj = event.GetEventObject()
2651            G2frame.ContourColor = Obj.GetValue()
2652            G2plt.PlotTexture(G2frame,data)
2653           
2654        def OnAngRef(event):
2655            Obj = event.GetEventObject()
2656            textureData[angIndx[Obj.GetId()]][0] = Obj.GetValue()
2657           
2658        def OnAngValue(event):
2659            Obj = event.GetEventObject()
2660            try:
2661                value =  float(Obj.GetValue())
2662            except ValueError:
2663                value = textureData[valIndx[Obj.GetId()]][1]
2664            Obj.SetValue('%8.2f'%(value))
2665            textureData[valIndx[Obj.GetId()]][1] = value
2666           
2667        def OnODFValue(event): 
2668            Obj = event.GetEventObject()
2669            try:
2670                value =  float(Obj.GetValue())
2671            except ValueError:
2672                value = textureData['SH Coeff'][1][ODFIndx[Obj.GetId()]]
2673            Obj.SetValue('%8.3f'%(value))
2674            textureData['SH Coeff'][1][ODFIndx[Obj.GetId()]] = value
2675            G2plt.PlotTexture(G2frame,data)
2676           
2677        def OnPfType(event):
2678            Obj = event.GetEventObject()
2679            textureData['PlotType'] = Obj.GetValue()
2680            wx.CallAfter(UpdateTexture)
2681            G2plt.PlotTexture(G2frame,data)
2682           
2683        def OnPFValue(event):
2684            Obj = event.GetEventObject()
2685            Saxis = Obj.GetValue().split()
2686            if textureData['PlotType'] in ['Pole figure','Axial pole distribution']:               
2687                try:
2688                    hkl = [int(Saxis[i]) for i in range(3)]
2689                except (ValueError,IndexError):
2690                    hkl = textureData['PFhkl']
2691                if not np.any(np.array(hkl)):       #can't be all zeros!
2692                    hkl = textureData['PFhkl']
2693                Obj.SetValue('%d %d %d'%(hkl[0],hkl[1],hkl[2]))
2694                textureData['PFhkl'] = hkl
2695            else:
2696                try:
2697                    xyz = [float(Saxis[i]) for i in range(3)]
2698                except (ValueError,IndexError):
2699                    xyz = textureData['PFxyz']
2700                if not np.any(np.array(xyz)):       #can't be all zeros!
2701                    xyz = textureData['PFxyz']
2702                Obj.SetValue('%3.1f %3.1f %3.1f'%(xyz[0],xyz[1],xyz[2]))
2703                textureData['PFxyz'] = xyz
2704            G2plt.PlotTexture(G2frame,data)
2705
2706        if Texture.GetSizer():
2707            Texture.GetSizer().Clear(True)
2708        mainSizer = wx.BoxSizer(wx.VERTICAL)
2709        titleSizer = wx.BoxSizer(wx.HORIZONTAL)
2710        titleSizer.Add(wx.StaticText(Texture,-1,'Spherical harmonics texture data for '+PhaseName+':'),0,wx.ALIGN_CENTER_VERTICAL)
2711        titleSizer.Add(wx.StaticText(Texture,-1,
2712            ' Texture Index J = %7.3f'%(G2lat.textureIndex(textureData['SH Coeff'][1]))),
2713            0,wx.ALIGN_CENTER_VERTICAL)
2714        mainSizer.Add(titleSizer,0)
2715        mainSizer.Add((0,5),0)
2716        shSizer = wx.FlexGridSizer(1,6,5,5)
2717        shSizer.Add(wx.StaticText(Texture,-1,'Texture model: '),0,wx.ALIGN_CENTER_VERTICAL)
2718        shModel = wx.ComboBox(Texture,-1,value=textureData['Model'],choices=shModels,
2719            style=wx.CB_READONLY|wx.CB_DROPDOWN)
2720        shModel.Bind(wx.EVT_COMBOBOX,OnShModel)
2721        shSizer.Add(shModel,0,wx.ALIGN_CENTER_VERTICAL)
2722        shSizer.Add(wx.StaticText(Texture,-1,'  Harmonic order: '),0,wx.ALIGN_CENTER_VERTICAL)
2723        shOrder = wx.ComboBox(Texture,-1,value=str(textureData['Order']),choices=[str(2*i) for i in range(18)],
2724            style=wx.CB_READONLY|wx.CB_DROPDOWN)
2725        shOrder.Bind(wx.EVT_COMBOBOX,OnShOrder)
2726        shSizer.Add(shOrder,0,wx.ALIGN_CENTER_VERTICAL)
2727        shRef = wx.CheckBox(Texture,-1,label=' Refine texture?')
2728        shRef.SetValue(textureData['SH Coeff'][0])
2729        shRef.Bind(wx.EVT_CHECKBOX, OnSHRefine)
2730        shSizer.Add(shRef,0,wx.ALIGN_CENTER_VERTICAL)
2731        shShow = wx.CheckBox(Texture,-1,label=' Show coeff.?')
2732        shShow.SetValue(textureData['SHShow'])
2733        shShow.Bind(wx.EVT_CHECKBOX, OnSHShow)
2734        shSizer.Add(shShow,0,wx.ALIGN_CENTER_VERTICAL)
2735        mainSizer.Add(shSizer,0,0)
2736        mainSizer.Add((0,5),0)
2737        PTSizer = wx.FlexGridSizer(2,4,5,5)
2738        PTSizer.Add(wx.StaticText(Texture,-1,' Texture plot type: '),0,wx.ALIGN_CENTER_VERTICAL)
2739        choices = ['Axial pole distribution','Pole figure','Inverse pole figure']           
2740        pfType = wx.ComboBox(Texture,-1,value=str(textureData['PlotType']),choices=choices,
2741            style=wx.CB_READONLY|wx.CB_DROPDOWN)
2742        pfType.Bind(wx.EVT_COMBOBOX,OnPfType)
2743        PTSizer.Add(pfType,0,wx.ALIGN_CENTER_VERTICAL)
2744        if 'Axial' not in textureData['PlotType']:
2745            PTSizer.Add(wx.StaticText(Texture,-1,' Projection type: '),0,wx.ALIGN_CENTER_VERTICAL)
2746            projSel = wx.ComboBox(Texture,-1,value=G2frame.Projection,choices=['equal area','stereographic','3D display'],
2747                style=wx.CB_READONLY|wx.CB_DROPDOWN)
2748            projSel.Bind(wx.EVT_COMBOBOX,OnProjSel)
2749            PTSizer.Add(projSel,0,wx.ALIGN_CENTER_VERTICAL)
2750        if textureData['PlotType'] in ['Pole figure','Axial pole distribution']:
2751            PTSizer.Add(wx.StaticText(Texture,-1,' Pole figure HKL: '),0,wx.ALIGN_CENTER_VERTICAL)
2752            PH = textureData['PFhkl']
2753            pfVal = wx.TextCtrl(Texture,-1,'%d %d %d'%(PH[0],PH[1],PH[2]),style=wx.TE_PROCESS_ENTER)
2754        else:
2755            PTSizer.Add(wx.StaticText(Texture,-1,' Inverse pole figure XYZ: '),0,wx.ALIGN_CENTER_VERTICAL)
2756            PX = textureData['PFxyz']
2757            pfVal = wx.TextCtrl(Texture,-1,'%3.1f %3.1f %3.1f'%(PX[0],PX[1],PX[2]),style=wx.TE_PROCESS_ENTER)
2758        pfVal.Bind(wx.EVT_TEXT_ENTER,OnPFValue)
2759        pfVal.Bind(wx.EVT_KILL_FOCUS,OnPFValue)
2760        PTSizer.Add(pfVal,0,wx.ALIGN_CENTER_VERTICAL)
2761        if 'Axial' not in textureData['PlotType']:
2762            PTSizer.Add(wx.StaticText(Texture,-1,' Color scheme'),0,wx.ALIGN_CENTER_VERTICAL)
2763            choice = [m for m in mpl.cm.datad.keys() if not m.endswith("_r")]
2764            choice.sort()
2765            colorSel = wx.ComboBox(Texture,-1,value=G2frame.ContourColor,choices=choice,
2766                style=wx.CB_READONLY|wx.CB_DROPDOWN)
2767            colorSel.Bind(wx.EVT_COMBOBOX,OnColorSel)
2768            PTSizer.Add(colorSel,0,wx.ALIGN_CENTER_VERTICAL)       
2769        mainSizer.Add(PTSizer,0,wx.ALIGN_CENTER_VERTICAL)
2770        mainSizer.Add((0,5),0)
2771        if textureData['SHShow']:
2772            mainSizer.Add(wx.StaticText(Texture,-1,'Spherical harmonic coefficients: '),0,wx.ALIGN_CENTER_VERTICAL)
2773            mainSizer.Add((0,5),0)
2774            ODFSizer = wx.FlexGridSizer(2,8,2,2)
2775            ODFIndx = {}
2776            ODFkeys = textureData['SH Coeff'][1].keys()
2777            ODFkeys.sort()
2778            for item in ODFkeys:
2779                ODFSizer.Add(wx.StaticText(Texture,-1,item),0,wx.ALIGN_CENTER_VERTICAL)
2780                ODFval = wx.TextCtrl(Texture,wx.ID_ANY,'%8.3f'%(textureData['SH Coeff'][1][item]),style=wx.TE_PROCESS_ENTER)
2781                ODFIndx[ODFval.GetId()] = item
2782                ODFval.Bind(wx.EVT_TEXT_ENTER,OnODFValue)
2783                ODFval.Bind(wx.EVT_KILL_FOCUS,OnODFValue)
2784                ODFSizer.Add(ODFval,0,wx.ALIGN_CENTER_VERTICAL)
2785            mainSizer.Add(ODFSizer,0,wx.ALIGN_CENTER_VERTICAL)
2786            mainSizer.Add((0,5),0)
2787        mainSizer.Add((0,5),0)
2788        mainSizer.Add(wx.StaticText(Texture,-1,'Sample orientation angles: '),0,wx.ALIGN_CENTER_VERTICAL)
2789        mainSizer.Add((0,5),0)
2790        angSizer = wx.BoxSizer(wx.HORIZONTAL)
2791        angIndx = {}
2792        valIndx = {}
2793        for item in ['Sample omega','Sample chi','Sample phi']:
2794            angRef = wx.CheckBox(Texture,-1,label=item+': ')
2795            angRef.SetValue(textureData[item][0])
2796            angIndx[angRef.GetId()] = item
2797            angRef.Bind(wx.EVT_CHECKBOX, OnAngRef)
2798            angSizer.Add(angRef,0,wx.ALIGN_CENTER_VERTICAL)
2799            angVal = wx.TextCtrl(Texture,wx.ID_ANY,'%8.2f'%(textureData[item][1]),style=wx.TE_PROCESS_ENTER)
2800            valIndx[angVal.GetId()] = item
2801            angVal.Bind(wx.EVT_TEXT_ENTER,OnAngValue)
2802            angVal.Bind(wx.EVT_KILL_FOCUS,OnAngValue)
2803            angSizer.Add(angVal,0,wx.ALIGN_CENTER_VERTICAL)
2804            angSizer.Add((5,0),0)
2805        mainSizer.Add(angSizer,0,wx.ALIGN_CENTER_VERTICAL)
2806        Texture.SetSizer(mainSizer,True)
2807        mainSizer.Fit(G2frame.dataFrame)
2808        Size = mainSizer.GetMinSize()
2809        Size[0] += 40
2810        Size[1] = max(Size[1],250) + 35
2811        Texture.SetSize(Size)
2812        Texture.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
2813        Size[1] = min(Size[1],450)
2814        G2frame.dataFrame.setSizePosLeft(Size)
2815
2816################################################################################
2817##### DData routines
2818################################################################################
2819       
2820    def UpdateDData():
2821        G2frame.dataFrame.SetStatusText('')
2822        UseList = data['Histograms']
2823        if UseList:
2824            G2frame.dataFrame.DataMenu.Enable(G2gd.wxID_DATADELETE,True)
2825            G2frame.Refine.Enable(True)
2826        else:
2827            G2frame.dataFrame.DataMenu.Enable(G2gd.wxID_DATADELETE,False)
2828            G2frame.Refine.Enable(False)           
2829        generalData = data['General']       
2830        SGData = generalData['SGData']
2831        keyList = UseList.keys()
2832        keyList.sort()
2833        PWDR = any(['PWDR' in item for item in keyList])
2834        Indx = {}
2835       
2836        def PlotSizer():
2837
2838            def OnPlotSel(event):
2839                Obj = event.GetEventObject()
2840                generalData['Data plot type'] = Obj.GetStringSelection()
2841                wx.CallAfter(UpdateDData)
2842                G2plt.PlotSizeStrainPO(G2frame,data)
2843               
2844            def OnPOhkl(event):
2845                Obj = event.GetEventObject()
2846                Saxis = Obj.GetValue().split()
2847                try:
2848                    hkl = [int(Saxis[i]) for i in range(3)]
2849                except (ValueError,IndexError):
2850                    hkl = generalData['POhkl']
2851                if not np.any(np.array(hkl)):
2852                    hkl = generalData['POhkl']
2853                generalData['POhkl'] = hkl
2854                h,k,l = hkl
2855                Obj.SetValue('%3d %3d %3d'%(h,k,l)) 
2856                G2plt.PlotSizeStrainPO(G2frame,data)
2857           
2858            plotSizer = wx.BoxSizer(wx.VERTICAL)
2859            choice = ['None','Mustrain','Size','Preferred orientation']
2860            plotSel = wx.RadioBox(DData,-1,'Select plot type:',choices=choice,
2861                majorDimension=2,style=wx.RA_SPECIFY_COLS)
2862            plotSel.SetStringSelection(generalData['Data plot type'])
2863            plotSel.Bind(wx.EVT_RADIOBOX,OnPlotSel)   
2864            plotSizer.Add(plotSel)
2865            if generalData['Data plot type'] == 'Preferred orientation':
2866                POhklSizer = wx.BoxSizer(wx.HORIZONTAL)
2867                POhklSizer.Add(wx.StaticText(DData,-1,' Plot preferred orientation for H K L: '),0,wx.ALIGN_CENTER_VERTICAL)
2868                h,k,l = generalData['POhkl']
2869                poAxis = wx.TextCtrl(DData,-1,'%3d %3d %3d'%(h,k,l),style=wx.TE_PROCESS_ENTER)
2870                poAxis.Bind(wx.EVT_TEXT_ENTER,OnPOhkl)
2871                poAxis.Bind(wx.EVT_KILL_FOCUS,OnPOhkl)
2872                POhklSizer.Add(poAxis,0,wx.ALIGN_CENTER_VERTICAL)
2873                plotSizer.Add(POhklSizer)           
2874            return plotSizer
2875           
2876        def ScaleSizer():
2877           
2878            def OnScaleRef(event):
2879                Obj = event.GetEventObject()
2880                UseList[Indx[Obj.GetId()]]['Scale'][1] = Obj.GetValue()
2881               
2882            def OnScaleVal(event):
2883                Obj = event.GetEventObject()
2884                try:
2885                    scale = float(Obj.GetValue())
2886                    if scale > 0:
2887                        UseList[Indx[Obj.GetId()]]['Scale'][0] = scale
2888                except ValueError:
2889                    pass
2890                Obj.SetValue("%.4f"%(UseList[Indx[Obj.GetId()]]['Scale'][0]))          #reset in case of error
2891                           
2892            scaleSizer = wx.BoxSizer(wx.HORIZONTAL)
2893            if 'PWDR' in item:
2894                scaleRef = wx.CheckBox(DData,-1,label=' Phase fraction: ')
2895            elif 'HKLF' in item:
2896                scaleRef = wx.CheckBox(DData,-1,label=' Scale factor: ')               
2897            scaleRef.SetValue(UseList[item]['Scale'][1])
2898            Indx[scaleRef.GetId()] = item
2899            scaleRef.Bind(wx.EVT_CHECKBOX, OnScaleRef)
2900            scaleSizer.Add(scaleRef,0,wx.ALIGN_CENTER_VERTICAL)
2901            scaleVal = wx.TextCtrl(DData,wx.ID_ANY,
2902                '%.4f'%(UseList[item]['Scale'][0]),style=wx.TE_PROCESS_ENTER)
2903            Indx[scaleVal.GetId()] = item
2904            scaleVal.Bind(wx.EVT_TEXT_ENTER,OnScaleVal)
2905            scaleVal.Bind(wx.EVT_KILL_FOCUS,OnScaleVal)
2906            scaleSizer.Add(scaleVal,0,wx.ALIGN_CENTER_VERTICAL)
2907            return scaleSizer
2908           
2909        def OnUseData(event):
2910            Obj = event.GetEventObject()
2911            hist = Indx[Obj.GetId()]
2912            UseList[hist]['Use'] = Obj.GetValue()
2913           
2914        def OnShowData(event):
2915            Obj = event.GetEventObject()
2916            hist = Indx[Obj.GetId()]
2917            UseList[hist]['Show'] = Obj.GetValue()
2918            wx.CallAfter(UpdateDData)
2919            G2plt.PlotSizeStrainPO(G2frame,data)
2920           
2921        def OnCopyData(event):
2922            #how about HKLF data? This is only for PWDR data
2923            Obj = event.GetEventObject()
2924            hist = Indx[Obj.GetId()]
2925            sourceDict = UseList[hist]
2926            copyNames = ['Scale','Pref.Ori.','Size','Mustrain','HStrain','Extinction']
2927            copyDict = {}
2928            for name in copyNames: 
2929                copyDict[name] = copy.deepcopy(sourceDict[name])        #force copy
2930            keyList = ['All',]+UseList.keys()
2931            if UseList:
2932                copyList = []
2933                dlg = wx.MultiChoiceDialog(G2frame, 
2934                    'Copy parameters to which histograms?', 'Copy parameters', 
2935                    keyList, wx.CHOICEDLG_STYLE)
2936                try:
2937                    if dlg.ShowModal() == wx.ID_OK:
2938                        result = dlg.GetSelections()
2939                        for i in result: 
2940                            copyList.append(keyList[i])
2941                        if 'All' in copyList: 
2942                            copyList = keyList[1:]
2943                        for item in copyList:
2944                            UseList[item].update(copy.deepcopy(copyDict))
2945                        wx.CallAfter(UpdateDData)
2946                finally:
2947                    dlg.Destroy()
2948                   
2949        def OnCopyFlags(event):
2950            Obj = event.GetEventObject()
2951            hist = Indx[Obj.GetId()]
2952            sourceDict = UseList[hist]
2953            copyDict = {}
2954            copyNames = ['Scale','Pref.Ori.','Size','Mustrain','HStrain','Extinction']
2955            for name in copyNames:
2956                if name in ['Scale','Extinction','HStrain']:
2957                    copyDict[name] = sourceDict[name][1]
2958                elif name in ['Size','Mustrain']:
2959                    copyDict[name] = [sourceDict[name][0],sourceDict[name][2],sourceDict[name][4]]
2960                elif name == 'Pref.Ori.':
2961                    copyDict[name] = [sourceDict[name][0],sourceDict[name][2]]
2962                    if sourceDict[name][0] == 'SH':
2963                        SHterms = sourceDict[name][5]
2964                        SHflags = {}
2965                        for item in SHterms:
2966                            SHflags[item] = SHterms[item][1]
2967                        copyDict[name].append(SHflags)                       
2968            keyList = ['All',]+UseList.keys()
2969            if UseList:
2970                copyList = []
2971                dlg = wx.MultiChoiceDialog(G2frame, 
2972                    'Copy parameters to which histograms?', 'Copy parameters', 
2973                    keyList, wx.CHOICEDLG_STYLE)
2974                try:
2975                    if dlg.ShowModal() == wx.ID_OK:
2976                        result = dlg.GetSelections()
2977                        for i in result: 
2978                            copyList.append(keyList[i])
2979                        if 'All' in copyList: 
2980                            copyList = keyList[1:]
2981                        for item in copyList:
2982                            UseList[item]                           
2983                            for name in copyNames:
2984                                if name in ['Scale','Extinction','HStrain']:
2985                                    UseList[item][name][1] = copy.copy(copyDict[name])
2986                                elif name in ['Size','Mustrain']:
2987                                    UseList[item][name][0] = copy.copy(copyDict[name][0])
2988                                    UseList[item][name][2] = copy.copy(copyDict[name][1])
2989                                    UseList[item][name][4] = copy.copy(copyDict[name][2])
2990                                elif name == 'Pref.Ori.':
2991                                    UseList[item][name][0] = copy.copy(copyDict[name][0])
2992                                    UseList[item][name][2] = copy.copy(copyDict[name][1])
2993                                    if sourceDict[name][0] == 'SH':
2994                                        SHflags = copy.copy(copyDict[name][2])
2995                                        SHterms = copy.copy(sourceDict[name][5])
2996                                        for item in SHflags:
2997                                            SHterms[item][1] = copy.copy(SHflags[item])                                             
2998                        wx.CallAfter(UpdateDData)
2999                finally:
3000                    dlg.Destroy()
3001           
3002           
3003        def OnLGmixRef(event):
3004            Obj = event.GetEventObject()
3005            hist,name = Indx[Obj.GetId()]
3006            UseList[hist][name][2][2] = Obj.GetValue()
3007           
3008        def OnLGmixVal(event):
3009            Obj = event.GetEventObject()
3010            hist,name = Indx[Obj.GetId()]
3011            try:
3012                value = float(Obj.GetValue())
3013                if 0.1 <= value <= 1:
3014                    UseList[hist][name][1][2] = value
3015                else:
3016                    raise ValueError
3017            except ValueError:
3018                pass
3019            Obj.SetValue("%.4f"%(UseList[hist][name][1][2]))          #reset in case of error
3020
3021        def OnSizeType(event):
3022            Obj = event.GetEventObject()
3023            hist = Indx[Obj.GetId()]
3024            UseList[hist]['Size'][0] = Obj.GetValue()
3025            G2plt.PlotSizeStrainPO(G2frame,data)
3026            wx.CallAfter(UpdateDData)
3027           
3028        def OnSizeRef(event):
3029            Obj = event.GetEventObject()
3030            hist,pid = Indx[Obj.GetId()]
3031            if UseList[hist]['Size'][0] == 'ellipsoidal':
3032                UseList[hist]['Size'][5][pid] = Obj.GetValue()               
3033            else:
3034                UseList[hist]['Size'][2][pid] = Obj.GetValue()
3035           
3036        def OnSizeVal(event):
3037            Obj = event.GetEventObject()
3038            hist,pid = Indx[Obj.GetId()]
3039            if UseList[hist]['Size'][0] == 'ellipsoidal':
3040                try:
3041                    size = float(Obj.GetValue())
3042                    if pid < 3 and size <= 0.001:            #10A lower limit!
3043                        raise ValueError
3044                    UseList[hist]['Size'][4][pid] = size                   
3045                except ValueError:
3046                    pass
3047                Obj.SetValue("%.3f"%(UseList[hist]['Size'][4][pid]))          #reset in case of error
3048            else:
3049                try:
3050                    size = float(Obj.GetValue())
3051                    if size <= 0.001:            #10A lower limit!
3052                        raise ValueError
3053                    UseList[hist]['Size'][1][pid] = size
3054                except ValueError:
3055                    pass
3056                Obj.SetValue("%.3f"%(UseList[hist]['Size'][1][pid]))          #reset in case of error
3057            G2plt.PlotSizeStrainPO(G2frame,data)
3058           
3059        def OnSizeAxis(event):           
3060            Obj = event.GetEventObject()
3061            hist = Indx[Obj.GetId()]
3062            Saxis = Obj.GetValue().split()
3063            try:
3064                hkl = [int(Saxis[i]) for i in range(3)]
3065            except (ValueError,IndexError):
3066                hkl = UseList[hist]['Size'][3]
3067            if not np.any(np.array(hkl)):
3068                hkl = UseList[hist]['Size'][3]
3069            UseList[hist]['Size'][3] = hkl
3070            h,k,l = hkl
3071            Obj.SetValue('%3d %3d %3d'%(h,k,l)) 
3072                       
3073        def OnStrainType(event):
3074            Obj = event.GetEventObject()
3075            hist = Indx[Obj.GetId()]
3076            UseList[hist]['Mustrain'][0] = Obj.GetValue()
3077            wx.CallAfter(UpdateDData)
3078            G2plt.PlotSizeStrainPO(G2frame,data)
3079           
3080        def OnStrainRef(event):
3081            Obj = event.GetEventObject()
3082            hist,pid = Indx[Obj.GetId()]
3083            if UseList[hist]['Mustrain'][0] == 'generalized':
3084                UseList[hist]['Mustrain'][5][pid] = Obj.GetValue()
3085            else:
3086                UseList[hist]['Mustrain'][2][pid] = Obj.GetValue()
3087           
3088        def OnStrainVal(event):
3089            Snames = G2spc.MustrainNames(SGData)
3090            Obj = event.GetEventObject()
3091            hist,pid = Indx[Obj.GetId()]
3092            try:
3093                strain = float(Obj.GetValue())
3094                if UseList[hist]['Mustrain'][0] == 'generalized':
3095                    if '4' in Snames[pid] and strain < 0:
3096                        raise ValueError
3097                    UseList[hist]['Mustrain'][4][pid] = strain
3098                else:
3099                    if strain <= 0:
3100                        raise ValueError
3101                    UseList[hist]['Mustrain'][1][pid] = strain
3102            except ValueError:
3103                pass
3104            if UseList[hist]['Mustrain'][0] == 'generalized':
3105                Obj.SetValue("%.3f"%(UseList[hist]['Mustrain'][4][pid]))          #reset in case of error
3106            else:
3107                Obj.SetValue("%.1f"%(UseList[hist]['Mustrain'][1][pid]))          #reset in case of error
3108            G2plt.PlotSizeStrainPO(G2frame,data)
3109           
3110        def OnStrainAxis(event):
3111            Obj = event.GetEventObject()
3112            hist = Indx[Obj.GetId()]
3113            Saxis = Obj.GetValue().split()
3114            try:
3115                hkl = [int(Saxis[i]) for i in range(3)]
3116            except (ValueError,IndexError):
3117                hkl = UseList[hist]['Mustrain'][3]
3118            if not np.any(np.array(hkl)):
3119                hkl = UseList[hist]['Mustrain'][3]
3120            UseList[hist]['Mustrain'][3] = hkl
3121            h,k,l = hkl
3122            Obj.SetValue('%3d %3d %3d'%(h,k,l)) 
3123            G2plt.PlotSizeStrainPO(G2frame,data)
3124           
3125        def OnHstrainRef(event):
3126            Obj = event.GetEventObject()
3127            hist,pid = Indx[Obj.GetId()]
3128            UseList[hist]['HStrain'][1][pid] = Obj.GetValue()
3129           
3130        def OnHstrainVal(event):
3131            Snames = G2spc.HStrainNames(SGData)
3132            Obj = event.GetEventObject()
3133            hist,pid = Indx[Obj.GetId()]
3134            try:
3135                strain = float(Obj.GetValue())
3136                UseList[hist]['HStrain'][0][pid] = strain
3137            except ValueError:
3138                pass
3139            Obj.SetValue("%.5f"%(UseList[hist]['HStrain'][0][pid]))          #reset in case of error
3140
3141        def OnPOVal(event):
3142            Obj = event.GetEventObject()
3143            hist = Indx[Obj.GetId()]
3144            try:
3145                mdVal = float(Obj.GetValue())
3146                if mdVal > 0:
3147                    UseList[hist]['Pref.Ori.'][1] = mdVal
3148            except ValueError:
3149                pass
3150            Obj.SetValue("%.3f"%(UseList[hist]['Pref.Ori.'][1]))          #reset in case of error
3151           
3152        def OnPOAxis(event):
3153            Obj = event.GetEventObject()
3154            hist = Indx[Obj.GetId()]
3155            Saxis = Obj.GetValue().split()
3156            try:
3157                hkl = [int(Saxis[i]) for i in range(3)]
3158            except (ValueError,IndexError):
3159                hkl = UseList[hist]['Pref.Ori.'][3]
3160            if not np.any(np.array(hkl)):
3161                hkl = UseList[hist]['Pref.Ori.'][3]
3162            UseList[hist]['Pref.Ori.'][3] = hkl
3163            h,k,l = hkl
3164            Obj.SetValue('%3d %3d %3d'%(h,k,l)) 
3165           
3166        def OnPOOrder(event):
3167            Obj = event.GetEventObject()
3168            hist = Indx[Obj.GetId()]
3169            Order = int(Obj.GetValue())
3170            UseList[hist]['Pref.Ori.'][4] = Order
3171            UseList[hist]['Pref.Ori.'][5] = SetPOCoef(Order,hist)
3172            wx.CallAfter(UpdateDData)
3173
3174        def OnPOType(event):
3175            Obj = event.GetEventObject()
3176            hist = Indx[Obj.GetId()]
3177            if 'March' in Obj.GetValue():
3178                UseList[hist]['Pref.Ori.'][0] = 'MD'
3179            else:
3180                UseList[hist]['Pref.Ori.'][0] = 'SH'
3181            wx.CallAfter(UpdateDData)           
3182   
3183        def OnPORef(event):
3184            Obj = event.GetEventObject()
3185            hist = Indx[Obj.GetId()]
3186            UseList[hist]['Pref.Ori.'][2] = Obj.GetValue()
3187               
3188        def SetPOCoef(Order,hist):
3189            cofNames = G2lat.GenSHCoeff(SGData['SGLaue'],'0',Order,False)     #cylindrical & no M
3190            newPOCoef = dict(zip(cofNames,np.zeros(len(cofNames))))
3191            POCoeff = UseList[hist]['Pref.Ori.'][5]
3192            for cofName in POCoeff:
3193                if cofName in  cofNames:
3194                    newPOCoef[cofName] = POCoeff[cofName]
3195            return newPOCoef
3196       
3197        def OnExtRef(event):
3198            Obj = event.GetEventObject()
3199            UseList[Indx[Obj.GetId()]]['Extinction'][1] = Obj.GetValue()
3200           
3201        def OnExtVal(event):
3202            Obj = event.GetEventObject()
3203            try:
3204                ext = float(Obj.GetValue())
3205                if ext >= 0:
3206                    UseList[Indx[Obj.GetId()]]['Extinction'][0] = ext
3207            except ValueError:
3208                pass
3209            Obj.SetValue("%.2f"%(UseList[Indx[Obj.GetId()]]['Extinction'][0]))
3210           
3211        def OnTbarVal(event):
3212            Obj = event.GetEventObject()
3213            try:
3214                tbar = float(Obj.GetValue())
3215                if tbar >= 0:
3216                    UseList[Indx[Obj.GetId()]]['Extinction'][2]['Tbar'] = tbar
3217            except ValueError:
3218                pass
3219            Obj.SetValue("%.2f"%(UseList[Indx[Obj.GetId()]]['Extinction'][2]['Tbar']))
3220           
3221        def OnEval(event):
3222            Obj = event.GetEventObject()
3223            item = Indx[Obj.GetId()]
3224            try:
3225                val = float(Obj.GetValue())
3226                if val >= 0:
3227                    UseList[item[0]]['Extinction'][2][item[1]][0] = val
3228            except ValueError:
3229                pass
3230            Obj.SetValue("%9.3g"%(UseList[item[0]]['Extinction'][2][item[1]][0]))
3231           
3232        def OnEref(event):
3233            Obj = event.GetEventObject()
3234            item = Indx[Obj.GetId()]
3235            UseList[item[0]]['Extinction'][2][item[1]][1] = Obj.GetValue()
3236
3237        def OnSCExtType(event):
3238            Obj = event.GetEventObject()
3239            item = Indx[Obj.GetId()]
3240            UseList[item[0]]['Extinction'][item[1]] = Obj.GetValue()
3241            wx.CallAfter(UpdateDData)
3242               
3243        def checkAxis(axis):
3244            if not np.any(np.array(axis)):
3245                return False
3246            return axis
3247           
3248        def TopSizer(name,choices,parm,OnType):
3249            topSizer = wx.BoxSizer(wx.HORIZONTAL)
3250            topSizer.Add(wx.StaticText(DData,-1,name),0,wx.ALIGN_CENTER_VERTICAL)
3251            sizeType = wx.ComboBox(DData,wx.ID_ANY,value=UseList[item][parm][0],choices=choices,
3252                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3253            sizeType.Bind(wx.EVT_COMBOBOX, OnType)
3254            Indx[sizeType.GetId()] = item
3255            topSizer.Add(sizeType)
3256            topSizer.Add((5,0),0)
3257            return topSizer
3258           
3259        def LGmixSizer(name,OnVal,OnRef):
3260            lgmixSizer = wx.BoxSizer(wx.HORIZONTAL)
3261            lgmixRef = wx.CheckBox(DData,-1,label='LGmix')
3262            lgmixRef.thisown = False
3263            lgmixRef.SetValue(UseList[item][name][2][2])
3264            Indx[lgmixRef.GetId()] = [item,name]
3265            lgmixRef.Bind(wx.EVT_CHECKBOX, OnRef)
3266            lgmixSizer.Add(lgmixRef,0,wx.ALIGN_CENTER_VERTICAL)
3267            lgmixVal = wx.TextCtrl(DData,wx.ID_ANY,
3268                '%.4f'%(UseList[item][name][1][2]),style=wx.TE_PROCESS_ENTER)
3269            Indx[lgmixVal.GetId()] = [item,name]
3270            lgmixVal.Bind(wx.EVT_TEXT_ENTER,OnVal)
3271            lgmixVal.Bind(wx.EVT_KILL_FOCUS,OnVal)
3272            lgmixSizer.Add(lgmixVal,0,wx.ALIGN_CENTER_VERTICAL)
3273            return lgmixSizer
3274                       
3275        def IsoSizer(name,parm,fmt,OnVal,OnRef):
3276            isoSizer = wx.BoxSizer(wx.HORIZONTAL)
3277            sizeRef = wx.CheckBox(DData,-1,label=name)
3278            sizeRef.thisown = False
3279            sizeRef.SetValue(UseList[item][parm][2][0])
3280            Indx[sizeRef.GetId()] = [item,0]
3281            sizeRef.Bind(wx.EVT_CHECKBOX, OnRef)
3282            isoSizer.Add(sizeRef,0,wx.ALIGN_CENTER_VERTICAL)
3283            sizeVal = wx.TextCtrl(DData,wx.ID_ANY,
3284                fmt%(UseList[item][parm][1][0]),style=wx.TE_PROCESS_ENTER)
3285            Indx[sizeVal.GetId()] = [item,0]
3286            sizeVal.Bind(wx.EVT_TEXT_ENTER,OnVal)
3287            sizeVal.Bind(wx.EVT_KILL_FOCUS,OnVal)
3288            isoSizer.Add(sizeVal,0,wx.ALIGN_CENTER_VERTICAL)
3289            return isoSizer
3290           
3291        def UniSizer(parm,OnAxis):
3292            uniSizer = wx.BoxSizer(wx.HORIZONTAL)
3293            uniSizer.Add(wx.StaticText(DData,-1,' Unique axis, H K L: '),0,wx.ALIGN_CENTER_VERTICAL)
3294            h,k,l = UseList[item][parm][3]
3295            Axis = wx.TextCtrl(DData,-1,'%3d %3d %3d'%(h,k,l),style=wx.TE_PROCESS_ENTER)
3296            Indx[Axis.GetId()] = item
3297            Axis.Bind(wx.EVT_TEXT_ENTER,OnAxis)
3298            Axis.Bind(wx.EVT_KILL_FOCUS,OnAxis)
3299            uniSizer.Add(Axis,0,wx.ALIGN_CENTER_VERTICAL)
3300            return uniSizer
3301           
3302        def UniDataSizer(parmName,parm,fmt,OnVal,OnRef):
3303            dataSizer = wx.BoxSizer(wx.HORIZONTAL)
3304            parms = zip([' Equatorial '+parmName,' Axial '+parmName],
3305                UseList[item][parm][1],UseList[item][parm][2],range(2))
3306            for Pa,val,ref,id in parms:
3307                sizeRef = wx.CheckBox(DData,-1,label=Pa)
3308                sizeRef.thisown = False
3309                sizeRef.SetValue(ref)
3310                Indx[sizeRef.GetId()] = [item,id]
3311                sizeRef.Bind(wx.EVT_CHECKBOX, OnRef)
3312                dataSizer.Add(sizeRef,0,wx.ALIGN_CENTER_VERTICAL)
3313                sizeVal = wx.TextCtrl(DData,wx.ID_ANY,fmt%(val),style=wx.TE_PROCESS_ENTER)
3314                Indx[sizeVal.GetId()] = [item,id]
3315                sizeVal.Bind(wx.EVT_TEXT_ENTER,OnVal)
3316                sizeVal.Bind(wx.EVT_KILL_FOCUS,OnVal)
3317                dataSizer.Add(sizeVal,0,wx.ALIGN_CENTER_VERTICAL)
3318                dataSizer.Add((5,0),0)
3319            return dataSizer
3320           
3321        def EllSizeDataSizer():
3322            parms = zip(['S11','S22','S33','S12','S13','S23'],UseList[item]['Size'][4],
3323                UseList[item]['Size'][5],range(6))
3324            dataSizer = wx.FlexGridSizer(1,6,5,5)
3325            for Pa,val,ref,id in parms:
3326                sizeRef = wx.CheckBox(DData,-1,label=Pa)
3327                sizeRef.thisown = False
3328                sizeRef.SetValue(ref)
3329                Indx[sizeRef.GetId()] = [item,id]
3330                sizeRef.Bind(wx.EVT_CHECKBOX, OnSizeRef)
3331                dataSizer.Add(sizeRef,0,wx.ALIGN_CENTER_VERTICAL)
3332                sizeVal = wx.TextCtrl(DData,wx.ID_ANY,'%.3f'%(val),style=wx.TE_PROCESS_ENTER)
3333                Indx[sizeVal.GetId()] = [item,id]
3334                sizeVal.Bind(wx.EVT_TEXT_ENTER,OnSizeVal)
3335                sizeVal.Bind(wx.EVT_KILL_FOCUS,OnSizeVal)
3336                dataSizer.Add(sizeVal,0,wx.ALIGN_CENTER_VERTICAL)
3337            return dataSizer
3338           
3339        def GenStrainDataSizer():
3340            Snames = G2spc.MustrainNames(SGData)
3341            numb = len(Snames)
3342            if len(UseList[item]['Mustrain'][4]) < numb:
3343                UseList[item]['Mustrain'][4] = numb*[0.0,]
3344                UseList[item]['Mustrain'][5] = numb*[False,]
3345            parms = zip(Snames,UseList[item]['Mustrain'][4],UseList[item]['Mustrain'][5],range(numb))
3346            dataSizer = wx.FlexGridSizer(1,6,5,5)
3347            for Pa,val,ref,id in parms:
3348                strainRef = wx.CheckBox(DData,-1,label=Pa)
3349                strainRef.thisown = False
3350                strainRef.SetValue(ref)
3351                Indx[strainRef.GetId()] = [item,id]
3352                strainRef.Bind(wx.EVT_CHECKBOX, OnStrainRef)
3353                dataSizer.Add(strainRef,0,wx.ALIGN_CENTER_VERTICAL)
3354                strainVal = wx.TextCtrl(DData,wx.ID_ANY,'%.5f'%(val),style=wx.TE_PROCESS_ENTER)
3355                Indx[strainVal.GetId()] = [item,id]
3356                strainVal.Bind(wx.EVT_TEXT_ENTER,OnStrainVal)
3357                strainVal.Bind(wx.EVT_KILL_FOCUS,OnStrainVal)
3358                dataSizer.Add(strainVal,0,wx.ALIGN_CENTER_VERTICAL)
3359            return dataSizer
3360           
3361        def HstrainSizer():
3362            hstrainSizer = wx.FlexGridSizer(1,6,5,5)
3363            Hsnames = G2spc.HStrainNames(SGData)
3364            parms = zip(Hsnames,UseList[item]['HStrain'][0],UseList[item]['HStrain'][1],range(len(Hsnames)))
3365            for Pa,val,ref,id in parms:
3366                hstrainRef = wx.CheckBox(DData,-1,label=Pa)
3367                hstrainRef.thisown = False
3368                hstrainRef.SetValue(ref)
3369                Indx[hstrainRef.GetId()] = [item,id]
3370                hstrainRef.Bind(wx.EVT_CHECKBOX, OnHstrainRef)
3371                hstrainSizer.Add(hstrainRef,0,wx.ALIGN_CENTER_VERTICAL)
3372                hstrainVal = wx.TextCtrl(DData,wx.ID_ANY,'%.5f'%(val),style=wx.TE_PROCESS_ENTER)
3373                Indx[hstrainVal.GetId()] = [item,id]
3374                hstrainVal.Bind(wx.EVT_TEXT_ENTER,OnHstrainVal)
3375                hstrainVal.Bind(wx.EVT_KILL_FOCUS,OnHstrainVal)
3376                hstrainSizer.Add(hstrainVal,0,wx.ALIGN_CENTER_VERTICAL)
3377            return hstrainSizer
3378           
3379        def PoTopSizer(POData):
3380            poSizer = wx.FlexGridSizer(1,6,5,5)
3381            choice = ['March-Dollase','Spherical harmonics']
3382            POtype = choice[['MD','SH'].index(POData[0])]
3383            poSizer.Add(wx.StaticText(DData,-1,' Preferred orientation model '),0,wx.ALIGN_CENTER_VERTICAL)
3384            POType = wx.ComboBox(DData,wx.ID_ANY,value=POtype,choices=choice,
3385                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3386            Indx[POType.GetId()] = item
3387            POType.Bind(wx.EVT_COMBOBOX, OnPOType)
3388            poSizer.Add(POType)
3389            if POData[0] == 'SH':
3390                poSizer.Add(wx.StaticText(DData,-1,' Harmonic order: '),0,wx.ALIGN_CENTER_VERTICAL)
3391                poOrder = wx.ComboBox(DData,wx.ID_ANY,value=str(POData[4]),choices=[str(2*i) for i in range(18)],
3392                    style=wx.CB_READONLY|wx.CB_DROPDOWN)
3393                Indx[poOrder.GetId()] = item
3394                poOrder.Bind(wx.EVT_COMBOBOX,OnPOOrder)
3395                poSizer.Add(poOrder,0,wx.ALIGN_CENTER_VERTICAL)
3396                poRef = wx.CheckBox(DData,-1,label=' Refine? ')
3397                poRef.SetValue(POData[2])
3398                Indx[poRef.GetId()] = item
3399                poRef.Bind(wx.EVT_CHECKBOX,OnPORef)
3400                poSizer.Add(poRef,0,wx.ALIGN_CENTER_VERTICAL)
3401            return poSizer
3402           
3403        def MDDataSizer(POData):
3404            poSizer = wx.BoxSizer(wx.HORIZONTAL)
3405            poRef = wx.CheckBox(DData,-1,label=' March-Dollase ratio: ')
3406            poRef.SetValue(POData[2])
3407            Indx[poRef.GetId()] = item
3408            poRef.Bind(wx.EVT_CHECKBOX,OnPORef)
3409            poSizer.Add(poRef,0,wx.ALIGN_CENTER_VERTICAL)
3410            poVal = wx.TextCtrl(DData,wx.ID_ANY,
3411                '%.3f'%(POData[1]),style=wx.TE_PROCESS_ENTER)
3412            Indx[poVal.GetId()] = item
3413            poVal.Bind(wx.EVT_TEXT_ENTER,OnPOVal)
3414            poVal.Bind(wx.EVT_KILL_FOCUS,OnPOVal)
3415            poSizer.Add(poVal,0,wx.ALIGN_CENTER_VERTICAL)
3416            poSizer.Add(wx.StaticText(DData,-1,' Unique axis, H K L: '),0,wx.ALIGN_CENTER_VERTICAL)
3417            h,k,l =POData[3]
3418            poAxis = wx.TextCtrl(DData,-1,'%3d %3d %3d'%(h,k,l),style=wx.TE_PROCESS_ENTER)
3419            Indx[poAxis.GetId()] = item
3420            poAxis.Bind(wx.EVT_TEXT_ENTER,OnPOAxis)
3421            poAxis.Bind(wx.EVT_KILL_FOCUS,OnPOAxis)
3422            poSizer.Add(poAxis,0,wx.ALIGN_CENTER_VERTICAL)
3423            return poSizer
3424           
3425        def SHDataSizer(POData):
3426            textJ = G2lat.textureIndex(POData[5])
3427            mainSizer.Add(wx.StaticText(DData,-1,' Spherical harmonic coefficients: '+'Texture index: %.3f'%(textJ)),0,wx.ALIGN_CENTER_VERTICAL)
3428            mainSizer.Add((0,5),0)
3429            ODFSizer = wx.FlexGridSizer(2,8,2,2)
3430            ODFIndx = {}
3431            ODFkeys = POData[5].keys()
3432            ODFkeys.sort()
3433            for odf in ODFkeys:
3434                ODFSizer.Add(wx.StaticText(DData,-1,odf),0,wx.ALIGN_CENTER_VERTICAL)
3435                ODFval = wx.TextCtrl(DData,wx.ID_ANY,'%8.3f'%(POData[5][odf]),style=wx.TE_PROCESS_ENTER)
3436                ODFIndx[ODFval.GetId()] = odf
3437#                ODFval.Bind(wx.EVT_TEXT_ENTER,OnODFValue)
3438#                ODFval.Bind(wx.EVT_KILL_FOCUS,OnODFValue)
3439                ODFSizer.Add(ODFval,0,wx.ALIGN_CENTER_VERTICAL)
3440            return ODFSizer
3441           
3442        def ExtSizer():           
3443            extSizer = wx.BoxSizer(wx.HORIZONTAL)
3444            extRef = wx.CheckBox(DData,-1,label=' Extinction: ')
3445            extRef.SetValue(UseList[item]['Extinction'][1])
3446            Indx[extRef.GetId()] = item
3447            extRef.Bind(wx.EVT_CHECKBOX, OnExtRef)
3448            extSizer.Add(extRef,0,wx.ALIGN_CENTER_VERTICAL)
3449            extVal = wx.TextCtrl(DData,wx.ID_ANY,
3450                '%.2f'%(UseList[item]['Extinction'][0]),style=wx.TE_PROCESS_ENTER)
3451            Indx[extVal.GetId()] = item
3452            extVal.Bind(wx.EVT_TEXT_ENTER,OnExtVal)
3453            extVal.Bind(wx.EVT_KILL_FOCUS,OnExtVal)
3454            extSizer.Add(extVal,0,wx.ALIGN_CENTER_VERTICAL)
3455            return extSizer
3456       
3457        def SCExtSizer():
3458            extSizer = wx.BoxSizer(wx.VERTICAL)
3459            typeSizer = wx.BoxSizer(wx.HORIZONTAL)           
3460            typeSizer.Add(wx.StaticText(DData,-1,' Extinction type: '),0,wx.ALIGN_CENTER_VERTICAL)
3461            Choices = ['Primary','Secondary Type I','Secondary Type II','Secondary Type I & II']
3462            typeTxt = wx.ComboBox(DData,-1,choices=Choices,value=UseList[item]['Extinction'][1],
3463                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3464            Indx[typeTxt.GetId()] = [item,1]
3465            typeTxt.Bind(wx.EVT_COMBOBOX,OnSCExtType)
3466            typeSizer.Add(typeTxt)
3467            typeSizer.Add(wx.StaticText(DData,-1,' Approx: '),0,wx.ALIGN_CENTER_VERTICAL)
3468            Choices=['Lorentzian','Gaussian']
3469            approxTxT = wx.ComboBox(DData,-1,choices=Choices,value=UseList[item]['Extinction'][0],
3470                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3471            Indx[approxTxT.GetId()] = [item,0]
3472            approxTxT.Bind(wx.EVT_COMBOBOX,OnSCExtType)
3473            typeSizer.Add(approxTxT)
3474            extSizer.Add(typeSizer,0,wx.ALIGN_CENTER_VERTICAL)
3475            extSizer.Add((0,5),)
3476            valSizer =wx.BoxSizer(wx.HORIZONTAL)
3477            valSizer.Add(wx.StaticText(DData,-1,' Tbar(mm):'),0,wx.ALIGN_CENTER_VERTICAL)
3478            tbarVal = wx.TextCtrl(DData,wx.ID_ANY,
3479                '%.3f'%(UseList[item]['Extinction'][2]['Tbar']),style=wx.TE_PROCESS_ENTER)
3480            Indx[tbarVal.GetId()] = item
3481            tbarVal.Bind(wx.EVT_TEXT_ENTER,OnTbarVal)
3482            tbarVal.Bind(wx.EVT_KILL_FOCUS,OnTbarVal)
3483            valSizer.Add(tbarVal,0,wx.ALIGN_CENTER_VERTICAL)
3484            if 'Primary' in UseList[item]['Extinction'][1]:
3485                Ekey = ['Ep',]
3486            elif 'Secondary Type II' == UseList[item]['Extinction'][1]:
3487                Ekey = ['Es',]
3488            elif 'Secondary Type I' == UseList[item]['Extinction'][1]:
3489                Ekey = ['Eg',]
3490            else:
3491                Ekey = ['Eg','Es']
3492            for ekey in Ekey:
3493                Eref = wx.CheckBox(DData,-1,label=ekey+' : ')
3494                Eref.SetValue(UseList[item]['Extinction'][2][ekey][1])
3495                Indx[Eref.GetId()] = [item,ekey]
3496                Eref.Bind(wx.EVT_CHECKBOX, OnEref)
3497                valSizer.Add(Eref,0,wx.ALIGN_CENTER_VERTICAL)
3498                Eval = wx.TextCtrl(DData,wx.ID_ANY,
3499                    '%9.3g'%(UseList[item]['Extinction'][2][ekey][0]),style=wx.TE_PROCESS_ENTER)
3500                Indx[Eval.GetId()] = [item,ekey]
3501                Eval.Bind(wx.EVT_TEXT_ENTER,OnEval)
3502                Eval.Bind(wx.EVT_KILL_FOCUS,OnEval)
3503                valSizer.Add(Eval,0,wx.ALIGN_CENTER_VERTICAL)
3504
3505            extSizer.Add(valSizer,0,wx.ALIGN_CENTER_VERTICAL)
3506            return extSizer
3507           
3508        if DData.GetSizer():
3509            DData.GetSizer().Clear(True)
3510        mainSizer = wx.BoxSizer(wx.VERTICAL)
3511        mainSizer.Add(wx.StaticText(DData,-1,'Histogram data for '+PhaseName+':'),0,wx.ALIGN_CENTER_VERTICAL)
3512        if PWDR:
3513            mainSizer.Add(PlotSizer())           
3514           
3515        for item in keyList:
3516            histData = UseList[item]
3517            if 'Use' not in UseList[item]:      #patch
3518                UseList[item]['Use'] = True
3519            showSizer = wx.BoxSizer(wx.HORIZONTAL)
3520            showData = wx.CheckBox(DData,-1,label=' Show '+item)
3521            showData.SetValue(UseList[item]['Show'])
3522            Indx[showData.GetId()] = item
3523            showData.Bind(wx.EVT_CHECKBOX, OnShowData)
3524            showSizer.Add(showData,0,wx.ALIGN_CENTER_VERTICAL)
3525            useData = wx.CheckBox(DData,-1,label='Use?')
3526            Indx[useData.GetId()] = item
3527            showSizer.Add(useData,0,wx.ALIGN_CENTER_VERTICAL)
3528            useData.Bind(wx.EVT_CHECKBOX, OnUseData)
3529            useData.SetValue(UseList[item]['Use'])
3530            copyData = wx.Button(DData,-1,label=' Copy?')
3531            Indx[copyData.GetId()] = item
3532            copyData.Bind(wx.EVT_BUTTON,OnCopyData)
3533            showSizer.Add(copyData,wx.ALIGN_CENTER_VERTICAL)
3534            copyFlags = wx.Button(DData,-1,label=' Copy flags?')
3535            Indx[copyFlags.GetId()] = item
3536            copyFlags.Bind(wx.EVT_BUTTON,OnCopyFlags)
3537            showSizer.Add(copyFlags,wx.ALIGN_CENTER_VERTICAL)
3538            mainSizer.Add((5,5),0)
3539            mainSizer.Add(showSizer,0,wx.ALIGN_CENTER_VERTICAL)
3540            mainSizer.Add((0,5),0)
3541           
3542            if UseList[item]['Show']:
3543                mainSizer.Add(ScaleSizer())
3544                mainSizer.Add((0,5),0)
3545               
3546            if item[:4] == 'PWDR' and UseList[item]['Show']:
3547                if UseList[item]['Size'][0] == 'isotropic':
3548                    isoSizer = wx.BoxSizer(wx.HORIZONTAL)
3549                    isoSizer.Add(TopSizer(' Size model: ',['isotropic','uniaxial','ellipsoidal'],
3550                        'Size',OnSizeType),0,wx.ALIGN_CENTER_VERTICAL)
3551                    isoSizer.Add(LGmixSizer('Size',OnLGmixVal,OnLGmixRef))
3552                    mainSizer.Add(isoSizer)
3553                    mainSizer.Add(IsoSizer(u' Cryst. size(\xb5m): ','Size','%.3f',
3554                        OnSizeVal,OnSizeRef),0,wx.ALIGN_CENTER_VERTICAL)
3555                elif UseList[item]['Size'][0] == 'uniaxial':
3556                    uniSizer = wx.BoxSizer(wx.HORIZONTAL)
3557                    uniSizer.Add(TopSizer(' Size model: ',['isotropic','uniaxial','ellipsoidal'],
3558                        'Size',OnSizeType),0,wx.ALIGN_CENTER_VERTICAL)
3559                    uniSizer.Add(LGmixSizer('Size',OnLGmixVal,OnLGmixRef))
3560                    uniSizer.Add(UniSizer('Size',OnSizeAxis),0,wx.ALIGN_CENTER_VERTICAL)
3561                    mainSizer.Add(uniSizer)
3562                    mainSizer.Add(UniDataSizer(u'size(\xb5m): ','Size','%.3f',OnSizeVal,OnSizeRef))
3563                elif UseList[item]['Size'][0] == 'ellipsoidal':
3564                    ellSizer = wx.BoxSizer(wx.HORIZONTAL)
3565                    ellSizer.Add(TopSizer(' Size model: ',['isotropic','uniaxial','ellipsoidal'],
3566                        'Size',OnSizeType),0,wx.ALIGN_CENTER_VERTICAL)
3567                    ellSizer.Add(LGmixSizer('Size',OnLGmixVal,OnLGmixRef))
3568                    mainSizer.Add(ellSizer)
3569                    mainSizer.Add(EllSizeDataSizer())
3570                mainSizer.Add((0,5),0)                   
3571               
3572                if UseList[item]['Mustrain'][0] == 'isotropic':
3573                    isoSizer = wx.BoxSizer(wx.HORIZONTAL)
3574                    isoSizer.Add(TopSizer(' Mustrain model: ',['isotropic','uniaxial','generalized',],
3575                        'Mustrain',OnStrainType),0,wx.ALIGN_CENTER_VERTICAL)
3576                    isoSizer.Add(LGmixSizer('Mustrain',OnLGmixVal,OnLGmixRef))
3577                    mainSizer.Add(isoSizer)
3578                    mainSizer.Add(IsoSizer(' microstrain: ','Mustrain','%.1f',
3579                        OnStrainVal,OnStrainRef),0,wx.ALIGN_CENTER_VERTICAL)                   
3580                    mainSizer.Add((0,5),0)
3581                elif UseList[item]['Mustrain'][0] == 'uniaxial':
3582                    uniSizer = wx.BoxSizer(wx.HORIZONTAL)
3583                    uniSizer.Add(TopSizer(' Mustrain model: ',['isotropic','uniaxial','generalized',],
3584                        'Mustrain',OnStrainType),0,wx.ALIGN_CENTER_VERTICAL)
3585                    uniSizer.Add(LGmixSizer('Mustrain',OnLGmixVal,OnLGmixRef))
3586                    uniSizer.Add(UniSizer('Mustrain',OnStrainAxis),0,wx.ALIGN_CENTER_VERTICAL)
3587                    mainSizer.Add(uniSizer)
3588                    mainSizer.Add(UniDataSizer('mustrain: ','Mustrain','%.1f',OnStrainVal,OnStrainRef))
3589                elif UseList[item]['Mustrain'][0] == 'generalized':
3590                    genSizer = wx.BoxSizer(wx.HORIZONTAL)
3591                    genSizer.Add(TopSizer(' Mustrain model: ',['isotropic','uniaxial','generalized',],
3592                        'Mustrain',OnStrainType),0,wx.ALIGN_CENTER_VERTICAL)
3593                    genSizer.Add(LGmixSizer('Mustrain',OnLGmixVal,OnLGmixRef))
3594                    mainSizer.Add(genSizer)
3595                    mainSizer.Add(GenStrainDataSizer())                       
3596                mainSizer.Add((0,5),0)
3597               
3598                mainSizer.Add(wx.StaticText(DData,-1,' Hydrostatic/elastic strain:'))
3599                mainSizer.Add(HstrainSizer())
3600                   
3601                #texture  'Pref. Ori.':['MD',1.0,False,[0,0,1],0,[]] last two for 'SH' are SHorder & coeff
3602                poSizer = wx.BoxSizer(wx.VERTICAL)
3603                POData = UseList[item]['Pref.Ori.']
3604                poSizer.Add(PoTopSizer(POData))
3605                if POData[0] == 'MD':
3606                    poSizer.Add(MDDataSizer(POData))
3607                else:           #'SH'
3608                    if POData[4]:       #SH order > 0
3609                        poSizer.Add(SHDataSizer(POData))
3610                       
3611                mainSizer.Add(poSizer)
3612                mainSizer.Add((0,5),0)               
3613                #Extinction  'Extinction':[0.0,False]
3614                mainSizer.Add(ExtSizer())
3615                mainSizer.Add((0,5),0)
3616            elif item[:4] == 'HKLF' and UseList[item]['Show']:
3617                mainSizer.Add((0,5),0)               
3618                mainSizer.Add(SCExtSizer())
3619                mainSizer.Add((0,5),0)
3620                pass
3621        mainSizer.Add((5,5),0)
3622
3623        DData.SetSizer(mainSizer,True)
3624        mainSizer.FitInside(G2frame.dataFrame)
3625        Size = mainSizer.GetMinSize()
3626        Size[0] += 40
3627        Size[1] = max(Size[1],290) + 35
3628        DData.SetSize(Size)
3629        DData.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
3630        Size[1] = min(Size[1],450)
3631        G2frame.dataFrame.setSizePosLeft(Size)
3632       
3633    def OnHklfAdd(event):
3634        UseList = data['Histograms']
3635        keyList = UseList.keys()
3636        TextList = []
3637        if G2frame.PatternTree.GetCount():
3638            item, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
3639            while item:
3640                name = G2frame.PatternTree.GetItemText(item)
3641                if name not in keyList and 'HKLF' in name:
3642                    TextList.append(name)
3643                item, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)                       
3644            dlg = wx.MultiChoiceDialog(G2frame, 'Which new data to use?', 'Use data', TextList, wx.CHOICEDLG_STYLE)
3645            try:
3646                if dlg.ShowModal() == wx.ID_OK:
3647                    result = dlg.GetSelections()
3648                    for i in result:
3649                        histoName = TextList[i]
3650                        UseList[histoName] = {'Histogram':histoName,'Show':False,'Scale':[1.0,True],
3651                            'Extinction':['Lorentzian','Secondary Type I',
3652                            {'Tbar':0.0,'Eg':[0.0,False],'Es':[0.0,False],'Ep':[0.0,False]},]}                       
3653                    data['Histograms'] = UseList
3654                    wx.BeginBusyCursor()
3655                    UpdateHKLFdata(histoName)
3656                    wx.EndBusyCursor()
3657                    wx.CallAfter(UpdateDData)
3658            finally:
3659                dlg.Destroy()
3660               
3661    def UpdateHKLFdata(histoName):
3662        generalData = data['General']
3663        Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,histoName)
3664        reflData = G2frame.PatternTree.GetItemPyData(Id)[1]
3665        SGData = generalData['SGData']
3666        Cell = generalData['Cell'][1:7]
3667        G,g = G2lat.cell2Gmat(Cell)
3668        for ref in reflData:
3669            H = ref[:3]
3670            ref[4] = np.sqrt(1./G2lat.calc_rDsq2(H,G))
3671            iabsnt,ref[3],ref[11],ref[12] = G2spc.GenHKLf(H,SGData)
3672        G2frame.PatternTree.SetItemPyData(Id,[histoName,reflData])
3673       
3674    def OnPwdrAdd(event):
3675        generalData = data['General']
3676        SGData = generalData['SGData']
3677        UseList = data['Histograms']
3678        newList = []
3679        NShkl = len(G2spc.MustrainNames(SGData))
3680        NDij = len(G2spc.HStrainNames(SGData))
3681        keyList = UseList.keys()
3682        TextList = ['All PWDR']
3683        if G2frame.PatternTree.GetCount():
3684            item, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
3685            while item:
3686                name = G2frame.PatternTree.GetItemText(item)
3687                if name not in keyList and 'PWDR' in name:
3688                    TextList.append(name)
3689                item, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
3690            dlg = wx.MultiChoiceDialog(G2frame, 'Which new data to use?', 'Use data', TextList, wx.CHOICEDLG_STYLE)
3691            try:
3692                if dlg.ShowModal() == wx.ID_OK:
3693                    result = dlg.GetSelections()
3694                    for i in result: newList.append(TextList[i])
3695                    if 'All PWDR' in newList:
3696                        newList = TextList[1:]
3697                    for histoName in newList:
3698                        pId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,histoName)
3699                        UseList[histoName] = {'Histogram':histoName,'Show':False,
3700                            'Scale':[1.0,False],'Pref.Ori.':['MD',1.0,False,[0,0,1],0,{}],
3701                            'Size':['isotropic',[4.,4.,1.0],[False,False,False],[0,0,1],
3702                                [4.,4.,4.,0.,0.,0.],6*[False,]],
3703                            'Mustrain':['isotropic',[1000.0,1000.0,1.0],[False,False,False],[0,0,1],
3704                                NShkl*[0.01,],NShkl*[False,]],
3705                            'HStrain':[NDij*[0.0,],NDij*[False,]],                         
3706                            'Extinction':[0.0,False]}
3707                        refList = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,pId,'Reflection Lists'))
3708                        refList[generalData['Name']] = []                       
3709                    data['Histograms'] = UseList
3710                    wx.CallAfter(UpdateDData)
3711            finally:
3712                dlg.Destroy()
3713       
3714    def OnDataDelete(event):
3715        UseList = data['Histograms']
3716        keyList = ['All',]+UseList.keys()
3717        keyList.sort()
3718        DelList = []
3719        if UseList:
3720            DelList = []
3721            dlg = wx.MultiChoiceDialog(G2frame, 
3722                'Which histogram to delete from this phase?', 'Delete histogram', 
3723                keyList, wx.CHOICEDLG_STYLE)
3724            try:
3725                if dlg.ShowModal() == wx.ID_OK:
3726                    result = dlg.GetSelections()
3727                    for i in result: 
3728                        DelList.append(keyList[i])
3729                    if 'All' in DelList:
3730                        DelList = keyList[1:]
3731                    for i in DelList:
3732                        del UseList[i]
3733                    wx.CallAfter(UpdateDData)
3734            finally:
3735                dlg.Destroy()
3736
3737################################################################################
3738##### Pawley routines
3739################################################################################
3740
3741    def FillPawleyReflectionsGrid():
3742        G2frame.dataFrame.SetStatusText('')
3743                       
3744        def KeyEditPawleyGrid(event):
3745            colList = G2frame.PawleyRefl.GetSelectedCols()
3746            PawleyPeaks = data['Pawley ref']
3747            if event.GetKeyCode() == wx.WXK_RETURN:
3748                event.Skip(True)
3749            elif event.GetKeyCode() == wx.WXK_CONTROL:
3750                event.Skip(True)
3751            elif event.GetKeyCode() == wx.WXK_SHIFT:
3752                event.Skip(True)
3753            elif colList:
3754                G2frame.PawleyRefl.ClearSelection()
3755                key = event.GetKeyCode()
3756                for col in colList:
3757                    if PawleyTable.GetTypeName(0,col) == wg.GRID_VALUE_BOOL:
3758                        if key == 89: #'Y'
3759                            for row in range(PawleyTable.GetNumberRows()): PawleyPeaks[row][col]=True
3760                        elif key == 78:  #'N'
3761                            for row in range(PawleyTable.GetNumberRows()): PawleyPeaks[row][col]=False
3762                        FillPawleyReflectionsGrid()
3763           
3764        if 'Pawley ref' in data:
3765            PawleyPeaks = data['Pawley ref']                       
3766            rowLabels = []
3767            for i in range(len(PawleyPeaks)): rowLabels.append(str(i))
3768            colLabels = ['h','k','l','mul','d','refine','Fsq(hkl)','sig(Fsq)']
3769            Types = 4*[wg.GRID_VALUE_LONG,]+[wg.GRID_VALUE_FLOAT+':10,4',wg.GRID_VALUE_BOOL,]+ \
3770                2*[wg.GRID_VALUE_FLOAT+':10,2',]
3771            PawleyTable = G2gd.Table(PawleyPeaks,rowLabels=rowLabels,colLabels=colLabels,types=Types)
3772            G2frame.PawleyRefl.SetTable(PawleyTable, True)
3773            G2frame.PawleyRefl.Bind(wx.EVT_KEY_DOWN, KeyEditPawleyGrid)                 
3774            for r in range(G2frame.PawleyRefl.GetNumberRows()):
3775                for c in range(G2frame.PawleyRefl.GetNumberCols()):
3776                    if c in [5,6]:
3777                        G2frame.PawleyRefl.SetReadOnly(r,c,isReadOnly=False)
3778                    else:
3779                        G2frame.PawleyRefl.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
3780            G2frame.PawleyRefl.SetMargins(0,0)
3781            G2frame.PawleyRefl.AutoSizeColumns(False)
3782            G2frame.dataFrame.setSizePosLeft([500,300])
3783                   
3784    def OnPawleyLoad(event):
3785        generalData = data['General']
3786        dmin = generalData['Pawley dmin']
3787        cell = generalData['Cell'][1:7]
3788        A = G2lat.cell2A(cell)
3789        SGData = generalData['SGData']
3790        HKLd = np.array(G2lat.GenHLaue(dmin,SGData,A))
3791        PawleyPeaks = []
3792        wx.BeginBusyCursor()
3793        try:
3794            for h,k,l,d in HKLd:
3795                ext,mul = G2spc.GenHKLf([h,k,l],SGData)[:2]
3796                if not ext:
3797                    mul *= 2        #for powder multiplicity
3798                    PawleyPeaks.append([h,k,l,mul,d,False,100.0,1.0])
3799        finally:
3800            wx.EndBusyCursor()
3801        data['Pawley ref'] = PawleyPeaks
3802        FillPawleyReflectionsGrid()
3803       
3804    def OnPawleyEstimate(event):
3805        try:
3806            Refs = data['Pawley ref']
3807            Histograms = data['Histograms']
3808        except KeyError:
3809            print '**** Error - no histograms defined for this phase ****'
3810            return
3811        HistoNames = Histograms.keys()
3812        PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,HistoNames[0])
3813        xdata = G2frame.PatternTree.GetItemPyData(PatternId)[1]
3814        Inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Instrument Parameters'))
3815        Inst = dict(zip(Inst[3],Inst[1]))
3816        Sample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Sample Parameters'))
3817        if 'Lam' in Inst:
3818            wave = Inst['Lam']
3819        else:
3820            wave = Inst['Lam1']
3821        posCorr = Inst['Zero']
3822        const = 9.e-2/(np.pi*Sample['Gonio. radius'])                  #shifts in microns
3823       
3824        for ref in Refs:
3825            pos = 2.0*asind(wave/(2.0*ref[4]))
3826            if 'Bragg' in Sample['Type']:
3827                pos -= const*(4.*Sample['Shift'][0]*cosd(pos/2.0)+ \
3828                    Sample['Transparency'][0]*sind(pos)*100.0)            #trans(=1/mueff) in cm
3829            else:               #Debye-Scherrer - simple but maybe not right
3830                pos -= const*(Sample['DisplaceX'][0]*cosd(pos)+Sample['DisplaceY'][0]*sind(pos))
3831            indx = np.searchsorted(xdata[0],pos)
3832            try:
3833                FWHM = max(0.001,G2pwd.getFWHM(pos,Inst))/2.
3834                dx = xdata[0][indx+1]-xdata[0][indx]
3835                ref[6] = FWHM*xdata[1][indx]/dx
3836                Lorenz = 1./(2.*sind(xdata[0][indx]/2.)**2*cosd(xdata[0][indx]/2.))           #Lorentz correction
3837                pola,dIdPola = G2pwd.Polarization(Inst['Polariz.'],xdata[0][indx],Inst['Azimuth'])
3838                ref[6] /= (Lorenz*pola*ref[3])
3839            except IndexError:
3840                pass
3841        FillPawleyReflectionsGrid()
3842
3843    def OnPawleyUpdate(event):
3844        try:
3845            Refs = data['Pawley ref']
3846            Histograms = data['Histograms']
3847        except KeyError:
3848            print '**** Error - no histograms defined for this phase ****'
3849            return
3850        HistoNames = Histograms.keys()
3851        PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,HistoNames[0])
3852        refData = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Reflection Lists'))[PhaseName]
3853        for iref,ref in enumerate(Refs):
3854            try:
3855                ref[6] = abs(refData[iref][9])
3856                ref[7] = 1.0
3857            except IndexError:
3858                pass
3859        FillPawleyReflectionsGrid()
3860                           
3861    def OnPawleyDelete(event):
3862        dlg = wx.MessageDialog(G2frame,'Do you really want to delete Pawley reflections?','Delete', 
3863            wx.YES_NO | wx.ICON_QUESTION)
3864        try:
3865            result = dlg.ShowModal()
3866        finally:
3867            dlg.Destroy()
3868        if result == wx.ID_YES: 
3869            data['Pawley ref'] = []
3870            FillPawleyReflectionsGrid()
3871
3872################################################################################
3873##### Fourier routines
3874################################################################################
3875
3876    def FillMapPeaksGrid():
3877                       
3878        def RowSelect(event):
3879            r,c =  event.GetRow(),event.GetCol()
3880            if r < 0 and c < 0:
3881                if MapPeaks.IsSelection():
3882                    MapPeaks.ClearSelection()
3883                else:
3884                    for row in range(MapPeaks.GetNumberRows()):
3885                        MapPeaks.SelectRow(row,True)
3886                   
3887            elif c < 0:                   #only row clicks
3888                if event.ControlDown():                   
3889                    if r in MapPeaks.GetSelectedRows():
3890                        MapPeaks.DeselectRow(r)
3891                    else:
3892                        MapPeaks.SelectRow(r,True)
3893                elif event.ShiftDown():
3894                    for row in range(r+1):
3895                        MapPeaks.SelectRow(row,True)
3896                else:
3897                    MapPeaks.ClearSelection()
3898                    MapPeaks.SelectRow(r,True)
3899            elif r < 0:                 #a column pick
3900                mapPeaks = data['Map Peaks']
3901                c =  event.GetCol()
3902                if colLabels[c] == 'mag':
3903                    mapPeaks = G2mth.sortArray(mapPeaks,0,reverse=True)
3904                elif colLabels[c] == 'dzero':
3905                    mapPeaks = G2mth.sortArray(mapPeaks,4)
3906                else:
3907                    return
3908                data['Map Peaks'] = mapPeaks
3909                wx.CallAfter(FillMapPeaksGrid)
3910            G2plt.PlotStructure(G2frame,data)                   
3911           
3912        G2frame.dataFrame.setSizePosLeft([450,300])
3913        G2frame.dataFrame.SetStatusText('')
3914        if 'Map Peaks' in data:
3915            G2frame.dataFrame.SetStatusText('Select mag or dzero columns to sort')
3916            mapPeaks = data['Map Peaks']                       
3917            rowLabels = []
3918            for i in range(len(mapPeaks)): rowLabels.append(str(i))
3919            colLabels = ['mag','x','y','z','dzero']
3920            Types = 5*[wg.GRID_VALUE_FLOAT+':10,4',]
3921            MapPeaksTable = G2gd.Table(mapPeaks,rowLabels=rowLabels,colLabels=colLabels,types=Types)
3922            MapPeaks.SetTable(MapPeaksTable, True)
3923            MapPeaks.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK, RowSelect)
3924            for r in range(MapPeaks.GetNumberRows()):
3925                for c in range(MapPeaks.GetNumberCols()):
3926                    MapPeaks.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
3927            MapPeaks.SetMargins(0,0)
3928            MapPeaks.AutoSizeColumns(False)
3929                   
3930    def OnPeaksMove(event):
3931        if 'Map Peaks' in data:
3932            mapPeaks = data['Map Peaks']                       
3933            Ind = MapPeaks.GetSelectedRows()
3934            for ind in Ind:
3935                x,y,z,d = mapPeaks[ind][1:]
3936                AtomAdd(x,y,z,'C')
3937   
3938    def OnPeaksClear(event):
3939        data['Map Peaks'] = []
3940        FillMapPeaksGrid()
3941        G2plt.PlotStructure(G2frame,data)
3942       
3943    def OnPeaksDelete(event):
3944        if 'Map Peaks' in data:
3945            mapPeaks = data['Map Peaks']
3946            Ind = MapPeaks.GetSelectedRows()
3947            Ind.sort()
3948            Ind.reverse()
3949            for ind in Ind:
3950                mapPeaks = np.delete(mapPeaks,ind,0)
3951            data['Map Peaks'] = mapPeaks
3952        FillMapPeaksGrid()
3953        G2plt.PlotStructure(G2frame,data)
3954               
3955    def OnPeaksUnique(event):
3956        if 'Map Peaks' in data:
3957            mapPeaks = data['Map Peaks']
3958            Ind = MapPeaks.GetSelectedRows()
3959            if Ind:
3960                Ind = G2mth.PeaksUnique(data,Ind)
3961                for r in range(MapPeaks.GetNumberRows()):
3962                    if r in Ind:
3963                        MapPeaks.SelectRow(r,addToSelected=True)
3964                    else:
3965                        MapPeaks.DeselectRow(r)
3966                G2plt.PlotStructure(G2frame,data)
3967   
3968    def OnPeaksDA(event):
3969        #distance, angle
3970        indx = MapPeaks.GetSelectedRows()
3971        if len(indx) not in [2,3]:
3972            print '**** ERROR - wrong number of atoms for distance or angle calculation'
3973            return
3974        generalData = data['General']
3975        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])           
3976        mapPeaks = data['Map Peaks']
3977        xyz = []
3978        for i in indx:
3979            xyz.append(mapPeaks[i][1:4])
3980        if len(indx) == 2:
3981            print ' distance for atoms %s = %.3f'%(str(indx),G2mth.getRestDist(xyz,Amat))
3982        else:
3983            print ' angle for atoms %s = %.2f'%(str(indx),G2mth.getRestAngle(xyz,Amat))
3984                   
3985               
3986    def OnFourierMaps(event):
3987        generalData = data['General']
3988        mapData = generalData['Map']
3989        reflName = mapData['RefList']
3990        phaseName = generalData['Name']
3991        if 'PWDR' in reflName:
3992            PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, reflName)
3993            reflSets = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Reflection Lists'))
3994            reflData = reflSets[phaseName]
3995        elif 'HKLF' in reflName:
3996            PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, reflName)
3997            reflData = G2frame.PatternTree.GetItemPyData(PatternId)[1]
3998        mapData.update(G2mth.FourierMap(data,reflData))
3999        mapData['Flip'] = False
4000        mapSig = np.std(mapData['rho'])
4001        if not data['Drawing']:                 #if new drawing - no drawing data!
4002            SetupDrawingData()
4003        data['Drawing']['contourLevel'] = 1.
4004        data['Drawing']['mapSize'] = 10.
4005        print mapData['MapType']+' computed: rhomax = %.3f rhomin = %.3f sigma = %.3f'%(np.max(mapData['rho']),np.min(mapData['rho']),mapSig)
4006        UpdateDrawAtoms()
4007        G2plt.PlotStructure(G2frame,data)
4008       
4009    def OnFourClear(event):
4010        generalData = data['General']
4011        generalData['Map'] = mapDefault
4012        G2plt.PlotStructure(G2frame,data)
4013       
4014    def printRho(SGLaue,rho,rhoMax):                         
4015# map printing for testing purposes
4016        dim = len(rho.shape)
4017        if dim == 2:
4018            ix,jy = rho.shape
4019            for j in range(jy):
4020                line = ''
4021                if SGLaue in ['3','3m1','31m','6/m','6/mmm']:
4022                    line += (jy-j)*'  '
4023                for i in range(ix):
4024                    r = int(100*rho[i,j]/rhoMax)
4025                    line += '%4d'%(r)
4026                print line+'\n'
4027        else:
4028            ix,jy,kz = rho.shape
4029            for k in range(kz):
4030                print 'k = ',k
4031                for j in range(jy):
4032                    line = ''
4033                    if SGLaue in ['3','3m1','31m','6/m','6/mmm']:
4034                        line += (jy-j)*'  '
4035                    for i in range(ix):
4036                        r = int(100*rho[i,j,k]/rhoMax)
4037                        line += '%4d'%(r)
4038                    print line+'\n'
4039## keep this               
4040   
4041    def OnSearchMaps(event):
4042       
4043#        def FindBondsPeaks(peaks):                    #uses numpy & masks - very fast even for proteins!
4044#            import numpy.ma as ma
4045#            Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])
4046#            for peak in peaks:
4047#                peak[-1] = []
4048#            Indx = range(len(peaks))
4049#            Peaks = []
4050#            Radii = []
4051#            for peak in peaks:
4052#                Peaks.append(np.array(peak[1:4]))
4053#                Radii.append(1.0)
4054#            Atoms = np.array(Atoms)
4055#            Radii = np.array(Radii)
4056#            IAR = zip(Indx,Atoms,Radii)
4057#            for atomA in IAR:
4058#                Dx = Atoms-atomA[1]
4059#                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
4060#                sumR = atomA[3]+Radii
4061#                IndB = ma.nonzero(ma.masked_greater(dist-data['Drawing']['radiusFactor']*sumR,0.))                 #get indices of bonded atoms
4062#                i = atomA[0]
4063#                for j in IndB[0]:
4064#                    if Styles[i] == 'polyhedra':
4065#                        atomData[i][-2].append(np.inner(Amat,Dx[j]))
4066#                    elif Styles[j] != 'polyhedra' and j > i:
4067#                        atomData[i][-2].append(Dx[j]*Radii[i]/sumR[j])
4068#                        atomData[j][-2].append(-Dx[j]*Radii[j]/sumR[j])
4069                           
4070        peaks = []
4071        mags = []
4072        print ' Begin fourier map search - can take some time'
4073        time0 = time.time()
4074        generalData = data['General']
4075        mapData = generalData['Map']
4076        if len(mapData['rho']):
4077            pgbar = wx.ProgressDialog('Map search','No. Peaks found =',501.0, 
4078                style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_CAN_ABORT)
4079            screenSize = wx.ClientDisplayRect()
4080            Size = pgbar.GetSize()
4081            Size = (int(Size[0]*1.2),Size[1]) # increase size a bit along x
4082            pgbar.SetPosition(wx.Point(screenSize[2]-Size[0]-305,screenSize[1]+5))
4083            pgbar.SetSize(Size)
4084            try:
4085                peaks,mags,dzeros = G2mth.SearchMap(data,keepDup=True,Pgbar=pgbar)
4086            finally:
4087                pgbar.Destroy()
4088            sortIdx = np.argsort(mags.flatten())
4089            if len(peaks):
4090                data['Map Peaks'] = np.concatenate((mags,peaks,dzeros),axis=1)           
4091                print ' Map search finished, time = %.2fs'%(time.time()-time0)
4092            Page = G2frame.dataDisplay.FindPage('Map peaks')
4093            G2frame.dataDisplay.ChangeSelection(Page)
4094            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.MapPeaksMenu)
4095            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksMove, id=G2gd.wxID_PEAKSMOVE)
4096            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksDA, id=G2gd.wxID_PEAKSDA)
4097            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksUnique, id=G2gd.wxID_PEAKSUNIQUE)
4098            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksDelete, id=G2gd.wxID_PEAKSDELETE)
4099            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksClear, id=G2gd.wxID_PEAKSCLEAR)
4100            UpdateDrawAtoms()
4101            FillMapPeaksGrid()
4102        else:
4103            print 'No map available'
4104       
4105    def OnChargeFlip(event):
4106        generalData = data['General']
4107        mapData = generalData['Map']
4108        flipData = generalData['Flip']
4109        reflName = flipData['RefList']
4110        phaseName = generalData['Name']
4111        if 'PWDR' in reflName:
4112            PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, reflName)
4113            reflSets = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Reflection Lists'))
4114            reflData = reflSets[phaseName]
4115        elif 'HKLF' in reflName:
4116            PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, reflName)
4117            reflData = G2frame.PatternTree.GetItemPyData(PatternId)[1]
4118        else:
4119            print '**** ERROR - No data defined for charge flipping'
4120            return
4121        pgbar = wx.ProgressDialog('Charge flipping','Residual Rcf =',101.0, 
4122            style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_CAN_ABORT)
4123        screenSize = wx.ClientDisplayRect()
4124        Size = pgbar.GetSize()
4125        Size = (int(Size[0]*1.2),Size[1]) # increase size a bit along x
4126        pgbar.SetPosition(wx.Point(screenSize[2]-Size[0]-305,screenSize[1]+5))
4127        pgbar.SetSize(Size)
4128        try:
4129            mapData.update(G2mth.ChargeFlip(data,reflData,pgbar))
4130        finally:
4131            pgbar.Destroy()
4132        mapData['Flip'] = True       
4133        mapSig = np.std(mapData['rho'])
4134        if not data['Drawing']:                 #if new drawing - no drawing data!
4135            SetupDrawingData()
4136        data['Drawing']['contourLevel'] = 1.
4137        data['Drawing']['mapSize'] = 10.
4138        print ' Charge flip map computed: rhomax = %.3f rhomin = %.3f sigma = %.3f'%(np.max(mapData['rho']),np.min(mapData['rho']),mapSig)
4139        if mapData['Rcf'] < 99.:
4140            OnSearchMaps(event)             #does a plot structure at end
4141        else:
4142            print 'Bad charge flip map - no peak search done'
4143               
4144    def OnTextureRefine(event):
4145        print 'refine texture?'
4146        event.Skip()       
4147           
4148    def OnTextureClear(event):
4149        print 'clear texture?'
4150        event.Skip()
4151
4152    def OnPageChanged(event):
4153        page = event.GetSelection()
4154        text = G2frame.dataDisplay.GetPageText(page)
4155        if text == 'Atoms':
4156            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.AtomsMenu)
4157            G2frame.dataFrame.Bind(wx.EVT_MENU, OnAtomAdd, id=G2gd.wxID_ATOMSEDITADD)
4158            G2frame.dataFrame.Bind(wx.EVT_MENU, OnAtomTestAdd, id=G2gd.wxID_ATOMSTESTADD)
4159            G2frame.dataFrame.Bind(wx.EVT_MENU, OnAtomInsert, id=G2gd.wxID_ATOMSEDITINSERT)
4160            G2frame.dataFrame.Bind(wx.EVT_MENU, OnAtomTestInsert, id=G2gd.wxID_ATONTESTINSERT)
4161            G2frame.dataFrame.Bind(wx.EVT_MENU, AtomDelete, id=G2gd.wxID_ATOMSEDITDELETE)
4162            G2frame.dataFrame.Bind(wx.EVT_MENU, AtomRefine, id=G2gd.wxID_ATOMSREFINE)
4163            G2frame.dataFrame.Bind(wx.EVT_MENU, AtomModify, id=G2gd.wxID_ATOMSMODIFY)
4164            G2frame.dataFrame.Bind(wx.EVT_MENU, AtomTransform, id=G2gd.wxID_ATOMSTRANSFORM)
4165            G2frame.dataFrame.Bind(wx.EVT_MENU, OnReloadDrawAtoms, id=G2gd.wxID_RELOADDRAWATOMS)
4166            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDistAngle, id=G2gd.wxID_ATOMSDISAGL)
4167            FillAtomsGrid()
4168        elif text == 'General':
4169            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.DataGeneral)
4170            G2frame.dataFrame.Bind(wx.EVT_MENU, OnFourierMaps, id=G2gd.wxID_FOURCALC)
4171            G2frame.dataFrame.Bind(wx.EVT_MENU, OnSearchMaps, id=G2gd.wxID_FOURSEARCH)
4172            G2frame.dataFrame.Bind(wx.EVT_MENU, OnChargeFlip, id=G2gd.wxID_CHARGEFLIP)
4173            G2frame.dataFrame.Bind(wx.EVT_MENU, OnFourClear, id=G2gd.wxID_FOURCLEAR)
4174            UpdateGeneral()
4175        elif text == 'Data':
4176            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.DataMenu)