source: trunk/GSASIIpwdGUI.py @ 1585

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

remove Pwr from FitPeaksZ, SSZ & T - wasn't used
put in derivatives for FitPeaksZ, etc. - works better
reorder arrows & make the expand/shrink symmetric about view point
remove zero & refine? from SS Unit Cells display - not refinable with modulation coeff.

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