source: trunk/GSASIIpwdGUI.py @ 1498

Last change on this file since 1498 was 1498, checked in by vondreele, 7 years ago

try to implement drag/drop of tree items - commented out as it doesn't work
add 'ShowCell?' to Controls to avoid cell errors for sequential single peak fitting when normal sequential refinement has been done
fix a neg. peak width error

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