source: trunk/GSASIIpwdGUI.py @ 1572

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

complete SS indexing, apply hklm extinction rules
cleanup indexing, cell refine, load cell, make new phase, calibration, etc.

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