source: trunk/GSASIIpwdGUI.py @ 1770

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

moved MultipleChoicesDialog? and SingleChoiceDialog? from G2grid to G2ctrls

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