source: trunk/GSASIIpwdGUI.py @ 1643

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

fix input of TOF hkl data
fix bond angle calculations
fix 2D & 3D hkl plotting

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