source: trunk/GSASIIpwdGUI.py @ 1541

Last change on this file since 1541 was 1541, checked in by toby, 8 years ago

wx bug changing background terms

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