source: trunk/GSASIIpwdGUI.py @ 2514

Last change on this file since 2514 was 2514, checked in by vondreele, 5 years ago

change default for Bank from None to 1 in G2IO
put in patch in G2pwdGUI to fix fail on old gpx files where bank = None

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