source: trunk/GSASIIphsGUI.py @ 750

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

put inverse checker back in SearchMap?
add atom rename facility
update of Map peaks when map/peaks are shifted by U/D/L/R key commands

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