source: trunk/GSASIIpwdGUI.py @ 1623

Last change on this file since 1623 was 1623, checked in by vondreele, 7 years ago

remove stray prints
double up modulation plot
set roll of 4D map to match that for 3D map
remove PlotPattern? call after reflection list selection - not needed & crashes for single crystal data
4D charge flipping reproduces J2K modulation maps!

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