source: trunk/GSASIIpwdGUI.py @ 1551

Last change on this file since 1551 was 1551, checked in by vondreele, 8 years ago

fixes to calibration

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