source: trunk/GSASIIpwdGUI.py @ 2461

Last change on this file since 2461 was 2431, checked in by vondreele, 9 years ago

fix problem with wxPython 3.x with changing text entry focus. Needed a event.Skip() in every TextCtrl? event handler. Hope I got them all...

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