source: trunk/GSASIIpwdGUI.py @ 1518

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

Add metadata file processing for Image stress/strain data - reads sample load & sample phi from text file.
Correction to PWDR metadata file processing

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