source: trunk/GSASIIpwdGUI.py @ 2572

Last change on this file since 2572 was 2572, checked in by vondreele, 6 years ago

TextCtrl? -- ValidatedTextCtrl?

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