source: trunk/GSASIIpwdGUI.py @ 1592

Last change on this file since 1592 was 1592, checked in by vondreele, 8 years ago

finish modulation vector determination - use so.brute - slow but works
add peak indexing option to not scale M20 by 1+X20 - might be useful

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 210.1 KB
Line 
1# -*- coding: utf-8 -*-
2#GSASIIpwdGUI - powder data display routines
3########### SVN repository information ###################
4# $Date: 2014-12-02 20:16:00 +0000 (Tue, 02 Dec 2014) $
5# $Author: vondreele $
6# $Revision: 1592 $
7# $URL: trunk/GSASIIpwdGUI.py $
8# $Id: GSASIIpwdGUI.py 1592 2014-12-02 20:16:00Z vondreele $
9########### SVN repository information ###################
10'''
11*GSASIIpwdGUI: Powder Pattern GUI routines*
12-------------------------------------------
13
14Used to define GUI controls for the routines that interact
15with the powder histogram (PWDR) data tree items.
16
17'''
18import sys
19import os.path
20import wx
21import wx.grid as wg
22import wx.lib.scrolledpanel as wxscroll
23import numpy as np
24import numpy.ma as ma
25import math
26import time
27import copy
28import random as ran
29import cPickle
30import GSASIIpath
31GSASIIpath.SetVersionNumber("$Revision: 1592 $")
32import GSASIImath as G2mth
33import GSASIIpwd as G2pwd
34import GSASIIIO as G2IO
35import GSASIIlattice as G2lat
36import GSASIIspc as G2spc
37import GSASIIindex as G2indx
38import GSASIIplot as G2plt
39import GSASIIgrid as G2gd
40import GSASIIElemGUI as G2elemGUI
41import GSASIIElem as G2elem
42import GSASIIsasd as G2sasd
43import GSASIIexprGUI as G2exG
44VERY_LIGHT_GREY = wx.Colour(235,235,235)
45WACV = wx.ALIGN_CENTER_VERTICAL
46Pwr10 = unichr(0x0b9)+unichr(0x0b0)
47Pwr20 = unichr(0x0b2)+unichr(0x0b0)
48Pwrm1 = unichr(0x207b)+unichr(0x0b9)
49Pwrm2 = unichr(0x207b)+unichr(0x0b2)
50Pwrm4 = unichr(0x207b)+unichr(0x2074)   #really -d but looks like -4 as a superscript
51# trig functions in degrees
52sind = lambda x: math.sin(x*math.pi/180.)
53tand = lambda x: math.tan(x*math.pi/180.)
54cosd = lambda x: math.cos(x*math.pi/180.)
55asind = lambda x: 180.*math.asin(x)/math.pi
56   
57def IsHistogramInAnyPhase(G2frame,histoName):
58    'Needs a doc string'
59    phases = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Phases')
60    if phases:
61        item, cookie = G2frame.PatternTree.GetFirstChild(phases)
62        while item:
63            data = G2frame.PatternTree.GetItemPyData(item)
64            histoList = data['Histograms'].keys()
65            if histoName in histoList:
66                return G2frame.PatternTree.GetItemText(item)
67            item, cookie = G2frame.PatternTree.GetNextChild(phases, cookie)
68        return False
69    else:
70        return False
71
72def SetDefaultSample():
73    'Fills in default items for the Sample dictionary'
74    return {
75        'InstrName':'',
76        'ranId':ran.randint(0,sys.maxint),
77        'Scale':[1.0,True],'Type':'Debye-Scherrer','Absorption':[0.0,False],
78        'DisplaceX':[0.0,False],'DisplaceY':[0.0,False],'Diffuse':[],
79        'Temperature':300.,'Pressure':0.1,'Time':0.0,
80        'FreePrm1':0.,'FreePrm2':0.,'FreePrm3':0.,
81        'Gonio. radius':200.0,
82        'Omega':0.0,'Chi':0.0,'Phi':0.0,
83#SASD items
84        'Materials':[{'Name':'vacuum','VolFrac':1.0,},{'Name':'vacuum','VolFrac':0.0,}],
85        'Thick':1.0,'Contrast':[0.0,0.0],       #contrast & anomalous contrast
86        'Trans':1.0,                            #measured transmission
87        'SlitLen':0.0,                          #Slit length - in Q(A-1)
88        }
89def SetupSampleLabels(histName,dataType,histType):
90    '''Setup a list of labels and number formatting for use in
91    labeling sample parameters.
92    :param str histName: Name of histogram, ("PWDR ...")
93    :param str dataType:
94    '''
95    parms = []
96    parms.append(['Scale','Histogram scale factor: ',[10,4]])
97    if 'C' in histType:
98        parms.append(['Gonio. radius','Goniometer radius (mm): ',[10,3]])
99    if 'PWDR' in histName:
100        if dataType == 'Debye-Scherrer':
101            parms += [['DisplaceX',u'Sample X displ. perp. to beam (\xb5m): ',[10,3]],
102                ['DisplaceY',u'Sample Y displ. || to beam (\xb5m): ',[10,3]],
103                ['Absorption',u'Sample absorption (\xb5\xb7r): ',[10,4]],]
104            if 'T' in histType:
105                parms[-1] = ['Absorption',u'Sample absorption (\xb5\xb7r/l): ',[10,4]]
106        elif dataType == 'Bragg-Brentano':
107            parms += [['Shift',u'Sample displacement(\xb5m): ',[10,4]],
108                ['Transparency',u'Sample transparency(1/\xb5eff, cm): ',[10,3]],
109                ['SurfRoughA','Surface roughness A: ',[10,4]],
110                ['SurfRoughB','Surface roughness B: ',[10,4]]]
111    elif 'SASD' in histName:
112        parms.append(['Thick','Sample thickness (mm)',[10,3]])
113        parms.append(['Trans','Transmission (meas)',[10,3]])
114        parms.append(['SlitLen',u'Slit length (Q,\xc5'+Pwrm1+')',[10,3]])
115    parms.append(['Omega','Goniometer omega:',[10,3]])
116    parms.append(['Chi','Goniometer chi:',[10,3]])
117    parms.append(['Phi','Goniometer phi:',[10,3]])
118    parms.append(['Time','Clock time (s)',[12,3]])
119    parms.append(['Temperature','Sample temperature (K): ',[10,3]])
120    parms.append(['Pressure','Sample pressure (MPa): ',[10,3]])
121    return parms
122
123def SetDefaultSASDModel():
124    'Fills in default items for the SASD Models dictionary'   
125    return {'Back':[0.0,False],'Size':{'MinDiam':50,'MaxDiam':10000,'Nbins':100,'logBins':True,'Method':'MaxEnt','Distribution':[],
126        'Shape':['Spheroid',1.0],'MaxEnt':{'Niter':100,'Precision':0.01,'Sky':-3},
127        'IPG':{'Niter':100,'Approach':0.8,'Power':-1},'Reg':{},},           
128        'Particle':{'Matrix':{'Name':'vacuum','VolFrac':[0.0,False]},'Levels':[],},
129        'Current':'Size dist.','BackFile':'',
130        }
131       
132def SetDefaultSubstances():
133    'Fills in default items for the SASD Substances dictionary'
134    return {'Substances':{'vacuum':{'Elements':{},'Volume':1.0,'Density':0.0,'Scatt density':0.0}}}
135
136def GetHistsLikeSelected(G2frame):
137    '''Get the histograms that match the current selected one:
138    The histogram prefix and data type (PXC etc.), the number of
139    wavelengths and the instrument geometry (Debye-Scherrer etc.)
140    must all match. The current histogram is not included in the list.
141
142    :param wx.Frame G2frame: pointer to main GSAS-II data tree
143    '''
144    histList = []
145    inst,inst2 = G2frame.PatternTree.GetItemPyData(
146        G2gd.GetPatternTreeItemId(
147            G2frame,G2frame.PatternId, 'Instrument Parameters')
148        )
149    hType = inst['Type'][0]
150    if 'Lam1' in inst:
151        hLam = 2
152    elif 'Lam' in inst:
153        hLam = 1
154    else:
155        hLam = 0
156    sample = G2frame.PatternTree.GetItemPyData(
157        G2gd.GetPatternTreeItemId(
158            G2frame,G2frame.PatternId, 'Sample Parameters')
159        )
160    hGeom = sample.get('Type')
161    hstName = G2frame.PatternTree.GetItemText(G2frame.PatternId)
162    hPrefix = hstName.split()[0]+' '
163    # cycle through tree looking for items that match the above
164    item, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)       
165    while item:
166        name = G2frame.PatternTree.GetItemText(item)
167        if name.startswith(hPrefix) and name != hstName:
168            cGeom,cType,cLam, = '?','?',-1
169            subitem, subcookie = G2frame.PatternTree.GetFirstChild(item)
170            while subitem:
171                subname = G2frame.PatternTree.GetItemText(subitem)
172                if subname == 'Sample Parameters':
173                    sample = G2frame.PatternTree.GetItemPyData(subitem)
174                    cGeom = sample.get('Type')
175                elif subname == 'Instrument Parameters':
176                    inst,inst2 = G2frame.PatternTree.GetItemPyData(subitem)
177                    cType = inst['Type'][0]
178                    if 'Lam1' in inst:
179                        cLam = 2
180                    elif 'Lam' in inst:
181                        cLam = 1
182                    else:
183                        cLam = 0
184                subitem, subcookie = G2frame.PatternTree.GetNextChild(item, subcookie)
185            if cLam == hLam and cType == hType and cGeom == hGeom:
186                if name not in histList: histList.append(name)
187        item, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
188    return histList
189
190def SetCopyNames(histName,dataType,addNames=[]):
191    '''Determine the items in the sample parameters that should be copied,
192    depending on the histogram type and the instrument type.
193    '''
194    copyNames = ['Scale',]
195    histType = 'HKLF'
196    if 'PWDR' in histName:
197        histType = 'PWDR'
198        if 'Debye' in dataType:
199            copyNames += ['DisplaceX','DisplaceY','Absorption']
200        else:       #Bragg-Brentano
201            copyNames += ['Shift','Transparency','SurfRoughA','SurfRoughB']
202    elif 'SASD' in histName:
203        histType = 'SASD'
204        copyNames += ['Materials','Thick',]
205    if len(addNames):
206        copyNames += addNames
207    return histType,copyNames
208
209def CopySelectedHistItems(G2frame):
210    '''Global copy: Copy items from current histogram to others.
211    This is called from the menubar and is available only when the top histogram tree entry
212    is selected.
213    '''
214    hst = G2frame.PatternTree.GetItemText(G2frame.PatternId)
215    histList = GetHistsLikeSelected(G2frame)
216    if not histList:
217        G2frame.ErrorDialog('No match','No histograms match '+hst,G2frame.dataFrame)
218        return
219    choices = ['Limits','Background','Instrument Parameters','Sample Parameters']
220    dlg = G2gd.G2MultiChoiceDialog(
221        G2frame.dataFrame, 
222        'Copy which histogram sections from\n'+str(hst[5:]),
223        'Select copy sections', choices, filterBox=False)
224    dlg.SetSelections(range(len(choices)))
225    choiceList = []
226    if dlg.ShowModal() == wx.ID_OK:
227        choiceList = [choices[i] for i in dlg.GetSelections()]
228    if not choiceList: return
229   
230    dlg = G2gd.G2MultiChoiceDialog(
231        G2frame.dataFrame, 
232        'Copy parameters from\n'+str(hst[5:])+' to...',
233        'Copy parameters', histList)
234    results = []
235    try:
236        if dlg.ShowModal() == wx.ID_OK:
237            results = dlg.GetSelections()
238    finally:
239        dlg.Destroy()
240    copyList = []
241    for i in results: 
242        copyList.append(histList[i])
243
244    if 'Limits' in choiceList: # Limits
245        data = G2frame.PatternTree.GetItemPyData(
246            G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId,'Limits'))
247        for item in copyList:
248            Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,item)
249            G2frame.PatternTree.SetItemPyData(
250                G2gd.GetPatternTreeItemId(G2frame,Id,'Limits'),
251                copy.deepcopy(data))
252    if 'Background' in choiceList:  # Background
253        data = G2frame.PatternTree.GetItemPyData(
254            G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId,'Background'))
255        for item in copyList:
256            Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,item)
257            G2frame.PatternTree.SetItemPyData(
258                G2gd.GetPatternTreeItemId(G2frame,Id,'Background'),
259                copy.deepcopy(data))
260    if 'Instrument Parameters' in choiceList:  # Instrument Parameters
261        # for now all items in Inst. parms are copied
262        data,data1 = G2frame.PatternTree.GetItemPyData(
263            G2gd.GetPatternTreeItemId(
264                G2frame,G2frame.PatternId,'Instrument Parameters'))
265        for item in copyList:
266            Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,item)
267            G2frame.PatternTree.GetItemPyData(
268                G2gd.GetPatternTreeItemId(G2frame,Id,'Instrument Parameters')
269                )[0].update(copy.deepcopy(data))
270            G2frame.PatternTree.GetItemPyData(
271                G2gd.GetPatternTreeItemId(G2frame,Id,'Instrument Parameters')
272                )[1].update(copy.deepcopy(data1))
273    if 'Sample Parameters' in choiceList:  # Sample Parameters
274        data = G2frame.PatternTree.GetItemPyData(
275            G2gd.GetPatternTreeItemId(
276                G2frame,G2frame.PatternId,'Sample Parameters'))
277        # selects items to be copied
278        histType,copyNames = SetCopyNames(hst,data['Type'],
279            addNames = ['Omega','Chi','Phi','Gonio. radius','InstrName'])
280        copyDict = {parm:data[parm] for parm in copyNames}
281        for item in copyList:
282            Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,item)
283            G2frame.PatternTree.GetItemPyData(
284                G2gd.GetPatternTreeItemId(G2frame,Id,'Sample Parameters')
285                ).update(copy.deepcopy(copyDict))
286                         
287################################################################################
288#####  Powder Peaks
289################################################################################           
290       
291def UpdatePeakGrid(G2frame, data):
292    '''respond to selection of PWDR powder peaks data tree item.
293    '''
294    if G2frame.dataDisplay:
295        G2frame.dataFrame.Clear()
296       
297    def OnAutoSearch(event):
298        PatternId = G2frame.PatternId
299        PickId = G2frame.PickId
300        limits = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Limits'))[1]
301        inst,inst2 = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Instrument Parameters'))
302        profile = G2frame.PatternTree.GetItemPyData(PatternId)[1]
303        x0 = profile[0]
304        iBeg = np.searchsorted(x0,limits[0])
305        iFin = np.searchsorted(x0,limits[1])
306        x = x0[iBeg:iFin]
307        y0 = profile[1][iBeg:iFin]
308        y1 = copy.copy(y0)
309        ysig = np.std(y1)
310        offset = [-1,1]
311        ymask = ma.array(y0,mask=(y0<ysig))
312        for off in offset:
313            ymask = ma.array(ymask,mask=(ymask-np.roll(y0,off)<=0.))
314        indx = ymask.nonzero()
315        mags = ymask[indx]
316        poss = x[indx]
317        refs = zip(poss,mags)
318        if 'C' in Inst['Type'][0]:   
319            refs = G2mth.sortArray(refs,0,reverse=True)     #small 2-Thetas first
320        else:   #'T'OF
321            refs = G2mth.sortArray(refs,0,reverse=False)    #big TOFs first
322        for i,ref1 in enumerate(refs):
323            for ref2 in refs[i+1:]:
324                if abs(ref2[0]-ref1[0]) < 0.1*G2pwd.getFWHM(ref1[0],inst):
325                    del(refs[i])
326        if 'C' in Inst['Type'][0]:   
327            refs = G2mth.sortArray(refs,1,reverse=True)
328        else:   #'T'OF
329            refs = G2mth.sortArray(refs,1,reverse=False)
330        for pos,mag in refs:
331            data['peaks'].append(G2mth.setPeakparms(inst,inst2,pos,mag))
332        UpdatePeakGrid(G2frame,data)
333        G2plt.PlotPatterns(G2frame,plotType='PWDR')
334       
335    def OnCopyPeaks(event):
336        hst = G2frame.PatternTree.GetItemText(G2frame.PatternId)
337        histList = GetHistsLikeSelected(G2frame)
338        if not histList:
339            G2frame.ErrorDialog('No match','No histograms match '+hst,G2frame.dataFrame)
340            return
341        copyList = []
342        dlg = G2gd.G2MultiChoiceDialog(
343            G2frame.dataFrame, 
344            'Copy peak list from\n'+str(hst[5:])+' to...',
345            'Copy peaks', histList)
346        try:
347            if dlg.ShowModal() == wx.ID_OK:
348                for i in dlg.GetSelections():
349                    copyList.append(histList[i])
350        finally:
351            dlg.Destroy()
352        for item in copyList:
353            Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,item)
354            G2frame.PatternTree.SetItemPyData(
355                G2gd.GetPatternTreeItemId(G2frame,Id,'Peak List'),copy.deepcopy(data))
356   
357    def OnUnDo(event):
358        DoUnDo()
359        G2frame.dataFrame.UnDo.Enable(False)
360       
361    def DoUnDo():
362        print 'Undo last refinement'
363        file = open(G2frame.undofile,'rb')
364        PatternId = G2frame.PatternId
365        for item in ['Background','Instrument Parameters','Peak List']:
366            G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, item),cPickle.load(file))
367            if G2frame.dataDisplay.GetName() == item:
368                if item == 'Background':
369                    UpdateBackground(G2frame,G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, item)))
370                elif item == 'Instrument Parameters':
371                    UpdateInstrumentGrid(G2frame,G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, item)))
372                elif item == 'Peak List':
373                    UpdatePeakGrid(G2frame,G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, item)))
374            print item,' recovered'
375        file.close()
376       
377    def SaveState():
378        G2frame.undofile = os.path.join(G2frame.dirname,'GSASII.save')
379        file = open(G2frame.undofile,'wb')
380        PatternId = G2frame.PatternId
381        for item in ['Background','Instrument Parameters','Peak List']:
382            cPickle.dump(G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,item)),file,1)
383        file.close()
384        G2frame.dataFrame.UnDo.Enable(True)
385       
386    def OnLSQPeakFit(event):
387        if not G2frame.GSASprojectfile:            #force a save of the gpx file so SaveState can wirte in the same directory
388            G2frame.OnFileSaveas(event)
389        OnPeakFit('LSQ')
390       
391    def OnOneCycle(event):
392        OnPeakFit('LSQ',oneCycle=True)
393       
394    def OnSeqPeakFit(event):
395        hst = G2frame.PatternTree.GetItemText(G2frame.PatternId)
396        histList = GetHistsLikeSelected(G2frame)
397        if not histList:
398            G2frame.ErrorDialog('No match','No histograms match '+hst,G2frame.dataFrame)
399            return
400        sel = []
401        dlg = G2gd.G2MultiChoiceDialog(G2frame.dataFrame, 'Sequential peak fits',
402             'Select dataset to include',histList)
403        dlg.SetSelections(sel)
404        names = []
405        if dlg.ShowModal() == wx.ID_OK:
406            for sel in dlg.GetSelections():
407                names.append(histList[sel])
408        dlg.Destroy()
409        SeqResult = {}
410        Reverse = False
411        CopyForward = False
412        choice = ['Reverse sequence','Copy from prev.',]
413        dlg = wx.MultiChoiceDialog(G2frame.dataFrame,'Sequential controls','Select controls',choice)
414        if dlg.ShowModal() == wx.ID_OK:
415            for sel in dlg.GetSelections():
416                if sel:
417                    CopyForward = True
418                else:
419                    Reverse = True
420        dlg.Destroy()
421        dlg = wx.ProgressDialog('Sequential peak fit','Data set name = '+names[0],len(names), 
422            style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_REMAINING_TIME|wx.PD_CAN_ABORT)
423        Controls = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.root, 'Controls'))
424        controls = {'deriv type':'analytic','min dM/M':0.0001,}
425        Controls['ShowCell'] = False
426        print 'Peak Fitting with '+controls['deriv type']+' derivatives:'
427        oneCycle = False
428        FitPgm = 'LSQ'
429        prevVaryList = []
430        Names = []
431        if Reverse:
432            names.reverse()
433        try:
434            for i,name in enumerate(names):
435                print ' Sequential fit for ',name
436                GoOn = dlg.Update(i,newmsg='Data set name = '+name)[0]
437                if not GoOn:
438                    break
439                PatternId =  G2gd.GetPatternTreeItemId(G2frame,G2frame.root,name)
440                if i and CopyForward:
441                    G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Peak List'),copy.deepcopy(peaks))
442                    prevVaryList = varyList[:]
443                peaks = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Peak List'))
444                background = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Background'))
445                limits = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Limits'))[1]
446                inst,inst2 = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Instrument Parameters'))
447                data = G2frame.PatternTree.GetItemPyData(PatternId)[1]
448                wx.BeginBusyCursor()
449                dlg2 = wx.ProgressDialog('Residual','Peak fit Rwp = ',101.0, 
450                    style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_REMAINING_TIME|wx.PD_CAN_ABORT)
451                screenSize = wx.ClientDisplayRect()
452                Size = dlg.GetSize()
453                dlg2.SetPosition(wx.Point(screenSize[2]-Size[0]-305,screenSize[1]+5))
454                try:
455                    peaks['sigDict'],result,sig,Rvals,varyList,parmDict,fullvaryList,badVary = G2pwd.DoPeakFit(FitPgm,peaks['peaks'],
456                        background,limits,inst,inst2,data,prevVaryList,oneCycle,controls,dlg2)
457                finally:
458                    dlg2.Destroy()
459                if len(result[0]) != len(fullvaryList):
460                    print ' ***** Sequential peak fit stopped at '+name+' *****'
461                    break
462                else:
463                    Names.append(name)   
464                    G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Peak List'),copy.deepcopy(peaks))
465                    SeqResult[name] = {'variables':result[0],'varyList':varyList,'sig':sig,'Rvals':Rvals,
466                        'covMatrix':np.eye(len(result[0])),'title':name,'parmDict':parmDict,
467                        'fullVary':fullvaryList,'badVary':badVary}
468            dlg.Destroy()
469            print ' ***** Sequential peak fit successful *****'
470        finally:
471            wx.EndBusyCursor()
472        SeqResult['histNames'] = Names
473        Id =  G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Sequential results')
474        if Id:
475            G2frame.PatternTree.SetItemPyData(Id,SeqResult)
476        else:
477            Id = G2frame.PatternTree.AppendItem(parent=G2frame.root,text='Sequential results')
478            G2frame.PatternTree.SetItemPyData(Id,SeqResult)
479        G2frame.PatternTree.SelectItem(Id)
480       
481    def OnClearPeaks(event):
482        dlg = wx.MessageDialog(G2frame,'Delete all peaks?','Clear peak list',wx.OK|wx.CANCEL)
483        try:
484            if dlg.ShowModal() == wx.ID_OK:
485                peaks = {'peaks':[],'sigDict':{}}
486        finally:
487            dlg.Destroy()
488        UpdatePeakGrid(G2frame,peaks)
489        G2plt.PlotPatterns(G2frame,plotType='PWDR')
490       
491    def OnPeakFit(FitPgm,oneCycle=False):
492        SaveState()
493        controls = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.root, 'Controls'))
494        if not controls:
495            controls = {'deriv type':'analytic','min dM/M':0.0001,}     #fill in defaults if needed
496        print 'Peak Fitting with '+controls['deriv type']+' derivatives:'
497        PatternId = G2frame.PatternId
498        PickId = G2frame.PickId
499        peaks = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Peak List'))
500        if not peaks:
501            G2frame.ErrorDialog('No peaks!','Nothing to fit!')
502            return
503        background = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Background'))
504        limits = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Limits'))[1]
505        inst,inst2 = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Instrument Parameters'))
506        data = G2frame.PatternTree.GetItemPyData(PatternId)[1]
507        wx.BeginBusyCursor()
508        dlg = wx.ProgressDialog('Residual','Peak fit Rwp = ',101.0, 
509            style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_REMAINING_TIME|wx.PD_CAN_ABORT)
510        screenSize = wx.ClientDisplayRect()
511        Size = dlg.GetSize()
512        dlg.SetPosition(wx.Point(screenSize[2]-Size[0]-305,screenSize[1]+5))
513        try:
514            peaks['sigDict'] = G2pwd.DoPeakFit(FitPgm,peaks['peaks'],background,limits,inst,inst2,data,[],oneCycle,controls,dlg)[0]
515        finally:
516            wx.EndBusyCursor()   
517        G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Peak List'),copy.copy(peaks))
518        UpdatePeakGrid(G2frame,copy.copy(peaks))
519        G2plt.PlotPatterns(G2frame,plotType='PWDR')
520        print 'finished'
521        return
522       
523    def OnResetSigGam(event):
524        PatternId = G2frame.PatternId
525        PickId = G2frame.PickId
526        Inst,Inst2 = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Instrument Parameters'))
527        peaks = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Peak List'))
528        if not peaks['peaks']:
529            G2frame.ErrorDialog('No peaks!','Nothing to do!')
530            return
531        newpeaks = {'peaks':[],'sigDict':{}}
532        for peak in peaks['peaks']:
533            newpeaks['peaks'].append(G2mth.setPeakparms(Inst,Inst2,peak[0],peak[2]))
534        G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Peak List'),newpeaks)
535        UpdatePeakGrid(G2frame,newpeaks)
536               
537    def RefreshPeakGrid(event):
538        r,c =  event.GetRow(),event.GetCol()
539       
540        event.StopPropagation()
541        data['peaks'] = G2frame.PeakTable.GetData()
542        T = []
543        for peak in data['peaks']:T.append(peak[0])
544        D = dict(zip(T,data['peaks']))
545        T.sort()
546        X = []
547        for key in T: X.append(D[key])
548        data['peaks'] = X       
549       
550    def setBackgroundColors():
551       for r in range(G2frame.dataDisplay.GetNumberRows()):
552           for c in range(G2frame.dataDisplay.GetNumberCols()):
553               if G2frame.dataDisplay.GetColLabelValue(c) in ['position','intensity','alpha','beta','sigma','gamma']:
554                   if float(G2frame.dataDisplay.GetCellValue(r,c)) < 0.:
555                       G2frame.dataDisplay.SetCellBackgroundColour(r,c,wx.RED)
556                   else:
557                       G2frame.dataDisplay.SetCellBackgroundColour(r,c,wx.WHITE)
558                                                 
559    def KeyEditPeakGrid(event):
560        rowList = G2frame.dataDisplay.GetSelectedRows()
561        colList = G2frame.dataDisplay.GetSelectedCols()
562        selectList = G2frame.dataDisplay.GetSelectedCells()
563        data = G2frame.PatternTree.GetItemPyData(G2frame.PickId)
564        if event.GetKeyCode() == wx.WXK_RETURN:
565            event.Skip(True)
566        elif event.GetKeyCode() == wx.WXK_CONTROL:
567            event.Skip(True)
568        elif event.GetKeyCode() == wx.WXK_SHIFT:
569            event.Skip(True)
570        elif rowList:
571            G2frame.dataDisplay.ClearSelection()
572            if event.GetKeyCode() == wx.WXK_DELETE:
573                G2frame.dataDisplay.ClearGrid()
574                rowList.sort()
575                rowList.reverse()
576                nDel = 0
577                for row in rowList:
578                    G2frame.PeakTable.DeleteRow(row)
579                    nDel += 1
580                if nDel:
581                    msg = wg.GridTableMessage(G2frame.PeakTable, 
582                        wg.GRIDTABLE_NOTIFY_ROWS_DELETED,0,nDel)
583                    G2frame.dataDisplay.ProcessTableMessage(msg)
584                data = G2frame.PeakTable.GetData()
585                G2frame.PatternTree.SetItemPyData(G2frame.PickId,data[:-nDel])
586                G2frame.dataDisplay.ForceRefresh()
587                setBackgroundColors()
588                       
589        elif colList:
590            G2frame.dataDisplay.ClearSelection()
591            key = event.GetKeyCode()
592            for col in colList:
593                if G2frame.PeakTable.GetTypeName(0,col) == wg.GRID_VALUE_BOOL:
594                    if key == 89: #'Y'
595                        for row in range(G2frame.PeakTable.GetNumberRows()): data['peaks'][row][col]=True
596                    elif key == 78:  #'N'
597                        for row in range(G2frame.PeakTable.GetNumberRows()): data['peaks'][row][col]=False
598        elif selectList:
599            G2frame.dataDisplay.ClearSelection()
600            key = event.GetKeyCode()
601            for row,col in selectList:
602                if G2frame.PeakTable.GetTypeName(row,col) == wg.GRID_VALUE_BOOL:
603                    if key == 89: #'Y'
604                        data['peaks'][row][col]=True
605                    elif key == 78:  #'N'
606                        data['peaks'][row][col]=False
607        G2plt.PlotPatterns(G2frame,plotType='PWDR')
608           
609    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.PeakMenu)
610    if not G2frame.dataFrame.GetStatusBar():
611        Status = G2frame.dataFrame.CreateStatusBar()
612    Status.SetStatusText('Global refine: select refine column & press Y or N')
613    G2frame.Bind(wx.EVT_MENU, OnAutoSearch, id=G2gd.wxID_AUTOSEARCH)
614    G2frame.Bind(wx.EVT_MENU, OnCopyPeaks, id=G2gd.wxID_PEAKSCOPY)
615    G2frame.Bind(wx.EVT_MENU, OnUnDo, id=G2gd.wxID_UNDO)
616    G2frame.Bind(wx.EVT_MENU, OnLSQPeakFit, id=G2gd.wxID_LSQPEAKFIT)
617    G2frame.Bind(wx.EVT_MENU, OnOneCycle, id=G2gd.wxID_LSQONECYCLE)
618    G2frame.Bind(wx.EVT_MENU, OnSeqPeakFit, id=G2gd.wxID_SEQPEAKFIT)
619    G2frame.Bind(wx.EVT_MENU, OnClearPeaks, id=G2gd.wxID_CLEARPEAKS)
620    G2frame.Bind(wx.EVT_MENU, OnResetSigGam, id=G2gd.wxID_RESETSIGGAM)
621    if data['peaks']:
622        G2frame.dataFrame.AutoSearch.Enable(False)
623        G2frame.dataFrame.PeakCopy.Enable(True)
624        G2frame.dataFrame.PeakFit.Enable(True)
625        G2frame.dataFrame.PFOneCycle.Enable(True)
626        G2frame.dataFrame.SeqPeakFit.Enable(True)
627    else:
628        G2frame.dataFrame.PeakFit.Enable(False)
629        G2frame.dataFrame.PeakCopy.Enable(False)
630        G2frame.dataFrame.PFOneCycle.Enable(False)
631        G2frame.dataFrame.AutoSearch.Enable(True)
632        G2frame.dataFrame.SeqPeakFit.Enable(False)
633    G2frame.PickTable = []
634    rowLabels = []
635    PatternId = G2frame.PatternId
636    Inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Instrument Parameters'))[0]
637    for i in range(len(data['peaks'])): rowLabels.append(str(i+1))
638    if 'C' in Inst['Type'][0]:
639        colLabels = ['position','refine','intensity','refine','sigma','refine','gamma','refine']
640        Types = [wg.GRID_VALUE_FLOAT+':10,4',wg.GRID_VALUE_BOOL,
641            wg.GRID_VALUE_FLOAT+':10,1',wg.GRID_VALUE_BOOL,
642            wg.GRID_VALUE_FLOAT+':10,5',wg.GRID_VALUE_BOOL,
643            wg.GRID_VALUE_FLOAT+':10,5',wg.GRID_VALUE_BOOL]
644    else:
645        colLabels = ['position','refine','intensity','refine','alpha','refine',
646            'beta','refine','sigma','refine','gamma','refine']
647        Types = [wg.GRID_VALUE_FLOAT+':10,1',wg.GRID_VALUE_BOOL,
648            wg.GRID_VALUE_FLOAT+':10,4',wg.GRID_VALUE_BOOL,
649            wg.GRID_VALUE_FLOAT+':10,4',wg.GRID_VALUE_BOOL,
650            wg.GRID_VALUE_FLOAT+':10,5',wg.GRID_VALUE_BOOL,
651            wg.GRID_VALUE_FLOAT+':10,5',wg.GRID_VALUE_BOOL,
652            wg.GRID_VALUE_FLOAT+':10,5',wg.GRID_VALUE_BOOL]
653    T = []
654    for peak in data['peaks']:
655        T.append(peak[0])
656    D = dict(zip(T,data['peaks']))
657    T.sort()
658    if 'T' in Inst['Type'][0]:  #want big TOF's first
659        T.reverse()
660    X = []
661    for key in T: X.append(D[key])
662    data['peaks'] = X
663    G2frame.PatternTree.SetItemPyData(G2frame.PickId,data)
664    G2frame.PeakTable = G2gd.Table(data['peaks'],rowLabels=rowLabels,colLabels=colLabels,types=Types)
665    G2frame.dataFrame.SetLabel('Peak List')
666    G2frame.dataDisplay = G2gd.GSGrid(parent=G2frame.dataFrame)
667    G2frame.dataDisplay.SetTable(G2frame.PeakTable, True)
668    setBackgroundColors()                         
669    G2frame.dataDisplay.Bind(wg.EVT_GRID_CELL_CHANGE, RefreshPeakGrid)
670    G2frame.dataDisplay.Bind(wx.EVT_KEY_DOWN, KeyEditPeakGrid)
671    G2frame.dataDisplay.SetMargins(0,0)
672    G2frame.dataDisplay.AutoSizeColumns(False)
673    G2frame.dataFrame.setSizePosLeft([535,350])
674    G2frame.dataFrame.SendSizeEvent()
675       
676################################################################################
677#####  Background
678################################################################################           
679       
680def UpdateBackground(G2frame,data):
681    '''respond to selection of PWDR background data tree item.
682    '''
683    if len(data) < 2:       #add Debye diffuse & peaks scattering here
684        data.append({'nDebye':0,'debyeTerms':[],'nPeaks':0,'peaksList':[]})
685    if 'nPeaks' not in data[1]:
686        data[1].update({'nPeaks':0,'peaksList':[]})
687    ValObj = {}
688   
689    def OnBackFlagCopy(event):
690        flag = data[0][1]
691        backDict = data[-1]
692        if backDict['nDebye']:
693            DBflags = []
694            for term in backDict['debyeTerms']:
695                DBflags.append(term[1::2])
696        if backDict['nPeaks']:
697            PKflags = []
698            for term in backDict['peaksList']:
699                PKflags.append(term[1::2])           
700        hst = G2frame.PatternTree.GetItemText(G2frame.PatternId)
701        histList = GetHistsLikeSelected(G2frame)
702        if not histList:
703            G2frame.ErrorDialog('No match','No histograms match '+hst,G2frame.dataFrame)
704            return
705        dlg = G2gd.G2MultiChoiceDialog(
706            G2frame.dataFrame, 
707            'Copy bkg ref. flags from\n'+str(hst[5:])+' to...',
708            'Copy bkg flags', histList)
709        copyList = []
710        try:
711            if dlg.ShowModal() == wx.ID_OK:
712                for i in dlg.GetSelections(): 
713                    copyList.append(histList[i])
714        finally:
715            dlg.Destroy()
716        for item in copyList:
717            Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,item)
718            backData = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Background'))
719            backData[0][1] = copy.copy(flag)
720            bkDict = backData[-1]
721            if bkDict['nDebye'] == backDict['nDebye']:
722                for i,term in enumerate(bkDict['debyeTerms']):
723                    term[1::2] = copy.copy(DBflags[i])
724            if bkDict['nPeaks'] == backDict['nPeaks']:
725                for i,term in enumerate(bkDict['peaksList']):
726                    term[1::2] = copy.copy(PKflags[i])                   
727           
728    def OnBackCopy(event):
729        hst = G2frame.PatternTree.GetItemText(G2frame.PatternId)
730        histList = GetHistsLikeSelected(G2frame)
731        if not histList:
732            G2frame.ErrorDialog('No match','No histograms match '+hst,G2frame.dataFrame)
733            return
734        copyList = []
735        dlg = G2gd.G2MultiChoiceDialog(
736            G2frame.dataFrame, 
737            'Copy bkg params from\n'+str(hst[5:])+' to...',
738            'Copy parameters', histList)
739        try:
740            if dlg.ShowModal() == wx.ID_OK:
741                for i in dlg.GetSelections():
742                    copyList.append(histList[i])
743        finally:
744            dlg.Destroy()
745        for item in copyList:
746            Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,item)
747            G2frame.PatternTree.SetItemPyData(
748                G2gd.GetPatternTreeItemId(G2frame,Id,'Background'),copy.copy(data))
749       
750    def BackSizer():
751       
752        def OnNewType(event):
753            data[0][0] = bakType.GetValue()
754           
755        def OnBakRef(event):
756            data[0][1] = bakRef.GetValue()
757           
758        def OnBakTerms(event):
759            data[0][2] = int(bakTerms.GetValue())
760            M = len(data[0])
761            N = data[0][2]+3
762            item = data[0]
763            if N > M:       #add terms
764                for i in range(M,N): 
765                    item.append(0.0)
766            elif N < M:     #delete terms
767                for i in range(N,M):
768                    del(item[-1])
769            G2frame.PatternTree.SetItemPyData(BackId,data)
770            #wx.CallAfter(UpdateBackground,G2frame,data)
771            wx.CallLater(100,UpdateBackground,G2frame,data)
772           
773        def OnBakVal(event):
774            Obj = event.GetEventObject()
775            item = ValObj[Obj.GetId()][0]
776            try:
777                value = float(Obj.GetValue())
778            except ValueError:
779                value = data[0][item]
780            data[0][item] = value
781            Obj.SetValue('%10.4f'%(value))
782       
783        backSizer = wx.BoxSizer(wx.VERTICAL)
784        topSizer = wx.BoxSizer(wx.HORIZONTAL)
785        topSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,' Background function: '),0,WACV)
786        bakType = wx.ComboBox(G2frame.dataDisplay,value=data[0][0],
787                choices=Choices,style=wx.CB_READONLY|wx.CB_DROPDOWN)
788        bakType.Bind(wx.EVT_COMBOBOX, OnNewType)
789        topSizer.Add(bakType)
790        topSizer.Add((5,0),0)
791        bakRef = wx.CheckBox(G2frame.dataDisplay,label=' Refine?')
792        bakRef.SetValue(bool(data[0][1]))
793        bakRef.Bind(wx.EVT_CHECKBOX, OnBakRef)
794        topSizer.Add(bakRef,0,WACV)
795        topSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,' No. coeff.: '),0,WACV)
796        bakTerms = wx.ComboBox(G2frame.dataDisplay,-1,value=str(data[0][2]),choices=[str(i+1) for i in range(36)],
797            style=wx.CB_READONLY|wx.CB_DROPDOWN)
798        bakTerms.Bind(wx.EVT_COMBOBOX,OnBakTerms)
799        topSizer.Add(bakTerms,0,WACV)
800        topSizer.Add((5,0),0)
801        backSizer.Add(topSizer)
802        backSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,' Background coefficients:'),0,WACV)
803        bakSizer = wx.FlexGridSizer(0,5,5,5)
804        for i,value in enumerate(data[0][3:]):
805            bakVal = wx.TextCtrl(G2frame.dataDisplay,wx.ID_ANY,'%10.4f'%(value),style=wx.TE_PROCESS_ENTER)
806            bakSizer.Add(bakVal,0,WACV)
807            ValObj[bakVal.GetId()] = [i+3]
808            bakVal.Bind(wx.EVT_TEXT_ENTER,OnBakVal)
809            bakVal.Bind(wx.EVT_KILL_FOCUS,OnBakVal)
810        backSizer.Add(bakSizer)
811        return backSizer
812       
813    def DebyeSizer():
814       
815        def OnDebTerms(event):
816            data[1]['nDebye'] = int(debTerms.GetValue())
817            M = len(data[1]['debyeTerms'])
818            N = data[1]['nDebye']
819            if N > M:       #add terms
820                for i in range(M,N): 
821                    data[1]['debyeTerms'].append([1.0,False,1.0,False,0.010,False])
822            elif N < M:     #delete terms
823                for i in range(N,M):
824                    del(data[1]['debyeTerms'][-1])
825            #wx.CallAfter(UpdateBackground,G2frame,data)
826            wx.CallLater(100,UpdateBackground,G2frame,data)
827
828        def KeyEditPeakGrid(event):
829            colList = debyeGrid.GetSelectedCols()
830            if event.GetKeyCode() == wx.WXK_RETURN:
831                event.Skip(True)
832            elif event.GetKeyCode() == wx.WXK_CONTROL:
833                event.Skip(True)
834            elif event.GetKeyCode() == wx.WXK_SHIFT:
835                event.Skip(True)
836            elif colList:
837                debyeGrid.ClearSelection()
838                key = event.GetKeyCode()
839                for col in colList:
840                    if debyeTable.GetTypeName(0,col) == wg.GRID_VALUE_BOOL:
841                        if key == 89: #'Y'
842                            for row in range(debyeGrid.GetNumberRows()): data[1]['debyeTerms'][row][col]=True
843                        elif key == 78:  #'N'
844                            for row in range(debyeGrid.GetNumberRows()): data[1]['debyeTerms'][row][col]=False
845
846       
847        debSizer = wx.BoxSizer(wx.VERTICAL)
848        topSizer = wx.BoxSizer(wx.HORIZONTAL)
849        topSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,' Debye scattering: '),0,WACV)
850        topSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,' No. coeff.: '),0,WACV)
851        debTerms = wx.ComboBox(G2frame.dataDisplay,-1,value=str(data[1]['nDebye']),choices=[str(i) for i in range(12)],
852            style=wx.CB_READONLY|wx.CB_DROPDOWN)
853        debTerms.Bind(wx.EVT_COMBOBOX,OnDebTerms)
854        topSizer.Add(debTerms,0,WACV)
855        topSizer.Add((5,0),0)
856        debSizer.Add(topSizer)
857        if data[1]['nDebye']:
858            debSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,' Debye diffuse terms:'),0,WACV)       
859            rowLabels = []
860            for i in range(len(data[1]['debyeTerms'])): rowLabels.append(str(i))
861            colLabels = ['A','refine','R','refine','U','refine']
862            Types = [wg.GRID_VALUE_FLOAT+':10,2',wg.GRID_VALUE_BOOL,
863            wg.GRID_VALUE_FLOAT+':10,3',wg.GRID_VALUE_BOOL,
864            wg.GRID_VALUE_FLOAT+':10,5',wg.GRID_VALUE_BOOL]
865            debyeTable = G2gd.Table(data[1]['debyeTerms'],rowLabels=rowLabels,colLabels=colLabels,types=Types)
866            debyeGrid = G2gd.GSGrid(parent=G2frame.dataDisplay)
867            debyeGrid.SetTable(debyeTable, True)
868            debyeGrid.Bind(wx.EVT_KEY_DOWN, KeyEditPeakGrid)
869            debyeGrid.AutoSizeColumns(False)
870            debSizer.Add(debyeGrid)       
871        return debSizer
872     
873    def PeaksSizer():
874
875        def OnPeaks(event):
876            data[1]['nPeaks'] = int(peaks.GetValue())
877            M = len(data[1]['peaksList'])
878            N = data[1]['nPeaks']
879            if N > M:       #add terms
880                for i in range(M,N): 
881                    data[1]['peaksList'].append([1.0,False,1.0,False,0.10,False,0.10,False])
882            elif N < M:     #delete terms
883                for i in range(N,M):
884                    del(data[1]['peaksList'][-1])
885            #wx.CallAfter(UpdateBackground,G2frame,data)
886            wx.CallLater(100,UpdateBackground,G2frame,data)
887           
888        def KeyEditPeakGrid(event):
889            colList = peaksGrid.GetSelectedCols()
890            if event.GetKeyCode() == wx.WXK_RETURN:
891                event.Skip(True)
892            elif event.GetKeyCode() == wx.WXK_CONTROL:
893                event.Skip(True)
894            elif event.GetKeyCode() == wx.WXK_SHIFT:
895                event.Skip(True)
896            elif colList:
897                peaksGrid.ClearSelection()
898                key = event.GetKeyCode()
899                for col in colList:
900                    if peaksTable.GetTypeName(0,col) == wg.GRID_VALUE_BOOL:
901                        if key == 89: #'Y'
902                            for row in range(peaksGrid.GetNumberRows()): data[1]['peaksList'][row][col]=True
903                        elif key == 78:  #'N'
904                            for row in range(peaksGrid.GetNumberRows()): data[1]['peaksList'][row][col]=False
905
906        peaksSizer = wx.BoxSizer(wx.VERTICAL)
907        topSizer = wx.BoxSizer(wx.HORIZONTAL)
908        topSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,' Peaks in background: '),0,WACV)
909        topSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,' No. peaks: '),0,WACV)
910        peaks = wx.ComboBox(G2frame.dataDisplay,-1,value=str(data[1]['nPeaks']),choices=[str(i) for i in range(12)],
911            style=wx.CB_READONLY|wx.CB_DROPDOWN)
912        peaks.Bind(wx.EVT_COMBOBOX,OnPeaks)
913        topSizer.Add(peaks,0,WACV)
914        topSizer.Add((5,0),0)
915        peaksSizer.Add(topSizer)
916        if data[1]['nPeaks']:
917            peaksSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,' Peak list:'),0,WACV)       
918            rowLabels = []
919            for i in range(len(data[1]['peaksList'])): rowLabels.append(str(i))
920            colLabels = ['pos','refine','int','refine','sig','refine','gam','refine']
921            Types = [wg.GRID_VALUE_FLOAT+':10,2',wg.GRID_VALUE_BOOL,
922            wg.GRID_VALUE_FLOAT+':10,3',wg.GRID_VALUE_BOOL,
923            wg.GRID_VALUE_FLOAT+':10,3',wg.GRID_VALUE_BOOL,
924            wg.GRID_VALUE_FLOAT+':10,5',wg.GRID_VALUE_BOOL]
925            peaksTable = G2gd.Table(data[1]['peaksList'],rowLabels=rowLabels,colLabels=colLabels,types=Types)
926            peaksGrid = G2gd.GSGrid(parent=G2frame.dataDisplay)
927            peaksGrid.SetTable(peaksTable, True)
928            peaksGrid.Bind(wx.EVT_KEY_DOWN, KeyEditPeakGrid)
929            peaksGrid.AutoSizeColumns(False)
930            peaksSizer.Add(peaksGrid)       
931        return peaksSizer
932               
933    if G2frame.dataDisplay:
934        G2frame.dataFrame.DestroyChildren()
935    G2frame.dataDisplay = wx.Panel(G2frame.dataFrame)
936    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.BackMenu)
937    G2frame.dataFrame.SetLabel('Background')
938    if not G2frame.dataFrame.GetStatusBar():
939        Status = G2frame.dataFrame.CreateStatusBar()
940    G2frame.Bind(wx.EVT_MENU,OnBackCopy,id=G2gd.wxID_BACKCOPY)
941    G2frame.Bind(wx.EVT_MENU,OnBackFlagCopy,id=G2gd.wxID_BACKFLAGCOPY)
942    BackId = G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Background')
943    Choices = ['chebyschev','cosine','lin interpolate','inv interpolate','log interpolate']
944    mainSizer = wx.BoxSizer(wx.VERTICAL)
945    mainSizer.Add(BackSizer())
946    mainSizer.Add((0,5),0)
947    mainSizer.Add(DebyeSizer())
948    mainSizer.Add((0,5),0)
949    mainSizer.Add(PeaksSizer())
950    mainSizer.Layout()   
951    G2frame.dataDisplay.SetSizer(mainSizer)
952    G2frame.dataFrame.setSizePosLeft(mainSizer.Fit(G2frame.dataFrame))
953       
954################################################################################
955#####  Limits
956################################################################################           
957       
958def UpdateLimitsGrid(G2frame, data,plottype):
959    '''respond to selection of PWDR Limits data tree item.
960    '''
961    if G2frame.dataDisplay:
962        G2frame.dataFrame.Clear()
963    G2frame.ifGetExclude = False
964       
965    def KeyEditPeakGrid(event):
966        if event.GetKeyCode() == wx.WXK_DELETE:
967            row = G2frame.dataDisplay.GetSelectedRows()[0]
968            if row > 1: #can't delete limits!
969                del(data[row])
970                wx.CallAfter(UpdateLimitsGrid,G2frame,data,plottype)
971                G2plt.PlotPatterns(G2frame,plotType=plottype)
972                       
973    def RefreshLimitsGrid(event):
974        event.StopPropagation()
975        data = G2frame.LimitsTable.GetData()
976        old = data[0]
977        new = data[1]
978        new[0] = max(old[0],new[0])
979        new[1] = max(new[0],min(old[1],new[1]))
980        excl = []
981        if len(data) > 2:
982            excl = data[2:]
983            for item in excl:
984                item[0] = max(old[0],item[0])
985                item[1] = max(item[0],min(old[1],item[1]))
986        data = [old,new]+excl
987        G2frame.LimitsTable.SetData(data)
988        G2plt.PlotPatterns(G2frame,plotType=plottype)
989       
990    def OnLimitCopy(event):
991        hst = G2frame.PatternTree.GetItemText(G2frame.PatternId)
992        histList = GetHistsLikeSelected(G2frame)
993        if not histList:
994            G2frame.ErrorDialog('No match','No histograms match '+hst,G2frame.dataFrame)
995            return
996        copyList = []
997        dlg = G2gd.G2MultiChoiceDialog(
998            G2frame.dataFrame, 
999            'Copy limits from\n'+str(hst[5:])+' to...',
1000            'Copy limits', histList)
1001        try:
1002            if dlg.ShowModal() == wx.ID_OK:
1003                for i in dlg.GetSelections(): 
1004                    item = histList[i]
1005                    Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,item)
1006                    G2frame.PatternTree.SetItemPyData(
1007                        G2gd.GetPatternTreeItemId(G2frame,Id,'Limits'),copy.copy(data))
1008        finally:
1009            dlg.Destroy()
1010           
1011    def OnAddExcl(event):
1012        G2frame.ifGetExclude = True
1013        print 'Add excluded region'
1014       
1015    G2frame.LimitsTable = []
1016    colLabels = ['Tmin','Tmax']
1017    rowLabels = ['original','changed']
1018    for i in range(len(data)-2):
1019        rowLabels.append('exclude')
1020    Types = 2*[wg.GRID_VALUE_FLOAT+':12,5',]
1021    G2frame.LimitsTable = G2gd.Table(data,rowLabels=rowLabels,colLabels=colLabels,types=Types)
1022    G2frame.dataFrame.SetLabel('Limits')
1023    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.LimitMenu)
1024    if not G2frame.dataFrame.GetStatusBar():
1025        Status = G2frame.dataFrame.CreateStatusBar()
1026    G2frame.Bind(wx.EVT_MENU,OnLimitCopy,id=G2gd.wxID_LIMITCOPY)
1027    G2frame.Bind(wx.EVT_MENU,OnAddExcl,id=G2gd.wxID_ADDEXCLREGION)   
1028    G2frame.dataDisplay = G2gd.GSGrid(parent=G2frame.dataFrame)
1029    G2frame.dataDisplay.SetTable(G2frame.LimitsTable, True)   
1030    G2frame.dataDisplay.SetCellStyle(0,0,VERY_LIGHT_GREY,True)
1031    G2frame.dataDisplay.SetCellStyle(0,1,VERY_LIGHT_GREY,True)
1032    G2frame.dataDisplay.Bind(wg.EVT_GRID_CELL_CHANGE, RefreshLimitsGrid)               
1033    G2frame.dataDisplay.Bind(wx.EVT_KEY_DOWN, KeyEditPeakGrid)
1034    G2frame.dataDisplay.SetMargins(0,0)
1035    G2frame.dataDisplay.AutoSizeColumns(False)
1036    G2frame.dataFrame.setSizePosLeft([230,260])                               
1037    G2frame.dataFrame.SendSizeEvent()
1038   
1039################################################################################
1040#####  Instrument parameters
1041################################################################################           
1042       
1043def UpdateInstrumentGrid(G2frame,data):
1044    '''respond to selection of PWDR/SASD Instrument Parameters
1045    data tree item.
1046    '''
1047    def keycheck(keys):
1048        good = []
1049        for key in keys:
1050            if key in ['Type','U','V','W','X','Y','SH/L','I(L2)/I(L1)','alpha',
1051                'beta-0','beta-1','beta-q','sig-0','sig-1','sig-2','sig-q','Polariz.',
1052                'Lam','Azimuth','2-theta','fltPath','difC','difA','difB','Zero','Lam1','Lam2']:
1053                good.append(key)
1054        return good
1055       
1056    def inst2data(inst,ref,data):
1057        for item in data:
1058            try:
1059                data[item] = [data[item][0],inst[item],ref[item]]
1060            except KeyError:
1061                pass        #skip 'Polariz.' for N-data
1062        return data
1063       
1064    def updateData(inst,ref):
1065        return inst2data(inst,ref,G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,
1066            G2frame.PatternId,'Instrument Parameters'))[0])       
1067   
1068    def RefreshInstrumentGrid(event,doAnyway=False):
1069        if doAnyway or event.GetRow() == 1:
1070            peaks = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Peak List'))
1071            newpeaks = []
1072            for peak in peaks['peaks']:
1073                newpeaks.append(G2mth.setPeakparms(data,Inst2,peak[0],peak[2]))
1074            peaks['peaks'] = newpeaks
1075            G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Peak List'),peaks)
1076           
1077    def OnCalibrate(event):
1078        Pattern = G2frame.PatternTree.GetItemPyData(G2frame.PatternId)
1079        xye = ma.array(ma.getdata(Pattern[1]))
1080        cw = np.diff(xye[0])
1081        IndexPeaks = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Index Peak List'))
1082        if not len(IndexPeaks[0]):
1083            G2frame.ErrorDialog('Can not calibrate','Index Peak List empty')
1084            return
1085        Ok = False
1086        for peak in IndexPeaks[0]:
1087            if peak[2] and peak[3]:
1088                Ok = True
1089        if not Ok:
1090            G2frame.ErrorDialog('Can not calibrate','Index Peak List not indexed')
1091            return           
1092        if G2pwd.DoCalibInst(IndexPeaks,data):
1093            UpdateInstrumentGrid(G2frame,data)
1094            XY = []
1095            Sigs = []
1096            for ip,peak in enumerate(IndexPeaks[0]):
1097                if peak[2] and peak[3]:
1098                    binwid = cw[np.searchsorted(xye[0],peak[0])]
1099                    XY.append([peak[-1],peak[0],binwid])
1100                    Sigs.append(IndexPeaks[1][ip])
1101            if len(XY):
1102                XY = np.array(XY)
1103                G2plt.PlotCalib(G2frame,data,XY,Sigs,newPlot=True)
1104        else:
1105            G2frame.ErrorDialog('Can not calibrate','Nothing selected for refinement')
1106           
1107
1108    def OnLoad(event):
1109        '''Loads instrument parameters from a G2 .instprm file
1110        in response to the Instrument Parameters-Operations/Load Profile menu
1111       
1112        Note that similar code is found in ReadPowderInstprm (GSASII.py)
1113        '''
1114        dlg = wx.FileDialog(G2frame, 'Choose GSAS-II instrument parameters file', '.', '', 
1115            'instrument parameter files (*.instprm)|*.instprm',wx.OPEN|wx.CHANGE_DIR)
1116        try:
1117            if dlg.ShowModal() == wx.ID_OK:
1118                filename = dlg.GetPath()
1119                File = open(filename,'r')
1120                S = File.readline()
1121                newItems = []
1122                newVals = []
1123                while S:
1124                    if S[0] == '#':
1125                        S = File.readline()
1126                        continue
1127                    [item,val] = S[:-1].split(':')
1128                    newItems.append(item)
1129                    try:
1130                        newVals.append(float(val))
1131                    except ValueError:
1132                        newVals.append(val)                       
1133                    S = File.readline()               
1134                File.close()
1135                Inst,Inst2 = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId,'Instrument Parameters'))
1136                data = G2IO.makeInstDict(newItems,newVals,len(newVals)*[False,])
1137                G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId,'Instrument Parameters'),[data,Inst2])
1138                RefreshInstrumentGrid(event,doAnyway=True)          #to get peaks updated
1139                UpdateInstrumentGrid(G2frame,data)
1140                G2plt.PlotPeakWidths(G2frame)
1141        finally:
1142            dlg.Destroy()
1143       
1144    def OnSave(event):
1145        '''Respond to the Instrument Parameters Operations/Save Profile menu
1146        item: writes current parameters to a .instprm file
1147        '''
1148        dlg = wx.FileDialog(G2frame, 'Choose GSAS-II instrument parameters file', '.', '', 
1149            'instrument parameter files (*.instprm)|*.instprm',wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT|wx.CHANGE_DIR)
1150        try:
1151            if dlg.ShowModal() == wx.ID_OK:
1152                filename = dlg.GetPath()
1153                # make sure extension is .instprm
1154                filename = os.path.splitext(filename)[0]+'.instprm'
1155                File = open(filename,'w')
1156                File.write("#GSAS-II instrument parameter file; do not add/delete items!\n")
1157                for item in data:
1158                    File.write(item+':'+str(data[item][1])+'\n')
1159                File.close()
1160        finally:
1161            dlg.Destroy()
1162                                               
1163    def OnReset(event):
1164        insVal.update(insDef)
1165        updateData(insVal,insRef)
1166        RefreshInstrumentGrid(event,doAnyway=True)          #to get peaks updated
1167        UpdateInstrumentGrid(G2frame,data)
1168        G2plt.PlotPeakWidths(G2frame)
1169       
1170    def OnInstFlagCopy(event):
1171        hst = G2frame.PatternTree.GetItemText(G2frame.PatternId)
1172        histList = GetHistsLikeSelected(G2frame)
1173        if not histList:
1174            G2frame.ErrorDialog('No match','No histograms match '+hst,G2frame.dataFrame)
1175            return
1176        keys = data.keys()
1177        flags = dict(zip(keys,[data[key][2] for key in keys]))
1178        instType = data['Type'][0]
1179        copyList = []
1180        dlg = G2gd.G2MultiChoiceDialog(
1181            G2frame.dataFrame, 
1182            'Copy inst ref. flags from\n'+hst[5:],
1183            'Copy refinement flags', histList)
1184        try:
1185            if dlg.ShowModal() == wx.ID_OK:
1186                for i in dlg.GetSelections():
1187                    copyList.append(histList[i])
1188        finally:
1189            dlg.Destroy()
1190        for item in copyList:
1191            Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,item)
1192            instData = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Instrument Parameters'))[0]
1193            if len(data) == len(instData) and instType == instData['Type'][0]:   #don't mix data types or lam & lam1/lam2 parms!
1194                for item in instData:
1195                    instData[item][2] = copy.copy(flags[item])
1196            else:
1197                print item+' not copied - instrument parameters not commensurate'
1198       
1199    def OnInstCopy(event):
1200        #need fix for dictionary
1201        hst = G2frame.PatternTree.GetItemText(G2frame.PatternId)
1202        histList = GetHistsLikeSelected(G2frame)
1203        if not histList:
1204            G2frame.ErrorDialog('No match','No histograms match '+hst,G2frame.dataFrame)
1205            return
1206        copyList = []
1207        instType = data['Type'][0]
1208        dlg = G2gd.G2MultiChoiceDialog(
1209            G2frame.dataFrame, 
1210            'Copy inst params from\n'+hst,
1211            'Copy parameters', histList)
1212        try:
1213            if dlg.ShowModal() == wx.ID_OK:
1214                for i in dlg.GetSelections(): 
1215                    copyList.append(histList[i])
1216        finally:
1217            dlg.Destroy()
1218        for item in copyList:
1219            Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,item)
1220            instData = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Instrument Parameters'))[0]
1221            if len(data) == len(instData) and instType == instData['Type'][0]:  #don't mix data types or lam & lam1/lam2 parms!
1222                instData.update(data)
1223            else:
1224                print item+' not copied - instrument parameters not commensurate'
1225                         
1226    def AfterChange(invalid,value,tc):
1227        if invalid: return
1228        updateData(insVal,insRef)
1229       
1230    def OnItemRef(event):
1231        Obj = event.GetEventObject()
1232        item = RefObj[Obj.GetId()]
1233        insRef[item] = Obj.GetValue()
1234        updateData(insVal,insRef)
1235
1236    def OnCopy1Val(event):
1237        '''Select one instrument parameter value to edit and copy to many histograms
1238        optionally allow values to be edited in a table
1239        '''
1240        updateData(insVal,insRef)
1241        G2gd.SelectEdit1Var(G2frame,data,labelLst,elemKeysLst,dspLst,refFlgElem)
1242        insVal.update({key:data[key][1] for key in instkeys})
1243        insRef.update({key:data[key][2] for key in instkeys})
1244        wx.CallAfter(MakeParameterWindow)
1245       
1246    def lblWdef(lbl,dec,val):
1247        'Label parameter showing the default value'
1248        fmt = "%15."+str(dec)+"f"
1249        return " " + lbl + " (" + (fmt % val).strip() + "): "
1250
1251    def RefineBox(item):
1252        'Define a refine checkbox with binding'
1253        wid = wx.CheckBox(G2frame.dataDisplay,label=' Refine?  ')
1254        wid.SetValue(bool(insRef[item]))
1255        RefObj[wid.GetId()] = item
1256        wid.Bind(wx.EVT_CHECKBOX, OnItemRef)
1257        return wid
1258
1259    def OnLamPick(event):
1260        data['Source'][1] = lamType = event.GetEventObject().GetValue()
1261        insVal['Lam1'] = waves[lamType][0]
1262        insVal['Lam2'] = waves[lamType][1]
1263        updateData(insVal,insRef)
1264        i,j= wx.__version__.split('.')[0:2]
1265        if int(i)+int(j)/10. > 2.8:
1266            pass # repaint crashes wxpython 2.9
1267            wx.CallLater(100, MakeParameterWindow)
1268            #wx.CallAfter(MakeParameterWindow)
1269        else:
1270            wx.CallAfter(MakeParameterWindow)
1271
1272    def MakeParameterWindow():
1273        'Displays the Instrument parameters in the datadisplay frame'
1274        if G2frame.dataDisplay:
1275            G2frame.dataFrame.Clear()
1276        G2frame.dataFrame.SetLabel('Instrument Parameters')
1277        G2frame.dataDisplay = wx.Panel(G2frame.dataFrame)
1278        mainSizer = wx.BoxSizer(wx.VERTICAL)
1279        instSizer = wx.FlexGridSizer(0,6,5,5)
1280        subSizer = wx.BoxSizer(wx.HORIZONTAL)
1281        subSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,' Histogram Type: '+insVal['Type']),0,WACV)
1282        mainSizer.Add(subSizer)
1283        labelLst[:],elemKeysLst[:],dspLst[:],refFlgElem[:] = [],[],[],[]
1284        if 'P' in insVal['Type']:                   #powder data
1285            if 'C' in insVal['Type']:               #constant wavelength
1286                labelLst.append('Azimuth angle')
1287                elemKeysLst.append(['Azimuth',1])
1288                dspLst.append([10,2])
1289                refFlgElem.append(None)                   
1290                if 'Lam1' in insVal:
1291                    subSizer = wx.BoxSizer(wx.HORIZONTAL)
1292                    subSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,' Azimuth: '),0,WACV)
1293                    txt = '%7.2f'%(insVal['Azimuth'])
1294                    subSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,txt.strip()),0,WACV)
1295                    subSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,'   Ka1/Ka2: '),0,WACV)
1296                    txt = u%8.6f/%8.6f\xc5'%(insVal['Lam1'],insVal['Lam2'])
1297                    subSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,txt.strip()),0,WACV)
1298                    waveSizer = wx.BoxSizer(wx.HORIZONTAL)
1299                    waveSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,'  Source type: '),0,WACV)
1300                    # PATCH?: for now at least, Source is not saved anywhere before here
1301                    if 'Source' not in data: data['Source'] = ['CuKa','?']
1302                    choice = ['TiKa','CrKa','FeKa','CoKa','CuKa','MoKa','AgKa']
1303                    lamPick = wx.ComboBox(G2frame.dataDisplay,value=data['Source'][1],choices=choice,style=wx.CB_READONLY|wx.CB_DROPDOWN)
1304                    lamPick.Bind(wx.EVT_COMBOBOX, OnLamPick)
1305                    waveSizer.Add(lamPick,0)
1306                    subSizer.Add(waveSizer,0)
1307                    mainSizer.Add(subSizer)
1308                    instSizer.Add(wx.StaticText(
1309                        G2frame.dataDisplay,-1,
1310                        lblWdef('I(L2)/I(L1)',4,insDef['I(L2)/I(L1)'])),
1311                        0,WACV)
1312                    key = 'I(L2)/I(L1)'
1313                    labelLst.append(key)
1314                    elemKeysLst.append([key,1])
1315                    dspLst.append([10,4])
1316                    refFlgElem.append([key,2])                   
1317                    ratVal = G2gd.ValidatedTxtCtrl(G2frame.dataDisplay,insVal,key,nDig=(10,4),typeHint=float,OnLeave=AfterChange)
1318                    instSizer.Add(ratVal,0)
1319                    instSizer.Add(RefineBox(key),0,WACV)
1320                    instSizer.Add((5,5),0)
1321                    instSizer.Add((5,5),0)
1322                    instSizer.Add((5,5),0)               
1323                else: # single wavelength
1324                    instSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,' Azimuth: '),0,WACV)
1325                    txt = '%7.2f'%(insVal['Azimuth'])
1326                    instSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,txt.strip()),0,WACV)
1327                    instSizer.Add((5,5),0)
1328                    key = 'Lam'
1329                    instSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,u' Lam (\xc5): (%10.6f)'%(insDef[key])),
1330                        0,WACV)
1331                    waveVal = G2gd.ValidatedTxtCtrl(G2frame.dataDisplay,insVal,key,nDig=(10,6),typeHint=float,OnLeave=AfterChange)
1332                    labelLst.append(u'Lam (\xc5)')
1333                    elemKeysLst.append([key,1])
1334                    dspLst.append([10,6])
1335                    instSizer.Add(waveVal,0,WACV)
1336                    refFlgElem.append([key,2])                   
1337                    instSizer.Add(RefineBox(key),0,WACV)
1338#                    if ifHisto:
1339#                        refFlgElem.append([key,2])                   
1340#                        instSizer.Add(RefineBox(key),0,WACV)
1341#                    else:
1342#                        refFlgElem.append(None)                   
1343#                        instSizer.Add((5,5),0)
1344                for item in ['Zero','Polariz.']:
1345                    if item in insDef:
1346                        labelLst.append(item)
1347                        elemKeysLst.append([item,1])
1348                        dspLst.append([10,4])
1349                        instSizer.Add(
1350                            wx.StaticText(G2frame.dataDisplay,-1,lblWdef(item,4,insDef[item])),
1351                            0,WACV)
1352                        itemVal = G2gd.ValidatedTxtCtrl(G2frame.dataDisplay,insVal,item,nDig=(10,4),typeHint=float,OnLeave=AfterChange)
1353                        instSizer.Add(itemVal,0,WACV)
1354                        refFlgElem.append([item,2])
1355                        instSizer.Add(RefineBox(item),0,WACV)
1356#                        if ifHisto:
1357#                            refFlgElem.append([item,2])
1358#                            instSizer.Add(RefineBox(item),0,WACV)
1359#                        else:
1360#                            refFlgElem.append(None)                   
1361#                            instSizer.Add((5,5),0)
1362                    else:                           #skip Polariz. for neutrons
1363                        instSizer.Add((5,5),0)
1364                        instSizer.Add((5,5),0)
1365                        instSizer.Add((5,5),0)
1366                for item in ['U','V','W','','X','Y','SH/L']:
1367                    if item == '':
1368                        instSizer.Add((5,5),0)
1369                        instSizer.Add((5,5),0)
1370                        instSizer.Add((5,5),0)
1371                        continue
1372                    nDig = (10,3)
1373                    if item == 'SH/L':
1374                        nDig = (10,5)
1375                    labelLst.append(item)
1376                    elemKeysLst.append([item,1])
1377                    dspLst.append(nDig)
1378                    refFlgElem.append([item,2])
1379                    instSizer.Add(
1380                        wx.StaticText(G2frame.dataDisplay,-1,lblWdef(item,nDig[1],insDef[item])),
1381                        0,WACV)
1382                    itemVal = G2gd.ValidatedTxtCtrl(G2frame.dataDisplay,insVal,item,nDig=nDig,typeHint=float,OnLeave=AfterChange)
1383                    instSizer.Add(itemVal,0,WACV)
1384                    instSizer.Add(RefineBox(item),0,WACV)
1385            else:                                   #time of flight (neutrons)
1386                subSizer = wx.BoxSizer(wx.HORIZONTAL)
1387                subSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,' Fligth path: '),0,WACV)
1388                txt = '%8.3f'%(insVal['fltPath'])
1389                subSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,txt.strip()),0,WACV)
1390                labelLst.append('flight path')
1391                elemKeysLst.append(['fltpath',1])
1392                dspLst.append([10,2])
1393                refFlgElem.append(None)                   
1394                subSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,'  2-theta: '),0,WACV)
1395                txt = '%7.2f'%(insVal['2-theta'])
1396                subSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,txt.strip()),0,WACV)
1397                labelLst.append('2-theta')
1398                elemKeysLst.append(['2-theta',1])
1399                dspLst.append([10,2])
1400                refFlgElem.append(None)                   
1401                if 'Pdabc' in Inst2:
1402                    Items = ['sig-0','sig-1','sig-2','sig-q','X','Y']
1403                    subSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,'  difC: '),0,WACV)
1404                    txt = '%8.2f'%(insVal['difC'])
1405                    subSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,txt.strip()),0,WACV)
1406                    labelLst.append('difC')
1407                    elemKeysLst.append(['difC',1])
1408                    dspLst.append([10,2])
1409                    refFlgElem.append(None)
1410                    subSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,'  alpha, beta: fixed by table'),0,WACV)
1411                else:
1412                    Items = ['difC','difA','difB','Zero','alpha','beta-0','beta-1','beta-q','sig-0','sig-1','sig-2','sig-q','X','Y']
1413                mainSizer.Add((5,5),0)
1414                mainSizer.Add(subSizer)
1415                mainSizer.Add((5,5),0)
1416                for item in Items:
1417                    if item == '':
1418                        instSizer.Add((5,5),0)
1419                        instSizer.Add((5,5),0)
1420                        instSizer.Add((5,5),0)
1421                        continue
1422                    nDig = (10,3)
1423                    fmt = '%10.3f'
1424                    if 'beta' in item:
1425                        fmt = '%12.4g'
1426                        nDig = (12,4)
1427                    Fmt = ' %s: ('+fmt+')'
1428                    instSizer.Add(
1429                            wx.StaticText(G2frame.dataDisplay,-1,lblWdef(item,nDig[1],insDef[item])),
1430                            0,WACV)
1431                    itemVal = G2gd.ValidatedTxtCtrl(G2frame.dataDisplay,insVal,item,nDig=nDig,typeHint=float,OnLeave=AfterChange)
1432                    instSizer.Add(itemVal,0,WACV)
1433                    labelLst.append(item)
1434                    elemKeysLst.append([item,1])
1435                    dspLst.append(nDig)
1436                    refFlgElem.append([item,2])
1437                    instSizer.Add(RefineBox(item),0,WACV)
1438        elif 'S' in insVal['Type']:                       #single crystal data
1439            if 'C' in insVal['Type']:               #constant wavelength
1440                instSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,u' Lam (\xc5): (%10.6f)'%(insDef['Lam'])),
1441                    0,WACV)
1442                waveVal = G2gd.ValidatedTxtCtrl(G2frame.dataDisplay,insVal,'Lam',nDig=(10,6),typeHint=float,OnLeave=AfterChange)
1443                instSizer.Add(waveVal,0,WACV)
1444                labelLst.append(u'Lam (\xc5)')
1445                elemKeysLst.append(['Lam',1])
1446                dspLst.append([10,6])
1447                refFlgElem.append(None)
1448            else:                                   #time of flight (neutrons)
1449                pass                                #for now
1450        elif 'L' in insVal['Type']:
1451            if 'C' in insVal['Type']:       
1452                instSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,u' Lam (\xc5): (%10.6f)'%(insDef['Lam'])),
1453                    0,WACV)
1454                waveVal = G2gd.ValidatedTxtCtrl(G2frame.dataDisplay,insVal,'Lam',nDig=(10,6),typeHint=float,OnLeave=AfterChange)
1455                instSizer.Add(waveVal,0,WACV)
1456                labelLst.append(u'Lam (\xc5)')
1457                elemKeysLst.append(['Lam',1])
1458                dspLst.append([10,6])
1459                refFlgElem.append(None)
1460                instSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,'  Azimuth: %7.2f'%(insVal['Azimuth'])),0,WACV)
1461                labelLst.append('Azimuth angle')
1462                elemKeysLst.append(['Azimuth',1])
1463                dspLst.append([10,2])
1464                refFlgElem.append(None)                   
1465            else:                                   #time of flight (neutrons)
1466                pass                                #for now
1467
1468        mainSizer.Add(instSizer,0)
1469        mainSizer.Layout()   
1470        G2frame.dataDisplay.SetSizer(mainSizer)
1471        G2frame.dataFrame.setSizePosLeft(mainSizer.Fit(G2frame.dataFrame))
1472        G2frame.dataFrame.SendSizeEvent()  # this causes a frame repaint, even if the size does not change!
1473        # end of MakeParameterWindow
1474               
1475    # beginning of UpdateInstrumentGrid code   
1476    #patch: make sure all parameter items are lists
1477    patched = 0
1478    for key in data:
1479        if type(data[key]) is tuple:
1480            data[key] = list(data[key])
1481            patched += 1
1482    if patched: print patched,' instrument parameters changed from tuples'
1483    #end of patch
1484    labelLst,elemKeysLst,dspLst,refFlgElem = [],[],[],[]
1485    instkeys = keycheck(data.keys())
1486    if 'P' in data['Type'][0]:          #powder data
1487        insVal = dict(zip(instkeys,[data[key][1] for key in instkeys]))
1488        insDef = dict(zip(instkeys,[data[key][0] for key in instkeys]))
1489        insRef = dict(zip(instkeys,[data[key][2] for key in instkeys]))
1490        if 'NC' in data['Type'][0]:
1491            del(insDef['Polariz.'])
1492            del(insVal['Polariz.'])
1493            del(insRef['Polariz.'])
1494    elif 'S' in data['Type'][0]:                               #single crystal data
1495        insVal = dict(zip(instkeys,[data[key][1] for key in instkeys]))
1496        insDef = dict(zip(instkeys,[data[key][0] for key in instkeys]))
1497        insRef = {}
1498    elif 'L' in data['Type'][0]:                               #low angle data
1499        insVal = dict(zip(instkeys,[data[key][1] for key in instkeys]))
1500        insDef = dict(zip(instkeys,[data[key][0] for key in instkeys]))
1501        insRef = {}
1502    ValObj = {}
1503    RefObj = {}
1504    waves = {'CuKa':[1.54051,1.54433],'TiKa':[2.74841,2.75207],'CrKa':[2.28962,2.29351],
1505        'FeKa':[1.93597,1.93991],'CoKa':[1.78892,1.79278],'MoKa':[0.70926,0.713543],
1506        'AgKa':[0.559363,0.563775]}
1507    Inst2 = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,
1508            G2frame.PatternId,'Instrument Parameters'))[1]       
1509    try:
1510        histoName = G2frame.PatternTree.GetItemPyData(G2frame.PatternId)[-1]
1511        ifHisto = IsHistogramInAnyPhase(G2frame,histoName)
1512    except TypeError:       #PKS data never used in a phase as data
1513        ifhisto = False
1514    G2gd.SetDataMenuBar(G2frame)
1515    #patch
1516    if 'P' in insVal['Type']:                   #powder data
1517        if 'C' in insVal['Type']:               #constant wavelength
1518            if 'Azimuth' not in insVal:
1519                insVal['Azimuth'] = 0.0
1520                insDef['Azimuth'] = 0.0
1521                insRef['Azimuth'] = False
1522#        if 'T' in insVal['Type']:
1523#            if 'difB' not in insVal:
1524#                insVal['difB'] = 0.0
1525#                insDef['difB'] = 0.0
1526#                insRef['difB'] = False
1527    #end of patch
1528    if 'P' in insVal['Type']:                   #powder data menu commands
1529        G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.InstMenu)
1530        if not G2frame.dataFrame.GetStatusBar():
1531            Status = G2frame.dataFrame.CreateStatusBar()           
1532        G2frame.Bind(wx.EVT_MENU,OnCalibrate,id=G2gd.wxID_INSTCALIB)
1533        G2frame.Bind(wx.EVT_MENU,OnLoad,id=G2gd.wxID_INSTLOAD)
1534        G2frame.Bind(wx.EVT_MENU,OnSave,id=G2gd.wxID_INSTSAVE)
1535        G2frame.Bind(wx.EVT_MENU,OnReset,id=G2gd.wxID_INSTPRMRESET)
1536        G2frame.Bind(wx.EVT_MENU,OnInstCopy,id=G2gd.wxID_INSTCOPY)
1537        G2frame.Bind(wx.EVT_MENU,OnInstFlagCopy,id=G2gd.wxID_INSTFLAGCOPY)
1538        #G2frame.Bind(wx.EVT_MENU,OnWaveChange,id=G2gd.wxID_CHANGEWAVETYPE)       
1539        G2frame.Bind(wx.EVT_MENU,OnCopy1Val,id=G2gd.wxID_INST1VAL)
1540    elif 'L' in insVal['Type']:                   #SASD data menu commands
1541        G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.InstMenu)
1542        if not G2frame.dataFrame.GetStatusBar():
1543            Status = G2frame.dataFrame.CreateStatusBar()           
1544        G2frame.Bind(wx.EVT_MENU,OnInstCopy,id=G2gd.wxID_INSTCOPY)
1545    MakeParameterWindow()
1546       
1547   
1548################################################################################
1549#####  Sample parameters
1550################################################################################           
1551       
1552def UpdateSampleGrid(G2frame,data):
1553    '''respond to selection of PWDR/SASD Sample Parameters
1554    data tree item.
1555    '''
1556
1557    def OnSampleSave(event):
1558        '''Respond to the Sample Parameters Operations/Save menu
1559        item: writes current parameters to a .samprm file
1560        '''
1561        dlg = wx.FileDialog(G2frame, 'Choose GSAS-II sample parameters file', '.', '', 
1562            'sample parameter files (*.samprm)|*.samprm',wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT|wx.CHANGE_DIR)
1563        try:
1564            if dlg.ShowModal() == wx.ID_OK:
1565                filename = dlg.GetPath()
1566                # make sure extension is .samprm
1567                filename = os.path.splitext(filename)[0]+'.samprm'
1568                File = open(filename,'w')
1569                File.write("#GSAS-II sample parameter file\n")
1570                File.write("'Type':'"+str(data['Type'])+"'\n")
1571                File.write("'Gonio. radius':"+str(data['Gonio. radius'])+"\n")
1572                if data.get('InstrName'):
1573                    File.write("'InstrName':'"+str(data['InstrName'])+"'\n")
1574                File.close()
1575        finally:
1576            dlg.Destroy()
1577           
1578    def OnSampleLoad(event):
1579        '''Loads sample parameters from a G2 .samprm file
1580        in response to the Sample Parameters-Operations/Load menu
1581       
1582        Note that similar code is found in ReadPowderInstprm (GSASII.py)
1583        '''
1584        dlg = wx.FileDialog(G2frame, 'Choose GSAS-II sample parameters file', '.', '', 
1585            'sample parameter files (*.samprm)|*.samprm',wx.OPEN|wx.CHANGE_DIR)
1586        try:
1587            if dlg.ShowModal() == wx.ID_OK:
1588                filename = dlg.GetPath()
1589                File = open(filename,'r')
1590                S = File.readline()
1591                newItems = {}
1592                while S:
1593                    if S[0] == '#':
1594                        S = File.readline()
1595                        continue
1596                    [item,val] = S[:-1].split(':')
1597                    newItems[item.strip("'")] = eval(val)
1598                    S = File.readline()               
1599                File.close()
1600                data.update(newItems)
1601                G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId,'Sample Parameters'),data)
1602                UpdateSampleGrid(G2frame,data)
1603        finally:
1604            dlg.Destroy()
1605           
1606    def OnAllSampleLoad(event):
1607        filename = ''
1608        dlg = wx.FileDialog(G2frame, 'Choose multihistogram metadata text file', '.', '', 
1609            'metadata file (*.*)|*.*',wx.OPEN|wx.CHANGE_DIR)
1610        try:
1611            if dlg.ShowModal() == wx.ID_OK:
1612                filename = dlg.GetPath()
1613                File = open(filename,'r')
1614                S = File.readline()
1615                newItems = []
1616                itemNames = []
1617                Comments = []
1618                while S:
1619                    if S[0] == '#':
1620                        Comments.append(S)
1621                        S = File.readline()
1622                        continue
1623                    S = S.replace(',',' ').replace('\t',' ')
1624                    Stuff = S[:-1].split()
1625                    itemNames.append(Stuff[0])
1626                    newItems.append(Stuff[1:])
1627                    S = File.readline()               
1628                File.close()
1629        finally:
1630            dlg.Destroy()
1631        if not filename:
1632            G2frame.ErrorDialog('Nothing to do','No file selected')
1633            return
1634        dataDict = dict(zip(itemNames,newItems))
1635        ifany = False
1636        Controls = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Controls'))
1637        Names = [' ','Phi','Chi','Omega','Time','Temperature','Pressure']
1638        freeNames = {}
1639        for name in ['FreePrm1','FreePrm2','FreePrm3']:
1640            freeNames[Controls[name]] = name
1641            Names.append(Controls[name])
1642        dlg = G2gd.G2ColumnIDDialog( G2frame,' Choose multihistogram metadata columns:',
1643            'Select columns',Comments,Names,np.array(newItems).T)
1644        try:
1645            if dlg.ShowModal() == wx.ID_OK:
1646                colNames,newData = dlg.GetSelection()
1647                dataDict = dict(zip(itemNames,newData.T))
1648                for item in colNames:
1649                    if item != ' ':
1650                        ifany = True
1651        finally:
1652            dlg.Destroy()
1653        if not ifany:
1654            G2frame.ErrorDialog('Nothing to do','No columns identified')
1655            return
1656        histList = [G2frame.PatternTree.GetItemText(G2frame.PatternId),]
1657        histList += GetHistsLikeSelected(G2frame)
1658        colIds = {}
1659        for i,name in enumerate(colNames):
1660            if name != ' ':
1661                colIds[name] = i
1662        for hist in histList:
1663            name = hist.split()[1]  #this is file name
1664            newItems = {}
1665            for item in colIds:
1666                key = freeNames.get(item,item)
1667                newItems[key] = float(dataDict[name][colIds[item]])
1668            Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,hist)
1669            sampleData = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Sample Parameters'))
1670            sampleData.update(newItems)       
1671        UpdateSampleGrid(G2frame,data)       
1672   
1673    def OnSetScale(event):
1674        histList = []
1675        item, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
1676        while item:
1677            name = G2frame.PatternTree.GetItemText(item)
1678            if 'SASD' in name and name != histName:
1679                histList.append(name)
1680            item, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
1681        if not len(histList):      #nothing to copy to!
1682            return
1683        dlg = wx.SingleChoiceDialog(G2frame,'Select reference histogram for scaling',
1684            'Reference histogram',histList)
1685        try:
1686            if dlg.ShowModal() == wx.ID_OK:
1687                sel = dlg.GetSelection()
1688                refHist = histList[sel]
1689        finally:
1690            dlg.Destroy()
1691        Limits = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Limits'))
1692        Profile = G2frame.PatternTree.GetItemPyData(G2frame.PatternId)[1]
1693        Data = [Profile,Limits,data]
1694        refId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,refHist)
1695        refSample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,refId, 'Sample Parameters'))
1696        refLimits = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,refId, 'Limits'))
1697        refProfile = G2frame.PatternTree.GetItemPyData(refId)[1]
1698        refData = [refProfile,refLimits,refSample]
1699        G2sasd.SetScale(Data,refData)
1700        G2plt.PlotPatterns(G2frame,plotType='SASD',newPlot=True)
1701        UpdateSampleGrid(G2frame,data)       
1702       
1703    def OnSampleCopy(event):
1704        histType,copyNames = SetCopyNames(histName,data['Type'],
1705            addNames = ['Omega','Chi','Phi','Gonio. radius','InstrName'])
1706        copyDict = {}
1707        for parm in copyNames:
1708            copyDict[parm] = data[parm]
1709        hst = G2frame.PatternTree.GetItemText(G2frame.PatternId)
1710        histList = GetHistsLikeSelected(G2frame)
1711        if not histList:
1712            G2frame.ErrorDialog('No match','No histograms match '+hst,G2frame.dataFrame)
1713            return
1714        dlg = G2gd.G2MultiChoiceDialog(
1715            G2frame.dataFrame,
1716            'Copy sample params from\n'+str(hst[5:])+' to...',
1717            'Copy sample parameters', histList)
1718        try:
1719            if dlg.ShowModal() == wx.ID_OK:
1720                result = dlg.GetSelections()
1721                for i in result: 
1722                    item = histList[i]
1723                    Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,item)
1724                    sampleData = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Sample Parameters'))
1725                    sampleData.update(copy.deepcopy(copyDict))
1726        finally:
1727            dlg.Destroy()
1728
1729    def OnSampleCopySelected(event):
1730        hst = G2frame.PatternTree.GetItemText(G2frame.PatternId)
1731        Controls = G2frame.PatternTree.GetItemPyData(
1732            G2gd.GetPatternTreeItemId(G2frame,G2frame.root, 'Controls'))
1733        histList = GetHistsLikeSelected(G2frame)
1734        if not histList:
1735            G2frame.ErrorDialog('No match','No histograms match '+hst,G2frame.dataFrame)
1736            return
1737        # Assemble a list of item labels
1738        TextTable = {key:label for key,label,dig in
1739                     SetupSampleLabels(hst,data.get('Type'),Inst['Type'][0])
1740                     }
1741        # get flexible labels
1742        TextTable.update({
1743            key:Controls[key] for key in Controls if key.startswith('FreePrm')
1744            })
1745        # add a few extra
1746        TextTable.update({
1747            'Type':'Diffractometer type',
1748            'InstrName':'Instrument Name',
1749            })
1750        # Assemble a list of dict entries that would be labeled in the Sample
1751        # params data window (drop ranId and items not used).
1752        keyList = [i for i in data.keys() if i in TextTable]
1753        keyText = [TextTable[i] for i in keyList]
1754        # sort both lists together, ordered by keyText
1755        keyText, keyList = zip(*sorted(zip(keyText,keyList))) # sort lists
1756        selectedKeys = []
1757        dlg = G2gd.G2MultiChoiceDialog(
1758            G2frame.dataFrame,
1759            'Select which sample parameters\nto copy',
1760            'Select sample parameters', keyText)
1761        try:
1762            if dlg.ShowModal() == wx.ID_OK:
1763                selectedKeys = [keyList[i] for i in dlg.GetSelections()]
1764        finally:
1765            dlg.Destroy()
1766        if not selectedKeys: return # nothing to copy
1767        copyDict = {}
1768        for parm in selectedKeys:
1769            copyDict[parm] = data[parm]
1770        dlg = G2gd.G2MultiChoiceDialog(
1771            G2frame.dataFrame,
1772            'Copy sample params from\n'+str(hst[5:])+' to...',
1773            'Copy sample parameters', histList)
1774        try:
1775            if dlg.ShowModal() == wx.ID_OK:
1776                result = dlg.GetSelections()
1777                for i in result: 
1778                    item = histList[i]
1779                    Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,item)
1780                    sampleData = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Sample Parameters'))
1781                    sampleData.update(copy.deepcopy(copyDict))
1782        finally:
1783            dlg.Destroy()           
1784        G2plt.PlotPatterns(G2frame,plotType='SASD',newPlot=False)
1785
1786    def OnSampleFlagCopy(event):
1787        histType,copyNames = SetCopyNames(histName,data['Type'])
1788        flagDict = {}
1789        for parm in copyNames:
1790            flagDict[parm] = data[parm][1]
1791        hst = G2frame.PatternTree.GetItemText(G2frame.PatternId)
1792        histList = GetHistsLikeSelected(G2frame)
1793        if not histList:
1794            G2frame.ErrorDialog('No match','No histograms match '+hst,G2frame.dataFrame)
1795            return
1796        dlg = G2gd.G2MultiChoiceDialog(
1797            G2frame.dataFrame, 
1798            'Copy sample ref. flags from\n'+str(hst[5:])+' to...',
1799            'Copy sample flags', histList)
1800        try:
1801            if dlg.ShowModal() == wx.ID_OK:
1802                result = dlg.GetSelections()
1803                for i in result: 
1804                    item = histList[i]
1805                    Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,item)
1806                    sampleData = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Sample Parameters'))
1807                    for name in copyNames:
1808                        sampleData[name][1] = copy.copy(flagDict[name])
1809        finally:
1810            dlg.Destroy()
1811
1812    def OnHistoChange():
1813        '''Called when the histogram type is changed to refresh the window
1814        '''
1815        wx.CallAfter(UpdateSampleGrid,G2frame,data)
1816       
1817    def SetNameVal():
1818        inst = instNameVal.GetValue()
1819        data['InstrName'] = inst.strip()
1820
1821    def OnNameVal(event):
1822        event.Skip()
1823        wx.CallAfter(SetNameVal)
1824       
1825    def AfterChange(invalid,value,tc):
1826        if invalid:
1827            return
1828        if tc.key == 0 and 'SASD' in histName:          #a kluge for Scale!
1829            G2plt.PlotPatterns(G2frame,plotType='SASD',newPlot=True)
1830        elif tc.key == 'Thick':
1831            wx.CallAfter(UpdateSampleGrid,G2frame,data)           
1832           
1833    def OnMaterial(event):
1834        Obj = event.GetEventObject()
1835        id,key = Info[Obj.GetId()]
1836        if key == 'Name':
1837            data['Materials'][id][key] = Obj.GetValue()
1838        elif key == 'VolFrac':
1839            try:
1840                value = min(max(0.,float(Obj.GetValue())),1.)
1841            except ValueError:
1842                value = data['Materials'][id][key]
1843            data['Materials'][id][key] = value
1844            data['Materials'][not id][key] = 1.-value
1845        wx.CallAfter(UpdateSampleGrid,G2frame,data)
1846
1847    def OnCopy1Val(event):
1848        'Select one value to copy to many histograms and optionally allow values to be edited in a table'
1849        G2gd.SelectEdit1Var(G2frame,data,labelLst,elemKeysLst,dspLst,refFlgElem)
1850        wx.CallAfter(UpdateSampleGrid,G2frame,data)
1851       
1852    ######## DEBUG #######################################################
1853    #import GSASIIpwdGUI
1854    #reload(GSASIIpwdGUI)
1855    #reload(G2gd)
1856    ######################################################################
1857    Inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(
1858            G2frame,G2frame.PatternId, 'Instrument Parameters'))[0]
1859    histName = G2frame.PatternTree.GetItemText(G2frame.PatternId)
1860    if G2frame.dataDisplay:
1861        G2frame.dataFrame.Clear()
1862    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.SampleMenu)
1863    G2frame.dataFrame.SetLabel('Sample Parameters')
1864    G2frame.Bind(wx.EVT_MENU, OnSetScale, id=G2gd.wxID_SETSCALE)
1865    G2frame.Bind(wx.EVT_MENU, OnSampleCopy, id=G2gd.wxID_SAMPLECOPY)
1866    G2frame.Bind(wx.EVT_MENU, OnSampleCopySelected, id=G2gd.wxID_SAMPLECOPYSOME)
1867    G2frame.Bind(wx.EVT_MENU, OnSampleFlagCopy, id=G2gd.wxID_SAMPLEFLAGCOPY)
1868    G2frame.Bind(wx.EVT_MENU, OnSampleSave, id=G2gd.wxID_SAMPLESAVE)
1869    G2frame.Bind(wx.EVT_MENU, OnSampleLoad, id=G2gd.wxID_SAMPLELOAD)
1870    G2frame.Bind(wx.EVT_MENU, OnCopy1Val, id=G2gd.wxID_SAMPLE1VAL)
1871    G2frame.Bind(wx.EVT_MENU, OnAllSampleLoad, id=G2gd.wxID_ALLSAMPLELOAD)
1872    if 'SASD' in histName:
1873        G2frame.dataFrame.SetScale.Enable(True)
1874    if not G2frame.dataFrame.GetStatusBar():
1875        Status = G2frame.dataFrame.CreateStatusBar()   
1876    G2frame.dataDisplay = wx.Panel(G2frame.dataFrame)
1877    Controls = G2frame.PatternTree.GetItemPyData(
1878        G2gd.GetPatternTreeItemId(G2frame,G2frame.root, 'Controls'))
1879#patch
1880    if 'ranId' not in data:
1881        data['ranId'] = ran.randint(0,sys.maxint)
1882    if not 'Gonio. radius' in data:
1883        data['Gonio. radius'] = 200.0
1884    if not 'Omega' in data:
1885        data.update({'Omega':0.0,'Chi':0.0,'Phi':0.0})
1886    if type(data['Temperature']) is int:
1887        data['Temperature'] = float(data['Temperature'])
1888    if 'Time' not in data:
1889        data['Time'] = 0.0
1890    if 'FreePrm1' not in Controls:
1891        Controls['FreePrm1'] = 'Sample humidity (%)'
1892    if 'FreePrm2' not in Controls:
1893        Controls['FreePrm2'] = 'Sample voltage (V)'
1894    if 'FreePrm3' not in Controls:
1895        Controls['FreePrm3'] = 'Applied load (MN)'
1896    if 'FreePrm1' not in data:
1897        data['FreePrm1'] = 0.
1898    if 'FreePrm2' not in data:
1899        data['FreePrm2'] = 0.
1900    if 'FreePrm3' not in data:
1901        data['FreePrm3'] = 0.
1902    if 'SurfRoughA' not in data and 'PWDR' in histName:
1903        data['SurfRoughA'] = [0.,False]
1904        data['SurfRoughB'] = [0.,False]
1905    if 'Trans' not in data and 'SASD' in histName:
1906        data['Trans'] = 1.0
1907    if 'SlitLen' not in data and 'SASD' in histName:
1908        data['SlitLen'] = 0.0
1909    if 'Shift' not in data:
1910        data['Shift'] = [0.0,False]
1911    if 'Transparency' not in data:
1912        data['Transparency'] = [0.0,False]
1913    data['InstrName'] = data.get('InstrName','')
1914#patch end
1915    labelLst,elemKeysLst,dspLst,refFlgElem = [],[],[],[]
1916    parms = SetupSampleLabels(histName,data.get('Type'),Inst['Type'][0])
1917    mainSizer = wx.BoxSizer(wx.VERTICAL)
1918    topSizer = wx.BoxSizer(wx.HORIZONTAL)
1919    topSizer.Add((-1,-1),1,wx.EXPAND,1)
1920    topSizer.Add(wx.StaticText(G2frame.dataDisplay,label='Sample and Experimental Parameters'))
1921    topSizer.Add((-1,-1),1,wx.EXPAND,1)
1922    mainSizer.Add(topSizer,0,wx.EXPAND,1)
1923    nameSizer = wx.BoxSizer(wx.HORIZONTAL)
1924    nameSizer.Add(wx.StaticText(G2frame.dataDisplay,wx.ID_ANY,' Instrument Name'),
1925                0,WACV)
1926    nameSizer.Add((-1,-1),1,wx.EXPAND,1)
1927    instNameVal = wx.TextCtrl(G2frame.dataDisplay,wx.ID_ANY,data['InstrName'],
1928                              size=(200,-1),style=wx.TE_PROCESS_ENTER)       
1929    nameSizer.Add(instNameVal)
1930    instNameVal.Bind(wx.EVT_CHAR,OnNameVal)
1931    mainSizer.Add(nameSizer,0,wx.EXPAND,1)
1932    mainSizer.Add((5,5),0)
1933    labelLst.append('Instrument Name')
1934    elemKeysLst.append(['InstrName'])
1935    dspLst.append(None)
1936    refFlgElem.append(None)
1937
1938    if 'PWDR' in histName:
1939        nameSizer = wx.BoxSizer(wx.HORIZONTAL)
1940        nameSizer.Add(wx.StaticText(G2frame.dataDisplay,wx.ID_ANY,' Diffractometer type: '),
1941                    0,WACV)
1942        if 'T' in Inst['Type'][0]:
1943            choices = ['Debye-Scherrer',]
1944        else:
1945            choices = ['Debye-Scherrer','Bragg-Brentano',]
1946        histoType = G2gd.G2ChoiceButton(G2frame.dataDisplay,choices,
1947                    strLoc=data,strKey='Type',
1948                    onChoice=OnHistoChange)
1949        nameSizer.Add(histoType)
1950        mainSizer.Add(nameSizer,0,wx.EXPAND,1)
1951        mainSizer.Add((5,5),0)
1952
1953    parmSizer = wx.FlexGridSizer(0,2,5,0)
1954    for key,lbl,nDig in parms:
1955        labelLst.append(lbl.strip().strip(':').strip())
1956        dspLst.append(nDig)
1957        if 'list' in str(type(data[key])):
1958            parmRef = G2gd.G2CheckBox(G2frame.dataDisplay,' '+lbl,data[key],1)
1959            parmSizer.Add(parmRef,0,WACV|wx.EXPAND)
1960            parmVal = G2gd.ValidatedTxtCtrl(G2frame.dataDisplay,data[key],0,
1961                nDig=nDig,typeHint=float,OnLeave=AfterChange)
1962            elemKeysLst.append([key,0])
1963            refFlgElem.append([key,1])
1964        else:
1965            parmSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' '+lbl),
1966                0,WACV|wx.EXPAND)
1967            parmVal = G2gd.ValidatedTxtCtrl(G2frame.dataDisplay,data,key,
1968                typeHint=float,OnLeave=AfterChange)
1969            elemKeysLst.append([key])
1970            refFlgElem.append(None)
1971        parmSizer.Add(parmVal,1,wx.EXPAND)
1972    Info = {}
1973       
1974    for key in ('FreePrm1','FreePrm2','FreePrm3'):
1975        parmVal = G2gd.ValidatedTxtCtrl(G2frame.dataDisplay,Controls,key,typeHint=str,
1976                                        notBlank=False)
1977        parmSizer.Add(parmVal,1,wx.EXPAND)
1978        parmVal = G2gd.ValidatedTxtCtrl(G2frame.dataDisplay,data,key,typeHint=float)
1979        parmSizer.Add(parmVal,1,wx.EXPAND)
1980        labelLst.append(Controls[key])
1981        dspLst.append(None)
1982        elemKeysLst.append([key])
1983        refFlgElem.append(None)
1984       
1985    mainSizer.Add(parmSizer,1,wx.EXPAND)
1986    mainSizer.Add((0,5),0)   
1987    if 'SASD' in histName:
1988        rho = [0.,0.]
1989        anomrho = [0.,0.]
1990        mu = 0.
1991        subSizer = wx.FlexGridSizer(0,4,5,5)
1992        Substances = G2frame.PatternTree.GetItemPyData(
1993            G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Substances'))
1994        for id,item in enumerate(data['Materials']):
1995            subSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Material: '),0,WACV)
1996            matsel = wx.ComboBox(G2frame.dataDisplay,value=item['Name'],choices=Substances['Substances'].keys(),
1997                style=wx.CB_READONLY|wx.CB_DROPDOWN)
1998            Info[matsel.GetId()] = [id,'Name']
1999            matsel.Bind(wx.EVT_COMBOBOX,OnMaterial)       
2000            subSizer.Add(matsel,0,WACV)
2001            subSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Volume fraction: '),0,WACV)
2002            volfrac = wx.TextCtrl(G2frame.dataDisplay,value=str('%.3f'%(item['VolFrac'])),style=wx.TE_PROCESS_ENTER)
2003            Info[volfrac.GetId()] = [id,'VolFrac']
2004            volfrac.Bind(wx.EVT_TEXT_ENTER,OnMaterial)
2005            volfrac.Bind(wx.EVT_KILL_FOCUS,OnMaterial)
2006            subSizer.Add(volfrac,0,WACV)
2007            material = Substances['Substances'][item['Name']]
2008            mu += item['VolFrac']*material.get('XAbsorption',0.)
2009            rho[id] = material['Scatt density']
2010            anomrho[id] = material.get('XAnom density',0.)
2011        data['Contrast'] = [(rho[1]-rho[0])**2,(anomrho[1]-anomrho[0])**2]
2012        mainSizer.Add(subSizer,0)
2013        conSizer = wx.BoxSizer(wx.HORIZONTAL)
2014        conSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Contrast: %10.2f '%(data['Contrast'][0])),0,WACV)
2015        conSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Anom. Contrast: %10.2f '%(data['Contrast'][1])),0,WACV)
2016        mut =  mu*data['Thick']
2017        conSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Transmission (calc): %10.3f  '%(np.exp(-mut))),0,WACV)
2018        mainSizer.Add(conSizer,0)
2019   
2020    mainSizer.Layout()   
2021    G2frame.dataDisplay.SetSizer(mainSizer)
2022    Size = mainSizer.Fit(G2frame.dataFrame)
2023    G2frame.dataDisplay.SetSize(Size)
2024    G2frame.dataFrame.setSizePosLeft(Size)
2025               
2026################################################################################
2027#####  Indexing Peaks
2028################################################################################           
2029       
2030def UpdateIndexPeaksGrid(G2frame, data):
2031    '''respond to selection of PWDR Index Peak List data
2032    tree item.
2033    '''
2034    bravaisSymb = ['Fm3m','Im3m','Pm3m','R3-H','P6/mmm','I4/mmm',
2035        'P4/mmm','Fmmm','Immm','Cmmm','Pmmm','C2/m','P2/m','P1']
2036    IndexId = G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Index Peak List')
2037    Inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Instrument Parameters'))[0]
2038
2039    def RefreshIndexPeaksGrid(event):
2040        r,c =  event.GetRow(),event.GetCol()
2041        peaks = G2frame.IndexPeaksTable.GetData()
2042        if c == 2:
2043            if peaks[r][c]:
2044                peaks[r][c] = False
2045            else:
2046                peaks[r][c] = True
2047            G2frame.IndexPeaksTable.SetData(peaks)
2048            G2frame.PatternTree.SetItemPyData(IndexId,[peaks,data[1]])
2049            G2frame.dataDisplay.ForceRefresh()
2050            if 'PKS' in G2frame.PatternTree.GetItemText(G2frame.PatternId):
2051                G2plt.PlotPowderLines(G2frame)
2052            else:
2053                G2plt.PlotPatterns(G2frame,plotType='PWDR')
2054           
2055    def OnReload(event):
2056        peaks = []
2057        sigs = []
2058        Peaks = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Peak List'))
2059        for ip,peak in enumerate(Peaks['peaks']):
2060            dsp = G2lat.Pos2dsp(Inst,peak[0])
2061            peaks.append([peak[0],peak[2],True,False,0,0,0,dsp,0.0])    #SS?
2062            try:
2063                sig = Peaks['sigDict']['pos'+str(ip)]
2064            except KeyError:
2065                sig = 0.
2066            sigs.append(sig)
2067        data = [peaks,sigs]
2068        G2frame.PatternTree.SetItemPyData(IndexId,data)
2069        UpdateIndexPeaksGrid(G2frame,data)
2070       
2071    def KeyEditPickGrid(event):
2072        colList = G2frame.dataDisplay.GetSelectedCols()
2073        rowList = G2frame.dataDisplay.GetSelectedRows()
2074        data = G2frame.PatternTree.GetItemPyData(IndexId)
2075        if event.GetKeyCode() == wx.WXK_RETURN:
2076            event.Skip(True)
2077        elif event.GetKeyCode() == wx.WXK_CONTROL:
2078            event.Skip(True)
2079        elif event.GetKeyCode() == wx.WXK_SHIFT:
2080            event.Skip(True)
2081        elif colList:
2082            G2frame.dataDisplay.ClearSelection()
2083            key = event.GetKeyCode()
2084            for col in colList:
2085                if G2frame.IndexPeaksTable.GetColLabelValue(col) in ['use',]:
2086                    if key == 89: #'Y'
2087                        for row in range(G2frame.IndexPeaksTable.GetNumberRows()): data[0][row][col]=True
2088                    elif key == 78:  #'N'
2089                        for row in range(G2frame.IndexPeaksTable.GetNumberRows()): data[0][row][col]=False
2090           
2091    if G2frame.dataDisplay:
2092        G2frame.dataFrame.Clear()
2093    if not G2frame.dataFrame.GetStatusBar():
2094        Status = G2frame.dataFrame.CreateStatusBar()
2095    if 'PWD' in G2frame.PatternTree.GetItemText(G2frame.PatternId):
2096        G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.IndPeaksMenu)
2097        G2frame.Bind(wx.EVT_MENU, OnReload, id=G2gd.wxID_INDXRELOAD)
2098    G2frame.dataFrame.IndexPeaks.Enable(False)
2099    G2frame.IndexPeaksTable = []
2100    if len(data[0]):
2101        G2frame.dataFrame.IndexPeaks.Enable(True)
2102        Unit = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Unit Cells List'))
2103        if Unit:
2104            if len(Unit) == 4:  #patch
2105                Unit.append({})
2106            controls,bravais,cellist,dmin,ssopt = Unit
2107            G2frame.HKL = []
2108            if ssopt.get('Use',False):
2109                cell = controls[6:12]
2110                A = G2lat.cell2A(cell)
2111                ibrav = bravaisSymb.index(controls[5])
2112                spc = controls[13]
2113                SGData = G2spc.SpcGroup(spc)[1]
2114                SSGData = G2spc.SSpcGroup(SGData,ssopt['ssSymb'])
2115                Vec = ssopt['ModVec']
2116                maxH = ssopt['maxH']
2117                G2frame.HKL = G2pwd.getHKLMpeak(dmin,Inst,SGData,SSGData,Vec,maxH,A)
2118                data[0] = G2indx.IndexSSPeaks(data[0],G2frame.HKL)[1]
2119            else:        #select cell from table - no SS
2120                for i,cell in enumerate(cellist):
2121                    if cell[-2]:
2122                        ibrav = cell[2]
2123                        A = G2lat.cell2A(cell[3:9])
2124                        G2frame.HKL = G2lat.GenHBravais(dmin,ibrav,A)
2125                        for hkl in G2frame.HKL:
2126                            hkl.insert(4,G2lat.Dsp2pos(Inst,hkl[3]))
2127                        data[0] = G2indx.IndexPeaks(data[0],G2frame.HKL)[1]
2128                        break
2129    rowLabels = []
2130    for i in range(len(data[0])): rowLabels.append(str(i+1))
2131    colLabels = ['position','intensity','use','indexed','h','k','l','d-obs','d-calc']
2132    Types = [wg.GRID_VALUE_FLOAT+':10,4',wg.GRID_VALUE_FLOAT+':10,1',]+2*[wg.GRID_VALUE_BOOL,]+ \
2133        3*[wg.GRID_VALUE_LONG,]+2*[wg.GRID_VALUE_FLOAT+':10,5',]
2134    if len(data[0]) and len(data[0][0]) > 9:
2135        colLabels = ['position','intensity','use','indexed','h','k','l','m','d-obs','d-calc']
2136        Types = [wg.GRID_VALUE_FLOAT+':10,4',wg.GRID_VALUE_FLOAT+':10,1',]+2*[wg.GRID_VALUE_BOOL,]+ \
2137            4*[wg.GRID_VALUE_LONG,]+2*[wg.GRID_VALUE_FLOAT+':10,5',]
2138    G2frame.PatternTree.SetItemPyData(IndexId,data)
2139    G2frame.IndexPeaksTable = G2gd.Table(data[0],rowLabels=rowLabels,colLabels=colLabels,types=Types)
2140    G2frame.dataFrame.SetLabel('Index Peak List')
2141    G2frame.dataDisplay = G2gd.GSGrid(parent=G2frame.dataFrame)               
2142    G2frame.dataDisplay.SetTable(G2frame.IndexPeaksTable, True)
2143    XY = []
2144    Sigs = []
2145    for r in range(G2frame.dataDisplay.GetNumberRows()):
2146        for c in range(G2frame.dataDisplay.GetNumberCols()):
2147            if c == 2:
2148                G2frame.dataDisplay.SetReadOnly(r,c,isReadOnly=False)
2149            else:
2150                G2frame.dataDisplay.SetReadOnly(r,c,isReadOnly=True)
2151        if data[0][r][2] and data[0][r][3]:
2152            XY.append([data[0][r][-1],data[0][r][0]])
2153            try:
2154                sig = data[1][r]
2155            except IndexError:
2156                sig = 0.
2157            Sigs.append(sig)
2158    G2frame.dataDisplay.Bind(wg.EVT_GRID_CELL_LEFT_CLICK, RefreshIndexPeaksGrid)
2159    G2frame.dataDisplay.Bind(wx.EVT_KEY_DOWN, KeyEditPickGrid)                 
2160    G2frame.dataDisplay.SetMargins(0,0)
2161    G2frame.dataDisplay.AutoSizeColumns(False)
2162    G2frame.dataFrame.setSizePosLeft([490,300])
2163    if len(XY):
2164        XY = np.array(XY)
2165        G2plt.PlotCalib(G2frame,Inst,XY,Sigs,newPlot=True)
2166    G2frame.dataFrame.SendSizeEvent()
2167     
2168################################################################################
2169#####  Unit cells
2170################################################################################           
2171       
2172def UpdateUnitCellsGrid(G2frame, data):
2173    '''respond to selection of PWDR Unit Cells data tree item.
2174    '''
2175    UnitCellsId = G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Unit Cells List')
2176    SPGlist = G2spc.spglist
2177    ifX20 = True
2178    bravaisSymb = ['Fm3m','Im3m','Pm3m','R3-H','P6/mmm','I4/mmm',
2179        'P4/mmm','Fmmm','Immm','Cmmm','Pmmm','C2/m','P2/m','P1']
2180    spaceGroups = ['F m 3 m','I m 3 m','P m 3 m','R 3 m','P 6/m m m','I 4/m m m',
2181        'P 4/m m m','F m m m','I m m m','C m m m','P m m m','C 2/m','P 2/m','P -1']
2182    Inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Instrument Parameters'))[0]
2183    if 'C' in Inst['Type'][0]:
2184        wave = G2mth.getWave(Inst)
2185    else:
2186        difC = Inst['difC'][1]
2187   
2188    def SetLattice(controls):
2189        ibrav = bravaisSymb.index(controls[5])
2190        if ibrav in [0,1,2]:
2191            controls[7] = controls[8] = controls[6]
2192            controls[9] = controls[10] = controls[11] = 90.
2193        elif ibrav in [3,4,5,6]:
2194            controls[7] = controls[6]
2195            controls[9] = controls[10] = controls[11] = 90.
2196            if ibrav in [3,4]:
2197                controls[11] = 120.
2198        elif ibrav in [7,8,9,10]:
2199            controls[9] = controls[10] = controls[11] = 90.
2200        elif ibrav in [11,12]:
2201            controls[9] = controls[11] = 90.  # b unique
2202        if len(controls) < 13: controls.append(0)
2203        controls[12] = G2lat.calc_V(G2lat.cell2A(controls[6:12]))
2204        return ibrav
2205       
2206    def OnNcNo(event):
2207        controls[2] = NcNo.GetValue()
2208       
2209    def OnIfX20(event):
2210        ifX20 = x20.GetValue()
2211       
2212    def OnStartVol(event):
2213        try:
2214            stVol = int(float(startVol.GetValue()))
2215            if stVol < 25:
2216                raise ValueError
2217        except ValueError:
2218            stVol = 25
2219        controls[3] = stVol
2220        startVol.SetValue("%d"%(stVol))
2221       
2222    def OnBravais(event):
2223        Obj = event.GetEventObject()
2224        bravais[bravList.index(Obj.GetId())] = Obj.GetValue()
2225       
2226    def OnZero(event):
2227        try:
2228            Zero = min(5.0,max(-5.0,float(zero.GetValue())))
2229        except ValueError:
2230            Zero = 0.0
2231        controls[1] = Zero
2232        zero.SetValue("%.4f"%(Zero))
2233       
2234    def OnZeroVar(event):
2235        controls[0] = zeroVar.GetValue()
2236       
2237    def OnSSopt(event):
2238        if controls[5] in ['Fm3m','Im3m','Pm3m']:
2239            SSopt.SetValue(False)
2240            G2frame.ErrorDialog('Cubic lattice', 'Superlattice not allowed for a cubic lattice')
2241            return
2242        ssopt['Use'] = SSopt.GetValue()
2243        wx.CallAfter(UpdateUnitCellsGrid,G2frame,data)
2244       
2245    def OnSelMG(event):
2246        ssopt['ssSymb'] = selMG.GetValue()
2247        Vec = ssopt['ModVec']
2248        modS = G2spc.splitSSsym(ssopt['ssSymb'])[0]
2249        ssopt['ModVec'] = G2spc.SSGModCheck(Vec,modS)[0]
2250        OnHklShow(event)
2251        wx.CallAfter(UpdateUnitCellsGrid,G2frame,data)
2252       
2253    def OnModVal(event):
2254        Obj = event.GetEventObject()
2255        ObjId = Obj.GetId()
2256        Id = Indx[ObjId]
2257        try:
2258            value = min(1.0,max(0.,float(Obj.GetValue())))
2259        except ValueError:
2260            value = ssopt['ModVec'][Id]
2261        Obj.SetValue('%.4f'%(value))
2262        ssopt['ModVec'][Id] = value
2263        OnHklShow(event)
2264       
2265    def OnMoveMod(event):
2266        Obj = event.GetEventObject()
2267        ObjId = Obj.GetId()
2268        Id,valObj = Indx[ObjId]
2269        move = Obj.GetValue()*0.0005
2270        Obj.SetValue(0)
2271        value = min(1.0,max(.0,float(valObj.GetValue())+move))
2272        valObj.SetValue('%.4f'%(value)) 
2273        ssopt['ModVec'][Id] = value
2274        OnHklShow(event)
2275       
2276    def OnMaxMH(event):
2277        ssopt['maxH'] = int(maxMH.GetValue())
2278        OnHklShow(event)
2279       
2280    def OnFindMV(event):
2281        Peaks = np.copy(peaks[0])
2282        ssopt['ModVec'] = G2indx.findMV(Peaks,controls,ssopt,Inst)
2283        OnHklShow(event)
2284        wx.CallAfter(UpdateUnitCellsGrid,G2frame,data)
2285       
2286    def OnBravSel(event):
2287        brav = bravSel.GetString(bravSel.GetSelection())
2288        controls[5] = brav
2289        controls[13] = SPGlist[brav][0]       
2290        wx.CallAfter(UpdateUnitCellsGrid,G2frame,data)
2291       
2292    def OnSpcSel(event):
2293        controls[13] = spcSel.GetString(spcSel.GetSelection())
2294       
2295    def SetCellValue(Obj,ObjId,value):
2296        ibrav = bravaisSymb.index(controls[5])
2297        if ibrav in [0,1,2]:
2298            controls[6] = controls[7] = controls[8] = value
2299            controls[9] = controls[10] = controls[11] = 90.0
2300            Obj.SetValue("%.5f"%(controls[6]))
2301        elif ibrav in [3,4,5,6]:
2302            if ObjId == 0:
2303                controls[6] = controls[7] = value
2304                Obj.SetValue("%.5f"%(controls[6]))
2305            else:
2306                controls[8] = value
2307                Obj.SetValue("%.5f"%(controls[8]))
2308            controls[9] = controls[10] = controls[11] = 90.0
2309            if ibrav in [3,4]:
2310                controls[11] = 120.
2311        elif ibrav in [7,8,9,10]:
2312            controls[6+ObjId] = value
2313            Obj.SetValue("%.5f"%(controls[6+ObjId]))
2314            controls[9] = controls[10] = controls[11] = 90.0
2315        elif ibrav in [11,12]:
2316            controls[9] = controls[11] = 90.0
2317            if ObjId != 3:
2318                controls[6+ObjId] = value
2319                Obj.SetValue("%.5f"%(controls[6+ObjId]))
2320            else:
2321                controls[10] = value
2322                Obj.SetValue("%.3f"%(controls[10]))
2323        else:
2324            controls[6+ObjId] = value
2325            if ObjId < 3:
2326                Obj.SetValue("%.5f"%(controls[6+ObjId]))
2327            else:
2328                Obj.SetValue("%.3f"%(controls[6+ObjId]))
2329        controls[12] = G2lat.calc_V(G2lat.cell2A(controls[6:12]))
2330        volVal.SetValue("%.3f"%(controls[12]))
2331       
2332    def OnMoveCell(event):
2333        Obj = event.GetEventObject()
2334        ObjId = cellList.index(Obj.GetId())
2335        valObj = valDict[Obj.GetId()]
2336        if ObjId/2 < 3:
2337            move = Obj.GetValue()*0.01
2338        else:
2339            move = Obj.GetValue()*0.1
2340        Obj.SetValue(0)
2341        value = float(valObj.GetValue())+move 
2342        SetCellValue(valObj,ObjId/2,value)
2343        OnHklShow(event)
2344       
2345    def OnCellChange(event):
2346        Obj = event.GetEventObject()
2347        ObjId = cellList.index(Obj.GetId())
2348        try:
2349            value = max(1.0,float(Obj.GetValue()))
2350        except ValueError:
2351            if ObjId/2 < 3:               #bad cell edge - reset
2352                value = controls[6+ObjId/2]
2353            else:                       #bad angle
2354                value = 90.
2355        SetCellValue(Obj,ObjId/2,value)
2356       
2357    def OnHklShow(event):
2358        PatternId = G2frame.PatternId
2359        PickId = G2frame.PickId   
2360        peaks = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Index Peak List'))
2361        limits = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Limits'))[1]
2362        controls,bravais,cells,dmin,ssopt = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Unit Cells List'))
2363        cell = controls[6:12]
2364        A = G2lat.cell2A(cell)
2365        ibrav = bravaisSymb.index(controls[5])
2366        spc = controls[13]
2367        SGData = G2spc.SpcGroup(spc)[1]
2368        if 'C' in Inst['Type'][0]:
2369            dmin = G2lat.Pos2dsp(Inst,limits[1])
2370        else:   #TOF - use other limit!
2371            dmin = G2lat.Pos2dsp(Inst,limits[0])
2372        if ssopt.get('Use',False):
2373            SSGData = G2spc.SSpcGroup(SGData,ssopt['ssSymb'])
2374            Vec = ssopt['ModVec']
2375            maxH = ssopt['maxH']
2376            G2frame.HKL = G2pwd.getHKLMpeak(dmin,Inst,SGData,SSGData,Vec,maxH,A)
2377            peaks = [G2indx.IndexSSPeaks(peaks[0],G2frame.HKL)[1],peaks[1]]   #keep esds from peak fit
2378            M20,X20 = G2indx.calc_M20SS(peaks[0],G2frame.HKL)
2379        else:
2380            G2frame.HKL = G2pwd.getHKLpeak(dmin,Inst,SGData,A)
2381            peaks = [G2indx.IndexPeaks(peaks[0],G2frame.HKL)[1],peaks[1]]   #keep esds from peak fit
2382            M20,X20 = G2indx.calc_M20(peaks[0],G2frame.HKL)
2383        print ' new M20,X20: %.2f %d'%(M20,X20)
2384        G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Index Peak List'),peaks)
2385        if 'PKS' in G2frame.PatternTree.GetItemText(G2frame.PatternId):
2386            G2plt.PlotPowderLines(G2frame)
2387        else:
2388            G2plt.PlotPatterns(G2frame)
2389           
2390    def OnSortCells(event):
2391        controls,bravais,cells,dmin,ssopt = G2frame.PatternTree.GetItemPyData(UnitCellsId)
2392        c =  event.GetCol()
2393        if colLabels[c] == 'M20':
2394            cells = G2indx.sortM20(cells)
2395        elif colLabels[c] in ['X20','Bravais','a','b','c','alpha','beta','gamma','Volume']:
2396            if c == 1:
2397                c += 1  #X20 before Use
2398            cells = G2indx.sortCells(cells,c-1)     #an extra column (Use) not in cells
2399        else:
2400            return
2401        data = [controls,bravais,cells,dmin,ssopt]
2402        G2frame.PatternTree.SetItemPyData(UnitCellsId,data)
2403        wx.CallAfter(UpdateUnitCellsGrid,G2frame,data)
2404       
2405    def CopyUnitCell(event):
2406        controls,bravais,cells,dmin,ssopt = G2frame.PatternTree.GetItemPyData(UnitCellsId)
2407        for Cell in cells:
2408            if Cell[-2]:
2409                break
2410        cell = Cell[2:9]
2411        controls[4] = 1
2412        controls[5] = bravaisSymb[cell[0]]
2413        controls[6:12] = cell[1:8]
2414        controls[12] = G2lat.calc_V(G2lat.cell2A(controls[6:12]))
2415        controls[13] = spaceGroups[bravaisSymb.index(controls[5])]
2416        G2frame.PatternTree.SetItemPyData(UnitCellsId,[controls,bravais,cells,dmin,ssopt])
2417        G2frame.dataFrame.RefineCell.Enable(True)
2418        wx.CallAfter(UpdateUnitCellsGrid,G2frame,data)       
2419               
2420    def RefineCell(event):
2421       
2422        def cellPrint(ibrav,A):
2423            cell = G2lat.A2cell(A)
2424            Vol = G2lat.calc_V(A)
2425            if ibrav in [0,1,2]:
2426                print " %s%10.6f" % ('a =',cell[0])
2427            elif ibrav in [3,4,5,6]:
2428                print " %s%10.6f %s%10.6f %s%12.3f" % ('a =',cell[0],' c =',cell[2],' volume =',Vol)
2429            elif ibrav in [7,8,9,10]:
2430                print " %s%10.6f %s%10.6f %s%10.6f %s%12.3f" % ('a =',cell[0],'b =',cell[1],'c =',cell[2],' volume =',Vol)
2431            elif ibrav in [11,12]:
2432                print " %s%10.6f %s%10.6f %s%10.6f %s%8.3f %s%12.3f" % ('a =',cell[0],'b =',cell[1],'c =',cell[2],'beta =',cell[4],' volume =',Vol)
2433            else:
2434                print " %s%10.6f %s%10.6f %s%10.6f" % ('a =',cell[0],'b =',cell[1],'c =',cell[2])
2435                print " %s%8.3f %s%8.3f %s%8.3f %s%12.3f" % ('alpha =',cell[3],'beta =',cell[4],'gamma =',cell[5],' volume =',Vol)
2436               
2437        def vecPrint(Vec):
2438            print ' %s %10.5f %10.5f %10.5f'%('Modulation vector:',Vec[0],Vec[1],Vec[2])
2439             
2440        PatternId = G2frame.PatternId
2441        PickId = G2frame.PickId   
2442        peaks = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Index Peak List'))
2443        if not len(peaks[0]):
2444            G2frame.ErrorDialog('No peaks!', 'Nothing to refine!')
2445            return       
2446        print ' Refine cell'
2447        controls,bravais,cells,dmin,ssopt = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Unit Cells List'))
2448        cell = controls[6:12]
2449        A = G2lat.cell2A(cell)
2450        ibrav = bravaisSymb.index(controls[5])
2451        SGData = G2spc.SpcGroup(controls[13])[1]
2452        dmin = G2indx.getDmin(peaks[0])-0.005
2453        if 'C' in Inst['Type'][0]:
2454            if ssopt.get('Use',False):
2455                vecFlags = [True if x in ssopt['ssSymb'] else False for x in ['a','b','g']]
2456                SSGData = G2spc.SSpcGroup(SGData,ssopt['ssSymb'])
2457                G2frame.HKL = G2pwd.getHKLMpeak(dmin,Inst,SGData,SSGData,ssopt['ModVec'],ssopt['maxH'],A)
2458                peaks = [G2indx.IndexSSPeaks(peaks[0],G2frame.HKL)[1],peaks[1]]   #put peak fit esds back in peaks
2459                Lhkl,M20,X20,Aref,Vec,Zero = \
2460                    G2indx.refinePeaksZSS(peaks[0],wave,Inst,SGData,SSGData,ssopt['maxH'],ibrav,A,ssopt['ModVec'],vecFlags,controls[1],controls[0])
2461            else:
2462                G2frame.HKL = G2pwd.getHKLpeak(dmin,Inst,SGData,A)
2463                peaks = [G2indx.IndexPeaks(peaks[0],G2frame.HKL)[1],peaks[1]]   #put peak fit esds back in peaks
2464                Lhkl,M20,X20,Aref,Zero = G2indx.refinePeaksZ(peaks[0],wave,ibrav,A,controls[1],controls[0])
2465        else:   #'T'OF - doesn't seem to work
2466            G2frame.HKL = G2pwd.getHKLpeak(dmin,Inst,SGData,A)
2467            peaks = [G2indx.IndexPeaks(peaks[0],G2frame.HKL)[1],peaks[1]]   #put peak fit esds back in peaks
2468            Lhkl,M20,X20,Aref,Zero = G2indx.refinePeaksT(peaks[0],difC,ibrav,A,controls[1],controls[0])           
2469        controls[1] = Zero
2470        controls[6:12] = G2lat.A2cell(Aref)
2471        controls[12] = G2lat.calc_V(Aref)
2472        cells = G2frame.PatternTree.GetItemPyData(UnitCellsId)[2]
2473        for cell in cells:
2474            cell[-2] = False
2475        cells.insert(0,[M20,X20,ibrav]+controls[6:13]+[True,False])
2476        if ssopt.get('Use',False):
2477            ssopt['ModVec'] = Vec
2478            G2frame.HKL = G2pwd.getHKLMpeak(dmin,Inst,SGData,SSGData,ssopt['ModVec'],ssopt['maxH'],A)
2479        else:
2480            G2frame.HKL = G2pwd.getHKLpeak(dmin,Inst,SGData,A)
2481        data = [controls,bravais,cells,dmin,ssopt]
2482        G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Unit Cells List'),data)
2483        print " %s%10.3f" % ('refinement M20 = ',M20)
2484        print ' unindexed lines = ',X20
2485        cellPrint(ibrav,Aref)
2486        ip = 4
2487        if ssopt.get('Use',False):
2488            vecPrint(Vec)
2489            ip = 5
2490        for hkl in G2frame.HKL:
2491            hkl[ip] = G2lat.Dsp2pos(Inst,hkl[ip-1])+controls[1]
2492        if 'PKS' in G2frame.PatternTree.GetItemText(G2frame.PatternId):
2493            G2plt.PlotPowderLines(G2frame)
2494        else:
2495            G2plt.PlotPatterns(G2frame)
2496        wx.CallAfter(UpdateUnitCellsGrid,G2frame,data)
2497       
2498    def IndexPeaks(event):
2499        PatternId = G2frame.PatternId   
2500        print 'Peak Indexing'
2501        keepcells = []
2502        try:
2503            controls,bravais,cells,dmin,ssopt = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Unit Cells List'))
2504            for cell in cells:
2505                if cell[11]:
2506                    cell[10] = False    #clear selection flag on keepers
2507                    keepcells.append(cell)
2508        except IndexError:
2509            pass
2510        except ValueError:
2511            G2frame.ErrorDialog('Error','Need to set controls in Unit Cell List first')
2512            return
2513        if ssopt.get('Use',False):
2514            G2frame.ErrorDialog('Super lattice error','Indexing not available for super lattices')
2515            return
2516        if True not in bravais:
2517            G2frame.ErrorDialog('Error','No Bravais lattices selected')
2518            return
2519        if not peaks[0]:
2520            G2frame.ErrorDialog('Error','Index Peak List is empty')
2521            return
2522        if len(peaks[0][0]) > 9:
2523            G2frame.ErrorDialog('Error','You need to reload Index Peaks List first')
2524            return
2525        G2frame.dataFrame.CopyCell.Enable(False)
2526        G2frame.dataFrame.RefineCell.Enable(False)
2527        OK,dmin,newcells = G2indx.DoIndexPeaks(peaks[0],controls,bravais,ifX20)
2528        cells = keepcells+newcells
2529        cells = G2indx.sortM20(cells)
2530        cells[0][10] = True         #select best M20
2531        if OK:
2532            data = [controls,bravais,cells,dmin,ssopt]
2533            G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Unit Cells List'),data)
2534            bestCell = cells[0]
2535            if bestCell[0] > 10.:
2536                G2frame.HKL = G2lat.GenHBravais(dmin,bestCell[2],G2lat.cell2A(bestCell[3:9]))
2537                for hkl in G2frame.HKL:
2538                    hkl.insert(4,G2lat.Dsp2pos(Inst,hkl[3])+controls[1])
2539                if 'PKS' in G2frame.PatternTree.GetItemText(G2frame.PatternId):
2540                    G2plt.PlotPowderLines(G2frame)
2541                else:
2542                    G2plt.PlotPatterns(G2frame)
2543            G2frame.dataFrame.CopyCell.Enable(True)
2544            G2frame.dataFrame.IndexPeaks.Enable(True)
2545            G2frame.dataFrame.MakeNewPhase.Enable(True)
2546        wx.CallAfter(UpdateUnitCellsGrid,G2frame,data)
2547               
2548    def RefreshUnitCellsGrid(event):
2549        data = G2frame.PatternTree.GetItemPyData(UnitCellsId)
2550        cells,dmin = data[2:4]
2551        r,c =  event.GetRow(),event.GetCol()
2552        if cells:
2553            if c == 2:
2554                for i in range(len(cells)):
2555                    cells[i][-2] = False
2556                    UnitCellsTable.SetValue(i,c,False)
2557                UnitCellsTable.SetValue(r,c,True)
2558                gridDisplay.Refresh()
2559                cells[r][-2] = True
2560                ibrav = cells[r][2]
2561                A = G2lat.cell2A(cells[r][3:9])
2562                G2frame.HKL = G2lat.GenHBravais(dmin,ibrav,A)
2563                for hkl in G2frame.HKL:
2564                    hkl.insert(4,G2lat.Dsp2pos(Inst,hkl[3])+controls[1])
2565                if 'PKS' in G2frame.PatternTree.GetItemText(G2frame.PatternId):
2566                    G2plt.PlotPowderLines(G2frame)
2567                else:
2568                    G2plt.PlotPatterns(G2frame)
2569            elif c == 11:
2570                if UnitCellsTable.GetValue(r,c):
2571                    UnitCellsTable.SetValue(r,c,False)
2572                    cells[r][c] = False
2573                else:
2574                    cells[r][c] = True
2575                    UnitCellsTable.SetValue(r,c,True)
2576                gridDisplay.ForceRefresh()
2577            G2frame.PatternTree.SetItemPyData(UnitCellsId,data)
2578       
2579    def MakeNewPhase(event):
2580        if not G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Phases'):
2581            sub = G2frame.PatternTree.AppendItem(parent=G2frame.root,text='Phases')
2582        else:
2583            sub = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Phases')
2584        PhaseName = ''
2585        dlg = wx.TextEntryDialog(None,'Enter a name for this phase','Phase Name Entry','New phase',
2586            style=wx.OK)
2587        try:
2588            if dlg.ShowModal() == wx.ID_OK:
2589                PhaseName = dlg.GetValue()
2590                cells = G2frame.PatternTree.GetItemPyData(UnitCellsId)[2]
2591                for Cell in cells:
2592                    if Cell[-2]:
2593                        break
2594                cell = Cell[2:10]       
2595                sub = G2frame.PatternTree.AppendItem(parent=sub,text=PhaseName)
2596                E,SGData = G2spc.SpcGroup(controls[13])
2597                G2frame.PatternTree.SetItemPyData(sub, \
2598                    G2IO.SetNewPhase(Name=PhaseName,SGData=SGData,cell=cell[1:],Super=ssopt))
2599                Status.SetStatusText('Change space group from '+str(controls[13])+' if needed')
2600        finally:
2601            dlg.Destroy()
2602    if G2frame.dataDisplay:
2603        print G2frame.dataDisplay.GetScrollPos(wx.VERTICAL)
2604        G2frame.dataFrame.DestroyChildren()
2605    G2frame.dataDisplay = wxscroll.ScrolledPanel(G2frame.dataFrame)
2606    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.IndexMenu)
2607    if not G2frame.dataFrame.GetStatusBar():
2608        Status = G2frame.dataFrame.CreateStatusBar()
2609    G2frame.Bind(wx.EVT_MENU, IndexPeaks, id=G2gd.wxID_INDEXPEAKS)
2610    G2frame.Bind(wx.EVT_MENU, CopyUnitCell, id=G2gd.wxID_COPYCELL)
2611    G2frame.Bind(wx.EVT_MENU, RefineCell, id=G2gd.wxID_REFINECELL)
2612    G2frame.Bind(wx.EVT_MENU, MakeNewPhase, id=G2gd.wxID_MAKENEWPHASE)
2613   
2614    controls,bravais,cells,dmin,ssopt = data
2615    if len(controls) < 13:              #add cell volume if missing
2616        controls.append(G2lat.calc_V(G2lat.cell2A(controls[6:12])))
2617    if len(controls) < 14:              #add space gropu used in indexing
2618        controls.append(spaceGroups[bravaisSymb.index(controls[5])])
2619    G2frame.PatternTree.SetItemPyData(UnitCellsId,data)            #update with volume
2620    bravaisNames = ['Cubic-F','Cubic-I','Cubic-P','Trigonal-R','Trigonal/Hexagonal-P',
2621        'Tetragonal-I','Tetragonal-P','Orthorhombic-F','Orthorhombic-I','Orthorhombic-C',
2622        'Orthorhombic-P','Monoclinic-C','Monoclinic-P','Triclinic']
2623    cellGUIlist = [[[0,1,2],4,zip([" Unit cell: a = "," Vol = "],["%.5f","%.3f"],[True,False],[0,0])],
2624    [[3,4,5,6],6,zip([" Unit cell: a = "," c = "," Vol = "],["%.5f","%.5f","%.3f"],[True,True,False],[0,2,0])],
2625    [[7,8,9,10],8,zip([" Unit cell: a = "," b = "," c = "," Vol = "],["%.5f","%.5f","%.5f","%.3f"],
2626        [True,True,True,False],[0,1,2,0])],
2627    [[11,12],10,zip([" Unit cell: a = "," b = "," c = "," beta = "," Vol = "],
2628        ["%.5f","%.5f","%.5f","%.3f","%.3f"],[True,True,True,True,False],[0,1,2,4,0])],
2629    [[13,],8,zip([" Unit cell: a = "," b = "," c = "," Vol = "," alpha = "," beta = "," gamma = "],
2630        ["%.5f","%.5f","%.5f","%.3f","%.3f","%.3f","%.3f"],
2631        [True,True,True,False,True,True,True],[0,1,2,0,3,4,5])]]
2632   
2633    G2frame.dataFrame.SetLabel('Unit Cells List')
2634    G2frame.dataFrame.IndexPeaks.Enable(False)
2635    peaks = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Index Peak List'))
2636    if peaks:
2637        G2frame.dataFrame.IndexPeaks.Enable(True)
2638    G2frame.dataFrame.RefineCell.Enable(False)
2639    if controls[12] > 1.0:                               #if a "real" volume (i.e. not default)
2640        G2frame.dataFrame.RefineCell.Enable(True)   
2641    G2frame.dataFrame.CopyCell.Enable(False)
2642    G2frame.dataFrame.MakeNewPhase.Enable(False)       
2643    if cells:
2644        G2frame.dataFrame.CopyCell.Enable(True)
2645        G2frame.dataFrame.MakeNewPhase.Enable(True)       
2646    mainSizer = wx.BoxSizer(wx.VERTICAL)
2647    mainSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Indexing controls: '),0,WACV)
2648    mainSizer.Add((5,5),0)
2649    littleSizer = wx.FlexGridSizer(0,5,5,5)
2650    littleSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Max Nc/Nobs '),0,WACV)
2651    NcNo = wx.SpinCtrl(G2frame.dataDisplay)
2652    NcNo.SetRange(2,6)
2653    NcNo.SetValue(controls[2])
2654    NcNo.Bind(wx.EVT_SPINCTRL,OnNcNo)
2655    littleSizer.Add(NcNo,0,WACV)
2656    littleSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Start Volume '),0,WACV)
2657    startVol = wx.TextCtrl(G2frame.dataDisplay,value=str('%d'%(controls[3])),style=wx.TE_PROCESS_ENTER)
2658    startVol.Bind(wx.EVT_TEXT_ENTER,OnStartVol)
2659    startVol.Bind(wx.EVT_KILL_FOCUS,OnStartVol)
2660    littleSizer.Add(startVol,0,WACV)
2661    x20 = wx.CheckBox(G2frame.dataDisplay,label='Use M20/(X20+1)?')
2662    x20.SetValue(ifX20)
2663    x20.Bind(wx.EVT_CHECKBOX,OnIfX20)
2664    littleSizer.Add(x20,0,WACV)
2665    mainSizer.Add(littleSizer,0)
2666    mainSizer.Add((5,5),0)
2667    mainSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Select Bravais Lattices for indexing: '),
2668        0,WACV)
2669    mainSizer.Add((5,5),0)
2670    littleSizer = wx.FlexGridSizer(0,7,5,5)
2671    bravList = []
2672    bravs = zip(bravais,bravaisNames)
2673    for brav,bravName in bravs:
2674        bravCk = wx.CheckBox(G2frame.dataDisplay,label=bravName)
2675        bravList.append(bravCk.GetId())
2676        bravCk.SetValue(brav)
2677        bravCk.Bind(wx.EVT_CHECKBOX,OnBravais)
2678        littleSizer.Add(bravCk,0,WACV)
2679    mainSizer.Add(littleSizer,0)
2680    mainSizer.Add((5,5),0)
2681   
2682    mainSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Cell Refinement: '),0,WACV)
2683    mainSizer.Add((5,5),0)
2684    littleSizer = wx.BoxSizer(wx.HORIZONTAL)
2685    littleSizer.Add(wx.StaticText(G2frame.dataDisplay,label=" Bravais lattice "),0,WACV)
2686    bravSel = wx.Choice(G2frame.dataDisplay,choices=bravaisSymb)
2687    bravSel.SetSelection(bravaisSymb.index(controls[5]))
2688    bravSel.Bind(wx.EVT_CHOICE,OnBravSel)
2689    littleSizer.Add(bravSel,0,WACV)
2690    littleSizer.Add(wx.StaticText(G2frame.dataDisplay,label=" Space group "),0,WACV)
2691    spcSel = wx.Choice(G2frame.dataDisplay,choices=SPGlist[controls[5]])
2692    spcSel.SetSelection(SPGlist[controls[5]].index(controls[13]))
2693    spcSel.Bind(wx.EVT_CHOICE,OnSpcSel)
2694    littleSizer.Add(spcSel,0,WACV)
2695    if ssopt.get('Use',False):        #zero for super lattice doesn't work!
2696        controls[0] = False
2697    else:
2698        littleSizer.Add(wx.StaticText(G2frame.dataDisplay,label=" Zero offset"),0,WACV)
2699        zero = wx.TextCtrl(G2frame.dataDisplay,value="%.4f"%(controls[1]),style=wx.TE_PROCESS_ENTER)
2700        zero.Bind(wx.EVT_TEXT_ENTER,OnZero)
2701        zero.Bind(wx.EVT_KILL_FOCUS,OnZero)
2702        littleSizer.Add(zero,0,WACV)
2703        zeroVar = wx.CheckBox(G2frame.dataDisplay,label="Refine?")
2704        zeroVar.SetValue(controls[0])
2705        zeroVar.Bind(wx.EVT_CHECKBOX,OnZeroVar)
2706        littleSizer.Add(zeroVar,0,WACV)
2707    SSopt = wx.CheckBox(G2frame.dataDisplay,label="Super lattice?")
2708    SSopt.SetValue(ssopt.get('Use',False))
2709    SSopt.Bind(wx.EVT_CHECKBOX,OnSSopt)
2710    littleSizer.Add(SSopt,0,WACV)
2711    hklShow = wx.Button(G2frame.dataDisplay,label="Show hkl positions")
2712    hklShow.Bind(wx.EVT_BUTTON,OnHklShow)
2713    littleSizer.Add(hklShow,0,WACV)
2714    mainSizer.Add(littleSizer,0)
2715   
2716    mainSizer.Add((5,5),0)
2717    ibrav = SetLattice(controls)
2718    for cellGUI in cellGUIlist:
2719        if ibrav in cellGUI[0]:
2720            useGUI = cellGUI
2721    cellList = []
2722    valDict = {}
2723    littleSizer = wx.FlexGridSizer(0,useGUI[1],5,5)
2724    for txt,fmt,ifEdit,Id in useGUI[2]:
2725        littleSizer.Add(wx.StaticText(G2frame.dataDisplay,label=txt),0,WACV)
2726        if ifEdit:          #a,b,c,etc.
2727            cellVal = wx.TextCtrl(G2frame.dataDisplay,value=(fmt%(controls[6+Id])),style=wx.TE_PROCESS_ENTER)
2728            cellVal.Bind(wx.EVT_TEXT_ENTER,OnCellChange)       
2729            cellVal.Bind(wx.EVT_KILL_FOCUS,OnCellChange)
2730            valSizer = wx.BoxSizer(wx.HORIZONTAL)
2731            valSizer.Add(cellVal,0,WACV)
2732            cellSpin = wx.SpinButton(G2frame.dataDisplay,style=wx.SP_VERTICAL,size=wx.Size(20,20))
2733            cellSpin.SetValue(0)
2734            cellSpin.SetRange(-1,1)
2735            cellSpin.Bind(wx.EVT_SPIN, OnMoveCell)
2736            valSizer.Add(cellSpin,0,WACV)
2737            littleSizer.Add(valSizer,0,WACV)
2738            cellList.append(cellVal.GetId())
2739            cellList.append(cellSpin.GetId())
2740            valDict[cellSpin.GetId()] = cellVal
2741        else:               #volume
2742            volVal = wx.TextCtrl(G2frame.dataDisplay,value=(fmt%(controls[12])),style=wx.TE_READONLY)
2743            volVal.SetBackgroundColour(VERY_LIGHT_GREY)
2744            littleSizer.Add(volVal,0,WACV)
2745    mainSizer.Add(littleSizer,0)
2746    if ssopt.get('Use',False):        #super lattice display
2747        indChoice = ['1','2','3','4',]
2748        SpSg = controls[13]
2749        ssChoice = G2spc.ssdict[SpSg]
2750        if ssopt['ssSymb'] not in ssChoice:
2751            ssopt['ssSymb'] = ssChoice[0]
2752        ssSizer = wx.BoxSizer(wx.HORIZONTAL)
2753        ssSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Supersymmetry space group: '+SpSg+' '),0,WACV)
2754        selMG = wx.ComboBox(G2frame.dataDisplay,value=ssopt['ssSymb'],
2755                choices=ssChoice,style=wx.CB_READONLY|wx.CB_DROPDOWN)
2756        selMG.Bind(wx.EVT_COMBOBOX, OnSelMG)
2757        ssSizer.Add(selMG,0,WACV)
2758        ssSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Mod. vector: '),0,WACV)
2759        modS = G2spc.splitSSsym(ssopt['ssSymb'])[0]
2760        Vec = ssopt['ModVec']
2761        Vec,ifShow = G2spc.SSGModCheck(Vec,modS)
2762        Indx = {}
2763        for i,[val,show] in enumerate(zip(Vec,ifShow)):
2764            if show:
2765                valSizer = wx.BoxSizer(wx.HORIZONTAL)
2766                modVal = wx.TextCtrl(G2frame.dataDisplay,value=('%.4f'%(val)),
2767                    size=wx.Size(50,20),style=wx.TE_PROCESS_ENTER)
2768                modVal.Bind(wx.EVT_TEXT_ENTER,OnModVal)       
2769                modVal.Bind(wx.EVT_KILL_FOCUS,OnModVal)
2770                valSizer.Add(modVal,0,WACV)
2771                modSpin = wx.SpinButton(G2frame.dataDisplay,style=wx.SP_VERTICAL,size=wx.Size(20,20))
2772                modSpin.SetValue(0)
2773                modSpin.SetRange(-1,1)
2774                modSpin.Bind(wx.EVT_SPIN, OnMoveMod)
2775                valSizer.Add(modSpin,0,WACV)
2776                ssSizer.Add(valSizer,0,WACV)
2777                Indx[modVal.GetId()] = i
2778                Indx[modSpin.GetId()] = [i,modVal]
2779            else:
2780                modVal = wx.TextCtrl(G2frame.dataDisplay,value=('%.3f'%(val)),
2781                    size=wx.Size(50,20),style=wx.TE_READONLY)
2782                modVal.SetBackgroundColour(VERY_LIGHT_GREY)
2783                ssSizer.Add(modVal,0,WACV)
2784        ssSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Max. M: '),0,WACV)
2785        maxMH = wx.ComboBox(G2frame.dataDisplay,value=str(ssopt['maxH']),
2786            choices=indChoice,style=wx.CB_READONLY|wx.CB_DROPDOWN)
2787        maxMH.Bind(wx.EVT_COMBOBOX, OnMaxMH)
2788        ssSizer.Add(maxMH,0,WACV)
2789        findMV = wx.wx.Button(G2frame.dataDisplay,label="Find mod. vec.?")
2790        findMV.Bind(wx.EVT_BUTTON,OnFindMV)
2791        ssSizer.Add(findMV,0,WACV)
2792        mainSizer.Add(ssSizer,0)
2793
2794    if cells:
2795        mainSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label='\n Indexing Result:'),0,WACV)
2796        rowLabels = []
2797        colLabels = ['M20','X20','use','Bravais','a','b','c','alpha','beta','gamma','Volume','Keep']
2798        Types = [wg.GRID_VALUE_FLOAT+':10,2',wg.GRID_VALUE_NUMBER,wg.GRID_VALUE_BOOL,wg.GRID_VALUE_STRING,]+ \
2799            3*[wg.GRID_VALUE_FLOAT+':10,5',]+3*[wg.GRID_VALUE_FLOAT+':10,3',]+ \
2800            [wg.GRID_VALUE_FLOAT+':10,2',wg.GRID_VALUE_BOOL]
2801        numRows = len(cells)
2802        table = []
2803        for cell in cells:
2804            rowLabels.append('')
2805            row = cell[0:2]+[cell[-2]]+[bravaisSymb[cell[2]]]+cell[3:10]+[cell[11],]
2806            if cell[-2]:
2807                A = G2lat.cell2A(cell[3:9])
2808                G2frame.HKL = G2lat.GenHBravais(dmin,cell[2],A)
2809                for hkl in G2frame.HKL:
2810                    hkl.insert(4,G2lat.Dsp2pos(Inst,hkl[3])+controls[1])
2811            table.append(row)
2812        UnitCellsTable = G2gd.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
2813        gridDisplay = G2gd.GSGrid(G2frame.dataDisplay)
2814        gridDisplay.SetTable(UnitCellsTable, True)
2815        G2frame.dataFrame.CopyCell.Enable(True)
2816        gridDisplay.Bind(wg.EVT_GRID_CELL_LEFT_CLICK,RefreshUnitCellsGrid)
2817        gridDisplay.Bind(wg.EVT_GRID_LABEL_LEFT_DCLICK,OnSortCells)
2818        gridDisplay.SetMargins(0,0)
2819        gridDisplay.SetRowLabelSize(0)
2820        gridDisplay.AutoSizeColumns(False)
2821        for r in range(gridDisplay.GetNumberRows()):
2822            for c in range(gridDisplay.GetNumberCols()):
2823                if c == 2:
2824                    gridDisplay.SetReadOnly(r,c,isReadOnly=False)
2825                else:
2826                    gridDisplay.SetReadOnly(r,c,isReadOnly=True)
2827        mainSizer.Add(gridDisplay,0,WACV)
2828    mainSizer.Layout()   
2829    G2frame.dataDisplay.SetSizer(mainSizer)
2830    G2frame.dataDisplay.SetAutoLayout(1)
2831    G2frame.dataDisplay.SetupScrolling()
2832    Size = mainSizer.Fit(G2frame.dataFrame)
2833    Size[0] += 25
2834    G2frame.dataDisplay.SetSize(Size)
2835    G2frame.dataFrame.setSizePosLeft(Size)   
2836   
2837################################################################################
2838#####  Reflection list
2839################################################################################           
2840       
2841def UpdateReflectionGrid(G2frame,data,HKLF=False,Name=''):
2842    '''respond to selection of PWDR Reflections data tree item.
2843    '''
2844    def OnPlotHKL(event):
2845        FoMax = np.max(refList.T[8+Super])
2846        Hmin = np.array([int(np.min(refList.T[0])),int(np.min(refList.T[1])),int(np.min(refList.T[2]))])
2847        Hmax = np.array([int(np.max(refList.T[0])),int(np.max(refList.T[1])),int(np.max(refList.T[2]))])
2848        controls = {'Type' : 'Fo','ifFc' : True,'HKLmax' : Hmax,'HKLmin' : Hmin,
2849            'FoMax' : FoMax,'Zone' : '001','Layer' : 0,'Scale' : 1.0,'Super':Super,'SuperVec':SuperVec}
2850        G2plt.PlotSngl(G2frame,newPlot=True,Data=controls,hklRef=refList,Title=phaseName)
2851       
2852    def OnPlot3DHKL(event):
2853        FoMax = np.max(refList.T[8+Super])
2854        Hmin = np.array([int(np.min(refList.T[0])),int(np.min(refList.T[1])),int(np.min(refList.T[2]))])
2855        Hmax = np.array([int(np.max(refList.T[0])),int(np.max(refList.T[1])),int(np.max(refList.T[2]))])
2856        Vpoint = [int(np.mean(refList.T[0])),int(np.mean(refList.T[1])),int(np.mean(refList.T[2]))]
2857        controls = {'Type':'Fosq','Iscale':False,'HKLmax':Hmax,'HKLmin':Hmin,
2858            'FoMax' : FoMax,'Scale' : 1.0,'Drawing':{'viewPoint':[Vpoint,[]],'default':Vpoint[:],
2859            'backColor':[0,0,0],'depthFog':False,'Zclip':10.0,'cameraPos':10.,'Zstep':0.05,
2860            'Scale':1.0,'oldxy':[],'viewDir':[1,0,0]},'Super':Super,'SuperVec':SuperVec}
2861        G2plt.Plot3DSngl(G2frame,newPlot=True,Data=controls,hklRef=refList,Title=phaseName)
2862       
2863    def OnSelectPhase(event):
2864        dlg = wx.SingleChoiceDialog(G2frame,'Select','Phase',phases)
2865        try:
2866            if dlg.ShowModal() == wx.ID_OK:
2867                sel = dlg.GetSelection()
2868                G2frame.RefList = phases[sel]
2869                UpdateReflectionGrid(G2frame,data)
2870        finally:
2871            dlg.Destroy()
2872        G2plt.PlotPatterns(G2frame)
2873           
2874    if not data:
2875        print 'No phases, no reflections'
2876        return
2877    if HKLF:
2878        G2frame.RefList = 1
2879        phaseName = IsHistogramInAnyPhase(G2frame,Name)
2880    else:
2881        phaseName = G2frame.RefList
2882        phases = data.keys()
2883    if G2frame.dataDisplay:
2884        G2frame.dataFrame.Clear()
2885    Inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Instrument Parameters'))[0]
2886    if phaseName:
2887        pId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Phases')
2888        phaseId =  G2gd.GetPatternTreeItemId(G2frame,pId,phaseName)
2889        General = G2frame.PatternTree.GetItemPyData(phaseId)['General']
2890        Super = General.get('Super',0)
2891        SuperVec = General.get('SuperVec',[])
2892    else:
2893        Super = 0
2894        SuperVec = []       
2895    rowLabels = []
2896    if HKLF:
2897        G2gd.SetDataMenuBar(G2frame)
2898        refList = data[1]['RefList']
2899        G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.ReflMenu)
2900        if not G2frame.dataFrame.GetStatusBar():
2901            Status = G2frame.dataFrame.CreateStatusBar()   
2902        G2frame.Bind(wx.EVT_MENU, OnPlotHKL, id=G2gd.wxID_PWDHKLPLOT)
2903        G2frame.Bind(wx.EVT_MENU, OnPlot3DHKL, id=G2gd.wxID_PWD3DHKLPLOT)
2904        G2frame.dataFrame.SelectPhase.Enable(False)
2905        refs = refList
2906    else:
2907        G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.ReflMenu)
2908        if not G2frame.dataFrame.GetStatusBar():
2909            Status = G2frame.dataFrame.CreateStatusBar()   
2910        G2frame.Bind(wx.EVT_MENU, OnSelectPhase, id=G2gd.wxID_SELECTPHASE)
2911        G2frame.Bind(wx.EVT_MENU, OnPlotHKL, id=G2gd.wxID_PWDHKLPLOT)
2912        G2frame.Bind(wx.EVT_MENU, OnPlot3DHKL, id=G2gd.wxID_PWD3DHKLPLOT)
2913        G2frame.dataFrame.SelectPhase.Enable(False)
2914        if len(data) > 1:
2915            G2frame.dataFrame.SelectPhase.Enable(True)
2916        try:            #patch for old reflection lists
2917            refList = np.array(data[G2frame.RefList]['RefList'])
2918            I100 = refList.T[8+Super]*refList.T[11+Super]
2919        except TypeError:
2920            refList = np.array([refl[:11+Super] for refl in data[G2frame.RefList]])
2921            I100 = refList.T[8+Super]*np.array([refl[11+Super] for refl in data[G2frame.RefList]])
2922        Imax = np.max(I100)
2923        if Imax:
2924            I100 *= 100.0/Imax
2925        if 'C' in Inst['Type'][0]:
2926            refs = np.vstack((refList.T[:15+Super],I100)).T
2927        elif 'T' in Inst['Type'][0]:
2928            refs = np.vstack((refList.T[:18+Super],I100)).T
2929           
2930    for i in range(len(refs)): rowLabels.append(str(i))
2931    Types = (4+Super)*[wg.GRID_VALUE_LONG,]+4*[wg.GRID_VALUE_FLOAT+':10,4',]+ \
2932        2*[wg.GRID_VALUE_FLOAT+':10,2',]+[wg.GRID_VALUE_FLOAT+':10,3',]+ \
2933        [wg.GRID_VALUE_FLOAT+':10,3',]
2934    superLabels = ['M1','M2','M3']
2935    if HKLF:
2936        colLabels = ['H','K','L','mul','d','Fosq','sig','Fcsq','FoTsq','FcTsq','phase','ExtC',]
2937        if 'T' in Inst['Type'][0]:
2938            colLabels = ['H','K','L','mul','d','Fosq','sig','Fcsq','FoTsq','FcTsq','phase','ExtC','wave','tbar']
2939            Types += 2*[wg.GRID_VALUE_FLOAT+':10,3',]
2940        if Super:
2941            for i in range(Super):
2942                colLabels.insert(3+i,superLabels[i])
2943    else:
2944        if 'C' in Inst['Type'][0]:
2945            colLabels = ['H','K','L','mul','d','pos','sig','gam','Fosq','Fcsq','phase','Icorr','Prfo','Trans','ExtP','I100']
2946            Types += 4*[wg.GRID_VALUE_FLOAT+':10,3',]
2947        elif 'T' in Inst['Type'][0]:
2948            colLabels = ['H','K','L','mul','d','pos','sig','gam','Fosq','Fcsq','phase','Icorr','alp','bet','wave','Prfo','Abs','Ext','I100']
2949            Types += 7*[wg.GRID_VALUE_FLOAT+':10,3',]
2950        if Super:
2951            for i in range(Super):
2952                colLabels.insert(3+i,superLabels[i])
2953           
2954    G2frame.PeakTable = G2gd.Table(refs,rowLabels=rowLabels,colLabels=colLabels,types=Types)
2955    G2frame.dataFrame.SetLabel('Reflection List for '+phaseName)
2956    G2frame.dataDisplay = G2gd.GSGrid(parent=G2frame.dataFrame)
2957    G2frame.dataDisplay.SetTable(G2frame.PeakTable, True)
2958    G2frame.dataDisplay.EnableEditing(False)
2959    G2frame.dataDisplay.SetMargins(0,0)
2960    G2frame.dataDisplay.AutoSizeColumns(False)
2961    G2frame.dataDisplay.Fit()
2962    size = G2frame.dataDisplay.GetSize()
2963    G2frame.dataFrame.setSizePosLeft([size[0]+32,350])
2964   
2965################################################################################
2966#####  SASD Substances
2967################################################################################
2968           
2969def UpdateSubstanceGrid(G2frame,data):
2970    '''respond to selection of SASD Substance data tree item.
2971    '''
2972    import Substances as substFile
2973   
2974    def OnLoadSubstance(event):
2975        names = substFile.Substances.keys()
2976        names.sort()
2977        dlg = wx.SingleChoiceDialog(G2frame, 'Which substance?', 'Select substance', names, wx.CHOICEDLG_STYLE)
2978        try:
2979            if dlg.ShowModal() == wx.ID_OK:
2980                name = names[dlg.GetSelection()]
2981            else:
2982                return
2983        finally:
2984            dlg.Destroy()
2985        data['Substances'][name] = {'Elements':{},'Volume':1.0,'Density':1.0,
2986            'Scatt density':0.0,'XAnom density':0.0,'XAbsorption':0.0}
2987        subst = substFile.Substances[name]
2988        ElList = subst['Elements'].keys()
2989        for El in ElList:
2990            Info = G2elem.GetAtomInfo(El.strip().capitalize())
2991            Info.update(subst['Elements'][El])
2992            data['Substances'][name]['Elements'][El] = Info
2993            if 'Volume' in subst:
2994                data['Substances'][name]['Volume'] = subst['Volume']
2995                data['Substances'][name]['Density'] = \
2996                    G2mth.Vol2Den(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])
2997            elif 'Density' in subst:
2998                data['Substances'][name]['Density'] = subst['Density']
2999                data['Substances'][name]['Volume'] = \
3000                    G2mth.Den2Vol(data['Substances'][name]['Elements'],data['Substances'][name]['Density'])
3001            else:
3002                data['Substances'][name]['Volume'] = G2mth.El2EstVol(data['Substances'][name]['Elements'])
3003                data['Substances'][name]['Density'] = \
3004                    G2mth.Vol2Den(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])
3005            data['Substances'][name]['Scatt density'] = \
3006                G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])[0]
3007            contrst,absorb = G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'],wave)         
3008            data['Substances'][name]['XAnom density'] = contrst
3009            data['Substances'][name]['XAbsorption'] = absorb
3010                         
3011        UpdateSubstanceGrid(G2frame,data)
3012       
3013    def OnCopySubstance(event):
3014        hst = G2frame.PatternTree.GetItemText(G2frame.PatternId)
3015        histList = GetHistsLikeSelected(G2frame)
3016        if not histList:
3017            G2frame.ErrorDialog('No match','No histograms match '+hst,G2frame.dataFrame)
3018            return
3019        copyList = []
3020        dlg = G2gd.G2MultiChoiceDialog(
3021            G2frame.dataFrame, 
3022            'Copy substances from\n'+hst[5:]+' to...',
3023            'Copy substances', histList)
3024        try:
3025            if dlg.ShowModal() == wx.ID_OK:
3026                for i in dlg.GetSelections(): 
3027                    copyList.append(histList[i])
3028        finally:
3029            dlg.Destroy()       
3030        for item in copyList:
3031            Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,item)
3032            G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Substances'),
3033                copy.copy(data))
3034   
3035    def OnAddSubstance(event):
3036        dlg = wx.TextEntryDialog(None,'Enter a name for this substance','Substance Name Entry','New substance',
3037            style=wx.OK)
3038        if dlg.ShowModal() == wx.ID_OK:
3039            Name = dlg.GetValue()
3040            data['Substances'][Name] = {'Elements':{},'Volume':1.0,'Density':1.0,
3041                'Scatt density':0.0,'XAnom density':0.,'XAbsorption':0.}
3042        dlg.Destroy()
3043        AddElement(Name)
3044        UpdateSubstanceGrid(G2frame,data)
3045       
3046    def OnDeleteSubstance(event):
3047        TextList = []
3048        for name in data['Substances']:
3049            if name != 'vacuum':
3050                TextList += [name,]
3051        if not TextList:
3052            return
3053        dlg = wx.SingleChoiceDialog(G2frame, 'Which substance?', 'Select substance to delete', TextList, wx.CHOICEDLG_STYLE)
3054        try:
3055            if dlg.ShowModal() == wx.ID_OK:
3056                name = TextList[dlg.GetSelection()]
3057            else:
3058                return
3059        finally:
3060            dlg.Destroy()
3061        del(data['Substances'][name])
3062        UpdateSubstanceGrid(G2frame,data)       
3063               
3064    def OnAddElement(event):       
3065        TextList = []
3066        for name in data['Substances']:
3067            if name != 'vacuum':
3068                TextList += [name,]
3069        if not TextList:
3070            return
3071        dlg = wx.SingleChoiceDialog(G2frame, 'Which substance?', 'Select substance', TextList, wx.CHOICEDLG_STYLE)
3072        try:
3073            if dlg.ShowModal() == wx.ID_OK:
3074                name = TextList[dlg.GetSelection()]
3075            else:
3076                return
3077        finally:
3078            dlg.Destroy()
3079        AddElement(name)
3080        UpdateSubstanceGrid(G2frame,data)
3081       
3082    def AddElement(name):
3083        ElList = data['Substances'][name]['Elements'].keys()
3084        dlg = G2elemGUI.PickElements(G2frame,ElList)
3085        if dlg.ShowModal() == wx.ID_OK:
3086            for El in dlg.Elem:
3087                El = El.strip().capitalize()
3088                Info = G2elem.GetAtomInfo(El)
3089                Info.update({'Num':1})
3090                data['Substances'][name]['Elements'][El] = Info
3091                data['Substances'][name]['Volume'] = G2mth.El2EstVol(data['Substances'][name]['Elements'])
3092                data['Substances'][name]['Density'] = \
3093                    G2mth.Vol2Den(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])
3094                data['Substances'][name]['Scatt density'] = \
3095                    G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])[0]
3096                contrst,absorb = G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'],wave)         
3097                data['Substances'][name]['XAnom density'] = contrst
3098                data['Substances'][name]['XAbsorption'] = absorb
3099        dlg.Destroy()
3100       
3101    def OnDeleteElement(event):
3102        TextList = []
3103        for name in data['Substances']:
3104            if name != 'vacuum':
3105                TextList += [name,]
3106        if not TextList:
3107            return
3108        dlg = wx.SingleChoiceDialog(G2frame, 'Which substance?', 'Select substance', TextList, wx.CHOICEDLG_STYLE)
3109        try:
3110            if dlg.ShowModal() == wx.ID_OK:
3111                name = TextList[dlg.GetSelection()]
3112            else:
3113                return
3114        finally:
3115            dlg.Destroy()
3116        ElList = data['Substances'][name]['Elements'].keys()
3117        if len(ElList):
3118            DE = G2elemGUI.DeleteElement(G2frame,ElList)
3119            if DE.ShowModal() == wx.ID_OK:
3120                El = DE.GetDeleteElement().strip().upper()
3121                del(data['Substances'][name]['Elements'][El])
3122                data['Substances'][name]['Volume'] = G2mth.El2EstVol(data['Substances'][name]['Elements'])
3123                data['Substances'][name]['Density'] = \
3124                    G2mth.Vol2Den(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])
3125                data['Substances'][name]['Scatt density'] = \
3126                    G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])[0]
3127                contrst,absorb = G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'],wave)         
3128                data['Substances'][name]['XAnom density'] = contrst
3129                data['Substances'][name]['XAbsorption'] = absorb
3130        UpdateSubstanceGrid(G2frame,data)
3131               
3132    def SubstSizer():
3133       
3134        def OnValueChange(event):
3135            Obj = event.GetEventObject()
3136            if len(Indx[Obj.GetId()]) == 3:
3137                name,El,keyId = Indx[Obj.GetId()]
3138                try:
3139                    value = max(0,float(Obj.GetValue()))
3140                except ValueError:
3141                    value = 0
3142                    Obj.SetValue('%.2f'%(value))
3143                data['Substances'][name]['Elements'][El][keyId] = value
3144                data['Substances'][name]['Volume'] = G2mth.El2EstVol(data['Substances'][name]['Elements'])
3145                data['Substances'][name]['Density'] = \
3146                    G2mth.Vol2Den(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])
3147            else:
3148                name,keyId = Indx[Obj.GetId()]
3149                try:
3150                    value = max(0,float(Obj.GetValue()))
3151                except ValueError:
3152                    value = 1.0
3153                data['Substances'][name][keyId] = value
3154                if keyId in 'Volume':
3155                    data['Substances'][name]['Density'] = \
3156                        G2mth.Vol2Den(data['Substances'][name]['Elements'],value)
3157                elif keyId in 'Density':
3158                    data['Substances'][name]['Volume'] = \
3159                        G2mth.Den2Vol(data['Substances'][name]['Elements'],value)
3160            data['Substances'][name]['Scatt density'] = \
3161                G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])[0]
3162            contrst,absorb = G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'],wave)         
3163            data['Substances'][name]['XAnom density'] = contrst
3164            data['Substances'][name]['XAbsorption'] = absorb
3165            wx.CallAfter(UpdateSubstanceGrid,G2frame,data)
3166       
3167        Indx = {}
3168        substSizer = wx.BoxSizer(wx.VERTICAL)
3169        substSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Substance list: wavelength: %.5fA'%(wave)),
3170            0,WACV)
3171        for name in data['Substances']:
3172            G2gd.HorizontalLine(substSizer,G2frame.dataDisplay)   
3173            substSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Data for '+name+':'),
3174                0,WACV)
3175            if name == 'vacuum':
3176                substSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label='        Not applicable'),
3177                    0,WACV)
3178            else:   
3179                elSizer = wx.FlexGridSizer(0,6,5,5)
3180                Substance = data['Substances'][name]
3181                Elems = Substance['Elements']
3182                for El in Elems:    #do elements as pull downs for isotopes for neutrons
3183                    elSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' '+El+': '),
3184                        0,WACV)
3185                    num = wx.TextCtrl(G2frame.dataDisplay,value='%.2f'%(Elems[El]['Num']),style=wx.TE_PROCESS_ENTER)
3186                    Indx[num.GetId()] = [name,El,'Num']
3187                    num.Bind(wx.EVT_TEXT_ENTER,OnValueChange)       
3188                    num.Bind(wx.EVT_KILL_FOCUS,OnValueChange)
3189                    elSizer.Add(num,0,WACV)
3190                substSizer.Add(elSizer,0)
3191                vdsSizer = wx.FlexGridSizer(0,4,5,5)
3192                vdsSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Volume: '),
3193                    0,WACV)
3194                vol = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(Substance['Volume']),style=wx.TE_PROCESS_ENTER)
3195                Indx[vol.GetId()] = [name,'Volume']
3196                vol.Bind(wx.EVT_TEXT_ENTER,OnValueChange)       
3197                vol.Bind(wx.EVT_KILL_FOCUS,OnValueChange)
3198                vdsSizer.Add(vol,0,WACV)               
3199                vdsSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Density: '),
3200                    0,WACV)
3201                den = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(Substance['Density']),style=wx.TE_PROCESS_ENTER)
3202                Indx[den.GetId()] = [name,'Density']
3203                den.Bind(wx.EVT_TEXT_ENTER,OnValueChange)       
3204                den.Bind(wx.EVT_KILL_FOCUS,OnValueChange)
3205                vdsSizer.Add(den,0,WACV)
3206                substSizer.Add(vdsSizer,0)
3207                substSizer.Add(wx.StaticText(G2frame.dataDisplay,
3208                    label=' Scattering density  : %.2f *10%scm%s'%(Substance['Scatt density'],Pwr10,Pwrm2)),
3209                    0,WACV)               
3210                substSizer.Add(wx.StaticText(G2frame.dataDisplay,       #allow neutrons here into NAnom density & NAbsorption
3211                    label=' Anomalous density : %.2f *10%scm%s'%(Substance['XAnom density'],Pwr10,Pwrm2)),
3212                    0,WACV)               
3213                substSizer.Add(wx.StaticText(G2frame.dataDisplay,
3214                    label=' X-ray absorption   : %.2f cm%s'%(Substance['XAbsorption'],Pwrm1)),
3215                    0,WACV)               
3216        return substSizer
3217           
3218    Inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Instrument Parameters'))[0]
3219    wave = G2mth.getWave(Inst)
3220    if G2frame.dataDisplay:
3221        G2frame.dataFrame.DestroyChildren()
3222    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.SubstanceMenu)
3223    if not G2frame.dataFrame.GetStatusBar():
3224        Status = G2frame.dataFrame.CreateStatusBar()
3225    G2frame.dataDisplay = wxscroll.ScrolledPanel(G2frame.dataFrame)
3226    G2frame.dataFrame.SetLabel('Substances')
3227    G2frame.dataFrame.Bind(wx.EVT_MENU, OnLoadSubstance, id=G2gd.wxID_LOADSUBSTANCE)   
3228    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddSubstance, id=G2gd.wxID_ADDSUBSTANCE)
3229    G2frame.dataFrame.Bind(wx.EVT_MENU, OnCopySubstance, id=G2gd.wxID_COPYSUBSTANCE)
3230    G2frame.dataFrame.Bind(wx.EVT_MENU, OnDeleteSubstance, id=G2gd.wxID_DELETESUBSTANCE)   
3231    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddElement, id=G2gd.wxID_ELEMENTADD)
3232    G2frame.dataFrame.Bind(wx.EVT_MENU, OnDeleteElement, id=G2gd.wxID_ELEMENTDELETE)
3233    mainSizer = wx.BoxSizer(wx.VERTICAL)
3234    mainSizer.Add(SubstSizer(),0)
3235
3236    mainSizer.Layout()   
3237    G2frame.dataDisplay.SetSizer(mainSizer)
3238    G2frame.dataDisplay.SetAutoLayout(1)
3239    G2frame.dataDisplay.SetupScrolling()
3240    Size = mainSizer.Fit(G2frame.dataFrame)
3241    Size[0] += 25
3242    G2frame.dataDisplay.SetSize(Size)
3243    G2frame.dataFrame.setSizePosLeft(Size)   
3244       
3245################################################################################
3246#####  SASD Models
3247################################################################################           
3248       
3249def UpdateModelsGrid(G2frame,data):
3250    '''respond to selection of SASD Models data tree item.
3251    '''
3252    #patches
3253    if 'Current' not in data:
3254        data['Current'] = 'Size dist.'
3255    if 'logBins' not in data['Size']:
3256        data['Size']['logBins'] = True
3257    if 'MinMaxDiam' in data['Size']:
3258        data['Size']['MinDiam'] = 50.
3259        data['Size']['MaxDiam'] = 10000.
3260        del data['Size']['MinMaxDiam']
3261    if isinstance(data['Size']['MaxEnt']['Sky'],float):
3262        data['Size']['MaxEnt']['Sky'] = -3
3263    if 'Power' not in data['Size']['IPG']:
3264        data['Size']['IPG']['Power'] = -1
3265    if 'Matrix' not in data['Particle']:
3266        data['Particle']['Matrix'] = {'Name':'vacuum','VolFrac':[0.0,False]}
3267    if 'BackFile' not in data:
3268        data['BackFile'] = ''
3269    #end patches
3270   
3271    def RefreshPlots(newPlot=False):
3272        PlotText = G2frame.G2plotNB.nb.GetPageText(G2frame.G2plotNB.nb.GetSelection())
3273        if 'Powder' in PlotText:
3274            G2plt.PlotPatterns(G2frame,plotType='SASD',newPlot=newPlot)
3275        elif 'Size' in PlotText:
3276            G2plt.PlotSASDSizeDist(G2frame)
3277               
3278    def OnAddModel(event):
3279        if data['Current'] == 'Particle fit':
3280            material = 'vacuum'
3281            if len(data['Particle']['Levels']):
3282                material = data['Particle']['Levels'][-1]['Controls']['Material']
3283            data['Particle']['Levels'].append({
3284                'Controls':{'FormFact':'Sphere','DistType':'LogNormal','Material':material,
3285                    'FFargs':{},'SFargs':{},'NumPoints':50,'Cutoff':0.01,'Contrast':0.0,
3286                    'SlitSmear':[0.0,False],'StrFact':'Dilute'},    #last 2 not used - future?
3287                'LogNormal':{'Volume':[0.05,False],'Mean':[1000.,False],'StdDev':[0.5,False],'MinSize':[10.,False],},
3288                'Gaussian':{'Volume':[0.05,False],'Mean':[1000.,False],'StdDev':[300.,False],},
3289                'LSW':{'Volume':[0.05,False],'Mean':[1000.0,False],},
3290                'Schulz-Zimm':{'Volume':[0.05,False],'Mean':[1000.,False],'StdDev':[300.,False],},
3291                'Unified':{'G':[1.e3,False],'Rg':[100,False],'B':[1.e-5,False],'P':[4,False],'Cutoff':[1e-5,False],},
3292                'Porod':{'B':[1.e-4,False],'P':[4,False],'Cutoff':[1e-5,False],},
3293                'Monodisperse':{'Volume':[0.05,False],'Radius':[100,False],},   #OK for spheres
3294                'Bragg':{'PkInt':[100,False],'PkPos':[0.2,False],
3295                    'PkSig':[10,False],'PkGam':[10,False],},        #reasonable 31A peak
3296                })
3297            G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
3298            RefreshPlots(True)
3299                   
3300        wx.CallAfter(UpdateModelsGrid,G2frame,data)
3301       
3302    def OnCopyModel(event):
3303        hst = G2frame.PatternTree.GetItemText(G2frame.PatternId)
3304        histList = GetHistsLikeSelected(G2frame)
3305        if not histList:
3306            G2frame.ErrorDialog('No match','No histograms match '+hst,G2frame.dataFrame)
3307            return
3308        copyList = []
3309        dlg = G2gd.G2MultiChoiceDialog(
3310            G2frame.dataFrame, 
3311            'Copy models from\n'+hst[5:]+' to...',
3312            'Copy models', histList)
3313        try:
3314            if dlg.ShowModal() == wx.ID_OK:
3315                for i in dlg.GetSelections(): 
3316                    copyList.append(histList[i])
3317        finally:
3318            dlg.Destroy()       
3319        for item in copyList:
3320            Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,item)
3321            newdata = copy.deepcopy(data)
3322            G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Models'),newdata)
3323            if newdata['BackFile']:
3324                Profile = G2frame.PatternTree.GetItemPyData(Id)[1]
3325                BackId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,newdata['BackFile'])
3326                BackSample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,BackId, 'Sample Parameters'))
3327                Profile[5] = BackSample['Scale'][0]*G2frame.PatternTree.GetItemPyData(BackId)[1][1]
3328        RefreshPlots(True)
3329               
3330    def OnCopyFlags(event):
3331        thisModel = copy.deepcopy(data)
3332        hst = G2frame.PatternTree.GetItemText(G2frame.PatternId)
3333        histList = GetHistsLikeSelected(G2frame)
3334        if not histList:
3335            G2frame.ErrorDialog('No match','No histograms match '+hst,G2frame.dataFrame)
3336            return
3337        dlg = G2gd.G2MultiChoiceDialog(
3338            G2frame.dataFrame, 
3339            'Copy sample ref. flags from\n'+str(hst[5:])+' to...',
3340            'Copy sample flags', histList)
3341        distChoice = ['LogNormal','Gaussian','LSW','Schulz-Zimm','Bragg','Unified',
3342            'Porod','Monodisperse',]
3343        parmOrder = ['Volume','Radius','Mean','StdDev','G','Rg','B','P',
3344            'Cutoff','PkInt','PkPos','PkSig','PkGam','VolFr','Dist',]
3345        try:
3346            if dlg.ShowModal() == wx.ID_OK:
3347                result = dlg.GetSelections()
3348                for i in result: 
3349                    item = histList[i]
3350                    Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,item)
3351                    newModel = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Models'))
3352                    newModel['Back'][1] = copy.copy(thisModel['Back'][1])
3353                    for ilev,level in enumerate(newModel['Particle']['Levels']):
3354                        for form in level:
3355                            if form in distChoice:
3356                                thisForm = thisModel['Particle']['Levels'][ilev][form]                               
3357                                for item in parmOrder:
3358                                    if item in thisForm:
3359                                       level[form][item][1] = copy.copy(thisForm[item][1])
3360                            elif form == 'Controls':
3361                                thisForm = thisModel['Particle']['Levels'][ilev][form]['SFargs']
3362                                for item in parmOrder:
3363                                    if item in thisForm:
3364                                        level[form]['SFargs'][item][1] = copy.copy(thisForm[item][1])
3365        finally:
3366            dlg.Destroy()
3367               
3368    def OnFitModelAll(event):
3369        choices = G2gd.GetPatternTreeDataNames(G2frame,['SASD',])
3370        sel = []
3371        dlg = G2gd.G2MultiChoiceDialog(G2frame.dataFrame, 'Sequential SASD refinement',
3372             'Select dataset to include',choices)
3373        dlg.SetSelections(sel)
3374        names = []
3375        if dlg.ShowModal() == wx.ID_OK:
3376            for sel in dlg.GetSelections():
3377                names.append(choices[sel])
3378        dlg.Destroy()
3379        SeqResult = {'histNames':names}
3380        Reverse = False
3381        CopyForward = False
3382        choice = ['Reverse sequence','Copy from prev.']
3383        dlg = wx.MultiChoiceDialog(G2frame.dataFrame,'Sequential controls','Select controls',choice)
3384        if dlg.ShowModal() == wx.ID_OK:
3385            for sel in dlg.GetSelections():
3386                if sel:
3387                    CopyForward = True
3388                else:
3389                    Reverse = True
3390        dlg.Destroy()
3391        dlg = wx.ProgressDialog('SASD Sequential fit','Data set name = '+names[0],len(names), 
3392            style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_REMAINING_TIME|wx.PD_CAN_ABORT)
3393        wx.BeginBusyCursor()
3394        if Reverse:
3395            names.reverse()
3396        try:
3397            for i,name in enumerate(names):
3398                print ' Sequential fit for ',name
3399                GoOn = dlg.Update(i,newmsg='Data set name = '+name)[0]
3400                if not GoOn:
3401                    break
3402                Id =  G2gd.GetPatternTreeItemId(G2frame,G2frame.root,name)
3403                if i and CopyForward:
3404                    G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Models'),JModel)
3405                IProfDict,IProfile = G2frame.PatternTree.GetItemPyData(Id)[:2]
3406                IModel = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Models'))
3407                ISample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Sample Parameters'))
3408                ILimits = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Limits'))
3409                IfOK,result,varyList,sig,Rvals,covMatrix,parmDict,Msg = G2sasd.ModelFit(IProfile,IProfDict,ILimits,ISample,IModel)
3410                JModel = copy.deepcopy(IModel)
3411                if not IfOK:
3412                    G2frame.ErrorDialog('Failed sequential refinement for data '+name,
3413                        ' Msg: '+Msg+'\nYou need to rethink your selection of parameters\n'+    \
3414                        ' Model restored to previous version for'+name)
3415                    SeqResult['histNames'] = names[:i]
3416                    dlg.Destroy()
3417                    break
3418                else:
3419                    G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Models'),copy.deepcopy(IModel))
3420               
3421                G2sasd.ModelFxn(IProfile,IProfDict,ILimits,ISample,IModel)
3422                SeqResult[name] = {'variables':result[0],'varyList':varyList,'sig':sig,'Rvals':Rvals,
3423                    'covMatrix':covMatrix,'title':name,'parmDict':parmDict}
3424            else:
3425                dlg.Destroy()
3426                print ' ***** Small angle sequential refinement successful *****'
3427        finally:
3428            wx.EndBusyCursor()   
3429        Id =  G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Sequential results')
3430        if Id:
3431            G2frame.PatternTree.SetItemPyData(Id,SeqResult)
3432        else:
3433            Id = G2frame.PatternTree.AppendItem(parent=G2frame.root,text='Sequential results')
3434            G2frame.PatternTree.SetItemPyData(Id,SeqResult)
3435        G2frame.PatternTree.SelectItem(Id)
3436       
3437    def OnFitModel(event):
3438        if data['Current'] == 'Size dist.':
3439            if not any(Sample['Contrast']):
3440                G2frame.ErrorDialog('No contrast; your sample is a vacuum!',
3441                    'You need to define a scattering substance!\n'+    \
3442                    ' Do Substances and then Sample parameters')
3443                return
3444            G2sasd.SizeDistribution(Profile,ProfDict,Limits,Sample,data)
3445            G2plt.PlotSASDSizeDist(G2frame)
3446            RefreshPlots(True)
3447           
3448        elif data['Current'] == 'Particle fit':
3449            SaveState()
3450            Results = G2sasd.ModelFit(Profile,ProfDict,Limits,Sample,data)
3451            if not Results[0]:
3452                    G2frame.ErrorDialog('Failed refinement',
3453                        ' Msg: '+Results[-1]+'\nYou need to rethink your selection of parameters\n'+    \
3454                        ' Model restored to previous version')
3455            G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
3456            RefreshPlots(True)
3457            wx.CallAfter(UpdateModelsGrid,G2frame,data)
3458           
3459    def OnUnDo(event):
3460        DoUnDo()
3461        data = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,
3462            G2frame.PatternId,'Models'))
3463        G2frame.dataFrame.SasdUndo.Enable(False)
3464        UpdateModelsGrid(G2frame,data)
3465        G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
3466        RefreshPlots(True)
3467
3468    def DoUnDo():
3469        print 'Undo last refinement'
3470        file = open(G2frame.undosasd,'rb')
3471        PatternId = G2frame.PatternId
3472        G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Models'),cPickle.load(file))
3473        print ' Models recovered'
3474        file.close()
3475       
3476    def SaveState():
3477        G2frame.undosasd = os.path.join(G2frame.dirname,'GSASIIsasd.save')
3478        file = open(G2frame.undosasd,'wb')
3479        PatternId = G2frame.PatternId
3480        for item in ['Models']:
3481            cPickle.dump(G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,item)),file,1)
3482        file.close()
3483        G2frame.dataFrame.SasdUndo.Enable(True)
3484       
3485    def OnSelectFit(event):
3486        data['Current'] = fitSel.GetValue()
3487        wx.CallAfter(UpdateModelsGrid,G2frame,data)
3488       
3489    def OnCheckBox(event):
3490        Obj = event.GetEventObject()
3491        item,ind = Indx[Obj.GetId()]
3492        item[ind] = Obj.GetValue()
3493       
3494    def OnIntVal(event):
3495        Obj = event.GetEventObject()
3496        item,ind,minVal = Indx[Obj.GetId()]
3497        try:
3498            value = int(Obj.GetValue())
3499            if value <= minVal:
3500                raise ValueError
3501        except ValueError:
3502            value = item[ind]
3503        Obj.SetValue(str(value))
3504        item[ind] = value
3505
3506    def SizeSizer():
3507       
3508        def OnShape(event):
3509            data['Size']['Shape'][0] = partsh.GetValue()
3510            wx.CallAfter(UpdateModelsGrid,G2frame,data)
3511           
3512        def OnMethod(event):
3513            data['Size']['Method'] = method.GetValue()
3514            wx.CallAfter(UpdateModelsGrid,G2frame,data)
3515           
3516        def OnPartVal(event):
3517            try:
3518                val = max(0.0,float(partprm.GetValue()))
3519            except ValueError:
3520                val = 1
3521            data['Size']['Shape'][1] = val
3522            partprm.SetValue('%.3f'%(val))
3523           
3524        sizeSizer = wx.BoxSizer(wx.VERTICAL)
3525        sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Size distribution parameters: '),0,WACV)
3526        binSizer = wx.FlexGridSizer(0,7,5,5)
3527        binSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' No. size bins: '),0,WACV)
3528        bins = ['50','100','150','200']
3529        nbins = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['Nbins']),choices=bins,
3530            style=wx.CB_READONLY|wx.CB_DROPDOWN)
3531        Indx[nbins.GetId()] = [data['Size'],'Nbins',0]
3532        nbins.Bind(wx.EVT_COMBOBOX,OnIntVal)       
3533        binSizer.Add(nbins,0,WACV)
3534        binSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Min diam.: '),0,WACV)
3535        minDias = ['10','25','50','100','150','200']
3536        mindiam = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['MinDiam']),choices=minDias,
3537            style=wx.CB_DROPDOWN)
3538        mindiam.Bind(wx.EVT_LEAVE_WINDOW,OnIntVal)
3539        mindiam.Bind(wx.EVT_TEXT_ENTER,OnIntVal)       
3540        mindiam.Bind(wx.EVT_KILL_FOCUS,OnIntVal)
3541        Indx[mindiam.GetId()] = [data['Size'],'MinDiam',0]
3542        binSizer.Add(mindiam,0,WACV)
3543        binSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Max diam.: '),0,WACV)
3544        maxDias = [str(1000*(i+1)) for i in range(10)]
3545        maxdiam = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['MaxDiam']),choices=maxDias,
3546            style=wx.CB_DROPDOWN)
3547        maxdiam.Bind(wx.EVT_LEAVE_WINDOW,OnIntVal)
3548        maxdiam.Bind(wx.EVT_TEXT_ENTER,OnIntVal)       
3549        maxdiam.Bind(wx.EVT_KILL_FOCUS,OnIntVal)
3550        Indx[maxdiam.GetId()] = [data['Size'],'MaxDiam',0]
3551        binSizer.Add(maxdiam,0,WACV)
3552        logbins = wx.CheckBox(G2frame.dataDisplay,label='Log bins?')
3553        Indx[logbins.GetId()] = [data['Size'],'logBins']
3554        logbins.SetValue(data['Size']['logBins'])
3555        logbins.Bind(wx.EVT_CHECKBOX, OnCheckBox)
3556        binSizer.Add(logbins,0,WACV)
3557        sizeSizer.Add(binSizer,0)
3558        sizeSizer.Add((5,5),0)
3559        partSizer = wx.BoxSizer(wx.HORIZONTAL)
3560        partSizer.Add(wx.StaticText(G2frame.dataDisplay,label='Particle description: '),0,WACV)
3561        shapes = {'Spheroid':' Aspect ratio: ','Cylinder':' Diameter ','Cylinder AR':' Aspect ratio: ',
3562            'Unified sphere':'','Unified rod':' Diameter: ','Unified rod AR':' Aspect ratio: ',
3563            'Unified disk':' Thickness: '}
3564        partsh = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['Shape'][0]),choices=shapes.keys(),
3565            style=wx.CB_READONLY|wx.CB_DROPDOWN)
3566        partsh.Bind(wx.EVT_COMBOBOX,OnShape)       
3567        partSizer.Add(partsh,0,WACV)
3568        if data['Size']['Shape'][0] not in ['Unified sphere',]:
3569            partSizer.Add(wx.StaticText(G2frame.dataDisplay,label=shapes[data['Size']['Shape'][0]]),0,WACV)
3570            partprm = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(data['Size']['Shape'][1]),
3571                style=wx.TE_PROCESS_ENTER)
3572            partprm.Bind(wx.EVT_TEXT_ENTER,OnPartVal)       
3573            partprm.Bind(wx.EVT_KILL_FOCUS,OnPartVal)
3574            partSizer.Add(partprm,0,WACV)
3575        sizeSizer.Add(partSizer,0)
3576        sizeSizer.Add((5,5),0)
3577        fitSizer = wx.BoxSizer(wx.HORIZONTAL)
3578        methods = ['MaxEnt','IPG',]
3579        fitSizer.Add(wx.StaticText(G2frame.dataDisplay,label='Fitting method: '),0,WACV)
3580        method = wx.ComboBox(G2frame.dataDisplay,value=data['Size']['Method'],choices=methods,
3581            style=wx.CB_READONLY|wx.CB_DROPDOWN)
3582        method.Bind(wx.EVT_COMBOBOX,OnMethod)
3583        fitSizer.Add(method,0,WACV)
3584        iters = ['10','25','50','100','150','200']       
3585        fitSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' No. iterations: '),0,WACV)
3586        Method = data['Size']['Method']
3587        iter = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size'][Method]['Niter']),choices=iters,
3588            style=wx.CB_READONLY|wx.CB_DROPDOWN)
3589        Indx[iter.GetId()] = [data['Size'][Method],'Niter',0]
3590        iter.Bind(wx.EVT_COMBOBOX,OnIntVal)
3591        fitSizer.Add(iter,0,WACV)
3592        if 'MaxEnt' in data['Size']['Method']:
3593            fitSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Log floor factor: '),0,WACV)
3594            floors = [str(-i) for i in range(9)]
3595            floor = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['MaxEnt']['Sky']),choices=floors,
3596                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3597            Indx[floor.GetId()] = [data['Size']['MaxEnt'],'Sky',-10]
3598            floor.Bind(wx.EVT_COMBOBOX,OnIntVal)
3599            fitSizer.Add(floor,0,WACV)
3600        elif 'IPG' in data['Size']['Method']:
3601            fitSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Q power weight (-1 for sigma): '),0,WACV)
3602            choices = ['-1','0','1','2','3','4']
3603            power = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['IPG']['Power']),choices=choices,
3604                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3605            Indx[power.GetId()] = [data['Size']['IPG'],'Power',-2]
3606            power.Bind(wx.EVT_COMBOBOX,OnIntVal)
3607            fitSizer.Add(power,0,WACV)
3608        sizeSizer.Add(fitSizer,0)
3609
3610        return sizeSizer
3611       
3612    def PartSizer():
3613       
3614        FormFactors = {'Sphere':{},'Spheroid':{'Aspect ratio':[1.0,False]},
3615            'Cylinder':{'Length':[100.,False]},'Cylinder diam':{'Diameter':[100.,False]},
3616            'Cylinder AR':{'Aspect ratio':[1.0,False]},'Unified sphere':{},
3617            'Unified rod':{'Length':[100.,False]},'Unified rod AR':{'Aspect ratio':[1.0,False]},
3618            'Unified disk':{'Thickness':[100.,False]},
3619            'Unified tube':{'Length':[100.,False],'Thickness':[10.,False]},}
3620               
3621        StructureFactors = {'Dilute':{},'Hard sphere':{'VolFr':[0.1,False],'Dist':[100.,False]},
3622            'Sticky hard sphere':{'VolFr':[0.1,False],'Dist':[100.,False],'epis':[0.05,False],'Sticky':[0.2,False]},
3623            'Square well':{'VolFr':[0.1,False],'Dist':[100.,False],'Depth':[0.1,False],'Width':[1.,False]},
3624            'InterPrecipitate':{'VolFr':[0.1,False],'Dist':[100.,False]},}
3625               
3626        ffDistChoices =  ['Sphere','Spheroid','Cylinder','Cylinder diam',
3627            'Cylinder AR','Unified sphere','Unified rod','Unified rod AR',
3628            'Unified disk','Unified tube',]
3629               
3630        ffMonoChoices = ['Sphere','Spheroid','Cylinder','Cylinder AR',]
3631       
3632        sfChoices = ['Dilute','Hard sphere','Sticky hard sphere','Square well','InterPrecipitate',]
3633           
3634        slMult = 1000.
3635                 
3636        def OnValue(event):
3637            Obj = event.GetEventObject()
3638            item,key,sldrObj = Indx[Obj.GetId()]
3639            try:
3640                value = float(Obj.GetValue())
3641                if value <= 0.:
3642                    raise ValueError
3643            except ValueError:
3644                value = item[key][0]
3645            item[key][0] = value
3646            Obj.SetValue('%.3g'%(value))
3647            if key in ['P','epis','Sticky','Depth','Width','VolFr','Dist']:
3648                sldrObj.SetValue(slMult*value)
3649            else:
3650                logv = np.log10(value)
3651                valMinMax = [logv-1,logv+1]
3652                sldrObj.SetRange(slMult*valMinMax[0],slMult*valMinMax[1])
3653                sldrObj.SetValue(slMult*logv)
3654            G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
3655            RefreshPlots()
3656           
3657        def OnSelect(event):
3658            Obj = event.GetEventObject()
3659            item,key = Indx[Obj.GetId()]
3660            item[key] = Obj.GetValue()
3661            if 'Refine' not in Obj.GetLabel():
3662                if 'FormFact' in key :
3663                    item['FFargs'] = FormFactors[Obj.GetValue()]
3664                elif 'StrFact' in key:
3665                    item['SFargs'] = StructureFactors[Obj.GetValue()]
3666                wx.CallAfter(UpdateModelsGrid,G2frame,data)
3667                G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
3668                RefreshPlots()
3669               
3670        def OnDelLevel(event):
3671            Obj = event.GetEventObject()
3672            item = Indx[Obj.GetId()]
3673            del data['Particle']['Levels'][item]
3674            wx.CallAfter(UpdateModelsGrid,G2frame,data)
3675            G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
3676            RefreshPlots()
3677           
3678        def OnParmSlider(event):
3679            Obj = event.GetEventObject()
3680            item,key,pvObj = Indx[Obj.GetId()]
3681            slide = Obj.GetValue()
3682            if key in ['P','epis','Sticky','Depth','Width','VolFr','Dist']:
3683                value = float(slide/slMult)
3684            else:
3685                value = 10.**float(slide/slMult)
3686            item[key][0] = value
3687            pvObj.SetValue('%.3g'%(item[key][0]))
3688            G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
3689            RefreshPlots()
3690           
3691        def SizeSizer():
3692            sizeSizer = wx.FlexGridSizer(0,4,5,5)
3693            sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Distribution: '),0,WACV)
3694            Distchoice = ['LogNormal','Gaussian','LSW','Schulz-Zimm','Bragg','Unified','Porod','Monodisperse',]
3695            distChoice = wx.ComboBox(G2frame.dataDisplay,value=level['Controls']['DistType'],choices=Distchoice,
3696                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3697            Indx[distChoice.GetId()] = [level['Controls'],'DistType']
3698            distChoice.Bind(wx.EVT_COMBOBOX,OnSelect)
3699            sizeSizer.Add(distChoice,0,WACV)    #put structure factor choices here
3700            if level['Controls']['DistType'] not in ['Bragg','Unified','Porod',]:
3701                sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Form Factor: '),0,WACV)
3702                if 'Mono' in level['Controls']['DistType']:
3703                    ffChoice = wx.ComboBox(G2frame.dataDisplay,value=level['Controls']['FormFact'],choices=ffMonoChoices,
3704                        style=wx.CB_READONLY|wx.CB_DROPDOWN)
3705                else:
3706                    ffChoice = wx.ComboBox(G2frame.dataDisplay,value=level['Controls']['FormFact'],choices=ffDistChoices,
3707                        style=wx.CB_READONLY|wx.CB_DROPDOWN)
3708                Indx[ffChoice.GetId()] = [level['Controls'],'FormFact']
3709                ffChoice.Bind(wx.EVT_COMBOBOX,OnSelect)
3710                sizeSizer.Add(ffChoice,0,WACV)
3711               
3712                sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Material: '),0,WACV)
3713                matSel = wx.ComboBox(G2frame.dataDisplay,value=level['Controls']['Material'],
3714                    choices=Substances['Substances'].keys(),style=wx.CB_READONLY|wx.CB_DROPDOWN)
3715                Indx[matSel.GetId()] = [level['Controls'],'Material']
3716                matSel.Bind(wx.EVT_COMBOBOX,OnSelect)       
3717                sizeSizer.Add(matSel,0,WACV) #do neutron test here?
3718                rho = Substances['Substances'][level['Controls']['Material']].get('XAnom density',0.0)
3719                level['Controls']['Contrast'] = contrast = (rho-rhoMat)**2                 
3720                sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Resonant X-ray contrast: '),0,WACV)
3721                sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=%.2f 10%scm%s'%(contrast,Pwr20,Pwrm4)),0,WACV)
3722                if 'Mono' not in level['Controls']['DistType']:
3723                    sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Num. radii: '),0,WACV)
3724                    radii = ['25','50','75','100','200']
3725                    nRadii = wx.ComboBox(G2frame.dataDisplay,value=str(level['Controls']['NumPoints']),choices=radii,
3726                        style=wx.CB_READONLY|wx.CB_DROPDOWN)
3727                    Indx[nRadii.GetId()] = [level['Controls'],'NumPoints']
3728                    nRadii.Bind(wx.EVT_COMBOBOX,OnSelect)
3729                    sizeSizer.Add(nRadii,0,WACV)
3730                    sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' R dist. cutoff: '),0,WACV)
3731                    rCutoff = G2gd.ValidatedTxtCtrl(G2frame.dataDisplay,level['Controls'],'Cutoff',
3732                        min=0.001,max=0.1,typeHint=float)
3733                    sizeSizer.Add(rCutoff,0,WACV)
3734            elif level['Controls']['DistType']  in ['Unified',]:
3735                Parms = level['Unified']
3736                Best = G2sasd.Bestimate(Parms['G'][0],Parms['Rg'][0],Parms['P'][0])
3737                sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Estimated Dist B: %12.4g'%(Best)),0,WACV)
3738            return sizeSizer
3739           
3740        def ParmSizer():
3741            parmSizer = wx.FlexGridSizer(0,3,5,5)
3742            parmSizer.AddGrowableCol(2,1)
3743            parmSizer.SetFlexibleDirection(wx.HORIZONTAL)
3744            Parms = level[level['Controls']['DistType']]
3745            FFargs = level['Controls']['FFargs']
3746            SFargs = level['Controls'].get('SFargs',{})
3747            parmOrder = ['Volume','Radius','Mean','StdDev','MinSize','G','Rg','B','P','Cutoff',
3748                'PkInt','PkPos','PkSig','PkGam',]
3749            for parm in parmOrder:
3750                if parm in Parms:
3751                    if parm == 'MinSize':
3752                        parmSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Dist '+parm),0,wx.ALIGN_CENTER)
3753                    else:
3754                        parmVar = wx.CheckBox(G2frame.dataDisplay,label='Refine? Dist '+parm) 
3755                        parmVar.SetValue(Parms[parm][1])
3756                        parmVar.Bind(wx.EVT_CHECKBOX, OnSelect)
3757                        parmSizer.Add(parmVar,0,WACV)
3758                        Indx[parmVar.GetId()] = [Parms[parm],1]
3759                    parmValue = wx.TextCtrl(G2frame.dataDisplay,value='%.3g'%(Parms[parm][0]),
3760                        style=wx.TE_PROCESS_ENTER)
3761                    parmValue.Bind(wx.EVT_TEXT_ENTER,OnValue)       
3762                    parmValue.Bind(wx.EVT_KILL_FOCUS,OnValue)
3763                    parmSizer.Add(parmValue,0,WACV)
3764                    if parm == 'P':
3765                        value = Parms[parm][0]
3766                        valMinMax = [0.1,4.2]
3767                    else:
3768                        value = np.log10(Parms[parm][0])
3769                        valMinMax = [value-1,value+1]
3770                    parmSldr = wx.Slider(G2frame.dataDisplay,minValue=slMult*valMinMax[0],
3771                        maxValue=slMult*valMinMax[1],value=slMult*value)
3772                    Indx[parmValue.GetId()] = [Parms,parm,parmSldr]
3773                    Indx[parmSldr.GetId()] = [Parms,parm,parmValue]
3774                    parmSldr.Bind(wx.EVT_SLIDER,OnParmSlider)
3775                    parmSizer.Add(parmSldr,1,wx.EXPAND)
3776            if level['Controls']['DistType'] not in ['Bragg']:
3777                parmOrder = ['Aspect ratio','Length','Diameter','Thickness','VolFr','Dist','epis','Sticky','Depth','Width']
3778                fTypes = ['FF ','SF ']
3779                for iarg,Args in enumerate([FFargs,SFargs]):
3780                    for parm in parmOrder:
3781                        if parm in Args:
3782                            parmVar = wx.CheckBox(G2frame.dataDisplay,label='Refine? '+fTypes[iarg]+parm) 
3783                            parmVar.SetValue(Args[parm][1])
3784                            Indx[parmVar.GetId()] = [Args[parm],1]
3785                            parmVar.Bind(wx.EVT_CHECKBOX, OnSelect)
3786                            parmSizer.Add(parmVar,0,WACV)
3787                            parmValue = wx.TextCtrl(G2frame.dataDisplay,value='%.3g'%(Args[parm][0]),
3788                                style=wx.TE_PROCESS_ENTER)
3789                            parmValue.Bind(wx.EVT_TEXT_ENTER,OnValue)       
3790                            parmValue.Bind(wx.EVT_KILL_FOCUS,OnValue)
3791                            parmSizer.Add(parmValue,0,WACV)
3792                            value = Args[parm][0]
3793                            if parm == 'epis':
3794                                valMinMax = [0,.1]
3795                            elif parm in ['Sticky','Width',]:
3796                                valMinMax = [0,1.]
3797                            elif parm == 'Depth':
3798                                valMinMax = [-2.,2.]
3799                            elif parm == 'Dist':
3800                                valMinMax = [100.,1000.]
3801                            elif parm == 'VolFr':
3802                                valMinMax = [1.e-4,1.]
3803                            else:
3804                                value = np.log10(Args[parm][0])
3805                                valMinMax = [value-1,value+1]
3806                            parmSldr = wx.Slider(G2frame.dataDisplay,minValue=slMult*valMinMax[0],
3807                                maxValue=slMult*valMinMax[1],value=slMult*value)
3808                            Indx[parmVar.GetId()] = [Args[parm],1]
3809                            Indx[parmValue.GetId()] = [Args,parm,parmSldr]
3810                            Indx[parmSldr.GetId()] = [Args,parm,parmValue]
3811                            parmSldr.Bind(wx.EVT_SLIDER,OnParmSlider)
3812                            parmSizer.Add(parmSldr,1,wx.EXPAND)
3813            return parmSizer               
3814           
3815        Indx = {}
3816        partSizer = wx.BoxSizer(wx.VERTICAL)
3817        topSizer = wx.BoxSizer(wx.HORIZONTAL)
3818        topSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Particle fit parameters: '),0,WACV)
3819        topSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Matrix: '),0,WACV)
3820        matsel = wx.ComboBox(G2frame.dataDisplay,value=data['Particle']['Matrix']['Name'],
3821            choices=Substances['Substances'].keys(),style=wx.CB_READONLY|wx.CB_DROPDOWN)
3822        Indx[matsel.GetId()] = [data['Particle']['Matrix'],'Name'] 
3823        matsel.Bind(wx.EVT_COMBOBOX,OnSelect) #Do neutron test here?
3824        rhoMat = Substances['Substances'][data['Particle']['Matrix']['Name']].get('XAnom density',0.0)       
3825        topSizer.Add(matsel,0,WACV)
3826        topSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Volume fraction: '),0,WACV)
3827        volfrac = G2gd.ValidatedTxtCtrl(G2frame.dataDisplay,data['Particle']['Matrix']['VolFrac'],0,
3828                typeHint=float)
3829        topSizer.Add(volfrac,0,WACV)
3830        volVar = wx.CheckBox(G2frame.dataDisplay,label=' Refine?')
3831        volVar.SetValue(data['Particle']['Matrix']['VolFrac'][1])
3832        Indx[volVar.GetId()] = [data['Particle']['Matrix']['VolFrac'],1]
3833        volVar.Bind(wx.EVT_CHECKBOX, OnSelect)
3834        topSizer.Add(volVar,0,WACV)
3835        partSizer.Add(topSizer,0,)
3836        for ilev,level in enumerate(data['Particle']['Levels']):
3837            G2gd.HorizontalLine(partSizer,G2frame.dataDisplay)
3838            topLevel = wx.BoxSizer(wx.HORIZONTAL)
3839            topLevel.Add(wx.StaticText(G2frame.dataDisplay,label=' Model component %d: '%(ilev)),0,WACV)
3840            delBtn = wx.Button(G2frame.dataDisplay,label=' Delete?')
3841            Indx[delBtn.GetId()] = ilev
3842            delBtn.Bind(wx.EVT_BUTTON,OnDelLevel)
3843            topLevel.Add(delBtn,0,WACV)
3844            partSizer.Add(topLevel,0)
3845            partSizer.Add(SizeSizer())
3846            if level['Controls']['DistType'] not in ['Bragg','Unified','Porod',]:
3847                topLevel.Add(wx.StaticText(G2frame.dataDisplay,label=' Structure factor: '),0,WACV)
3848                strfctr = wx.ComboBox(G2frame.dataDisplay,value=level['Controls']['StrFact'],
3849                    choices=sfChoices,style=wx.CB_READONLY|wx.CB_DROPDOWN)
3850                Indx[strfctr.GetId()] = [level['Controls'],'StrFact']
3851                strfctr.Bind(wx.EVT_COMBOBOX,OnSelect)
3852                topLevel.Add(strfctr,0,WACV)
3853            partSizer.Add(ParmSizer(),0,wx.EXPAND)
3854        return partSizer
3855       
3856    def OnEsdScale(event):
3857        try:
3858            value = float(esdScale.GetValue())
3859            if value <= 0.:
3860                raise ValueError
3861        except ValueError:
3862            value = 1./np.sqrt(ProfDict['wtFactor'])
3863        ProfDict['wtFactor'] = 1./value**2
3864        esdScale.SetValue('%.3f'%(value))
3865        RefreshPlots(True)
3866       
3867    def OnBackChange(event):
3868        try:
3869            value = float(backVal.GetValue())
3870        except ValueError:
3871            value = 0.0
3872        backVal.SetValue('%.3g'%(value))
3873        data['Back'][0] = value
3874        Profile[4][:] = value
3875        RefreshPlots()
3876       
3877    def OnBackFile(event):  #multiple backgrounds?
3878        data['BackFile'] = backFile.GetValue()
3879        if data['BackFile']:
3880            fixBack =  data['Back'][0]
3881            BackId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,data['BackFile'])
3882            BackSample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,BackId, 'Sample Parameters'))
3883            Profile[5] = BackSample['Scale'][0]*G2frame.PatternTree.GetItemPyData(BackId)[1][1]
3884        else:
3885            Profile[5] = np.zeros(len(Profile[5]))
3886        RefreshPlots(True)
3887           
3888    Sample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Sample Parameters'))
3889    Limits = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Limits'))
3890    Substances = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Substances'))
3891    ProfDict,Profile = G2frame.PatternTree.GetItemPyData(G2frame.PatternId)[:2]
3892    if data['BackFile']:
3893        BackId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,data['BackFile'])
3894        BackSample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,BackId, 'Sample Parameters'))
3895        Profile[5] = BackSample['Scale'][0]*G2frame.PatternTree.GetItemPyData(BackId)[1][1]
3896    if G2frame.dataDisplay:
3897        G2frame.dataFrame.DestroyChildren()
3898    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.ModelMenu)
3899    if not G2frame.dataFrame.GetStatusBar():
3900        Status = G2frame.dataFrame.CreateStatusBar()
3901    G2frame.dataFrame.SetLabel('Modelling')
3902    G2frame.dataDisplay = wxscroll.ScrolledPanel(G2frame.dataFrame)
3903    G2frame.dataFrame.Bind(wx.EVT_MENU, OnCopyModel, id=G2gd.wxID_MODELCOPY)
3904    G2frame.dataFrame.Bind(wx.EVT_MENU, OnCopyFlags, id=G2gd.wxID_MODELCOPYFLAGS)
3905    G2frame.dataFrame.Bind(wx.EVT_MENU, OnFitModel, id=G2gd.wxID_MODELFIT)
3906    G2frame.dataFrame.Bind(wx.EVT_MENU, OnFitModelAll, id=G2gd.wxID_MODELFITALL)
3907    G2frame.dataFrame.Bind(wx.EVT_MENU, OnUnDo, id=G2gd.wxID_MODELUNDO)
3908    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddModel, id=G2gd.wxID_MODELADD)
3909    Indx = {}
3910    mainSizer = wx.BoxSizer(wx.VERTICAL)
3911    topSizer = wx.BoxSizer(wx.HORIZONTAL)
3912    models = ['Size dist.','Particle fit']
3913    topSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Modeling by: '),0,WACV)
3914    fitSel = wx.ComboBox(G2frame.dataDisplay,value=data['Current'],choices=models,
3915        style=wx.CB_READONLY|wx.CB_DROPDOWN)
3916    fitSel.Bind(wx.EVT_COMBOBOX,OnSelectFit)       
3917    topSizer.Add(fitSel,0,WACV)
3918    topSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Error multiplier: '),0,WACV)
3919    esdScale = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(1./np.sqrt(ProfDict['wtFactor'])),style=wx.TE_PROCESS_ENTER)
3920    esdScale.Bind(wx.EVT_TEXT_ENTER,OnEsdScale)       
3921    esdScale.Bind(wx.EVT_KILL_FOCUS,OnEsdScale)
3922    topSizer.Add(esdScale,0,WACV)
3923    mainSizer.Add(topSizer)
3924    G2gd.HorizontalLine(mainSizer,G2frame.dataDisplay)
3925    if 'Size' in data['Current']:
3926        if 'MaxEnt' in data['Size']['Method']:
3927            Status.SetStatusText('Size distribution by Maximum entropy')
3928        elif 'IPG' in data['Size']['Method']:
3929            Status.SetStatusText('Size distribution by Interior-Point Gradient')
3930        mainSizer.Add(SizeSizer())       
3931    elif 'Particle' in data['Current']:
3932        mainSizer.Add(PartSizer(),1,wx.ALIGN_LEFT|wx.EXPAND)
3933    G2gd.HorizontalLine(mainSizer,G2frame.dataDisplay)   
3934    backSizer = wx.BoxSizer(wx.HORIZONTAL)
3935    backSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Background:'),0,WACV)
3936    backVal = wx.TextCtrl(G2frame.dataDisplay,value='%.3g'%(data['Back'][0]),style=wx.TE_PROCESS_ENTER)
3937    Indx[backVal.GetId()] = ['Back',0,'%.3g']
3938    backVal.Bind(wx.EVT_TEXT_ENTER,OnBackChange)       
3939    backVal.Bind(wx.EVT_KILL_FOCUS,OnBackChange)
3940    backSizer.Add(backVal,0,WACV)
3941    backVar = wx.CheckBox(G2frame.dataDisplay,label='Refine?')
3942    Indx[backVar.GetId()] = [data['Back'],1]
3943    backVar.SetValue(data['Back'][1])
3944    backVar.Bind(wx.EVT_CHECKBOX, OnCheckBox)
3945    backSizer.Add(backVar,0,WACV)
3946    #multiple background files?
3947    backSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,' Background file: '),0,WACV)
3948    Choices = ['',]+G2gd.GetPatternTreeDataNames(G2frame,['SASD',])
3949    backFile = wx.ComboBox(parent=G2frame.dataDisplay,value=data['BackFile'],choices=Choices,
3950        style=wx.CB_READONLY|wx.CB_DROPDOWN)
3951    backFile.Bind(wx.EVT_COMBOBOX,OnBackFile)
3952    backSizer.Add(backFile)   
3953    mainSizer.Add(backSizer)
3954
3955    mainSizer.Layout()   
3956    G2frame.dataDisplay.SetSizer(mainSizer)
3957    G2frame.dataDisplay.SetAutoLayout(1)
3958    G2frame.dataDisplay.SetupScrolling()
3959    Size = mainSizer.Fit(G2frame.dataFrame)
3960    Size[0] += 25
3961    G2frame.dataDisplay.SetSize(Size)
3962    G2frame.dataFrame.setSizePosLeft(Size)   
3963   
3964################################################################################
3965#####  PDF controls
3966################################################################################           
3967       
3968def UpdatePDFGrid(G2frame,data):
3969    '''respond to selection of PWDR PDF data tree item.
3970    '''
3971    global inst
3972    tth2q = lambda t,w:4.0*math.pi*sind(t/2.0)/w
3973    dataFile = G2frame.PatternTree.GetItemText(G2frame.PatternId)
3974    powName = 'PWDR'+dataFile[4:]
3975    powId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, powName)
3976    fullLimits,limits = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,powId, 'Limits'))[:2]
3977    inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,powId, 'Instrument Parameters'))[0]
3978    if 'Lam' in inst:
3979        keV = 12.397639/inst['Lam'][1]
3980    else:
3981        keV = 12.397639/inst['Lam1'][0]
3982    wave = 12.397639/keV
3983    qLimits = [tth2q(fullLimits[0],wave),tth2q(fullLimits[1],wave)]
3984    data['QScaleLim'][1] = min(qLimits[1],data['QScaleLim'][1])
3985    if data['QScaleLim'][0]:
3986        data['QScaleLim'][0] = max(qLimits[0],data['QScaleLim'][0])
3987    else:                                #initial setting at 90% of max Q
3988        data['QScaleLim'][0] = 0.90*data['QScaleLim'][1]
3989    polariz = inst['Polariz.'][1]
3990    azimuth = inst['Azimuth'][1]
3991    itemDict = {}
3992   
3993    def FillFileSizer(fileSizer,key):
3994        #fileSizer is a FlexGridSizer(3,6)
3995       
3996        def OnSelectFile(event):
3997            Obj = event.GetEventObject()
3998            fileKey,itemKey,fmt = itemDict[Obj.GetId()]
3999            if itemKey == 'Name':
4000                value = Obj.GetValue()
4001            Obj.SetValue(fmt%(value))
4002            data[fileKey][itemKey] = value
4003            UpdatePDFGrid(G2frame,data)
4004       
4005        def OnValueChange(event):
4006            Obj = event.GetEventObject()
4007            fileKey,itemKey,fmt = itemDict[Obj.GetId()]
4008            try:
4009                value = float(Obj.GetValue())
4010            except ValueError:
4011                value = -1.0
4012            Obj.SetValue(fmt%(value))
4013            data[fileKey][itemKey] = value
4014            auxPlot = ComputePDF(data)
4015            G2plt.PlotISFG(G2frame,newPlot=True)
4016                       
4017        item = data[key]
4018        fileList = np.array(GetFileList('PWDR')).T[1]
4019        fileSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' '+key+' file:'),0,WACV)
4020        fileName = wx.ComboBox(G2frame.dataDisplay,value=item['Name'],choices=fileList,
4021            style=wx.CB_READONLY|wx.CB_DROPDOWN)
4022        itemDict[fileName.GetId()] = [key,'Name','%s']
4023        fileName.Bind(wx.EVT_COMBOBOX,OnSelectFile)       
4024        fileSizer.Add(fileName,0,)
4025        fileSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label='Multiplier:'),0,WACV)
4026        mult = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(item['Mult']),style=wx.TE_PROCESS_ENTER)
4027        itemDict[mult.GetId()] = [key,'Mult','%.3f']
4028        mult.Bind(wx.EVT_TEXT_ENTER,OnValueChange)       
4029        mult.Bind(wx.EVT_KILL_FOCUS,OnValueChange)
4030        fileSizer.Add(mult,0,)
4031        fileSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label='Add:'),0,WACV)
4032        add = wx.TextCtrl(G2frame.dataDisplay,value='%.0f'%(item['Add']),style=wx.TE_PROCESS_ENTER)
4033        itemDict[add.GetId()] = [key,'Add','%.0f']
4034        add.Bind(wx.EVT_TEXT_ENTER,OnValueChange)       
4035        add.Bind(wx.EVT_KILL_FOCUS,OnValueChange)
4036        fileSizer.Add(add,0,)
4037       
4038    def SumElementVolumes():
4039        sumVol = 0.
4040        ElList = data['ElList']
4041        for El in ElList:
4042            Avol = (4.*math.pi/3.)*ElList[El]['Drad']**3
4043            sumVol += Avol*ElList[El]['FormulaNo']
4044        return sumVol
4045        auxPlot = ComputePDF(data)
4046        G2plt.PlotISFG(G2frame,newPlot=True)       
4047       
4048    def FillElemSizer(elemSizer,ElData):
4049       
4050        def OnFractionChange(event):
4051            try:
4052                value = max(0.0,float(num.GetValue()))
4053            except ValueError:
4054                value = 0.0
4055            num.SetValue('%.3f'%(value))
4056            ElData['FormulaNo'] = value
4057            data['Form Vol'] = max(10.0,SumElementVolumes())
4058            formVol.SetValue('%.2f'%(data['Form Vol']))
4059            wx.CallAfter(UpdatePDFGrid,G2frame,data)
4060            auxPlot = ComputePDF(data)
4061            G2plt.PlotISFG(G2frame,newPlot=True)       
4062       
4063        elemSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,
4064            label=' Element: '+'%2s'%(ElData['Symbol'])+' * '),0,WACV)
4065        num = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(ElData['FormulaNo']),style=wx.TE_PROCESS_ENTER)
4066        num.Bind(wx.EVT_TEXT_ENTER,OnFractionChange)       
4067        num.Bind(wx.EVT_KILL_FOCUS,OnFractionChange)
4068        elemSizer.Add(num,0,WACV)
4069        elemSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,
4070            label="f': %.3f"%(ElData['fp'])+' f": %.3f'%(ElData['fpp'])+' mu: %.2f barns'%(ElData['mu']) ),
4071            0,WACV)
4072           
4073    def OnGeometry(event):
4074        data['Geometry'] = geometry.GetValue()
4075        UpdatePDFGrid(G2frame,data)
4076        auxPlot = ComputePDF(data)
4077        G2plt.PlotISFG(G2frame,newPlot=True)       
4078       
4079    def OnDetType(event):
4080        data['DetType'] = detType.GetValue()
4081        UpdatePDFGrid(G2frame,data)
4082        auxPlot = ComputePDF(data)
4083        G2plt.PlotISFG(G2frame,newPlot=True)       
4084       
4085    def OnFormVol(event):
4086        try:
4087            value = float(formVol.GetValue())
4088            if value <= 0.0:
4089                raise ValueError
4090        except ValueError:
4091            value = data['Form Vol']
4092        data['Form Vol'] = value
4093        UpdatePDFGrid(G2frame,data)
4094        auxPlot = ComputePDF(data)
4095        G2plt.PlotISFG(G2frame,newPlot=False)       
4096       
4097    def OnDiameter(event):
4098        try:
4099            value = float(diam.GetValue())
4100            if value <= 0.0:
4101                raise ValueError
4102        except ValueError:
4103            value = data['Diam']
4104        data['Diam'] = value
4105        UpdatePDFGrid(G2frame,data)
4106        auxPlot = ComputePDF(data)
4107        G2plt.PlotISFG(G2frame,newPlot=False)
4108       
4109    def OnPolaVal(event):
4110        try:
4111            value = float(polaVal.GetValue())
4112            if not (0.0 <= value <= 1.0):
4113                raise ValueError
4114        except ValueError:
4115            value = inst['Polariz.'][1]
4116        inst['Polariz.'][1] = value
4117        polaVal.SetValue('%.2f'%(inst['Polariz.'][1]))
4118        UpdatePDFGrid(G2frame,data)
4119        auxPlot = ComputePDF(data)
4120        G2plt.PlotISFG(G2frame,newPlot=False)</