source: trunk/GSASIIpwdGUI.py @ 1619

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

add columnsorter for hetrogeneous seq ref; reorg to start moving widgets out of g2grid

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