source: trunk/GSASIIpwdGUI.py @ 1618

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

fix space group print in shelx export
fix errors when data is deleted
add HKLshow to change in space group in index page
more on supersymmetry refinement

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 213.0 KB
Line 
1# -*- coding: utf-8 -*-
2#GSASIIpwdGUI - powder data display routines
3########### SVN repository information ###################
4# $Date: 2014-12-27 03:08:45 +0000 (Sat, 27 Dec 2014) $
5# $Author: vondreele $
6# $Revision: 1618 $
7# $URL: trunk/GSASIIpwdGUI.py $
8# $Id: GSASIIpwdGUI.py 1618 2014-12-27 03:08:45Z 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: 1618 $")
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
2039    def RefreshIndexPeaksGrid(event):
2040        r,c =  event.GetRow(),event.GetCol()
2041        peaks = G2frame.IndexPeaksTable.GetData()
2042        if c == 2:
2043            if peaks[r][c]:
2044                peaks[r][c] = False
2045            else:
2046                peaks[r][c] = True
2047            G2frame.IndexPeaksTable.SetData(peaks)
2048            G2frame.PatternTree.SetItemPyData(IndexId,[peaks,data[1]])
2049            G2frame.dataDisplay.ForceRefresh()
2050            if 'PKS' in G2frame.PatternTree.GetItemText(G2frame.PatternId):
2051                G2plt.PlotPowderLines(G2frame)
2052            else:
2053                G2plt.PlotPatterns(G2frame,plotType='PWDR')
2054           
2055    def OnReload(event):
2056        peaks = []
2057        sigs = []
2058        Peaks = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Peak List'))
2059        for ip,peak in enumerate(Peaks['peaks']):
2060            dsp = G2lat.Pos2dsp(Inst,peak[0])
2061            peaks.append([peak[0],peak[2],True,False,0,0,0,dsp,0.0])    #SS?
2062            try:
2063                sig = Peaks['sigDict']['pos'+str(ip)]
2064            except KeyError:
2065                sig = 0.
2066            sigs.append(sig)
2067        data = [peaks,sigs]
2068        G2frame.PatternTree.SetItemPyData(IndexId,data)
2069        UpdateIndexPeaksGrid(G2frame,data)
2070       
2071    def KeyEditPickGrid(event):
2072        colList = G2frame.dataDisplay.GetSelectedCols()
2073        rowList = G2frame.dataDisplay.GetSelectedRows()
2074        data = G2frame.PatternTree.GetItemPyData(IndexId)
2075        if event.GetKeyCode() == wx.WXK_RETURN:
2076            event.Skip(True)
2077        elif event.GetKeyCode() == wx.WXK_CONTROL:
2078            event.Skip(True)
2079        elif event.GetKeyCode() == wx.WXK_SHIFT:
2080            event.Skip(True)
2081        elif colList:
2082            G2frame.dataDisplay.ClearSelection()
2083            key = event.GetKeyCode()
2084            for col in colList:
2085                if G2frame.IndexPeaksTable.GetColLabelValue(col) in ['use',]:
2086                    if key == 89: #'Y'
2087                        for row in range(G2frame.IndexPeaksTable.GetNumberRows()): data[0][row][col]=True
2088                    elif key == 78:  #'N'
2089                        for row in range(G2frame.IndexPeaksTable.GetNumberRows()): data[0][row][col]=False
2090           
2091    if G2frame.dataDisplay:
2092        G2frame.dataFrame.Clear()
2093    if not G2frame.dataFrame.GetStatusBar():
2094        Status = G2frame.dataFrame.CreateStatusBar()
2095    if 'PWD' in G2frame.PatternTree.GetItemText(G2frame.PatternId):
2096        G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.IndPeaksMenu)
2097        G2frame.Bind(wx.EVT_MENU, OnReload, id=G2gd.wxID_INDXRELOAD)
2098    G2frame.dataFrame.IndexPeaks.Enable(False)
2099    G2frame.IndexPeaksTable = []
2100    if len(data[0]):
2101        G2frame.dataFrame.IndexPeaks.Enable(True)
2102        Unit = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Unit Cells List'))
2103        if Unit:
2104            if len(Unit) == 4:  #patch
2105                Unit.append({})
2106            controls,bravais,cellist,dmin,ssopt = Unit
2107            G2frame.HKL = []
2108            if ssopt.get('Use',False):
2109                cell = controls[6:12]
2110                A = G2lat.cell2A(cell)
2111                ibrav = bravaisSymb.index(controls[5])
2112                spc = controls[13]
2113                SGData = G2spc.SpcGroup(spc)[1]
2114                SSGData = G2spc.SSpcGroup(SGData,ssopt['ssSymb'])[1]
2115                Vec = ssopt['ModVec']
2116                maxH = ssopt['maxH']
2117                G2frame.HKL = G2pwd.getHKLMpeak(dmin,Inst,SGData,SSGData,Vec,maxH,A)
2118                data[0] = G2indx.IndexSSPeaks(data[0],G2frame.HKL)[1]
2119            else:        #select cell from table - no SS
2120                for i,cell in enumerate(cellist):
2121                    if cell[-2]:
2122                        ibrav = cell[2]
2123                        A = G2lat.cell2A(cell[3:9])
2124                        G2frame.HKL = G2lat.GenHBravais(dmin,ibrav,A)
2125                        for hkl in G2frame.HKL:
2126                            hkl.insert(4,G2lat.Dsp2pos(Inst,hkl[3]))
2127                        data[0] = G2indx.IndexPeaks(data[0],G2frame.HKL)[1]
2128                        break
2129    rowLabels = []
2130    for i in range(len(data[0])): rowLabels.append(str(i+1))
2131    colLabels = ['position','intensity','use','indexed','h','k','l','d-obs','d-calc']
2132    Types = [wg.GRID_VALUE_FLOAT+':10,4',wg.GRID_VALUE_FLOAT+':10,1',]+2*[wg.GRID_VALUE_BOOL,]+ \
2133        3*[wg.GRID_VALUE_LONG,]+2*[wg.GRID_VALUE_FLOAT+':10,5',]
2134    if len(data[0]) and len(data[0][0]) > 9:
2135        colLabels = ['position','intensity','use','indexed','h','k','l','m','d-obs','d-calc']
2136        Types = [wg.GRID_VALUE_FLOAT+':10,4',wg.GRID_VALUE_FLOAT+':10,1',]+2*[wg.GRID_VALUE_BOOL,]+ \
2137            4*[wg.GRID_VALUE_LONG,]+2*[wg.GRID_VALUE_FLOAT+':10,5',]
2138    G2frame.PatternTree.SetItemPyData(IndexId,data)
2139    G2frame.IndexPeaksTable = G2gd.Table(data[0],rowLabels=rowLabels,colLabels=colLabels,types=Types)
2140    G2frame.dataFrame.SetLabel('Index Peak List')
2141    G2frame.dataDisplay = G2gd.GSGrid(parent=G2frame.dataFrame)               
2142    G2frame.dataDisplay.SetTable(G2frame.IndexPeaksTable, True)
2143    XY = []
2144    Sigs = []
2145    for r in range(G2frame.dataDisplay.GetNumberRows()):
2146        for c in range(G2frame.dataDisplay.GetNumberCols()):
2147            if c == 2:
2148                G2frame.dataDisplay.SetReadOnly(r,c,isReadOnly=False)
2149            else:
2150                G2frame.dataDisplay.SetReadOnly(r,c,isReadOnly=True)
2151        if data[0][r][2] and data[0][r][3]:
2152            XY.append([data[0][r][-1],data[0][r][0]])
2153            try:
2154                sig = data[1][r]
2155            except IndexError:
2156                sig = 0.
2157            Sigs.append(sig)
2158    G2frame.dataDisplay.Bind(wg.EVT_GRID_CELL_LEFT_CLICK, RefreshIndexPeaksGrid)
2159    G2frame.dataDisplay.Bind(wx.EVT_KEY_DOWN, KeyEditPickGrid)                 
2160    G2frame.dataDisplay.SetMargins(0,0)
2161    G2frame.dataDisplay.AutoSizeColumns(False)
2162    G2frame.dataFrame.setSizePosLeft([490,300])
2163    if len(XY):
2164        XY = np.array(XY)
2165        G2plt.PlotCalib(G2frame,Inst,XY,Sigs,newPlot=True)
2166    G2frame.dataFrame.SendSizeEvent()
2167     
2168################################################################################
2169#####  Unit cells
2170################################################################################           
2171       
2172def UpdateUnitCellsGrid(G2frame, data):
2173    '''respond to selection of PWDR Unit Cells data tree item.
2174    '''
2175    UnitCellsId = G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Unit Cells List')
2176    SPGlist = G2spc.spglist
2177    bravaisSymb = ['Fm3m','Im3m','Pm3m','R3-H','P6/mmm','I4/mmm',
2178        'P4/mmm','Fmmm','Immm','Cmmm','Pmmm','C2/m','P2/m','P1']
2179    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',
2180        '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']
2181    Inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Instrument Parameters'))[0]
2182    if 'C' in Inst['Type'][0]:
2183        wave = G2mth.getWave(Inst)
2184    else:
2185        difC = Inst['difC'][1]
2186   
2187    def SetLattice(controls):
2188        ibrav = bravaisSymb.index(controls[5])
2189        if ibrav in [0,1,2]:
2190            controls[7] = controls[8] = controls[6]
2191            controls[9] = controls[10] = controls[11] = 90.
2192        elif ibrav in [3,4,5,6]:
2193            controls[7] = controls[6]
2194            controls[9] = controls[10] = controls[11] = 90.
2195            if ibrav in [3,4]:
2196                controls[11] = 120.
2197        elif ibrav in [7,8,9,10]:
2198            controls[9] = controls[10] = controls[11] = 90.
2199        elif ibrav in [11,12]:
2200            controls[9] = controls[11] = 90.  # b unique
2201        if len(controls) < 13: controls.append(0)
2202        controls[12] = G2lat.calc_V(G2lat.cell2A(controls[6:12]))
2203        return ibrav
2204       
2205    def OnNcNo(event):
2206        controls[2] = NcNo.GetValue()
2207       
2208    def OnIfX20(event):
2209        G2frame.ifX20 = x20.GetValue()
2210       
2211    def OnStartVol(event):
2212        try:
2213            stVol = int(float(startVol.GetValue()))
2214            if stVol < 25:
2215                raise ValueError
2216        except ValueError:
2217            stVol = 25
2218        controls[3] = stVol
2219        startVol.SetValue("%d"%(stVol))
2220       
2221    def OnBravais(event):
2222        Obj = event.GetEventObject()
2223        bravais[bravList.index(Obj.GetId())] = Obj.GetValue()
2224       
2225    def OnZero(event):
2226        try:
2227            Zero = min(5.0,max(-5.0,float(zero.GetValue())))
2228        except ValueError:
2229            Zero = 0.0
2230        controls[1] = Zero
2231        zero.SetValue("%.4f"%(Zero))
2232       
2233    def OnZeroVar(event):
2234        controls[0] = zeroVar.GetValue()
2235       
2236    def OnSSopt(event):
2237        if controls[5] in ['Fm3m','Im3m','Pm3m']:
2238            SSopt.SetValue(False)
2239            G2frame.ErrorDialog('Cubic lattice', 'Superlattice not allowed for a cubic lattice')
2240            return
2241        ssopt['Use'] = SSopt.GetValue()
2242        if 'ssSymb' not in ssopt:
2243            ssopt.update({'ssSymb':'(abg)','ModVec':[0.1,0.1,0.1],'maxH':1})
2244        wx.CallAfter(UpdateUnitCellsGrid,G2frame,data)
2245       
2246    def OnSelMG(event):
2247        ssopt['ssSymb'] = selMG.GetValue()
2248        Vec = ssopt['ModVec']
2249        modS = G2spc.splitSSsym(ssopt['ssSymb'])[0]
2250        ssopt['ModVec'] = G2spc.SSGModCheck(Vec,modS)[0]
2251        print ' Selecting: ',controls[13],ssopt['ssSymb'], 'maxH:',ssopt['maxH']
2252        OnHklShow(event)
2253        wx.CallAfter(UpdateUnitCellsGrid,G2frame,data)
2254       
2255    def OnModVal(event):
2256        Obj = event.GetEventObject()
2257        ObjId = Obj.GetId()
2258        Id = Indx[ObjId]
2259        try:
2260            value = min(1.0,max(0.,float(Obj.GetValue())))
2261        except ValueError:
2262            value = ssopt['ModVec'][Id]
2263        Obj.SetValue('%.4f'%(value))
2264        ssopt['ModVec'][Id] = value
2265        OnHklShow(event)
2266       
2267    def OnMoveMod(event):
2268        Obj = event.GetEventObject()
2269        ObjId = Obj.GetId()
2270        Id,valObj = Indx[ObjId]
2271        move = Obj.GetValue()*0.0005
2272        Obj.SetValue(0)
2273        value = min(1.0,max(.0,float(valObj.GetValue())+move))
2274        valObj.SetValue('%.4f'%(value)) 
2275        ssopt['ModVec'][Id] = value
2276        OnHklShow(event)
2277       
2278    def OnMaxMH(event):
2279        ssopt['maxH'] = int(maxMH.GetValue())
2280        print ' Selecting: ',controls[13],ssopt['ssSymb'], 'maxH:',ssopt['maxH']
2281        OnHklShow(event)
2282       
2283    def OnFindMV(event):
2284        Peaks = np.copy(peaks[0])
2285        print ' Trying: ',controls[13],ssopt['ssSymb'], 'maxH:',ssopt['maxH']
2286        dlg = wx.ProgressDialog('Elapsed time','Modulation vector search',
2287            style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE)
2288        try:
2289            ssopt['ModVec'] = G2indx.findMV(Peaks,controls,ssopt,Inst,dlg)
2290        finally:
2291            dlg.Destroy()
2292        OnHklShow(event)
2293        wx.CallAfter(UpdateUnitCellsGrid,G2frame,data)
2294       
2295    def OnBravSel(event):
2296        brav = bravSel.GetString(bravSel.GetSelection())
2297        controls[5] = brav
2298        controls[13] = SPGlist[brav][0]       
2299        wx.CallAfter(UpdateUnitCellsGrid,G2frame,data)
2300       
2301    def OnSpcSel(event):
2302        controls[13] = spcSel.GetString(spcSel.GetSelection())
2303        G2frame.dataFrame.RefineCell.Enable(True)
2304        OnHklShow(event)
2305       
2306    def SetCellValue(Obj,ObjId,value):
2307        ibrav = bravaisSymb.index(controls[5])
2308        if ibrav in [0,1,2]:
2309            controls[6] = controls[7] = controls[8] = value
2310            controls[9] = controls[10] = controls[11] = 90.0
2311            Obj.SetValue("%.5f"%(controls[6]))
2312        elif ibrav in [3,4,5,6]:
2313            if ObjId == 0:
2314                controls[6] = controls[7] = value
2315                Obj.SetValue("%.5f"%(controls[6]))
2316            else:
2317                controls[8] = value
2318                Obj.SetValue("%.5f"%(controls[8]))
2319            controls[9] = controls[10] = controls[11] = 90.0
2320            if ibrav in [3,4]:
2321                controls[11] = 120.
2322        elif ibrav in [7,8,9,10]:
2323            controls[6+ObjId] = value
2324            Obj.SetValue("%.5f"%(controls[6+ObjId]))
2325            controls[9] = controls[10] = controls[11] = 90.0
2326        elif ibrav in [11,12]:
2327            controls[9] = controls[11] = 90.0
2328            if ObjId != 3:
2329                controls[6+ObjId] = value
2330                Obj.SetValue("%.5f"%(controls[6+ObjId]))
2331            else:
2332                controls[10] = value
2333                Obj.SetValue("%.3f"%(controls[10]))
2334        else:
2335            controls[6+ObjId] = value
2336            if ObjId < 3:
2337                Obj.SetValue("%.5f"%(controls[6+ObjId]))
2338            else:
2339                Obj.SetValue("%.3f"%(controls[6+ObjId]))
2340        controls[12] = G2lat.calc_V(G2lat.cell2A(controls[6:12]))
2341        volVal.SetValue("%.3f"%(controls[12]))
2342       
2343    def OnMoveCell(event):
2344        Obj = event.GetEventObject()
2345        ObjId = cellList.index(Obj.GetId())
2346        valObj = valDict[Obj.GetId()]
2347        if ObjId/2 < 3:
2348            move = Obj.GetValue()*0.01
2349        else:
2350            move = Obj.GetValue()*0.1
2351        Obj.SetValue(0)
2352        value = float(valObj.GetValue())+move 
2353        SetCellValue(valObj,ObjId/2,value)
2354        OnHklShow(event)
2355       
2356    def OnCellChange(event):
2357        Obj = event.GetEventObject()
2358        ObjId = cellList.index(Obj.GetId())
2359        try:
2360            value = max(1.0,float(Obj.GetValue()))
2361        except ValueError:
2362            if ObjId/2 < 3:               #bad cell edge - reset
2363                value = controls[6+ObjId/2]
2364            else:                       #bad angle
2365                value = 90.
2366        SetCellValue(Obj,ObjId/2,value)
2367       
2368    def OnHklShow(event):
2369        PatternId = G2frame.PatternId
2370        PickId = G2frame.PickId   
2371        peaks = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Index Peak List'))
2372        limits = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Limits'))[1]
2373        controls,bravais,cells,dmin,ssopt = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Unit Cells List'))
2374        cell = controls[6:12]
2375        A = G2lat.cell2A(cell)
2376        ibrav = bravaisSymb.index(controls[5])
2377        spc = controls[13]
2378        SGData = G2spc.SpcGroup(spc)[1]
2379#        if 'C' in Inst['Type'][0]:
2380#            dmin = G2lat.Pos2dsp(Inst,limits[1])
2381#        else:   #TOF - use other limit!
2382#            dmin = G2lat.Pos2dsp(Inst,limits[0])
2383        if ssopt.get('Use',False):
2384            dmin = peaks[0][-1][8]
2385            SSGData = G2spc.SSpcGroup(SGData,ssopt['ssSymb'])[1]
2386            Vec = ssopt['ModVec']
2387            maxH = ssopt['maxH']
2388            G2frame.HKL = G2pwd.getHKLMpeak(dmin,Inst,SGData,SSGData,Vec,maxH,A)
2389            peaks = [G2indx.IndexSSPeaks(peaks[0],G2frame.HKL)[1],peaks[1]]   #keep esds from peak fit
2390            M20,X20 = G2indx.calc_M20SS(peaks[0],G2frame.HKL)
2391        else:
2392            dmin = peaks[0][-1][7]
2393            G2frame.HKL = G2pwd.getHKLpeak(dmin,Inst,SGData,A)
2394            peaks = [G2indx.IndexPeaks(peaks[0],G2frame.HKL)[1],peaks[1]]   #keep esds from peak fit
2395            M20,X20 = G2indx.calc_M20(peaks[0],G2frame.HKL)
2396        print ' new M20,X20: %.2f %d fraction found: %.3f'%(M20,X20,float(len(peaks[0]))/len(G2frame.HKL))
2397        G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Index Peak List'),peaks)
2398        if 'PKS' in G2frame.PatternTree.GetItemText(G2frame.PatternId):
2399            G2plt.PlotPowderLines(G2frame)
2400        else:
2401            G2plt.PlotPatterns(G2frame)
2402           
2403    def OnSortCells(event):
2404        controls,bravais,cells,dmin,ssopt = G2frame.PatternTree.GetItemPyData(UnitCellsId)
2405        c =  event.GetCol()
2406        if colLabels[c] == 'M20':
2407            cells = G2indx.sortM20(cells)
2408        elif colLabels[c] in ['X20','Bravais','a','b','c','alpha','beta','gamma','Volume']:
2409            if c == 1:
2410                c += 1  #X20 before Use
2411            cells = G2indx.sortCells(cells,c-1)     #an extra column (Use) not in cells
2412        else:
2413            return
2414        data = [controls,bravais,cells,dmin,ssopt]
2415        G2frame.PatternTree.SetItemPyData(UnitCellsId,data)
2416        wx.CallAfter(UpdateUnitCellsGrid,G2frame,data)
2417       
2418    def CopyUnitCell(event):
2419        controls,bravais,cells,dmin,ssopt = G2frame.PatternTree.GetItemPyData(UnitCellsId)
2420        for Cell in cells:
2421            if Cell[-2]:
2422                break
2423        cell = Cell[2:9]
2424        controls[4] = 1
2425        controls[5] = bravaisSymb[cell[0]]
2426        controls[6:12] = cell[1:8]
2427        controls[12] = G2lat.calc_V(G2lat.cell2A(controls[6:12]))
2428        controls[13] = spaceGroups[bravaisSymb.index(controls[5])]
2429        G2frame.PatternTree.SetItemPyData(UnitCellsId,[controls,bravais,cells,dmin,ssopt])
2430        G2frame.dataFrame.RefineCell.Enable(True)
2431        wx.CallAfter(UpdateUnitCellsGrid,G2frame,data)       
2432               
2433    def RefineCell(event):
2434       
2435        def cellPrint(ibrav,A):
2436            cell = G2lat.A2cell(A)
2437            Vol = G2lat.calc_V(A)
2438            if ibrav in [0,1,2]:
2439                print " %s%10.6f" % ('a =',cell[0])
2440            elif ibrav in [3,4,5,6]:
2441                print " %s%10.6f %s%10.6f %s%12.3f" % ('a =',cell[0],' c =',cell[2],' volume =',Vol)
2442            elif ibrav in [7,8,9,10]:
2443                print " %s%10.6f %s%10.6f %s%10.6f %s%12.3f" % ('a =',cell[0],'b =',cell[1],'c =',cell[2],' volume =',Vol)
2444            elif ibrav in [11,12]:
2445                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)
2446            else:
2447                print " %s%10.6f %s%10.6f %s%10.6f" % ('a =',cell[0],'b =',cell[1],'c =',cell[2])
2448                print " %s%8.3f %s%8.3f %s%8.3f %s%12.3f" % ('alpha =',cell[3],'beta =',cell[4],'gamma =',cell[5],' volume =',Vol)
2449               
2450        def vecPrint(Vec):
2451            print ' %s %10.5f %10.5f %10.5f'%('Modulation vector:',Vec[0],Vec[1],Vec[2])
2452             
2453        PatternId = G2frame.PatternId
2454        PickId = G2frame.PickId   
2455        peaks = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Index Peak List'))
2456        if not len(peaks[0]):
2457            G2frame.ErrorDialog('No peaks!', 'Nothing to refine!')
2458            return       
2459        print ' Refine cell'
2460        controls,bravais,cells,dmin,ssopt = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Unit Cells List'))
2461        cell = controls[6:12]
2462        A = G2lat.cell2A(cell)
2463        ibrav = bravaisSymb.index(controls[5])
2464        SGData = G2spc.SpcGroup(controls[13])[1]
2465        dmin = G2indx.getDmin(peaks[0])-0.005
2466        if 'C' in Inst['Type'][0]:
2467            if ssopt.get('Use',False):
2468                vecFlags = [True if x in ssopt['ssSymb'] else False for x in ['a','b','g']]
2469                SSGData = G2spc.SSpcGroup(SGData,ssopt['ssSymb'])[1]
2470                G2frame.HKL = G2pwd.getHKLMpeak(dmin,Inst,SGData,SSGData,ssopt['ModVec'],ssopt['maxH'],A)
2471                peaks = [G2indx.IndexSSPeaks(peaks[0],G2frame.HKL)[1],peaks[1]]   #put peak fit esds back in peaks
2472                Lhkl,M20,X20,Aref,Vec,Zero = \
2473                    G2indx.refinePeaksZSS(peaks[0],wave,Inst,SGData,SSGData,ssopt['maxH'],ibrav,A,ssopt['ModVec'],vecFlags,controls[1],controls[0])
2474            else:
2475                G2frame.HKL = G2pwd.getHKLpeak(dmin,Inst,SGData,A)
2476                peaks = [G2indx.IndexPeaks(peaks[0],G2frame.HKL)[1],peaks[1]]   #put peak fit esds back in peaks
2477                Lhkl,M20,X20,Aref,Zero = G2indx.refinePeaksZ(peaks[0],wave,ibrav,A,controls[1],controls[0])
2478        else:   #'T'OF - doesn't seem to work
2479            G2frame.HKL = G2pwd.getHKLpeak(dmin,Inst,SGData,A)
2480            peaks = [G2indx.IndexPeaks(peaks[0],G2frame.HKL)[1],peaks[1]]   #put peak fit esds back in peaks
2481            Lhkl,M20,X20,Aref,Zero = G2indx.refinePeaksT(peaks[0],difC,ibrav,A,controls[1],controls[0])           
2482        controls[1] = Zero
2483        controls[6:12] = G2lat.A2cell(Aref)
2484        controls[12] = G2lat.calc_V(Aref)
2485        cells = G2frame.PatternTree.GetItemPyData(UnitCellsId)[2]
2486        for cell in cells:
2487            cell[-2] = False
2488        cells.insert(0,[M20,X20,ibrav]+controls[6:13]+[True,False])
2489        if ssopt.get('Use',False):
2490            ssopt['ModVec'] = Vec
2491            G2frame.HKL = G2pwd.getHKLMpeak(dmin,Inst,SGData,SSGData,ssopt['ModVec'],ssopt['maxH'],A)
2492        else:
2493            G2frame.HKL = G2pwd.getHKLpeak(dmin,Inst,SGData,A)
2494        data = [controls,bravais,cells,dmin,ssopt]
2495        G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Unit Cells List'),data)
2496        print " %s%10.3f" % ('refinement M20 = ',M20)
2497        print ' unindexed lines = ',X20
2498        cellPrint(ibrav,Aref)
2499        ip = 4
2500        if ssopt.get('Use',False):
2501            vecPrint(Vec)
2502            ip = 5
2503        for hkl in G2frame.HKL:
2504            hkl[ip] = G2lat.Dsp2pos(Inst,hkl[ip-1])+controls[1]
2505        if 'PKS' in G2frame.PatternTree.GetItemText(G2frame.PatternId):
2506            G2plt.PlotPowderLines(G2frame)
2507        else:
2508            G2plt.PlotPatterns(G2frame)
2509        wx.CallAfter(UpdateUnitCellsGrid,G2frame,data)
2510       
2511    def IndexPeaks(event):
2512        PatternId = G2frame.PatternId   
2513        print 'Peak Indexing'
2514        keepcells = []
2515        try:
2516            controls,bravais,cells,dmin,ssopt = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Unit Cells List'))
2517            for cell in cells:
2518                if cell[11]:
2519                    cell[10] = False    #clear selection flag on keepers
2520                    keepcells.append(cell)
2521        except IndexError:
2522            pass
2523        except ValueError:
2524            G2frame.ErrorDialog('Error','Need to set controls in Unit Cell List first')
2525            return
2526        if ssopt.get('Use',False):
2527            G2frame.ErrorDialog('Super lattice error','Indexing not available for super lattices')
2528            return
2529        if True not in bravais:
2530            G2frame.ErrorDialog('Error','No Bravais lattices selected')
2531            return
2532        if not len(peaks[0]):
2533            G2frame.ErrorDialog('Error','Index Peak List is empty')
2534            return
2535        if len(peaks[0][0]) > 9:
2536            G2frame.ErrorDialog('Error','You need to reload Index Peaks List first')
2537            return
2538        G2frame.dataFrame.CopyCell.Enable(False)
2539        G2frame.dataFrame.RefineCell.Enable(False)
2540        OK,dmin,newcells = G2indx.DoIndexPeaks(peaks[0],controls,bravais,G2frame.ifX20)
2541        cells = keepcells+newcells
2542        cells = G2indx.sortM20(cells)
2543        if OK:
2544            cells[0][10] = True         #select best M20
2545            data = [controls,bravais,cells,dmin,ssopt]
2546            G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Unit Cells List'),data)
2547            bestCell = cells[0]
2548            if bestCell[0] > 10.:
2549                G2frame.HKL = G2lat.GenHBravais(dmin,bestCell[2],G2lat.cell2A(bestCell[3:9]))
2550                for hkl in G2frame.HKL:
2551                    hkl.insert(4,G2lat.Dsp2pos(Inst,hkl[3])+controls[1])
2552                if 'PKS' in G2frame.PatternTree.GetItemText(G2frame.PatternId):
2553                    G2plt.PlotPowderLines(G2frame)
2554                else:
2555                    G2plt.PlotPatterns(G2frame)
2556            G2frame.dataFrame.CopyCell.Enable(True)
2557            G2frame.dataFrame.IndexPeaks.Enable(True)
2558            G2frame.dataFrame.MakeNewPhase.Enable(True)
2559            G2frame.ifX20 = True
2560            wx.CallAfter(UpdateUnitCellsGrid,G2frame,data)
2561               
2562    def RefreshUnitCellsGrid(event):
2563        data = G2frame.PatternTree.GetItemPyData(UnitCellsId)
2564        cells,dmin = data[2:4]
2565        r,c =  event.GetRow(),event.GetCol()
2566        if cells:
2567            if c == 2:
2568                for i in range(len(cells)):
2569                    cells[i][-2] = False
2570                    UnitCellsTable.SetValue(i,c,False)
2571                UnitCellsTable.SetValue(r,c,True)
2572                gridDisplay.Refresh()
2573                cells[r][-2] = True
2574                ibrav = cells[r][2]
2575                A = G2lat.cell2A(cells[r][3:9])
2576                G2frame.HKL = G2lat.GenHBravais(dmin,ibrav,A)
2577                for hkl in G2frame.HKL:
2578                    hkl.insert(4,G2lat.Dsp2pos(Inst,hkl[3])+controls[1])
2579                if 'PKS' in G2frame.PatternTree.GetItemText(G2frame.PatternId):
2580                    G2plt.PlotPowderLines(G2frame)
2581                else:
2582                    G2plt.PlotPatterns(G2frame)
2583            elif c == 11:
2584                if UnitCellsTable.GetValue(r,c):
2585                    UnitCellsTable.SetValue(r,c,False)
2586                    cells[r][c] = False
2587                else:
2588                    cells[r][c] = True
2589                    UnitCellsTable.SetValue(r,c,True)
2590                gridDisplay.ForceRefresh()
2591            G2frame.PatternTree.SetItemPyData(UnitCellsId,data)
2592       
2593    def MakeNewPhase(event):
2594        if not G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Phases'):
2595            sub = G2frame.PatternTree.AppendItem(parent=G2frame.root,text='Phases')
2596        else:
2597            sub = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Phases')
2598        PhaseName = ''
2599        dlg = wx.TextEntryDialog(None,'Enter a name for this phase','Phase Name Entry','New phase',
2600            style=wx.OK)
2601        try:
2602            if dlg.ShowModal() == wx.ID_OK:
2603                PhaseName = dlg.GetValue()
2604                cells = G2frame.PatternTree.GetItemPyData(UnitCellsId)[2]
2605                for Cell in cells:
2606                    if Cell[-2]:
2607                        break
2608                cell = Cell[2:10]       
2609                sub = G2frame.PatternTree.AppendItem(parent=sub,text=PhaseName)
2610                E,SGData = G2spc.SpcGroup(controls[13])
2611                G2frame.PatternTree.SetItemPyData(sub, \
2612                    G2IO.SetNewPhase(Name=PhaseName,SGData=SGData,cell=cell[1:],Super=ssopt))
2613                Status.SetStatusText('Change space group from '+str(controls[13])+' if needed')
2614        finally:
2615            dlg.Destroy()
2616           
2617    if G2frame.dataDisplay:
2618        G2frame.dataFrame.DestroyChildren()
2619    G2frame.dataDisplay = wxscroll.ScrolledPanel(G2frame.dataFrame)
2620    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.IndexMenu)
2621    if not G2frame.dataFrame.GetStatusBar():
2622        Status = G2frame.dataFrame.CreateStatusBar()
2623    G2frame.Bind(wx.EVT_MENU, IndexPeaks, id=G2gd.wxID_INDEXPEAKS)
2624    G2frame.Bind(wx.EVT_MENU, CopyUnitCell, id=G2gd.wxID_COPYCELL)
2625    G2frame.Bind(wx.EVT_MENU, RefineCell, id=G2gd.wxID_REFINECELL)
2626    G2frame.Bind(wx.EVT_MENU, MakeNewPhase, id=G2gd.wxID_MAKENEWPHASE)   
2627    controls,bravais,cells,dmin,ssopt = data
2628    if len(controls) < 13:              #add cell volume if missing
2629        controls.append(G2lat.calc_V(G2lat.cell2A(controls[6:12])))
2630    if len(controls) < 14:              #add space gropu used in indexing
2631        controls.append(spaceGroups[bravaisSymb.index(controls[5])])
2632    G2frame.PatternTree.SetItemPyData(UnitCellsId,data)            #update with volume
2633    bravaisNames = ['Cubic-F','Cubic-I','Cubic-P','Trigonal-R','Trigonal/Hexagonal-P',
2634        'Tetragonal-I','Tetragonal-P','Orthorhombic-F','Orthorhombic-I','Orthorhombic-C',
2635        'Orthorhombic-P','Monoclinic-C','Monoclinic-P','Triclinic']
2636    cellGUIlist = [[[0,1,2],4,zip([" Unit cell: a = "," Vol = "],["%.5f","%.3f"],[True,False],[0,0])],
2637    [[3,4,5,6],6,zip([" Unit cell: a = "," c = "," Vol = "],["%.5f","%.5f","%.3f"],[True,True,False],[0,2,0])],
2638    [[7,8,9,10],8,zip([" Unit cell: a = "," b = "," c = "," Vol = "],["%.5f","%.5f","%.5f","%.3f"],
2639        [True,True,True,False],[0,1,2,0])],
2640    [[11,12],10,zip([" Unit cell: a = "," b = "," c = "," beta = "," Vol = "],
2641        ["%.5f","%.5f","%.5f","%.3f","%.3f"],[True,True,True,True,False],[0,1,2,4,0])],
2642    [[13,],8,zip([" Unit cell: a = "," b = "," c = "," Vol = "," alpha = "," beta = "," gamma = "],
2643        ["%.5f","%.5f","%.5f","%.3f","%.3f","%.3f","%.3f"],
2644        [True,True,True,False,True,True,True],[0,1,2,0,3,4,5])]]
2645   
2646    G2frame.dataFrame.SetLabel('Unit Cells List')
2647    G2frame.dataFrame.IndexPeaks.Enable(False)
2648    peaks = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Index Peak List'))
2649    if peaks:
2650        G2frame.dataFrame.IndexPeaks.Enable(True)
2651    G2frame.dataFrame.RefineCell.Enable(False)
2652    if controls[12] > 1.0:                               #if a "real" volume (i.e. not default)
2653        G2frame.dataFrame.RefineCell.Enable(True)   
2654    G2frame.dataFrame.CopyCell.Enable(False)
2655    G2frame.dataFrame.MakeNewPhase.Enable(False)       
2656    if cells:
2657        G2frame.dataFrame.CopyCell.Enable(True)
2658        G2frame.dataFrame.MakeNewPhase.Enable(True)       
2659    mainSizer = wx.BoxSizer(wx.VERTICAL)
2660    mainSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Indexing controls: '),0,WACV)
2661    mainSizer.Add((5,5),0)
2662    littleSizer = wx.FlexGridSizer(0,5,5,5)
2663    littleSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Max Nc/Nobs '),0,WACV)
2664    NcNo = wx.SpinCtrl(G2frame.dataDisplay)
2665    NcNo.SetRange(2,6)
2666    NcNo.SetValue(controls[2])
2667    NcNo.Bind(wx.EVT_SPINCTRL,OnNcNo)
2668    littleSizer.Add(NcNo,0,WACV)
2669    littleSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Start Volume '),0,WACV)
2670    startVol = wx.TextCtrl(G2frame.dataDisplay,value=str('%d'%(controls[3])),style=wx.TE_PROCESS_ENTER)
2671    startVol.Bind(wx.EVT_TEXT_ENTER,OnStartVol)
2672    startVol.Bind(wx.EVT_KILL_FOCUS,OnStartVol)
2673    littleSizer.Add(startVol,0,WACV)
2674    x20 = wx.CheckBox(G2frame.dataDisplay,label='Use M20/(X20+1)?')
2675    x20.SetValue(G2frame.ifX20)
2676    x20.Bind(wx.EVT_CHECKBOX,OnIfX20)
2677    littleSizer.Add(x20,0,WACV)
2678    mainSizer.Add(littleSizer,0)
2679    mainSizer.Add((5,5),0)
2680    mainSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Select Bravais Lattices for indexing: '),
2681        0,WACV)
2682    mainSizer.Add((5,5),0)
2683    littleSizer = wx.FlexGridSizer(0,7,5,5)
2684    bravList = []
2685    bravs = zip(bravais,bravaisNames)
2686    for brav,bravName in bravs:
2687        bravCk = wx.CheckBox(G2frame.dataDisplay,label=bravName)
2688        bravList.append(bravCk.GetId())
2689        bravCk.SetValue(brav)
2690        bravCk.Bind(wx.EVT_CHECKBOX,OnBravais)
2691        littleSizer.Add(bravCk,0,WACV)
2692    mainSizer.Add(littleSizer,0)
2693    mainSizer.Add((5,5),0)
2694   
2695    mainSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Cell Refinement: '),0,WACV)
2696    mainSizer.Add((5,5),0)
2697    littleSizer = wx.BoxSizer(wx.HORIZONTAL)
2698    littleSizer.Add(wx.StaticText(G2frame.dataDisplay,label=" Bravais lattice "),0,WACV)
2699    bravSel = wx.Choice(G2frame.dataDisplay,choices=bravaisSymb)
2700    bravSel.SetSelection(bravaisSymb.index(controls[5]))
2701    bravSel.Bind(wx.EVT_CHOICE,OnBravSel)
2702    littleSizer.Add(bravSel,0,WACV)
2703    littleSizer.Add(wx.StaticText(G2frame.dataDisplay,label=" Space group "),0,WACV)
2704    spcSel = wx.Choice(G2frame.dataDisplay,choices=SPGlist[controls[5]])
2705    spcSel.SetSelection(SPGlist[controls[5]].index(controls[13]))
2706    spcSel.Bind(wx.EVT_CHOICE,OnSpcSel)
2707    littleSizer.Add(spcSel,0,WACV)
2708    if ssopt.get('Use',False):        #zero for super lattice doesn't work!
2709        controls[0] = False
2710    else:
2711        littleSizer.Add(wx.StaticText(G2frame.dataDisplay,label=" Zero offset"),0,WACV)
2712        zero = wx.TextCtrl(G2frame.dataDisplay,value="%.4f"%(controls[1]),style=wx.TE_PROCESS_ENTER)
2713        zero.Bind(wx.EVT_TEXT_ENTER,OnZero)
2714        zero.Bind(wx.EVT_KILL_FOCUS,OnZero)
2715        littleSizer.Add(zero,0,WACV)
2716        zeroVar = wx.CheckBox(G2frame.dataDisplay,label="Refine?")
2717        zeroVar.SetValue(controls[0])
2718        zeroVar.Bind(wx.EVT_CHECKBOX,OnZeroVar)
2719        littleSizer.Add(zeroVar,0,WACV)
2720    SSopt = wx.CheckBox(G2frame.dataDisplay,label="Super lattice?")
2721    SSopt.SetValue(ssopt.get('Use',False))
2722    SSopt.Bind(wx.EVT_CHECKBOX,OnSSopt)
2723    littleSizer.Add(SSopt,0,WACV)
2724    hklShow = wx.Button(G2frame.dataDisplay,label="Show hkl positions")
2725    hklShow.Bind(wx.EVT_BUTTON,OnHklShow)
2726    littleSizer.Add(hklShow,0,WACV)
2727    mainSizer.Add(littleSizer,0)
2728   
2729    mainSizer.Add((5,5),0)
2730    ibrav = SetLattice(controls)
2731    for cellGUI in cellGUIlist:
2732        if ibrav in cellGUI[0]:
2733            useGUI = cellGUI
2734    cellList = []
2735    valDict = {}
2736    littleSizer = wx.FlexGridSizer(0,useGUI[1],5,5)
2737    for txt,fmt,ifEdit,Id in useGUI[2]:
2738        littleSizer.Add(wx.StaticText(G2frame.dataDisplay,label=txt),0,WACV)
2739        if ifEdit:          #a,b,c,etc.
2740            cellVal = wx.TextCtrl(G2frame.dataDisplay,value=(fmt%(controls[6+Id])),style=wx.TE_PROCESS_ENTER)
2741            cellVal.Bind(wx.EVT_TEXT_ENTER,OnCellChange)       
2742            cellVal.Bind(wx.EVT_KILL_FOCUS,OnCellChange)
2743            valSizer = wx.BoxSizer(wx.HORIZONTAL)
2744            valSizer.Add(cellVal,0,WACV)
2745            cellSpin = wx.SpinButton(G2frame.dataDisplay,style=wx.SP_VERTICAL,size=wx.Size(20,20))
2746            cellSpin.SetValue(0)
2747            cellSpin.SetRange(-1,1)
2748            cellSpin.Bind(wx.EVT_SPIN, OnMoveCell)
2749            valSizer.Add(cellSpin,0,WACV)
2750            littleSizer.Add(valSizer,0,WACV)
2751            cellList.append(cellVal.GetId())
2752            cellList.append(cellSpin.GetId())
2753            valDict[cellSpin.GetId()] = cellVal
2754        else:               #volume
2755            volVal = wx.TextCtrl(G2frame.dataDisplay,value=(fmt%(controls[12])),style=wx.TE_READONLY)
2756            volVal.SetBackgroundColour(VERY_LIGHT_GREY)
2757            littleSizer.Add(volVal,0,WACV)
2758    mainSizer.Add(littleSizer,0)
2759    if ssopt.get('Use',False):        #super lattice display
2760        indChoice = ['1','2','3','4',]
2761        SpSg = controls[13]
2762        ssChoice = G2spc.ssdict[SpSg]
2763        if ssopt['ssSymb'] not in ssChoice:
2764            ssopt['ssSymb'] = ssChoice[0]
2765        ssSizer = wx.BoxSizer(wx.HORIZONTAL)
2766        ssSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Supersymmetry space group: '+SpSg+' '),0,WACV)
2767        selMG = wx.ComboBox(G2frame.dataDisplay,value=ssopt['ssSymb'],
2768                choices=ssChoice,style=wx.CB_READONLY|wx.CB_DROPDOWN)
2769        selMG.Bind(wx.EVT_COMBOBOX, OnSelMG)
2770        ssSizer.Add(selMG,0,WACV)
2771        ssSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Mod. vector: '),0,WACV)
2772        modS = G2spc.splitSSsym(ssopt['ssSymb'])[0]
2773        ssopt['ModVec'],ifShow = G2spc.SSGModCheck(ssopt['ModVec'],modS)
2774        Indx = {}
2775        for i,[val,show] in enumerate(zip(ssopt['ModVec'],ifShow)):
2776            if show:
2777                valSizer = wx.BoxSizer(wx.HORIZONTAL)
2778                modVal = wx.TextCtrl(G2frame.dataDisplay,value=('%.4f'%(val)),
2779                    size=wx.Size(50,20),style=wx.TE_PROCESS_ENTER)
2780                modVal.Bind(wx.EVT_TEXT_ENTER,OnModVal)       
2781                modVal.Bind(wx.EVT_KILL_FOCUS,OnModVal)
2782                valSizer.Add(modVal,0,WACV)
2783                modSpin = wx.SpinButton(G2frame.dataDisplay,style=wx.SP_VERTICAL,size=wx.Size(20,20))
2784                modSpin.SetValue(0)
2785                modSpin.SetRange(-1,1)
2786                modSpin.Bind(wx.EVT_SPIN, OnMoveMod)
2787                valSizer.Add(modSpin,0,WACV)
2788                ssSizer.Add(valSizer,0,WACV)
2789                Indx[modVal.GetId()] = i
2790                Indx[modSpin.GetId()] = [i,modVal]
2791            else:
2792                modVal = wx.TextCtrl(G2frame.dataDisplay,value=('%.3f'%(val)),
2793                    size=wx.Size(50,20),style=wx.TE_READONLY)
2794                modVal.SetBackgroundColour(VERY_LIGHT_GREY)
2795                ssSizer.Add(modVal,0,WACV)
2796        ssSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Max. M: '),0,WACV)
2797        maxMH = wx.ComboBox(G2frame.dataDisplay,value=str(ssopt['maxH']),
2798            choices=indChoice,style=wx.CB_READONLY|wx.CB_DROPDOWN)
2799        maxMH.Bind(wx.EVT_COMBOBOX, OnMaxMH)
2800        ssSizer.Add(maxMH,0,WACV)
2801        findMV = wx.wx.Button(G2frame.dataDisplay,label="Find mod. vec.?")
2802        findMV.Bind(wx.EVT_BUTTON,OnFindMV)
2803        ssSizer.Add(findMV,0,WACV)
2804        mainSizer.Add(ssSizer,0)
2805
2806    if cells:
2807        mainSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label='\n Indexing Result:'),0,WACV)
2808        rowLabels = []
2809        colLabels = ['M20','X20','use','Bravais','a','b','c','alpha','beta','gamma','Volume','Keep']
2810        Types = [wg.GRID_VALUE_FLOAT+':10,2',wg.GRID_VALUE_NUMBER,wg.GRID_VALUE_BOOL,wg.GRID_VALUE_STRING,]+ \
2811            3*[wg.GRID_VALUE_FLOAT+':10,5',]+3*[wg.GRID_VALUE_FLOAT+':10,3',]+ \
2812            [wg.GRID_VALUE_FLOAT+':10,2',wg.GRID_VALUE_BOOL]
2813        numRows = len(cells)
2814        table = []
2815        for cell in cells:
2816            rowLabels.append('')
2817            row = cell[0:2]+[cell[-2]]+[bravaisSymb[cell[2]]]+cell[3:10]+[cell[11],]
2818            if cell[-2]:
2819                A = G2lat.cell2A(cell[3:9])
2820                G2frame.HKL = G2lat.GenHBravais(dmin,cell[2],A)
2821                for hkl in G2frame.HKL:
2822                    hkl.insert(4,G2lat.Dsp2pos(Inst,hkl[3])+controls[1])
2823            table.append(row)
2824        UnitCellsTable = G2gd.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
2825        gridDisplay = G2gd.GSGrid(G2frame.dataDisplay)
2826        gridDisplay.SetTable(UnitCellsTable, True)
2827        G2frame.dataFrame.CopyCell.Enable(True)
2828        gridDisplay.Bind(wg.EVT_GRID_CELL_LEFT_CLICK,RefreshUnitCellsGrid)
2829        gridDisplay.Bind(wg.EVT_GRID_LABEL_LEFT_DCLICK,OnSortCells)
2830        gridDisplay.SetMargins(0,0)
2831        gridDisplay.SetRowLabelSize(0)
2832        gridDisplay.AutoSizeColumns(False)
2833        for r in range(gridDisplay.GetNumberRows()):
2834            for c in range(gridDisplay.GetNumberCols()):
2835                if c == 2:
2836                    gridDisplay.SetReadOnly(r,c,isReadOnly=False)
2837                else:
2838                    gridDisplay.SetReadOnly(r,c,isReadOnly=True)
2839        mainSizer.Add(gridDisplay,0,WACV)
2840    mainSizer.Layout()   
2841    G2frame.dataDisplay.SetSizer(mainSizer)
2842    G2frame.dataDisplay.SetAutoLayout(1)
2843    G2frame.dataDisplay.SetupScrolling()
2844    Size = mainSizer.Fit(G2frame.dataFrame)
2845    Size[0] += 25
2846    G2frame.dataDisplay.SetSize(Size)
2847    G2frame.dataFrame.setSizePosLeft(Size)   
2848   
2849################################################################################
2850#####  Reflection list
2851################################################################################           
2852       
2853def UpdateReflectionGrid(G2frame,data,HKLF=False,Name=''):
2854    '''respond to selection of PWDR Reflections data tree item by displaying
2855    a table of reflections in the data window.
2856    '''
2857    def OnPlotHKL(event):
2858        '''Plots a layer of reflections
2859        '''
2860        FoMax = np.max(refList.T[8+Super])
2861        Hmin = np.array([int(np.min(refList.T[0])),int(np.min(refList.T[1])),int(np.min(refList.T[2]))])
2862        Hmax = np.array([int(np.max(refList.T[0])),int(np.max(refList.T[1])),int(np.max(refList.T[2]))])
2863        controls = {'Type' : 'Fo','ifFc' : True,'HKLmax' : Hmax,'HKLmin' : Hmin,
2864            'FoMax' : FoMax,'Zone' : '001','Layer' : 0,'Scale' : 1.0,'Super':Super,'SuperVec':SuperVec}
2865        G2plt.PlotSngl(G2frame,newPlot=True,Data=controls,hklRef=refList,Title=phaseName)
2866       
2867    def OnPlot3DHKL(event):
2868        '''Plots the reflections in 3D
2869        '''
2870        FoMax = np.max(refList.T[8+Super])
2871        Hmin = np.array([int(np.min(refList.T[0])),int(np.min(refList.T[1])),int(np.min(refList.T[2]))])
2872        Hmax = np.array([int(np.max(refList.T[0])),int(np.max(refList.T[1])),int(np.max(refList.T[2]))])
2873        Vpoint = [int(np.mean(refList.T[0])),int(np.mean(refList.T[1])),int(np.mean(refList.T[2]))]
2874        controls = {'Type':'Fosq','Iscale':False,'HKLmax':Hmax,'HKLmin':Hmin,
2875            'FoMax' : FoMax,'Scale' : 1.0,'Drawing':{'viewPoint':[Vpoint,[]],'default':Vpoint[:],
2876            'backColor':[0,0,0],'depthFog':False,'Zclip':10.0,'cameraPos':10.,'Zstep':0.05,
2877            'Scale':1.0,'oldxy':[],'viewDir':[1,0,0]},'Super':Super,'SuperVec':SuperVec}
2878        G2plt.Plot3DSngl(G2frame,newPlot=True,Data=controls,hklRef=refList,Title=phaseName)
2879       
2880    def MakeReflectionTable(phaseName):
2881        '''Returns a wx.grid table (G2gd.Table) containing a list of all reflections
2882        for a phase.       
2883        '''
2884        if phaseName:
2885            pId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Phases')
2886            phaseId =  G2gd.GetPatternTreeItemId(G2frame,pId,phaseName)
2887            General = G2frame.PatternTree.GetItemPyData(phaseId)['General']
2888            Super = General.get('Super',0)
2889            SuperVec = General.get('SuperVec',[])
2890        else:
2891            Super = 0
2892            SuperVec = []       
2893        rowLabels = []
2894        if HKLF:
2895            refList = data[1]['RefList']
2896            refs = refList
2897        else:
2898            if len(data) > 1:
2899                G2frame.dataFrame.SelectPhase.Enable(True)
2900            try:            #patch for old reflection lists
2901                refList = np.array(data[phaseName]['RefList'])
2902                I100 = refList.T[8+Super]*refList.T[11+Super]
2903            except TypeError:
2904                refList = np.array([refl[:11+Super] for refl in data[phaseName]])
2905                I100 = refList.T[8+Super]*np.array([refl[11+Super] for refl in data[phaseName]])
2906            Imax = np.max(I100)
2907            if Imax:
2908                I100 *= 100.0/Imax
2909            if 'C' in Inst['Type'][0]:
2910                refs = np.vstack((refList.T[:15+Super],I100)).T
2911            elif 'T' in Inst['Type'][0]:
2912                refs = np.vstack((refList.T[:18+Super],I100)).T
2913        for i in range(len(refs)): rowLabels.append(str(i))
2914        Types = (4+Super)*[wg.GRID_VALUE_LONG,]+4*[wg.GRID_VALUE_FLOAT+':10,4',]+ \
2915            2*[wg.GRID_VALUE_FLOAT+':10,2',]+[wg.GRID_VALUE_FLOAT+':10,3',]+ \
2916            [wg.GRID_VALUE_FLOAT+':10,3',]
2917        if HKLF:
2918            colLabels = ['H','K','L','mul','d','Fosq','sig','Fcsq','FoTsq','FcTsq','phase','ExtC',]
2919            if 'T' in Inst['Type'][0]:
2920                colLabels = ['H','K','L','mul','d','Fosq','sig','Fcsq','FoTsq','FcTsq','phase','ExtC','wave','tbar']
2921                Types += 2*[wg.GRID_VALUE_FLOAT+':10,3',]
2922            if Super:
2923                colLabels.insert(3,'M')
2924        else:
2925            if 'C' in Inst['Type'][0]:
2926                colLabels = ['H','K','L','mul','d','pos','sig','gam','Fosq','Fcsq','phase','Icorr','Prfo','Trans','ExtP','I100']
2927                Types += 4*[wg.GRID_VALUE_FLOAT+':10,3',]
2928            elif 'T' in Inst['Type'][0]:
2929                colLabels = ['H','K','L','mul','d','pos','sig','gam','Fosq','Fcsq','phase','Icorr','alp','bet','wave','Prfo','Abs','Ext','I100']
2930                Types += 7*[wg.GRID_VALUE_FLOAT+':10,3',]
2931            if Super:
2932                colLabels.insert(3,'M')
2933        return G2gd.Table(refs,rowLabels=rowLabels,colLabels=colLabels,types=Types)
2934    def ShowReflTable(phaseName):
2935        '''Posts a table of reflections for a phase, creating the table
2936        if needed using MakeReflectionTable
2937        '''
2938        G2frame.RefList = phaseName
2939        G2frame.dataFrame.SetLabel('Reflection List for '+phaseName)
2940        # has this table already been displayed?
2941        if G2frame.refTable[phaseName].GetTable() is None:
2942            PeakTable = MakeReflectionTable(phaseName)
2943            G2frame.refTable[phaseName].SetTable(PeakTable, True)
2944            G2frame.refTable[phaseName].EnableEditing(False)
2945            G2frame.refTable[phaseName].SetMargins(0,0)
2946            G2frame.refTable[phaseName].AutoSizeColumns(False)
2947        # raise the tab (needed for 1st use and from OnSelectPhase)
2948        for PageNum in range(G2frame.dataDisplay.GetPageCount()):
2949            if phaseName == G2frame.dataDisplay.GetPageText(PageNum):
2950                G2frame.dataDisplay.SetSelection(PageNum)
2951                break
2952        else:
2953            print phaseName
2954            print phases
2955            raise Exception("how did we not find a phase name?")
2956        G2plt.PlotPatterns(G2frame) # replot, to activate phase's reflection tooltips
2957       
2958    def OnPageChanged(event):
2959        '''Respond to a press on a phase tab by displaying the reflections. This
2960        routine is needed because the reflection table may not have been created yet.
2961        '''
2962        page = event.GetSelection()
2963        phaseName = G2frame.dataDisplay.GetPageText(page)
2964        ShowReflTable(phaseName)
2965
2966    def OnSelectPhase(event):
2967        '''For PWDR, selects a phase with a selection box. Called from menu.
2968        '''
2969        if len(phases) < 2: return
2970        dlg = wx.SingleChoiceDialog(G2frame,'Select','Phase',phases)
2971        try:
2972            if dlg.ShowModal() == wx.ID_OK:
2973                sel = dlg.GetSelection()
2974                ShowReflTable(phases[sel])
2975        finally:
2976            dlg.Destroy()
2977           
2978    if not data:
2979        print 'No phases, no reflections'
2980        return
2981    if HKLF:
2982        G2frame.RefList = 1
2983        phaseName = IsHistogramInAnyPhase(G2frame,Name)
2984        phases = [phaseName]
2985    else:
2986        phaseName = G2frame.RefList
2987        phases = data.keys()
2988    if G2frame.dataDisplay:
2989        G2frame.dataFrame.Clear()
2990    Inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Instrument Parameters'))[0]
2991    if HKLF:
2992        G2gd.SetDataMenuBar(G2frame)
2993        G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.ReflMenu)
2994        if not G2frame.dataFrame.GetStatusBar():
2995            Status = G2frame.dataFrame.CreateStatusBar()   
2996        G2frame.Bind(wx.EVT_MENU, OnPlotHKL, id=G2gd.wxID_PWDHKLPLOT)
2997        G2frame.Bind(wx.EVT_MENU, OnPlot3DHKL, id=G2gd.wxID_PWD3DHKLPLOT)
2998        G2frame.dataFrame.SelectPhase.Enable(False)
2999    else:
3000        G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.ReflMenu)
3001        if not G2frame.dataFrame.GetStatusBar():
3002            Status = G2frame.dataFrame.CreateStatusBar()   
3003        G2frame.Bind(wx.EVT_MENU, OnSelectPhase, id=G2gd.wxID_SELECTPHASE)
3004        G2frame.Bind(wx.EVT_MENU, OnPlotHKL, id=G2gd.wxID_PWDHKLPLOT)
3005        G2frame.Bind(wx.EVT_MENU, OnPlot3DHKL, id=G2gd.wxID_PWD3DHKLPLOT)
3006        G2frame.dataFrame.SelectPhase.Enable(False)
3007           
3008    G2frame.dataDisplay = G2gd.GSNoteBook(parent=G2frame.dataFrame,size=G2frame.dataFrame.GetClientSize())
3009    G2frame.refTable = {}
3010    for tabnum,phase in enumerate(phases):
3011        G2frame.refTable[phase] = G2gd.GSGrid(parent=G2frame.dataDisplay)
3012        G2frame.dataDisplay.AddPage(G2frame.refTable[phase],phase)
3013    if phaseName not in G2frame.refTable:
3014        print phaseName
3015        print phases
3016        raise Exception("how did we get a invalid phase name?")   
3017    ShowReflTable(phaseName)
3018    G2frame.refTable[phaseName].Fit()
3019    size = G2frame.refTable[phaseName].GetSize()
3020    G2frame.dataFrame.setSizePosLeft([size[0]+32,350])       
3021    G2frame.dataDisplay.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CHANGED, OnPageChanged)
3022   
3023################################################################################
3024#####  SASD Substances
3025################################################################################
3026           
3027def UpdateSubstanceGrid(G2frame,data):
3028    '''respond to selection of SASD Substance data tree item.
3029    '''
3030    import Substances as substFile
3031   
3032    def OnLoadSubstance(event):
3033        names = substFile.Substances.keys()
3034        names.sort()
3035        dlg = wx.SingleChoiceDialog(G2frame, 'Which substance?', 'Select substance', names, wx.CHOICEDLG_STYLE)
3036        try:
3037            if dlg.ShowModal() == wx.ID_OK:
3038                name = names[dlg.GetSelection()]
3039            else:
3040                return
3041        finally:
3042            dlg.Destroy()
3043        data['Substances'][name] = {'Elements':{},'Volume':1.0,'Density':1.0,
3044            'Scatt density':0.0,'XAnom density':0.0,'XAbsorption':0.0}
3045        subst = substFile.Substances[name]
3046        ElList = subst['Elements'].keys()
3047        for El in ElList:
3048            Info = G2elem.GetAtomInfo(El.strip().capitalize())
3049            Info.update(subst['Elements'][El])
3050            data['Substances'][name]['Elements'][El] = Info
3051            if 'Volume' in subst:
3052                data['Substances'][name]['Volume'] = subst['Volume']
3053                data['Substances'][name]['Density'] = \
3054                    G2mth.Vol2Den(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])
3055            elif 'Density' in subst:
3056                data['Substances'][name]['Density'] = subst['Density']
3057                data['Substances'][name]['Volume'] = \
3058                    G2mth.Den2Vol(data['Substances'][name]['Elements'],data['Substances'][name]['Density'])
3059            else:
3060                data['Substances'][name]['Volume'] = G2mth.El2EstVol(data['Substances'][name]['Elements'])
3061                data['Substances'][name]['Density'] = \
3062                    G2mth.Vol2Den(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])
3063            data['Substances'][name]['Scatt density'] = \
3064                G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])[0]
3065            contrst,absorb = G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'],wave)         
3066            data['Substances'][name]['XAnom density'] = contrst
3067            data['Substances'][name]['XAbsorption'] = absorb
3068                         
3069        UpdateSubstanceGrid(G2frame,data)
3070       
3071    def OnCopySubstance(event):
3072        hst = G2frame.PatternTree.GetItemText(G2frame.PatternId)
3073        histList = GetHistsLikeSelected(G2frame)
3074        if not histList:
3075            G2frame.ErrorDialog('No match','No histograms match '+hst,G2frame.dataFrame)
3076            return
3077        copyList = []
3078        dlg = G2gd.G2MultiChoiceDialog(
3079            G2frame.dataFrame, 
3080            'Copy substances from\n'+hst[5:]+' to...',
3081            'Copy substances', histList)
3082        try:
3083            if dlg.ShowModal() == wx.ID_OK:
3084                for i in dlg.GetSelections(): 
3085                    copyList.append(histList[i])
3086        finally:
3087            dlg.Destroy()       
3088        for item in copyList:
3089            Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,item)
3090            G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Substances'),
3091                copy.copy(data))
3092   
3093    def OnAddSubstance(event):
3094        dlg = wx.TextEntryDialog(None,'Enter a name for this substance','Substance Name Entry','New substance',
3095            style=wx.OK)
3096        if dlg.ShowModal() == wx.ID_OK:
3097            Name = dlg.GetValue()
3098            data['Substances'][Name] = {'Elements':{},'Volume':1.0,'Density':1.0,
3099                'Scatt density':0.0,'XAnom density':0.,'XAbsorption':0.}
3100        dlg.Destroy()
3101        AddElement(Name)
3102        UpdateSubstanceGrid(G2frame,data)
3103       
3104    def OnDeleteSubstance(event):
3105        TextList = []
3106        for name in data['Substances']:
3107            if name != 'vacuum':
3108                TextList += [name,]
3109        if not TextList:
3110            return
3111        dlg = wx.SingleChoiceDialog(G2frame, 'Which substance?', 'Select substance to delete', TextList, wx.CHOICEDLG_STYLE)
3112        try:
3113            if dlg.ShowModal() == wx.ID_OK:
3114                name = TextList[dlg.GetSelection()]
3115            else:
3116                return
3117        finally:
3118            dlg.Destroy()
3119        del(data['Substances'][name])
3120        UpdateSubstanceGrid(G2frame,data)       
3121               
3122    def OnAddElement(event):       
3123        TextList = []
3124        for name in data['Substances']:
3125            if name != 'vacuum':
3126                TextList += [name,]
3127        if not TextList:
3128            return
3129        dlg = wx.SingleChoiceDialog(G2frame, 'Which substance?', 'Select substance', TextList, wx.CHOICEDLG_STYLE)
3130        try:
3131            if dlg.ShowModal() == wx.ID_OK:
3132                name = TextList[dlg.GetSelection()]
3133            else:
3134                return
3135        finally:
3136            dlg.Destroy()
3137        AddElement(name)
3138        UpdateSubstanceGrid(G2frame,data)
3139       
3140    def AddElement(name):
3141        ElList = data['Substances'][name]['Elements'].keys()
3142        dlg = G2elemGUI.PickElements(G2frame,ElList)
3143        if dlg.ShowModal() == wx.ID_OK:
3144            for El in dlg.Elem:
3145                El = El.strip().capitalize()
3146                Info = G2elem.GetAtomInfo(El)
3147                Info.update({'Num':1})
3148                data['Substances'][name]['Elements'][El] = Info
3149                data['Substances'][name]['Volume'] = G2mth.El2EstVol(data['Substances'][name]['Elements'])
3150                data['Substances'][name]['Density'] = \
3151                    G2mth.Vol2Den(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])
3152                data['Substances'][name]['Scatt density'] = \
3153                    G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])[0]
3154                contrst,absorb = G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'],wave)         
3155                data['Substances'][name]['XAnom density'] = contrst
3156                data['Substances'][name]['XAbsorption'] = absorb
3157        dlg.Destroy()
3158       
3159    def OnDeleteElement(event):
3160        TextList = []
3161        for name in data['Substances']:
3162            if name != 'vacuum':
3163                TextList += [name,]
3164        if not TextList:
3165            return
3166        dlg = wx.SingleChoiceDialog(G2frame, 'Which substance?', 'Select substance', TextList, wx.CHOICEDLG_STYLE)
3167        try:
3168            if dlg.ShowModal() == wx.ID_OK:
3169                name = TextList[dlg.GetSelection()]
3170            else:
3171                return
3172        finally:
3173            dlg.Destroy()
3174        ElList = data['Substances'][name]['Elements'].keys()
3175        if len(ElList):
3176            DE = G2elemGUI.DeleteElement(G2frame,ElList)
3177            if DE.ShowModal() == wx.ID_OK:
3178                El = DE.GetDeleteElement().strip().upper()
3179                del(data['Substances'][name]['Elements'][El])
3180                data['Substances'][name]['Volume'] = G2mth.El2EstVol(data['Substances'][name]['Elements'])
3181                data['Substances'][name]['Density'] = \
3182                    G2mth.Vol2Den(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])
3183                data['Substances'][name]['Scatt density'] = \
3184                    G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])[0]
3185                contrst,absorb = G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'],wave)         
3186                data['Substances'][name]['XAnom density'] = contrst
3187                data['Substances'][name]['XAbsorption'] = absorb
3188        UpdateSubstanceGrid(G2frame,data)
3189               
3190    def SubstSizer():
3191       
3192        def OnValueChange(event):
3193            Obj = event.GetEventObject()
3194            if len(Indx[Obj.GetId()]) == 3:
3195                name,El,keyId = Indx[Obj.GetId()]
3196                try:
3197                    value = max(0,float(Obj.GetValue()))
3198                except ValueError:
3199                    value = 0
3200                    Obj.SetValue('%.2f'%(value))
3201                data['Substances'][name]['Elements'][El][keyId] = value
3202                data['Substances'][name]['Volume'] = G2mth.El2EstVol(data['Substances'][name]['Elements'])
3203                data['Substances'][name]['Density'] = \
3204                    G2mth.Vol2Den(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])
3205            else:
3206                name,keyId = Indx[Obj.GetId()]
3207                try:
3208                    value = max(0,float(Obj.GetValue()))
3209                except ValueError:
3210                    value = 1.0
3211                data['Substances'][name][keyId] = value
3212                if keyId in 'Volume':
3213                    data['Substances'][name]['Density'] = \
3214                        G2mth.Vol2Den(data['Substances'][name]['Elements'],value)
3215                elif keyId in 'Density':
3216                    data['Substances'][name]['Volume'] = \
3217                        G2mth.Den2Vol(data['Substances'][name]['Elements'],value)
3218            data['Substances'][name]['Scatt density'] = \
3219                G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])[0]
3220            contrst,absorb = G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'],wave)         
3221            data['Substances'][name]['XAnom density'] = contrst
3222            data['Substances'][name]['XAbsorption'] = absorb
3223            wx.CallAfter(UpdateSubstanceGrid,G2frame,data)
3224       
3225        Indx = {}
3226        substSizer = wx.BoxSizer(wx.VERTICAL)
3227        substSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Substance list: wavelength: %.5fA'%(wave)),
3228            0,WACV)
3229        for name in data['Substances']:
3230            G2gd.HorizontalLine(substSizer,G2frame.dataDisplay)   
3231            substSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Data for '+name+':'),
3232                0,WACV)
3233            if name == 'vacuum':
3234                substSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label='        Not applicable'),
3235                    0,WACV)
3236            else:   
3237                elSizer = wx.FlexGridSizer(0,6,5,5)
3238                Substance = data['Substances'][name]
3239                Elems = Substance['Elements']
3240                for El in Elems:    #do elements as pull downs for isotopes for neutrons
3241                    elSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' '+El+': '),
3242                        0,WACV)
3243                    num = wx.TextCtrl(G2frame.dataDisplay,value='%.2f'%(Elems[El]['Num']),style=wx.TE_PROCESS_ENTER)
3244                    Indx[num.GetId()] = [name,El,'Num']
3245                    num.Bind(wx.EVT_TEXT_ENTER,OnValueChange)       
3246                    num.Bind(wx.EVT_KILL_FOCUS,OnValueChange)
3247                    elSizer.Add(num,0,WACV)
3248                substSizer.Add(elSizer,0)
3249                vdsSizer = wx.FlexGridSizer(0,4,5,5)
3250                vdsSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Volume: '),
3251                    0,WACV)
3252                vol = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(Substance['Volume']),style=wx.TE_PROCESS_ENTER)
3253                Indx[vol.GetId()] = [name,'Volume']
3254                vol.Bind(wx.EVT_TEXT_ENTER,OnValueChange)       
3255                vol.Bind(wx.EVT_KILL_FOCUS,OnValueChange)
3256                vdsSizer.Add(vol,0,WACV)               
3257                vdsSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Density: '),
3258                    0,WACV)
3259                den = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(Substance['Density']),style=wx.TE_PROCESS_ENTER)
3260                Indx[den.GetId()] = [name,'Density']
3261                den.Bind(wx.EVT_TEXT_ENTER,OnValueChange)       
3262                den.Bind(wx.EVT_KILL_FOCUS,OnValueChange)
3263                vdsSizer.Add(den,0,WACV)
3264                substSizer.Add(vdsSizer,0)
3265                substSizer.Add(wx.StaticText(G2frame.dataDisplay,
3266                    label=' Scattering density  : %.2f *10%scm%s'%(Substance['Scatt density'],Pwr10,Pwrm2)),
3267                    0,WACV)               
3268                substSizer.Add(wx.StaticText(G2frame.dataDisplay,       #allow neutrons here into NAnom density & NAbsorption
3269                    label=' Anomalous density : %.2f *10%scm%s'%(Substance['XAnom density'],Pwr10,Pwrm2)),
3270                    0,WACV)               
3271                substSizer.Add(wx.StaticText(G2frame.dataDisplay,
3272                    label=' X-ray absorption   : %.2f cm%s'%(Substance['XAbsorption'],Pwrm1)),
3273                    0,WACV)               
3274        return substSizer
3275           
3276    Inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Instrument Parameters'))[0]
3277    wave = G2mth.getWave(Inst)
3278    if G2frame.dataDisplay:
3279        G2frame.dataFrame.DestroyChildren()
3280    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.SubstanceMenu)
3281    if not G2frame.dataFrame.GetStatusBar():
3282        Status = G2frame.dataFrame.CreateStatusBar()
3283    G2frame.dataDisplay = wxscroll.ScrolledPanel(G2frame.dataFrame)
3284    G2frame.dataFrame.SetLabel('Substances')
3285    G2frame.dataFrame.Bind(wx.EVT_MENU, OnLoadSubstance, id=G2gd.wxID_LOADSUBSTANCE)   
3286    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddSubstance, id=G2gd.wxID_ADDSUBSTANCE)
3287    G2frame.dataFrame.Bind(wx.EVT_MENU, OnCopySubstance, id=G2gd.wxID_COPYSUBSTANCE)
3288    G2frame.dataFrame.Bind(wx.EVT_MENU, OnDeleteSubstance, id=G2gd.wxID_DELETESUBSTANCE)   
3289    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddElement, id=G2gd.wxID_ELEMENTADD)
3290    G2frame.dataFrame.Bind(wx.EVT_MENU, OnDeleteElement, id=G2gd.wxID_ELEMENTDELETE)
3291    mainSizer = wx.BoxSizer(wx.VERTICAL)
3292    mainSizer.Add(SubstSizer(),0)
3293
3294    mainSizer.Layout()   
3295    G2frame.dataDisplay.SetSizer(mainSizer)
3296    G2frame.dataDisplay.SetAutoLayout(1)
3297    G2frame.dataDisplay.SetupScrolling()
3298    Size = mainSizer.Fit(G2frame.dataFrame)
3299    Size[0] += 25
3300    G2frame.dataDisplay.SetSize(Size)
3301    G2frame.dataFrame.setSizePosLeft(Size)   
3302       
3303################################################################################
3304#####  SASD Models
3305################################################################################           
3306       
3307def UpdateModelsGrid(G2frame,data):
3308    '''respond to selection of SASD Models data tree item.
3309    '''
3310    #patches
3311    if 'Current' not in data:
3312        data['Current'] = 'Size dist.'
3313    if 'logBins' not in data['Size']:
3314        data['Size']['logBins'] = True
3315    if 'MinMaxDiam' in data['Size']:
3316        data['Size']['MinDiam'] = 50.
3317        data['Size']['MaxDiam'] = 10000.
3318        del data['Size']['MinMaxDiam']
3319    if isinstance(data['Size']['MaxEnt']['Sky'],float):
3320        data['Size']['MaxEnt']['Sky'] = -3
3321    if 'Power' not in data['Size']['IPG']:
3322        data['Size']['IPG']['Power'] = -1
3323    if 'Matrix' not in data['Particle']:
3324        data['Particle']['Matrix'] = {'Name':'vacuum','VolFrac':[0.0,False]}
3325    if 'BackFile' not in data:
3326        data['BackFile'] = ''
3327    #end patches
3328   
3329    def RefreshPlots(newPlot=False):
3330        PlotText = G2frame.G2plotNB.nb.GetPageText(G2frame.G2plotNB.nb.GetSelection())
3331        if 'Powder' in PlotText:
3332            G2plt.PlotPatterns(G2frame,plotType='SASD',newPlot=newPlot)
3333        elif 'Size' in PlotText:
3334            G2plt.PlotSASDSizeDist(G2frame)
3335               
3336    def OnAddModel(event):
3337        if data['Current'] == 'Particle fit':
3338            material = 'vacuum'
3339            if len(data['Particle']['Levels']):
3340                material = data['Particle']['Levels'][-1]['Controls']['Material']
3341            data['Particle']['Levels'].append({
3342                'Controls':{'FormFact':'Sphere','DistType':'LogNormal','Material':material,
3343                    'FFargs':{},'SFargs':{},'NumPoints':50,'Cutoff':0.01,'Contrast':0.0,
3344                    'SlitSmear':[0.0,False],'StrFact':'Dilute'},    #last 2 not used - future?
3345                'LogNormal':{'Volume':[0.05,False],'Mean':[1000.,False],'StdDev':[0.5,False],'MinSize':[10.,False],},
3346                'Gaussian':{'Volume':[0.05,False],'Mean':[1000.,False],'StdDev':[300.,False],},
3347                'LSW':{'Volume':[0.05,False],'Mean':[1000.0,False],},
3348                'Schulz-Zimm':{'Volume':[0.05,False],'Mean':[1000.,False],'StdDev':[300.,False],},
3349                'Unified':{'G':[1.e3,False],'Rg':[100,False],'B':[1.e-5,False],'P':[4,False],'Cutoff':[1e-5,False],},
3350                'Porod':{'B':[1.e-4,False],'P':[4,False],'Cutoff':[1e-5,False],},
3351                'Monodisperse':{'Volume':[0.05,False],'Radius':[100,False],},   #OK for spheres
3352                'Bragg':{'PkInt':[100,False],'PkPos':[0.2,False],
3353                    'PkSig':[10,False],'PkGam':[10,False],},        #reasonable 31A peak
3354                })
3355            G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
3356            RefreshPlots(True)
3357                   
3358        wx.CallAfter(UpdateModelsGrid,G2frame,data)
3359       
3360    def OnCopyModel(event):
3361        hst = G2frame.PatternTree.GetItemText(G2frame.PatternId)
3362        histList = GetHistsLikeSelected(G2frame)
3363        if not histList:
3364            G2frame.ErrorDialog('No match','No histograms match '+hst,G2frame.dataFrame)
3365            return
3366        copyList = []
3367        dlg = G2gd.G2MultiChoiceDialog(
3368            G2frame.dataFrame, 
3369            'Copy models from\n'+hst[5:]+' to...',
3370            'Copy models', histList)
3371        try:
3372            if dlg.ShowModal() == wx.ID_OK:
3373                for i in dlg.GetSelections(): 
3374                    copyList.append(histList[i])
3375        finally:
3376            dlg.Destroy()       
3377        for item in copyList:
3378            Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,item)
3379            newdata = copy.deepcopy(data)
3380            G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Models'),newdata)
3381            if newdata['BackFile']:
3382                Profile = G2frame.PatternTree.GetItemPyData(Id)[1]
3383                BackId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,newdata['BackFile'])
3384                BackSample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,BackId, 'Sample Parameters'))
3385                Profile[5] = BackSample['Scale'][0]*G2frame.PatternTree.GetItemPyData(BackId)[1][1]
3386        RefreshPlots(True)
3387               
3388    def OnCopyFlags(event):
3389        thisModel = copy.deepcopy(data)
3390        hst = G2frame.PatternTree.GetItemText(G2frame.PatternId)
3391        histList = GetHistsLikeSelected(G2frame)
3392        if not histList:
3393            G2frame.ErrorDialog('No match','No histograms match '+hst,G2frame.dataFrame)
3394            return
3395        dlg = G2gd.G2MultiChoiceDialog(
3396            G2frame.dataFrame, 
3397            'Copy sample ref. flags from\n'+str(hst[5:])+' to...',
3398            'Copy sample flags', histList)
3399        distChoice = ['LogNormal','Gaussian','LSW','Schulz-Zimm','Bragg','Unified',
3400            'Porod','Monodisperse',]
3401        parmOrder = ['Volume','Radius','Mean','StdDev','G','Rg','B','P',
3402            'Cutoff','PkInt','PkPos','PkSig','PkGam','VolFr','Dist',]
3403        try:
3404            if dlg.ShowModal() == wx.ID_OK:
3405                result = dlg.GetSelections()
3406                for i in result: 
3407                    item = histList[i]
3408                    Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,item)
3409                    newModel = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Models'))
3410                    newModel['Back'][1] = copy.copy(thisModel['Back'][1])
3411                    for ilev,level in enumerate(newModel['Particle']['Levels']):
3412                        for form in level:
3413                            if form in distChoice:
3414                                thisForm = thisModel['Particle']['Levels'][ilev][form]                               
3415                                for item in parmOrder:
3416                                    if item in thisForm:
3417                                       level[form][item][1] = copy.copy(thisForm[item][1])
3418                            elif form == 'Controls':
3419                                thisForm = thisModel['Particle']['Levels'][ilev][form]['SFargs']
3420                                for item in parmOrder:
3421                                    if item in thisForm:
3422                                        level[form]['SFargs'][item][1] = copy.copy(thisForm[item][1])
3423        finally:
3424            dlg.Destroy()
3425               
3426    def OnFitModelAll(event):
3427        choices = G2gd.GetPatternTreeDataNames(G2frame,['SASD',])
3428        sel = []
3429        dlg = G2gd.G2MultiChoiceDialog(G2frame.dataFrame, 'Sequential SASD refinement',
3430             'Select dataset to include',choices)
3431        dlg.SetSelections(sel)
3432        names = []
3433        if dlg.ShowModal() == wx.ID_OK:
3434            for sel in dlg.GetSelections():
3435                names.append(choices[sel])
3436        dlg.Destroy()
3437        SeqResult = {'histNames':names}
3438        Reverse = False
3439        CopyForward = False
3440        choice = ['Reverse sequence','Copy from prev.']
3441        dlg = wx.MultiChoiceDialog(G2frame.dataFrame,'Sequential controls','Select controls',choice)
3442        if dlg.ShowModal() == wx.ID_OK:
3443            for sel in dlg.GetSelections():
3444                if sel:
3445                    CopyForward = True
3446                else:
3447                    Reverse = True
3448        dlg.Destroy()
3449        dlg = wx.ProgressDialog('SASD Sequential fit','Data set name = '+names[0],len(names), 
3450            style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_REMAINING_TIME|wx.PD_CAN_ABORT)
3451        wx.BeginBusyCursor()
3452        if Reverse:
3453            names.reverse()
3454        try:
3455            for i,name in enumerate(names):
3456                print ' Sequential fit for ',name
3457                GoOn = dlg.Update(i,newmsg='Data set name = '+name)[0]
3458                if not GoOn:
3459                    break
3460                Id =  G2gd.GetPatternTreeItemId(G2frame,G2frame.root,name)
3461                if i and CopyForward:
3462                    G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Models'),JModel)
3463                IProfDict,IProfile = G2frame.PatternTree.GetItemPyData(Id)[:2]
3464                IModel = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Models'))
3465                ISample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Sample Parameters'))
3466                ILimits = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Limits'))
3467                IfOK,result,varyList,sig,Rvals,covMatrix,parmDict,Msg = G2sasd.ModelFit(IProfile,IProfDict,ILimits,ISample,IModel)
3468                JModel = copy.deepcopy(IModel)
3469                if not IfOK:
3470                    G2frame.ErrorDialog('Failed sequential refinement for data '+name,
3471                        ' Msg: '+Msg+'\nYou need to rethink your selection of parameters\n'+    \
3472                        ' Model restored to previous version for'+name)
3473                    SeqResult['histNames'] = names[:i]
3474                    dlg.Destroy()
3475                    break
3476                else:
3477                    G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Models'),copy.deepcopy(IModel))
3478               
3479                G2sasd.ModelFxn(IProfile,IProfDict,ILimits,ISample,IModel)
3480                SeqResult[name] = {'variables':result[0],'varyList':varyList,'sig':sig,'Rvals':Rvals,
3481                    'covMatrix':covMatrix,'title':name,'parmDict':parmDict}
3482            else:
3483                dlg.Destroy()
3484                print ' ***** Small angle sequential refinement successful *****'
3485        finally:
3486            wx.EndBusyCursor()   
3487        Id =  G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Sequential results')
3488        if Id:
3489            G2frame.PatternTree.SetItemPyData(Id,SeqResult)
3490        else:
3491            Id = G2frame.PatternTree.AppendItem(parent=G2frame.root,text='Sequential results')
3492            G2frame.PatternTree.SetItemPyData(Id,SeqResult)
3493        G2frame.PatternTree.SelectItem(Id)
3494       
3495    def OnFitModel(event):
3496        if data['Current'] == 'Size dist.':
3497            if not any(Sample['Contrast']):
3498                G2frame.ErrorDialog('No contrast; your sample is a vacuum!',
3499                    'You need to define a scattering substance!\n'+    \
3500                    ' Do Substances and then Sample parameters')
3501                return
3502            G2sasd.SizeDistribution(Profile,ProfDict,Limits,Sample,data)
3503            G2plt.PlotSASDSizeDist(G2frame)
3504            RefreshPlots(True)
3505           
3506        elif data['Current'] == 'Particle fit':
3507            SaveState()
3508            Results = G2sasd.ModelFit(Profile,ProfDict,Limits,Sample,data)
3509            if not Results[0]:
3510                    G2frame.ErrorDialog('Failed refinement',
3511                        ' Msg: '+Results[-1]+'\nYou need to rethink your selection of parameters\n'+    \
3512                        ' Model restored to previous version')
3513            G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
3514            RefreshPlots(True)
3515            wx.CallAfter(UpdateModelsGrid,G2frame,data)
3516           
3517    def OnUnDo(event):
3518        DoUnDo()
3519        data = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,
3520            G2frame.PatternId,'Models'))
3521        G2frame.dataFrame.SasdUndo.Enable(False)
3522        UpdateModelsGrid(G2frame,data)
3523        G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
3524        RefreshPlots(True)
3525
3526    def DoUnDo():
3527        print 'Undo last refinement'
3528        file = open(G2frame.undosasd,'rb')
3529        PatternId = G2frame.PatternId
3530        G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Models'),cPickle.load(file))
3531        print ' Models recovered'
3532        file.close()
3533       
3534    def SaveState():
3535        G2frame.undosasd = os.path.join(G2frame.dirname,'GSASIIsasd.save')
3536        file = open(G2frame.undosasd,'wb')
3537        PatternId = G2frame.PatternId
3538        for item in ['Models']:
3539            cPickle.dump(G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,item)),file,1)
3540        file.close()
3541        G2frame.dataFrame.SasdUndo.Enable(True)
3542       
3543    def OnSelectFit(event):
3544        data['Current'] = fitSel.GetValue()
3545        wx.CallAfter(UpdateModelsGrid,G2frame,data)
3546       
3547    def OnCheckBox(event):
3548        Obj = event.GetEventObject()
3549        item,ind = Indx[Obj.GetId()]
3550        item[ind] = Obj.GetValue()
3551       
3552    def OnIntVal(event):
3553        Obj = event.GetEventObject()
3554        item,ind,minVal = Indx[Obj.GetId()]
3555        try:
3556            value = int(Obj.GetValue())
3557            if value <= minVal:
3558                raise ValueError
3559        except ValueError:
3560            value = item[ind]
3561        Obj.SetValue(str(value))
3562        item[ind] = value
3563
3564    def SizeSizer():
3565       
3566        def OnShape(event):
3567            data['Size']['Shape'][0] = partsh.GetValue()
3568            wx.CallAfter(UpdateModelsGrid,G2frame,data)
3569           
3570        def OnMethod(event):
3571            data['Size']['Method'] = method.GetValue()
3572            wx.CallAfter(UpdateModelsGrid,G2frame,data)
3573           
3574        def OnPartVal(event):
3575            try:
3576                val = max(0.0,float(partprm.GetValue()))
3577            except ValueError:
3578                val = 1
3579            data['Size']['Shape'][1] = val
3580            partprm.SetValue('%.3f'%(val))
3581           
3582        sizeSizer = wx.BoxSizer(wx.VERTICAL)
3583        sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Size distribution parameters: '),0,WACV)
3584        binSizer = wx.FlexGridSizer(0,7,5,5)
3585        binSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' No. size bins: '),0,WACV)
3586        bins = ['50','100','150','200']
3587        nbins = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['Nbins']),choices=bins,
3588            style=wx.CB_READONLY|wx.CB_DROPDOWN)
3589        Indx[nbins.GetId()] = [data['Size'],'Nbins',0]
3590        nbins.Bind(wx.EVT_COMBOBOX,OnIntVal)       
3591        binSizer.Add(nbins,0,WACV)
3592        binSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Min diam.: '),0,WACV)
3593        minDias = ['10','25','50','100','150','200']
3594        mindiam = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['MinDiam']),choices=minDias,
3595            style=wx.CB_DROPDOWN)
3596        mindiam.Bind(wx.EVT_LEAVE_WINDOW,OnIntVal)
3597        mindiam.Bind(wx.EVT_TEXT_ENTER,OnIntVal)       
3598        mindiam.Bind(wx.EVT_KILL_FOCUS,OnIntVal)
3599        Indx[mindiam.GetId()] = [data['Size'],'MinDiam',0]
3600        binSizer.Add(mindiam,0,WACV)
3601        binSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Max diam.: '),0,WACV)
3602        maxDias = [str(1000*(i+1)) for i in range(10)]
3603        maxdiam = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['MaxDiam']),choices=maxDias,
3604            style=wx.CB_DROPDOWN)
3605        maxdiam.Bind(wx.EVT_LEAVE_WINDOW,OnIntVal)
3606        maxdiam.Bind(wx.EVT_TEXT_ENTER,OnIntVal)       
3607        maxdiam.Bind(wx.EVT_KILL_FOCUS,OnIntVal)
3608        Indx[maxdiam.GetId()] = [data['Size'],'MaxDiam',0]
3609        binSizer.Add(maxdiam,0,WACV)
3610        logbins = wx.CheckBox(G2frame.dataDisplay,label='Log bins?')
3611        Indx[logbins.GetId()] = [data['Size'],'logBins']
3612        logbins.SetValue(data['Size']['logBins'])
3613        logbins.Bind(wx.EVT_CHECKBOX, OnCheckBox)
3614        binSizer.Add(logbins,0,WACV)
3615        sizeSizer.Add(binSizer,0)
3616        sizeSizer.Add((5,5),0)
3617        partSizer = wx.BoxSizer(wx.HORIZONTAL)
3618        partSizer.Add(wx.StaticText(G2frame.dataDisplay,label='Particle description: '),0,WACV)
3619        shapes = {'Spheroid':' Aspect ratio: ','Cylinder':' Diameter ','Cylinder AR':' Aspect ratio: ',
3620            'Unified sphere':'','Unified rod':' Diameter: ','Unified rod AR':' Aspect ratio: ',
3621            'Unified disk':' Thickness: '}
3622        partsh = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['Shape'][0]),choices=shapes.keys(),
3623            style=wx.CB_READONLY|wx.CB_DROPDOWN)
3624        partsh.Bind(wx.EVT_COMBOBOX,OnShape)       
3625        partSizer.Add(partsh,0,WACV)
3626        if data['Size']['Shape'][0] not in ['Unified sphere',]:
3627            partSizer.Add(wx.StaticText(G2frame.dataDisplay,label=shapes[data['Size']['Shape'][0]]),0,WACV)
3628            partprm = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(data['Size']['Shape'][1]),
3629                style=wx.TE_PROCESS_ENTER)
3630            partprm.Bind(wx.EVT_TEXT_ENTER,OnPartVal)       
3631            partprm.Bind(wx.EVT_KILL_FOCUS,OnPartVal)
3632            partSizer.Add(partprm,0,WACV)
3633        sizeSizer.Add(partSizer,0)
3634        sizeSizer.Add((5,5),0)
3635        fitSizer = wx.BoxSizer(wx.HORIZONTAL)
3636        methods = ['MaxEnt','IPG',]
3637        fitSizer.Add(wx.StaticText(G2frame.dataDisplay,label='Fitting method: '),0,WACV)
3638        method = wx.ComboBox(G2frame.dataDisplay,value=data['Size']['Method'],choices=methods,
3639            style=wx.CB_READONLY|wx.CB_DROPDOWN)
3640        method.Bind(wx.EVT_COMBOBOX,OnMethod)
3641        fitSizer.Add(method,0,WACV)
3642        iters = ['10','25','50','100','150','200']       
3643        fitSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' No. iterations: '),0,WACV)
3644        Method = data['Size']['Method']
3645        iter = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size'][Method]['Niter']),choices=iters,
3646            style=wx.CB_READONLY|wx.CB_DROPDOWN)
3647        Indx[iter.GetId()] = [data['Size'][Method],'Niter',0]
3648        iter.Bind(wx.EVT_COMBOBOX,OnIntVal)
3649        fitSizer.Add(iter,0,WACV)
3650        if 'MaxEnt' in data['Size']['Method']:
3651            fitSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Log floor factor: '),0,WACV)
3652            floors = [str(-i) for i in range(9)]
3653            floor = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['MaxEnt']['Sky']),choices=floors,
3654                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3655            Indx[floor.GetId()] = [data['Size']['MaxEnt'],'Sky',-10]
3656            floor.Bind(wx.EVT_COMBOBOX,OnIntVal)
3657            fitSizer.Add(floor,0,WACV)
3658        elif 'IPG' in data['Size']['Method']:
3659            fitSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Q power weight (-1 for sigma): '),0,WACV)
3660            choices = ['-1','0','1','2','3','4']
3661            power = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['IPG']['Power']),choices=choices,
3662                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3663            Indx[power.GetId()] = [data['Size']['IPG'],'Power',-2]
3664            power.Bind(wx.EVT_COMBOBOX,OnIntVal)
3665            fitSizer.Add(power,0,WACV)
3666        sizeSizer.Add(fitSizer,0)
3667
3668        return sizeSizer
3669       
3670    def PartSizer():
3671       
3672        FormFactors = {'Sphere':{},'Spheroid':{'Aspect ratio':[1.0,False]},
3673            'Cylinder':{'Length':[100.,False]},'Cylinder diam':{'Diameter':[100.,False]},
3674            'Cylinder AR':{'Aspect ratio':[1.0,False]},'Unified sphere':{},
3675            'Unified rod':{'Length':[100.,False]},'Unified rod AR':{'Aspect ratio':[1.0,False]},
3676            'Unified disk':{'Thickness':[100.,False]},
3677            'Unified tube':{'Length':[100.,False],'Thickness':[10.,False]},}
3678               
3679        StructureFactors = {'Dilute':{},'Hard sphere':{'VolFr':[0.1,False],'Dist':[100.,False]},
3680            'Sticky hard sphere':{'VolFr':[0.1,False],'Dist':[100.,False],'epis':[0.05,False],'Sticky':[0.2,False]},
3681            'Square well':{'VolFr':[0.1,False],'Dist':[100.,False],'Depth':[0.1,False],'Width':[1.,False]},
3682            'InterPrecipitate':{'VolFr':[0.1,False],'Dist':[100.,False]},}
3683               
3684        ffDistChoices =  ['Sphere','Spheroid','Cylinder','Cylinder diam',
3685            'Cylinder AR','Unified sphere','Unified rod','Unified rod AR',
3686            'Unified disk','Unified tube',]
3687               
3688        ffMonoChoices = ['Sphere','Spheroid','Cylinder','Cylinder AR',]
3689       
3690        sfChoices = ['Dilute','Hard sphere','Sticky hard sphere','Square well','InterPrecipitate',]
3691           
3692        slMult = 1000.
3693                 
3694        def OnValue(event):
3695            Obj = event.GetEventObject()
3696            item,key,sldrObj = Indx[Obj.GetId()]
3697            try:
3698                value = float(Obj.GetValue())
3699                if value <= 0.:
3700                    raise ValueError
3701            except ValueError:
3702                value = item[key][0]
3703            item[key][0] = value
3704            Obj.SetValue('%.3g'%(value))
3705            if key in ['P','epis','Sticky','Depth','Width','VolFr','Dist']:
3706                sldrObj.SetValue(slMult*value)
3707            else:
3708                logv = np.log10(value)
3709                valMinMax = [logv-1,logv+1]
3710                sldrObj.SetRange(slMult*valMinMax[0],slMult*valMinMax[1])
3711                sldrObj.SetValue(slMult*logv)
3712            G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
3713            RefreshPlots()
3714           
3715        def OnSelect(event):
3716            Obj = event.GetEventObject()
3717            item,key = Indx[Obj.GetId()]
3718            item[key] = Obj.GetValue()
3719            if 'Refine' not in Obj.GetLabel():
3720                if 'FormFact' in key :
3721                    item['FFargs'] = FormFactors[Obj.GetValue()]
3722                elif 'StrFact' in key:
3723                    item['SFargs'] = StructureFactors[Obj.GetValue()]
3724                wx.CallAfter(UpdateModelsGrid,G2frame,data)
3725                G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
3726                RefreshPlots()
3727               
3728        def OnDelLevel(event):
3729            Obj = event.GetEventObject()
3730            item = Indx[Obj.GetId()]
3731            del data['Particle']['Levels'][item]
3732            wx.CallAfter(UpdateModelsGrid,G2frame,data)
3733            G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
3734            RefreshPlots()
3735           
3736        def OnParmSlider(event):
3737            Obj = event.GetEventObject()
3738            item,key,pvObj = Indx[Obj.GetId()]
3739            slide = Obj.GetValue()
3740            if key in ['P','epis','Sticky','Depth','Width','VolFr','Dist']:
3741                value = float(slide/slMult)
3742            else:
3743                value = 10.**float(slide/slMult)
3744            item[key][0] = value
3745            pvObj.SetValue('%.3g'%(item[key][0]))
3746            G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
3747            RefreshPlots()
3748           
3749        def SizeSizer():
3750            sizeSizer = wx.FlexGridSizer(0,4,5,5)
3751            sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Distribution: '),0,WACV)
3752            Distchoice = ['LogNormal','Gaussian','LSW','Schulz-Zimm','Bragg','Unified','Porod','Monodisperse',]
3753            distChoice = wx.ComboBox(G2frame.dataDisplay,value=level['Controls']['DistType'],choices=Distchoice,
3754                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3755            Indx[distChoice.GetId()] = [level['Controls'],'DistType']
3756            distChoice.Bind(wx.EVT_COMBOBOX,OnSelect)
3757            sizeSizer.Add(distChoice,0,WACV)    #put structure factor choices here
3758            if level['Controls']['DistType'] not in ['Bragg','Unified','Porod',]:
3759                sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Form Factor: '),0,WACV)
3760                if 'Mono' in level['Controls']['DistType']:
3761                    ffChoice = wx.ComboBox(G2frame.dataDisplay,value=level['Controls']['FormFact'],choices=ffMonoChoices,
3762                        style=wx.CB_READONLY|wx.CB_DROPDOWN)
3763                else:
3764                    ffChoice = wx.ComboBox(G2frame.dataDisplay,value=level['Controls']['FormFact'],choices=ffDistChoices,
3765                        style=wx.CB_READONLY|wx.CB_DROPDOWN)
3766                Indx[ffChoice.GetId()] = [level['Controls'],'FormFact']
3767                ffChoice.Bind(wx.EVT_COMBOBOX,OnSelect)
3768                sizeSizer.Add(ffChoice,0,WACV)
3769               
3770                sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Material: '),0,WACV)
3771                matSel = wx.ComboBox(G2frame.dataDisplay,value=level['Controls']['Material'],
3772                    choices=Substances['Substances'].keys(),style=wx.CB_READONLY|wx.CB_DROPDOWN)
3773                Indx[matSel.GetId()] = [level['Controls'],'Material']
3774                matSel.Bind(wx.EVT_COMBOBOX,OnSelect)       
3775                sizeSizer.Add(matSel,0,WACV) #do neutron test here?
3776                rho = Substances['Substances'][level['Controls']['Material']].get('XAnom density',0.0)
3777                level['Controls']['Contrast'] = contrast = (rho-rhoMat)**2                 
3778                sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Resonant X-ray contrast: '),0,WACV)
3779                sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=%.2f 10%scm%s'%(contrast,Pwr20,Pwrm4)),0,WACV)
3780                if 'Mono' not in level['Controls']['DistType']:
3781                    sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Num. radii: '),0,WACV)
3782                    radii = ['25','50','75','100','200']
3783                    nRadii = wx.ComboBox(G2frame.dataDisplay,value=str(level['Controls']['NumPoints']),choices=radii,
3784                        style=wx.CB_READONLY|wx.CB_DROPDOWN)
3785                    Indx[nRadii.GetId()] = [level['Controls'],'NumPoints']
3786                    nRadii.Bind(wx.EVT_COMBOBOX,OnSelect)
3787                    sizeSizer.Add(nRadii,0,WACV)
3788                    sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' R dist. cutoff: '),0,WACV)
3789                    rCutoff = G2gd.ValidatedTxtCtrl(G2frame.dataDisplay,level['Controls'],'Cutoff',
3790                        min=0.001,max=0.1,typeHint=float)
3791                    sizeSizer.Add(rCutoff,0,WACV)
3792            elif level['Controls']['DistType']  in ['Unified',]:
3793                Parms = level['Unified']
3794                Best = G2sasd.Bestimate(Parms['G'][0],Parms['Rg'][0],Parms['P'][0])
3795                sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Estimated Dist B: %12.4g'%(Best)),0,WACV)
3796            return sizeSizer
3797           
3798        def ParmSizer():
3799            parmSizer = wx.FlexGridSizer(0,3,5,5)
3800            parmSizer.AddGrowableCol(2,1)
3801            parmSizer.SetFlexibleDirection(wx.HORIZONTAL)
3802            Parms = level[level['Controls']['DistType']]
3803            FFargs = level['Controls']['FFargs']
3804            SFargs = level['Controls'].get('SFargs',{})
3805            parmOrder = ['Volume','Radius','Mean','StdDev','MinSize','G','Rg','B','P','Cutoff',
3806                'PkInt','PkPos','PkSig','PkGam',]
3807            for parm in parmOrder:
3808                if parm in Parms:
3809                    if parm == 'MinSize':
3810                        parmSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Dist '+parm),0,wx.ALIGN_CENTER)
3811                    else:
3812                        parmVar = wx.CheckBox(G2frame.dataDisplay,label='Refine? Dist '+parm) 
3813                        parmVar.SetValue(Parms[parm][1])
3814                        parmVar.Bind(wx.EVT_CHECKBOX, OnSelect)
3815                        parmSizer.Add(parmVar,0,WACV)
3816                        Indx[parmVar.GetId()] = [Parms[parm],1]
3817                    parmValue = wx.TextCtrl(G2frame.dataDisplay,value='%.3g'%(Parms[parm][0]),
3818                        style=wx.TE_PROCESS_ENTER)
3819                    parmValue.Bind(wx.EVT_TEXT_ENTER,OnValue)       
3820                    parmValue.Bind(wx.EVT_KILL_FOCUS,OnValue)
3821                    parmSizer.Add(parmValue,0,WACV)
3822                    if parm == 'P':
3823                        value = Parms[parm][0]
3824                        valMinMax = [0.1,4.2]
3825                    else:
3826                        value = np.log10(Parms[parm][0])
3827                        valMinMax = [value-1,value+1]
3828                    parmSldr = wx.Slider(G2frame.dataDisplay,minValue=slMult*valMinMax[0],
3829                        maxValue=slMult*valMinMax[1],value=slMult*value)
3830                    Indx[parmValue.GetId()] = [Parms,parm,parmSldr]
3831                    Indx[parmSldr.GetId()] = [Parms,parm,parmValue]
3832                    parmSldr.Bind(wx.EVT_SLIDER,OnParmSlider)
3833                    parmSizer.Add(parmSldr,1,wx.EXPAND)
3834            if level['Controls']['DistType'] not in ['Bragg']:
3835                parmOrder = ['Aspect ratio','Length','Diameter','Thickness','VolFr','Dist','epis','Sticky','Depth','Width']
3836                fTypes = ['FF ','SF ']
3837                for iarg,Args in enumerate([FFargs,SFargs]):
3838                    for parm in parmOrder:
3839                        if parm in Args:
3840                            parmVar = wx.CheckBox(G2frame.dataDisplay,label='Refine? '+fTypes[iarg]+parm) 
3841                            parmVar.SetValue(Args[parm][1])
3842                            Indx[parmVar.GetId()] = [Args[parm],1]
3843                            parmVar.Bind(wx.EVT_CHECKBOX, OnSelect)
3844                            parmSizer.Add(parmVar,0,WACV)
3845                            parmValue = wx.TextCtrl(G2frame.dataDisplay,value='%.3g'%(Args[parm][0]),
3846                                style=wx.TE_PROCESS_ENTER)
3847                            parmValue.Bind(wx.EVT_TEXT_ENTER,OnValue)       
3848                            parmValue.Bind(wx.EVT_KILL_FOCUS,OnValue)
3849                            parmSizer.Add(parmValue,0,WACV)
3850                            value = Args[parm][0]
3851                            if parm == 'epis':
3852                                valMinMax = [0,.1]
3853                            elif parm in ['Sticky','Width',]:
3854                                valMinMax = [0,1.]
3855                            elif parm == 'Depth':
3856                                valMinMax = [-2.,2.]
3857                            elif parm == 'Dist':
3858                                valMinMax = [100.,1000.]
3859                            elif parm == 'VolFr':
3860                                valMinMax = [1.e-4,1.]
3861                            else:
3862                                value = np.log10(Args[parm][0])
3863                                valMinMax = [value-1,value+1]
3864                            parmSldr = wx.Slider(G2frame.dataDisplay,minValue=slMult*valMinMax[0],
3865                                maxValue=slMult*valMinMax[1],value=slMult*value)
3866                            Indx[parmVar.GetId()] = [Args[parm],1]
3867                            Indx[parmValue.GetId()] = [Args,parm,parmSldr]
3868                            Indx[parmSldr.GetId()] = [Args,parm,parmValue]
3869                            parmSldr.Bind(wx.EVT_SLIDER,OnParmSlider)
3870                            parmSizer.Add(parmSldr,1,wx.EXPAND)
3871            return parmSizer               
3872           
3873        Indx = {}
3874        partSizer = wx.BoxSizer(wx.VERTICAL)
3875        topSizer = wx.BoxSizer(wx.HORIZONTAL)
3876        topSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Particle fit parameters: '),0,WACV)
3877        topSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Matrix: '),0,WACV)
3878        matsel = wx.ComboBox(G2frame.dataDisplay,value=data['Particle']['Matrix']['Name'],
3879            choices=Substances['Substances'].keys(),style=wx.CB_READONLY|wx.CB_DROPDOWN)
3880        Indx[matsel.GetId()] = [data['Particle']['Matrix'],'Name'] 
3881        matsel.Bind(wx.EVT_COMBOBOX,OnSelect) #Do neutron test here?
3882        rhoMat = Substances['Substances'][data['Particle']['Matrix']['Name']].get('XAnom density',0.0)       
3883        topSizer.Add(matsel,0,WACV)
3884        topSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Volume fraction: '),0,WACV)
3885        volfrac = G2gd.ValidatedTxtCtrl(G2frame.dataDisplay,data['Particle']['Matrix']['VolFrac'],0,
3886                typeHint=float)
3887        topSizer.Add(volfrac,0,WACV)
3888        volVar = wx.CheckBox(G2frame.dataDisplay,label=' Refine?')
3889        volVar.SetValue(data['Particle']['Matrix']['VolFrac'][1])
3890        Indx[volVar.GetId()] = [data['Particle']['Matrix']['VolFrac'],1]
3891        volVar.Bind(wx.EVT_CHECKBOX, OnSelect)
3892        topSizer.Add(volVar,0,WACV)
3893        partSizer.Add(topSizer,0,)
3894        for ilev,level in enumerate(data['Particle']['Levels']):
3895            G2gd.HorizontalLine(partSizer,G2frame.dataDisplay)
3896            topLevel = wx.BoxSizer(wx.HORIZONTAL)
3897            topLevel.Add(wx.StaticText(G2frame.dataDisplay,label=' Model component %d: '%(ilev)),0,WACV)
3898            delBtn = wx.Button(G2frame.dataDisplay,label=' Delete?')
3899            Indx[delBtn.GetId()] = ilev
3900            delBtn.Bind(wx.EVT_BUTTON,OnDelLevel)
3901            topLevel.Add(delBtn,0,WACV)
3902            partSizer.Add(topLevel,0)
3903            partSizer.Add(SizeSizer())
3904            if level['Controls']['DistType'] not in ['Bragg','Unified','Porod',]:
3905                topLevel.Add(wx.StaticText(G2frame.dataDisplay,label=' Structure factor: '),0,WACV)
3906                strfctr = wx.ComboBox(G2frame.dataDisplay,value=level['Controls']['StrFact'],
3907                    choices=sfChoices,style=wx.CB_READONLY|wx.CB_DROPDOWN)
3908                Indx[strfctr.GetId()] = [level['Controls'],'StrFact']
3909                strfctr.Bind(wx.EVT_COMBOBOX,OnSelect)
3910                topLevel.Add(strfctr,0,WACV)
3911            partSizer.Add(ParmSizer(),0,wx.EXPAND)
3912        return partSizer
3913       
3914    def OnEsdScale(event):
3915        try:
3916            value = float(esdScale.GetValue())
3917            if value <= 0.:
3918                raise ValueError
3919        except ValueError:
3920            value = 1./np.sqrt(ProfDict['wtFactor'])
3921        ProfDict['wtFactor'] = 1./value**2
3922        esdScale.SetValue('%.3f'%(value))
3923        RefreshPlots(True)
3924       
3925    def OnBackChange(event):
3926        try:
3927            value = float(backVal.GetValue())
3928        except ValueError:
3929            value = 0.0
3930        backVal.SetValue('%.3g'%(value))
3931        data['Back'][0] = value
3932        Profile[4][:] = value
3933        RefreshPlots()
3934       
3935    def OnBackFile(event):  #multiple backgrounds?
3936        data['BackFile'] = backFile.GetValue()
3937        if data['BackFile']:
3938            fixBack =  data['Back'][0]
3939            BackId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,data['BackFile'])
3940            BackSample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,BackId, 'Sample Parameters'))
3941            Profile[5] = BackSample['Scale'][0]*G2frame.PatternTree.GetItemPyData(BackId)[1][1]
3942        else:
3943            Profile[5] = np.zeros(len(Profile[5]))
3944        RefreshPlots(True)
3945           
3946    Sample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Sample Parameters'))
3947    Limits = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Limits'))
3948    Substances = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Substances'))
3949    ProfDict,Profile = G2frame.PatternTree.GetItemPyData(G2frame.PatternId)[:2]
3950    if data['BackFile']:
3951        BackId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,data['BackFile'])
3952        BackSample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,BackId, 'Sample Parameters'))
3953        Profile[5] = BackSample['Scale'][0]*G2frame.PatternTree.GetItemPyData(BackId)[1][1]
3954    if G2frame.dataDisplay:
3955        G2frame.dataFrame.DestroyChildren()
3956    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.ModelMenu)
3957    if not G2frame.dataFrame.GetStatusBar():
3958        Status = G2frame.dataFrame.CreateStatusBar()
3959    G2frame.dataFrame.SetLabel('Modelling')
3960    G2frame.dataDisplay = wxscroll.ScrolledPanel(G2frame.dataFrame)
3961    G2frame.dataFrame.Bind(wx.EVT_MENU, OnCopyModel, id=G2gd.wxID_MODELCOPY)
3962    G2frame.dataFrame.Bind(wx.EVT_MENU, OnCopyFlags, id=G2gd.wxID_MODELCOPYFLAGS)
3963    G2frame.dataFrame.Bind(wx.EVT_MENU, OnFitModel, id=G2gd.wxID_MODELFIT)
3964    G2frame.dataFrame.Bind(wx.EVT_MENU, OnFitModelAll, id=G2gd.wxID_MODELFITALL)
3965    G2frame.dataFrame.Bind(wx.EVT_MENU, OnUnDo, id=G2gd.wxID_MODELUNDO)
3966    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddModel, id=G2gd.wxID_MODELADD)
3967    Indx = {}
3968    mainSizer = wx.BoxSizer(wx.VERTICAL)
3969    topSizer = wx.BoxSizer(wx.HORIZONTAL)
3970    models = ['Size dist.','Particle fit']
3971    topSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Modeling by: '),0,WACV)
3972    fitSel = wx.ComboBox(G2frame.dataDisplay,value=data['Current'],choices=models,
3973        style=wx.CB_READONLY|wx.CB_DROPDOWN)
3974    fitSel.Bind(wx.EVT_COMBOBOX,OnSelectFit)       
3975    topSizer.Add(fitSel,0,WACV)
3976    topSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Error multiplier: '),0,WACV)
3977    esdScale = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(1./np.sqrt(ProfDict['wtFactor'])),style=wx.TE_PROCESS_ENTER)
3978    esdScale.Bind(wx.EVT_TEXT_ENTER,OnEsdScale)       
3979    esdScale.Bind(wx.EVT_KILL_FOCUS,OnEsdScale)
3980    topSizer.Add(esdScale,0,WACV)
3981    mainSizer.Add(topSizer)
3982    G2gd.HorizontalLine(mainSizer,G2frame.dataDisplay)
3983    if 'Size' in data['Current']:
3984        if 'MaxEnt' in data['Size']['Method']:
3985            Status.SetStatusText('Size distribution by Maximum entropy')
3986        elif 'IPG' in data['Size']['Method']:
3987            Status.SetStatusText('Size distribution by Interior-Point Gradient')
3988        mainSizer.Add(SizeSizer())       
3989    elif 'Particle' in data['Current']:
3990        mainSizer.Add(PartSizer(),1,wx.ALIGN_LEFT|wx.EXPAND)
3991    G2gd.HorizontalLine(mainSizer,G2frame.dataDisplay)   
3992    backSizer = wx.BoxSizer(wx.HORIZONTAL)
3993    backSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Background:'),0,WACV)
3994    backVal = wx.TextCtrl(G2frame.dataDisplay,value='%.3g'%(data['Back'][0]),style=wx.TE_PROCESS_ENTER)
3995    Indx[backVal.GetId()] = ['Back',0,'%.3g']
3996    backVal.Bind(wx.EVT_TEXT_ENTER,OnBackChange)       
3997    backVal.Bind(wx.EVT_KILL_FOCUS,OnBackChange)
3998    backSizer.Add(backVal,0,WACV)
3999    backVar = wx.CheckBox(G2frame.dataDisplay,label='Refine?')
4000    Indx[backVar.GetId()] = [data['Back'],1]
4001    backVar.SetValue(data['Back'][1])
4002    backVar.Bind(wx.EVT_CHECKBOX, OnCheckBox)
4003    backSizer.Add(backVar,0,WACV)
4004    #multiple background files?
4005    backSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,' Background file: '),0,WACV)
4006    Choices = ['',]+G2gd.GetPatternTreeDataNames(G2frame,['SASD',])
4007    backFile = wx.ComboBox(parent=G2frame.dataDisplay,value=data['BackFile'],choices=Choices,
4008        style=wx.CB_READONLY|wx.CB_DROPDOWN)
4009    backFile.Bind(wx.EVT_COMBOBOX,OnBackFile)
4010    backSizer.Add(backFile)   
4011    mainSizer.Add(backSizer)
4012
4013    mainSizer.Layout()   
4014    G2frame.dataDisplay.SetSizer(mainSizer)
4015    G2frame.dataDisplay.SetAutoLayout(1)
4016    G2frame.dataDisplay.SetupScrolling()
4017    Size = mainSizer.Fit(G2frame.dataFrame)
4018    Size[0] += 25
4019    G2frame.dataDisplay.SetSize(Size)
4020    G2frame.dataFrame.setSizePosLeft(Size)   
4021   
4022################################################################################
4023#####  PDF controls
4024################################################################################           
4025       
4026def UpdatePDFGrid(G2frame,data):
4027    '''respond to selection of PWDR PDF data tree item.
4028    '''
4029    global inst
4030    tth2q = lambda t,w:4.0*math.pi*sind(t/2.0)/w
4031    dataFile = G2frame.PatternTree.GetItemText(G2frame.PatternId)
4032    powName = 'PWDR'+dataFile[4:]
4033    powId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, powName)
4034    fullLimits,limits = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,powId, 'Limits'))[:2]
4035    inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,powId, 'Instrument Parameters'))[0]
4036    if 'Lam' in inst:
4037        keV = 12.397639/inst['Lam'][1]
4038    else:
4039        keV = 12.397639/inst['Lam1'][0]
4040    wave = 12.397639/keV
4041    qLimits = [tth2q(fullLimits[0],wave),tth2q(fullLimits[1],wave)]
4042    data['QScaleLim'][1] = min(qLimits[1],data['QScaleLim'][1])
4043    if data['QScaleLim'][0]:
4044        data['QScaleLim'][0] = max(qLimits[0],data['QScaleLim'][0])
4045    else:                                #initial setting at 90% of max Q
4046        data['QScaleLim'][0] = 0.90*data['QScaleLim'][1]
4047    polariz = inst['Polariz.'][1]
4048    azimuth = inst['Azimuth'][1]
4049    itemDict = {}
4050   
4051    def FillFileSizer(fileSizer,key):
4052        #fileSizer is a FlexGridSizer(3,6)
4053       
4054        def OnSelectFile(event):
4055            Obj = event.GetEventObject()
4056            fileKey,itemKey,fmt = itemDict[Obj.GetId()]
4057            if itemKey == 'Name':
4058                value = Obj.GetValue()
4059            Obj.SetValue(fmt%(value))
4060            data[fileKey][itemKey] = value
4061            UpdatePDFGrid(G2frame,data)
4062       
4063        def OnValueChange(event):
4064            Obj = event.GetEventObject()
4065            fileKey,itemKey,fmt = itemDict[Obj.GetId()]
4066            try:
4067                value = float(Obj.GetValue())
4068            except ValueError:
4069                value = -1.0
4070            Obj.SetValue(fmt%(value))
4071            data[fileKey][itemKey] = value
4072            auxPlot = ComputePDF(data)
4073            G2plt.PlotISFG(G2frame,newPlot=True)
4074                       
4075        item = data[key]
4076        fileList = np.array(GetFileList('PWDR')).T[1]
4077        fileSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' '+key+' file:'),0,WACV)
4078        fileName = wx.ComboBox(G2frame.dataDisplay,value=item['Name'],choices=fileList,
4079            style=wx.CB_READONLY|wx.CB_DROPDOWN)
4080        itemDict[fileName.GetId()] = [key,'Name','%s']
4081        fileName.Bind(wx.EVT_COMBOBOX,OnSelectFile)       
4082        fileSizer.Add(fileName,0,)
4083        fileSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label='Multiplier:'),0,WACV)
4084        mult = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(item['Mult']),style=wx.TE_PROCESS_ENTER)
4085        itemDict[mult.GetId()] = [key,'Mult','%.3f']
4086        mult.Bind(wx.EVT_TEXT_ENTER,OnValueChange)       
4087        mult.Bind(wx.EVT_KILL_FOCUS,OnValueChange)
4088        fileSizer.Add(mult,0,)
4089        fileSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label='Add:'),0,WACV)
4090        add = wx.TextCtrl(G2frame.dataDisplay,value='%.0f'%(item['Add']),style=wx.TE_PROCESS_ENTER)
4091        itemDict[add.GetId()] = [key,'Add','%.0f']
4092        add.Bind(wx.EVT_TEXT_ENTER,OnValueChange)       
4093        add.Bind(wx.EVT_KILL_FOCUS,OnValueChange)
4094        fileSizer.Add(add,0,)
4095       
4096    def SumElementVolumes():
4097        sumVol = 0.
4098        ElList = data['ElList']
4099        for El in ElList:
4100            Avol = (4.*math.pi/3.)*ElList[El]['Drad']**3
4101            sumVol += Avol*ElList[El]['FormulaNo']
4102        return sumVol
4103        auxPlot = ComputePDF(data)
4104        G2plt.PlotISFG(G2frame,newPlot=True)       
4105       
4106    def FillElemSizer(elemSizer,ElData):
4107       
4108        def OnFractionChange(event):
4109            try:
4110                value = max(0.0,float(num.GetValue()))
4111            except ValueError:
4112                value = 0.0
4113            num.SetValue('%.3f'%(value))
4114            ElData['FormulaNo'] = value
4115            data['Form Vol'] = max(10.0,SumElementVolumes())
4116            formVol.SetValue('%.2f'%(data['Form Vol']))
4117            wx.CallAfter(UpdatePDFGrid,G2frame,data)
4118            auxPlot = ComputePDF(data)
4119            G2plt.PlotISFG(G2frame,newPlot=True)