source: trunk/GSASIIpwdGUI.py @ 1496

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

Add sequential peak fitting.
Change Back:n to Back;n for background parameters
Also DebyeA, etc.

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