source: trunk/GSASIIpwdGUI.py @ 1537

Last change on this file since 1537 was 1537, checked in by toby, 9 years ago

fix redraw of Limits, Peaks and Index Peaks data window

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