source: trunk/GSASIIpwdGUI.py @ 1898

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

new constraint option - constrain atom variables as a set; constrain sum of frac & equivalence all other parameters - intended for multiple atoms on same site
fix bug in instrument parms flag copy

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