source: trunk/GSASIIpwdGUI.py @ 1637

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

fixes to peak indexing routines; new Inst argument for getHKLpeak messed up indexing routines. Now optional at end of arguments.
some more work on SS constraints.

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