source: trunk/GSASIIpwdGUI.py @ 2567

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

fix to export CIF sym. op. problem
use ValidatedTxtctrl? for all values in PDF Controls, Background & RDFDialog

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 240.4 KB
Line 
1# -*- coding: utf-8 -*-
2#GSASIIpwdGUI - powder data display routines
3########### SVN repository information ###################
4# $Date: 2016-12-08 19:11:10 +0000 (Thu, 08 Dec 2016) $
5# $Author: vondreele $
6# $Revision: 2567 $
7# $URL: trunk/GSASIIpwdGUI.py $
8# $Id: GSASIIpwdGUI.py 2567 2016-12-08 19:11:10Z 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: 2567 $")
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            volfrac = wx.TextCtrl(G2frame.dataDisplay,value=str('%.3f'%(item['VolFrac'])),style=wx.TE_PROCESS_ENTER)
2436            Info[volfrac.GetId()] = [id,'VolFrac']
2437            volfrac.Bind(wx.EVT_TEXT_ENTER,OnMaterial)
2438            volfrac.Bind(wx.EVT_KILL_FOCUS,OnMaterial)
2439            subSizer.Add(volfrac,0,WACV)
2440            material = Substances['Substances'][item['Name']]
2441            mu += item['VolFrac']*material.get('XAbsorption',0.)
2442            rho[id] = material['Scatt density']
2443            anomrho[id] = material.get('XAnom density',0.)
2444        data['Contrast'] = [(rho[1]-rho[0])**2,(anomrho[1]-anomrho[0])**2]
2445        mainSizer.Add(subSizer,0)
2446        conSizer = wx.BoxSizer(wx.HORIZONTAL)
2447        conSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Contrast: %10.2f '%(data['Contrast'][0])),0,WACV)
2448        conSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Anom. Contrast: %10.2f '%(data['Contrast'][1])),0,WACV)
2449        mut =  mu*data['Thick']
2450        conSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Transmission (calc): %10.3f  '%(np.exp(-mut))),0,WACV)
2451        mainSizer.Add(conSizer,0)
2452   
2453    mainSizer.Layout()   
2454    G2frame.dataDisplay.SetSizer(mainSizer)
2455    Size = mainSizer.Fit(G2frame.dataFrame)
2456    G2frame.dataDisplay.SetSize(Size)
2457    G2frame.dataFrame.setSizePosLeft(Size)
2458               
2459################################################################################
2460#####  Indexing Peaks
2461################################################################################           
2462       
2463def UpdateIndexPeaksGrid(G2frame, data):
2464    '''respond to selection of PWDR Index Peak List data
2465    tree item.
2466    '''
2467    bravaisSymb = ['Fm3m','Im3m','Pm3m','R3-H','P6/mmm','I4/mmm',
2468        'P4/mmm','Fmmm','Immm','Cmmm','Pmmm','C2/m','P2/m','P1']
2469    IndexId = G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Index Peak List')
2470    Inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Instrument Parameters'))[0]
2471    limitId = G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Limits')
2472    Limits = G2frame.PatternTree.GetItemPyData(limitId)
2473    def RefreshIndexPeaksGrid(event):
2474        r,c =  event.GetRow(),event.GetCol()
2475        peaks = G2frame.IndexPeaksTable.GetData()
2476        if c == 2:
2477            if peaks[r][c]:
2478                peaks[r][c] = False
2479            else:
2480                peaks[r][c] = True
2481            G2frame.IndexPeaksTable.SetData(peaks)
2482            G2frame.PatternTree.SetItemPyData(IndexId,[peaks,data[1]])
2483            G2frame.dataDisplay.ForceRefresh()
2484            if 'PKS' in G2frame.PatternTree.GetItemText(G2frame.PatternId):
2485                G2plt.PlotPowderLines(G2frame)
2486            else:
2487                G2plt.PlotPatterns(G2frame,plotType='PWDR')
2488           
2489    def OnReload(event):
2490        peaks = []
2491        sigs = []
2492        Peaks = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Peak List'))
2493        for ip,peak in enumerate(Peaks['peaks']):
2494            dsp = G2lat.Pos2dsp(Inst,peak[0])
2495            peaks.append([peak[0],peak[2],True,False,0,0,0,dsp,0.0])    #SS?
2496            try:
2497                sig = Peaks['sigDict']['pos'+str(ip)]
2498            except KeyError:
2499                sig = 0.
2500            sigs.append(sig)
2501        data = [peaks,sigs]
2502        G2frame.PatternTree.SetItemPyData(IndexId,data)
2503        UpdateIndexPeaksGrid(G2frame,data)
2504       
2505    def KeyEditPickGrid(event):
2506        colList = G2frame.dataDisplay.GetSelectedCols()
2507        data = G2frame.PatternTree.GetItemPyData(IndexId)
2508        if event.GetKeyCode() == wx.WXK_RETURN:
2509            event.Skip(True)
2510        elif event.GetKeyCode() == wx.WXK_CONTROL:
2511            event.Skip(True)
2512        elif event.GetKeyCode() == wx.WXK_SHIFT:
2513            event.Skip(True)
2514        elif colList:
2515            G2frame.dataDisplay.ClearSelection()
2516            key = event.GetKeyCode()
2517            for col in colList:
2518                if G2frame.IndexPeaksTable.GetColLabelValue(col) in ['use',]:
2519                    if key == 89: #'Y'
2520                        for row in range(G2frame.IndexPeaksTable.GetNumberRows()): data[0][row][col]=True
2521                    elif key == 78:  #'N'
2522                        for row in range(G2frame.IndexPeaksTable.GetNumberRows()): data[0][row][col]=False
2523                    elif key == 83: # 'S'
2524                        for row in range(G2frame.IndexPeaksTable.GetNumberRows()): data[0][row][col] = not data[0][row][col]
2525                       
2526           
2527    if G2frame.dataDisplay:
2528        G2frame.dataFrame.Clear()
2529    if not G2frame.dataFrame.GetStatusBar():
2530        G2frame.dataFrame.CreateStatusBar()
2531    if 'PWD' in G2frame.PatternTree.GetItemText(G2frame.PatternId):
2532        G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.IndPeaksMenu)
2533        G2frame.Bind(wx.EVT_MENU, OnReload, id=G2gd.wxID_INDXRELOAD)
2534    G2frame.dataFrame.IndexPeaks.Enable(False)
2535    G2frame.IndexPeaksTable = []
2536    if len(data[0]):
2537        G2frame.dataFrame.IndexPeaks.Enable(True)
2538        Unit = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Unit Cells List'))
2539        if Unit:
2540            if len(Unit) == 4:  #patch
2541                Unit.append({})
2542            controls,bravais,cellist,dmin,ssopt = Unit
2543            if 'T' in Inst['Type'][0]:   #TOF - use other limit!
2544                dmin = G2lat.Pos2dsp(Inst,Limits[1][0])
2545            else:
2546                dmin = G2lat.Pos2dsp(Inst,Limits[1][1])
2547            G2frame.HKL = []
2548            if ssopt.get('Use',False):
2549                cell = controls[6:12]
2550                A = G2lat.cell2A(cell)
2551                ibrav = bravaisSymb.index(controls[5])
2552                spc = controls[13]
2553                SGData = G2spc.SpcGroup(spc)[1]
2554                SSGData = G2spc.SSpcGroup(SGData,ssopt['ssSymb'])[1]
2555                Vec = ssopt['ModVec']
2556                maxH = ssopt['maxH']
2557                G2frame.HKL = G2pwd.getHKLMpeak(dmin,Inst,SGData,SSGData,Vec,maxH,A)
2558                G2frame.HKL = np.array(G2frame.HKL)
2559                data[0] = G2indx.IndexSSPeaks(data[0],G2frame.HKL)[1]
2560            else:        #select cell from table - no SS
2561                for i,cell in enumerate(cellist):
2562                    if cell[-2]:
2563                        ibrav = cell[2]
2564                        A = G2lat.cell2A(cell[3:9])
2565                        G2frame.HKL = G2lat.GenHBravais(dmin,ibrav,A)
2566                        for hkl in G2frame.HKL:
2567                            hkl.insert(4,G2lat.Dsp2pos(Inst,hkl[3]))
2568                        G2frame.HKL = np.array(G2frame.HKL)
2569                        data[0] = G2indx.IndexPeaks(data[0],G2frame.HKL)[1]
2570                        break
2571    rowLabels = []
2572    for i in range(len(data[0])): rowLabels.append(str(i+1))
2573    colLabels = ['position','intensity','use','indexed','h','k','l','d-obs','d-calc']
2574    Types = [wg.GRID_VALUE_FLOAT+':10,4',wg.GRID_VALUE_FLOAT+':10,1',]+2*[wg.GRID_VALUE_BOOL,]+ \
2575        3*[wg.GRID_VALUE_LONG,]+2*[wg.GRID_VALUE_FLOAT+':10,5',]
2576    if len(data[0]) and len(data[0][0]) > 9:
2577        colLabels = ['position','intensity','use','indexed','h','k','l','m','d-obs','d-calc']
2578        Types = [wg.GRID_VALUE_FLOAT+':10,4',wg.GRID_VALUE_FLOAT+':10,1',]+2*[wg.GRID_VALUE_BOOL,]+ \
2579            4*[wg.GRID_VALUE_LONG,]+2*[wg.GRID_VALUE_FLOAT+':10,5',]
2580    G2frame.PatternTree.SetItemPyData(IndexId,data)
2581    G2frame.IndexPeaksTable = G2G.Table(data[0],rowLabels=rowLabels,colLabels=colLabels,types=Types)
2582    G2frame.dataFrame.SetLabel('Index Peak List')
2583    G2frame.dataDisplay = G2G.GSGrid(parent=G2frame.dataFrame)               
2584    G2frame.dataDisplay.SetTable(G2frame.IndexPeaksTable, True)
2585    XY = []
2586    Sigs = []
2587    for r in range(G2frame.dataDisplay.GetNumberRows()):
2588        for c in range(G2frame.dataDisplay.GetNumberCols()):
2589            if c == 2:
2590                G2frame.dataDisplay.SetReadOnly(r,c,isReadOnly=False)
2591            else:
2592                G2frame.dataDisplay.SetReadOnly(r,c,isReadOnly=True)
2593        if data[0][r][2] and data[0][r][3]:
2594            XY.append([data[0][r][-1],data[0][r][0]])
2595            try:
2596                sig = data[1][r]
2597            except IndexError:
2598                sig = 0.
2599            Sigs.append(sig)
2600    G2frame.dataDisplay.Bind(wg.EVT_GRID_CELL_LEFT_CLICK, RefreshIndexPeaksGrid)
2601    G2frame.dataDisplay.Bind(wx.EVT_KEY_DOWN, KeyEditPickGrid)                 
2602    G2frame.dataDisplay.SetMargins(0,0)
2603    G2frame.dataDisplay.AutoSizeColumns(False)
2604    G2frame.dataFrame.setSizePosLeft([490,300])
2605    if len(XY):
2606        XY = np.array(XY)
2607        G2plt.PlotCalib(G2frame,Inst,XY,Sigs,newPlot=True)
2608    G2frame.dataFrame.SendSizeEvent()
2609     
2610################################################################################
2611#####  Unit cells
2612################################################################################           
2613       
2614def UpdateUnitCellsGrid(G2frame, data):
2615    '''respond to selection of PWDR Unit Cells data tree item.
2616    '''
2617    UnitCellsId = G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Unit Cells List')
2618    SPGlist = G2spc.spglist
2619    bravaisSymb = ['Fm3m','Im3m','Pm3m','R3-H','P6/mmm','I4/mmm','P4/mmm',
2620        'Fmmm','Immm','Cmmm','Pmmm','C2/m','P2/m','P1']
2621    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',
2622        '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']
2623    Inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Instrument Parameters'))[0]
2624    Limits = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Limits'))[1]
2625    if 'C' in Inst['Type'][0] or 'PKS' in Inst['Type'][0]:
2626        wave = G2mth.getWave(Inst)
2627        dmin = G2lat.Pos2dsp(Inst,Limits[1])
2628    else:
2629        difC = Inst['difC'][1]
2630        dmin = G2lat.Pos2dsp(Inst,Limits[0])
2631   
2632    def SetLattice(controls):
2633        ibrav = bravaisSymb.index(controls[5])
2634        if controls[5] in ['Fm3m','Im3m','Pm3m']:
2635            controls[7] = controls[8] = controls[6]
2636            controls[9] = controls[10] = controls[11] = 90.
2637        elif controls[5] in ['R3m','P6/mmm','I4/mmm','P4/mmm']:
2638            controls[7] = controls[6]
2639            controls[9] = controls[10] = controls[11] = 90.
2640            if controls[5] in ['R3-H','P6/mmm']:
2641                controls[11] = 120.
2642        elif controls[5] in ['Fmmm','Immm','Cmmm','Pmmm']:
2643            controls[9] = controls[10] = controls[11] = 90.
2644        elif controls[5] in ['C2/m','P2/m']:
2645            controls[9] = controls[11] = 90.  # b unique
2646        if len(controls) < 13: controls.append(0)
2647        controls[12] = G2lat.calc_V(G2lat.cell2A(controls[6:12]))
2648        return ibrav
2649       
2650    def OnNcNo(event):
2651        controls[2] = NcNo.GetValue()
2652       
2653    def OnIfX20(event):
2654        G2frame.ifX20 = x20.GetValue()
2655       
2656    def OnStartVol(event):
2657        event.Skip()
2658        try:
2659            stVol = int(float(startVol.GetValue()))
2660            if stVol < 25:
2661                raise ValueError
2662        except ValueError:
2663            stVol = 25
2664        controls[3] = stVol
2665        startVol.SetValue("%d"%(stVol))
2666       
2667    def OnBravais(event):
2668        Obj = event.GetEventObject()
2669        bravais[bravList.index(Obj.GetId())] = Obj.GetValue()
2670       
2671    def OnZero(event):
2672        event.Skip()
2673        try:
2674            Zero = min(5.0,max(-5.0,float(zero.GetValue())))
2675        except ValueError:
2676            Zero = 0.0
2677        controls[1] = Zero
2678        zero.SetValue("%.4f"%(Zero))
2679       
2680    def OnZeroVar(event):
2681        controls[0] = zeroVar.GetValue()
2682       
2683    def OnSSopt(event):
2684        if controls[5] in ['Fm3m','Im3m','Pm3m']:
2685            SSopt.SetValue(False)
2686            G2frame.ErrorDialog('Cubic lattice', 'Superlattice not allowed for a cubic lattice')
2687            return
2688        ssopt['Use'] = SSopt.GetValue()
2689        if 'ssSymb' not in ssopt:
2690            ssopt.update({'ssSymb':'(abg)','ModVec':[0.1,0.1,0.1],'maxH':1})
2691        wx.CallAfter(UpdateUnitCellsGrid,G2frame,data)
2692       
2693    def OnSelMG(event):
2694        ssopt['ssSymb'] = selMG.GetValue()
2695        Vec = ssopt['ModVec']
2696        modS = G2spc.splitSSsym(ssopt['ssSymb'])[0]
2697        ssopt['ModVec'] = G2spc.SSGModCheck(Vec,modS)[0]
2698        print ' Selecting: ',controls[13],ssopt['ssSymb'], 'maxH:',ssopt['maxH']
2699        OnHklShow(event)
2700        wx.CallAfter(UpdateUnitCellsGrid,G2frame,data)
2701       
2702    def OnModVal(event):
2703        event.Skip()
2704        Obj = event.GetEventObject()
2705        ObjId = Obj.GetId()
2706        Id = Indx[ObjId]
2707        try:
2708            value = min(0.98,max(-0.98,float(Obj.GetValue())))
2709        except ValueError:
2710            value = ssopt['ModVec'][Id]
2711        Obj.SetValue('%.4f'%(value))
2712        ssopt['ModVec'][Id] = value
2713        OnHklShow(event)
2714       
2715    def OnMoveMod(event):
2716        Obj = event.GetEventObject()
2717        ObjId = Obj.GetId()
2718        Id,valObj = Indx[ObjId]
2719        move = Obj.GetValue()*0.01
2720        Obj.SetValue(0)
2721        value = min(0.98,max(-0.98,float(valObj.GetValue())+move))
2722        valObj.SetValue('%.4f'%(value)) 
2723        ssopt['ModVec'][Id] = value
2724        OnHklShow(event)
2725       
2726    def OnMaxMH(event):
2727        ssopt['maxH'] = int(maxMH.GetValue())
2728        print ' Selecting: ',controls[13],ssopt['ssSymb'], 'maxH:',ssopt['maxH']
2729        OnHklShow(event)
2730       
2731    def OnFindMV(event):
2732        Peaks = np.copy(peaks[0])
2733        print ' Trying: ',controls[13],ssopt['ssSymb'], 'maxH:',1
2734        dlg = wx.ProgressDialog('Elapsed time','Modulation vector search',
2735            style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE)
2736        try:
2737            ssopt['ModVec'],result = G2indx.findMV(Peaks,controls,ssopt,Inst,dlg)
2738            if len(result[0]) == 2:
2739                G2plt.PlotXYZ(G2frame,result[2],1./result[3],labelX='a',labelY='g',
2740                    newPlot=True,Title='Modulation vector search')
2741        finally:
2742            dlg.Destroy()
2743        OnHklShow(event)
2744        wx.CallAfter(UpdateUnitCellsGrid,G2frame,data)
2745       
2746    def OnBravSel(event):
2747        brav = bravSel.GetString(bravSel.GetSelection())
2748        controls[5] = brav
2749        controls[13] = SPGlist[brav][0]       
2750        wx.CallAfter(UpdateUnitCellsGrid,G2frame,data)
2751       
2752    def OnSpcSel(event):
2753        controls[13] = spcSel.GetString(spcSel.GetSelection())
2754        G2frame.dataFrame.RefineCell.Enable(True)
2755        OnHklShow(event)
2756       
2757    def SetCellValue(Obj,ObjId,value):
2758        if controls[5] in ['Fm3m','Im3m','Pm3m']:
2759            controls[6] = controls[7] = controls[8] = value
2760            controls[9] = controls[10] = controls[11] = 90.0
2761            Obj.SetValue("%.5f"%(controls[6]))
2762        elif controls[5] in ['R3-H','P6/mmm','I4/mmm','P4/mmm']:
2763            if ObjId == 0:
2764                controls[6] = controls[7] = value
2765                Obj.SetValue("%.5f"%(controls[6]))
2766            else:
2767                controls[8] = value
2768                Obj.SetValue("%.5f"%(controls[8]))
2769            controls[9] = controls[10] = controls[11] = 90.0
2770            if controls[5] in ['R3-H','P6/mmm']:
2771                controls[11] = 120.
2772        elif controls[5] in ['Fmmm','Immm','Cmmm','Pmmm']:
2773            controls[6+ObjId] = value
2774            Obj.SetValue("%.5f"%(controls[6+ObjId]))
2775            controls[9] = controls[10] = controls[11] = 90.0
2776        elif controls[5] in ['C2/m','P2/m']:
2777            controls[9] = controls[11] = 90.0
2778            if ObjId != 3:
2779                controls[6+ObjId] = value
2780                Obj.SetValue("%.5f"%(controls[6+ObjId]))
2781            else:
2782                controls[10] = value
2783                Obj.SetValue("%.3f"%(controls[10]))
2784        else:
2785            controls[6+ObjId] = value
2786            if ObjId < 3:
2787                Obj.SetValue("%.5f"%(controls[6+ObjId]))
2788            else:
2789                Obj.SetValue("%.3f"%(controls[6+ObjId]))
2790        controls[12] = G2lat.calc_V(G2lat.cell2A(controls[6:12]))
2791        volVal.SetValue("%.3f"%(controls[12]))
2792       
2793    def OnMoveCell(event):
2794        Obj = event.GetEventObject()
2795        ObjId = cellList.index(Obj.GetId())
2796        valObj = valDict[Obj.GetId()]
2797        if ObjId/2 < 3:
2798            move = Obj.GetValue()*0.01
2799        else:
2800            move = Obj.GetValue()*0.1
2801        Obj.SetValue(0)
2802        value = float(valObj.GetValue())+move 
2803        SetCellValue(valObj,ObjId/2,value)
2804        OnHklShow(event)
2805       
2806    def OnExportCells(event):
2807        pth = G2G.GetExportPath(G2frame)
2808        dlg = wx.FileDialog(G2frame, 'Choose Indexing Result csv file', pth, '', 
2809            'indexing result file (*.csv)|*.csv',wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT)
2810        try:
2811            if dlg.ShowModal() == wx.ID_OK:
2812                filename = dlg.GetPath()
2813                filename = os.path.splitext(filename)[0]+'.csv'
2814                File = open(filename,'w')
2815                names = 'M20,X20,Bravais,a,b,c,alpha,beta,gamma,volume\n'
2816                File.write(names)
2817                fmt = '%.2f,%d,%s,%.4f,%.4f,%.4f,%.2f,%.2f,%.2f,%.3f\n'
2818                for cell in cells:
2819                    File.write(fmt%(cell[0],cell[1],bravaisSymb[cell[2]], cell[3],cell[4],cell[5], cell[6],cell[7],cell[8],cell[9]))
2820                File.close()
2821        finally:
2822            dlg.Destroy()
2823       
2824    def OnCellChange(event):
2825        event.Skip()
2826        Obj = event.GetEventObject()
2827        ObjId = cellList.index(Obj.GetId())
2828        try:
2829            value = max(1.0,float(Obj.GetValue()))
2830        except ValueError:
2831            if ObjId/2 < 3:               #bad cell edge - reset
2832                value = controls[6+ObjId/2]
2833            else:                       #bad angle
2834                value = 90.
2835        SetCellValue(Obj,ObjId/2,value)
2836        wx.CallAfter(UpdateUnitCellsGrid,G2frame,data)
2837       
2838    def OnHklShow(event):
2839        PatternId = G2frame.PatternId
2840        peaks = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Index Peak List'))
2841        controls,bravais,cells,dminx,ssopt = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Unit Cells List'))
2842        cell = controls[6:12]
2843        A = G2lat.cell2A(cell)
2844#        ibrav = bravaisSymb.index(controls[5])
2845        spc = controls[13]
2846        SGData = G2spc.SpcGroup(spc)[1]
2847        if ssopt.get('Use',False):
2848            SSGData = G2spc.SSpcGroup(SGData,ssopt['ssSymb'])[1]
2849            Vec = ssopt['ModVec']
2850            maxH = ssopt['maxH']
2851            G2frame.HKL = G2pwd.getHKLMpeak(dmin,Inst,SGData,SSGData,Vec,maxH,A)
2852            peaks = [G2indx.IndexSSPeaks(peaks[0],G2frame.HKL)[1],peaks[1]]   #keep esds from peak fit
2853            M20,X20 = G2indx.calc_M20SS(peaks[0],G2frame.HKL)
2854        else:
2855            if len(peaks[0]):
2856#                dmin = peaks[0][-1][7]
2857                G2frame.HKL = G2pwd.getHKLpeak(dmin,SGData,A,Inst)
2858                peaks = [G2indx.IndexPeaks(peaks[0],G2frame.HKL)[1],peaks[1]]   #keep esds from peak fit
2859                M20,X20 = G2indx.calc_M20(peaks[0],G2frame.HKL)
2860            else:
2861                M20 = X20 = 0.
2862                G2frame.HKL = G2pwd.getHKLpeak(dmin,SGData,A,Inst)
2863        G2frame.HKL = np.array(G2frame.HKL)
2864        if len(G2frame.HKL):
2865            print ' new M20,X20: %.2f %d fraction found: %.3f'%(M20,X20,float(len(peaks[0]))/len(G2frame.HKL))
2866        G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Index Peak List'),peaks)
2867        if 'PKS' in G2frame.PatternTree.GetItemText(G2frame.PatternId):
2868            G2plt.PlotPowderLines(G2frame)
2869        else:
2870            G2plt.PlotPatterns(G2frame)
2871           
2872    def OnSortCells(event):
2873        controls,bravais,cells,dminx,ssopt = G2frame.PatternTree.GetItemPyData(UnitCellsId)
2874        c =  event.GetCol()
2875        if colLabels[c] == 'M20':
2876            cells = G2indx.sortM20(cells)
2877        elif colLabels[c] in ['X20','Bravais','a','b','c','alpha','beta','gamma','Volume']:
2878            if c == 1:
2879                c += 1  #X20 before Use
2880            cells = G2indx.sortCells(cells,c-1)     #an extra column (Use) not in cells
2881        else:
2882            return
2883        data = [controls,bravais,cells,dmin,ssopt]
2884        G2frame.PatternTree.SetItemPyData(UnitCellsId,data)
2885        wx.CallAfter(UpdateUnitCellsGrid,G2frame,data)
2886       
2887    def CopyUnitCell(event):
2888        controls,bravais,cells,dminx,ssopt = G2frame.PatternTree.GetItemPyData(UnitCellsId)
2889        for Cell in cells:
2890            if Cell[-2]:
2891                break
2892        cell = Cell[2:9]
2893        controls[4] = 1
2894        controls[5] = bravaisSymb[cell[0]]
2895        controls[6:12] = cell[1:8]
2896        controls[12] = G2lat.calc_V(G2lat.cell2A(controls[6:12]))
2897        controls[13] = spaceGroups[bravaisSymb.index(controls[5])]
2898        G2frame.PatternTree.SetItemPyData(UnitCellsId,[controls,bravais,cells,dmin,ssopt])
2899        G2frame.dataFrame.RefineCell.Enable(True)
2900        wx.CallAfter(UpdateUnitCellsGrid,G2frame,data)       
2901               
2902    def RefineCell(event):
2903       
2904        def cellPrint(ibrav,A):
2905            cell = G2lat.A2cell(A)
2906            Vol = G2lat.calc_V(A)
2907            if ibrav in ['Fm3m','Im3m','Pm3m']:
2908                print " %s%10.6f" % ('a =',cell[0])
2909            elif ibrav in ['R3-H','P6/mmm','I4/mmm','P4/mmm']:
2910                print " %s%10.6f %s%10.6f %s%12.3f" % ('a =',cell[0],' c =',cell[2],' volume =',Vol)
2911            elif ibrav in ['P4/mmm','Fmmm','Immm','Cmmm','Pmmm']:
2912                print " %s%10.6f %s%10.6f %s%10.6f %s%12.3f" % ('a =',cell[0],'b =',cell[1],'c =',cell[2],' volume =',Vol)
2913            elif ibrav in ['C2/m','P2/m']:
2914                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)
2915            else:
2916                print " %s%10.6f %s%10.6f %s%10.6f" % ('a =',cell[0],'b =',cell[1],'c =',cell[2])
2917                print " %s%8.3f %s%8.3f %s%8.3f %s%12.3f" % ('alpha =',cell[3],'beta =',cell[4],'gamma =',cell[5],' volume =',Vol)
2918               
2919        def vecPrint(Vec):
2920            print ' %s %10.5f %10.5f %10.5f'%('Modulation vector:',Vec[0],Vec[1],Vec[2])
2921             
2922        PatternId = G2frame.PatternId
2923        peaks = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Index Peak List'))
2924        if not len(peaks[0]):
2925            G2frame.ErrorDialog('No peaks!', 'Nothing to refine!')
2926            return       
2927        print ' Refine cell'
2928        controls,bravais,cells,dminx,ssopt = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Unit Cells List'))
2929        cell = controls[6:12]
2930        A = G2lat.cell2A(cell)
2931        ibrav = bravaisSymb.index(controls[5])
2932        SGData = G2spc.SpcGroup(controls[13])[1]
2933        if 'C' in Inst['Type'][0] or 'PKS' in Inst['Type'][0]:
2934            if ssopt.get('Use',False):
2935                vecFlags = [True if x in ssopt['ssSymb'] else False for x in ['a','b','g']]
2936                SSGData = G2spc.SSpcGroup(SGData,ssopt['ssSymb'])[1]
2937                G2frame.HKL = G2pwd.getHKLMpeak(dmin,Inst,SGData,SSGData,ssopt['ModVec'],ssopt['maxH'],A)
2938                peaks = [G2indx.IndexSSPeaks(peaks[0],G2frame.HKL)[1],peaks[1]]   #put peak fit esds back in peaks
2939                Lhkl,M20,X20,Aref,Vec,Zero = \
2940                    G2indx.refinePeaksZSS(peaks[0],wave,Inst,SGData,SSGData,ssopt['maxH'],ibrav,A,ssopt['ModVec'],vecFlags,controls[1],controls[0])
2941            else:
2942                G2frame.HKL = G2pwd.getHKLpeak(dmin,SGData,A,Inst)
2943                peaks = [G2indx.IndexPeaks(peaks[0],G2frame.HKL)[1],peaks[1]]   #put peak fit esds back in peaks
2944                Lhkl,M20,X20,Aref,Zero = G2indx.refinePeaksZ(peaks[0],wave,ibrav,A,controls[1],controls[0])
2945        else:   
2946            if ssopt.get('Use',False):
2947                vecFlags = [True if x in ssopt['ssSymb'] else False for x in ['a','b','g']]
2948                SSGData = G2spc.SSpcGroup(SGData,ssopt['ssSymb'])[1]
2949                G2frame.HKL = G2pwd.getHKLMpeak(dmin,Inst,SGData,SSGData,ssopt['ModVec'],ssopt['maxH'],A)
2950                peaks = [G2indx.IndexSSPeaks(peaks[0],G2frame.HKL)[1],peaks[1]]   #put peak fit esds back in peaks
2951                Lhkl,M20,X20,Aref,Vec,Zero = \
2952                    G2indx.refinePeaksTSS(peaks[0],difC,Inst,SGData,SSGData,ssopt['maxH'],ibrav,A,ssopt['ModVec'],vecFlags,controls[1],controls[0])
2953            else:
2954                G2frame.HKL = G2pwd.getHKLpeak(dmin,SGData,A,Inst)
2955                peaks = [G2indx.IndexPeaks(peaks[0],G2frame.HKL)[1],peaks[1]]   #put peak fit esds back in peaks
2956                Lhkl,M20,X20,Aref,Zero = G2indx.refinePeaksT(peaks[0],difC,ibrav,A,controls[1],controls[0])           
2957        G2frame.HKL = np.array(G2frame.HKL)
2958        controls[1] = Zero
2959        controls[6:12] = G2lat.A2cell(Aref)
2960        controls[12] = G2lat.calc_V(Aref)
2961        cells = G2frame.PatternTree.GetItemPyData(UnitCellsId)[2]
2962        for cell in cells:
2963            cell[-2] = False
2964        cells.insert(0,[M20,X20,ibrav]+controls[6:13]+[True,False])
2965        if ssopt.get('Use',False):
2966            ssopt['ModVec'] = Vec
2967            G2frame.HKL = G2pwd.getHKLMpeak(dmin,Inst,SGData,SSGData,ssopt['ModVec'],ssopt['maxH'],A)
2968        else:
2969            G2frame.HKL = G2pwd.getHKLpeak(dmin,SGData,A,Inst)
2970        data = [controls,bravais,cells,dmin,ssopt]
2971        G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Unit Cells List'),data)
2972        print " %s%10.3f" % ('refinement M20 = ',M20)
2973        print ' unindexed lines = ',X20
2974        cellPrint(controls[5],Aref)
2975        ip = 4
2976        if ssopt.get('Use',False):
2977            vecPrint(Vec)
2978            ip = 5
2979        for hkl in G2frame.HKL:
2980            hkl[ip] = G2lat.Dsp2pos(Inst,hkl[ip-1])+controls[1]
2981        G2frame.HKL = np.array(G2frame.HKL)
2982        if 'PKS' in G2frame.PatternTree.GetItemText(G2frame.PatternId):
2983            G2plt.PlotPowderLines(G2frame)
2984        else:
2985            G2plt.PlotPatterns(G2frame)
2986        wx.CallAfter(UpdateUnitCellsGrid,G2frame,data)
2987       
2988    def OnIndexPeaks(event):
2989        PatternId = G2frame.PatternId   
2990        print 'Peak Indexing'
2991        keepcells = []
2992        try:
2993            controls,bravais,cells,dminx,ssopt = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Unit Cells List'))
2994            for cell in cells:
2995                if cell[11]:
2996                    cell[10] = False    #clear selection flag on keepers
2997                    keepcells.append(cell)
2998        except IndexError:
2999            pass
3000        except ValueError:
3001            G2frame.ErrorDialog('Error','Need to set controls in Unit Cell List first')
3002            return
3003        if ssopt.get('Use',False):
3004            G2frame.ErrorDialog('Super lattice error','Indexing not available for super lattices')
3005            return
3006        if True not in bravais:
3007            G2frame.ErrorDialog('Error','No Bravais lattices selected')
3008            return
3009        if not len(peaks[0]):
3010            G2frame.ErrorDialog('Error','Index Peak List is empty')
3011            return
3012        if len(peaks[0][0]) > 9:
3013            G2frame.ErrorDialog('Error','You need to reload Index Peaks List first')
3014            return
3015        G2frame.dataFrame.CopyCell.Enable(False)
3016        G2frame.dataFrame.RefineCell.Enable(False)
3017        dlg = wx.ProgressDialog("Generated reflections",'0 '+" cell search for "+bravaisNames[ibrav],101, 
3018#            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
3019            style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_REMAINING_TIME|wx.PD_CAN_ABORT)
3020        try:
3021            OK,dmin,newcells = G2indx.DoIndexPeaks(peaks[0],controls,bravais,dlg,G2frame.ifX20)
3022        finally:
3023            dlg.Destroy()
3024        cells = keepcells+newcells
3025        cells = G2indx.sortM20(cells)
3026        if OK:
3027            cells[0][10] = True         #select best M20
3028            data = [controls,bravais,cells,dmin,ssopt]
3029            G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Unit Cells List'),data)
3030            bestCell = cells[0]
3031            if bestCell[0] > 10.:
3032                G2frame.HKL = G2lat.GenHBravais(dmin,bestCell[2],G2lat.cell2A(bestCell[3:9]))
3033                for hkl in G2frame.HKL:
3034                    hkl.insert(4,G2lat.Dsp2pos(Inst,hkl[3])+controls[1])
3035                G2frame.HKL = np.array(G2frame.HKL)
3036                if 'PKS' in G2frame.PatternTree.GetItemText(G2frame.PatternId):
3037                    G2plt.PlotPowderLines(G2frame)
3038                else:
3039                    G2plt.PlotPatterns(G2frame)
3040            G2frame.dataFrame.CopyCell.Enable(True)
3041            G2frame.dataFrame.IndexPeaks.Enable(True)
3042            G2frame.dataFrame.MakeNewPhase.Enable(True)
3043            G2frame.ifX20 = True
3044            wx.CallAfter(UpdateUnitCellsGrid,G2frame,data)
3045               
3046    def RefreshUnitCellsGrid(event):
3047        data = G2frame.PatternTree.GetItemPyData(UnitCellsId)
3048        cells,dminx = data[2:4]
3049        r,c =  event.GetRow(),event.GetCol()
3050        if cells:
3051            if c == 2:
3052                for i in range(len(cells)):
3053                    cells[i][-2] = False
3054                    UnitCellsTable.SetValue(i,c,False)
3055                UnitCellsTable.SetValue(r,c,True)
3056                gridDisplay.ForceRefresh()
3057                cells[r][-2] = True
3058                ibrav = cells[r][2]
3059                A = G2lat.cell2A(cells[r][3:9])
3060                G2frame.HKL = G2lat.GenHBravais(dmin,ibrav,A)
3061                for hkl in G2frame.HKL:
3062                    hkl.insert(4,G2lat.Dsp2pos(Inst,hkl[3])+controls[1])
3063                G2frame.HKL = np.array(G2frame.HKL)
3064                if 'PKS' in G2frame.PatternTree.GetItemText(G2frame.PatternId):
3065                    G2plt.PlotPowderLines(G2frame)
3066                else:
3067                    G2plt.PlotPatterns(G2frame)
3068            elif c == 11:
3069                if UnitCellsTable.GetValue(r,c):
3070                    UnitCellsTable.SetValue(r,c,False)
3071                    cells[r][c] = False
3072                else:
3073                    cells[r][c] = True
3074                    UnitCellsTable.SetValue(r,c,True)
3075                gridDisplay.ForceRefresh()
3076            G2frame.PatternTree.SetItemPyData(UnitCellsId,data)
3077       
3078    def MakeNewPhase(event):
3079        if not G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Phases'):
3080            sub = G2frame.PatternTree.AppendItem(parent=G2frame.root,text='Phases')
3081        else:
3082            sub = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Phases')
3083        PhaseName = ''
3084        dlg = wx.TextEntryDialog(None,'Enter a name for this phase','Phase Name Entry','New phase',
3085            style=wx.OK)
3086        try:
3087            if dlg.ShowModal() == wx.ID_OK:
3088                PhaseName = dlg.GetValue()
3089                cells = G2frame.PatternTree.GetItemPyData(UnitCellsId)[2]
3090                for Cell in cells:
3091                    if Cell[-2]:
3092                        break
3093                cell = Cell[2:10]       
3094                sub = G2frame.PatternTree.AppendItem(parent=sub,text=PhaseName)
3095                E,SGData = G2spc.SpcGroup(controls[13])
3096                G2frame.PatternTree.SetItemPyData(sub, \
3097                    G2IO.SetNewPhase(Name=PhaseName,SGData=SGData,cell=cell[1:],Super=ssopt))
3098                Status.SetStatusText('Change space group from '+str(controls[13])+' if needed')
3099        finally:
3100            dlg.Destroy()
3101           
3102    if G2frame.dataDisplay:
3103        G2frame.dataFrame.DestroyChildren()
3104    G2frame.dataDisplay = wxscroll.ScrolledPanel(G2frame.dataFrame)
3105    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.IndexMenu)
3106    if not G2frame.dataFrame.GetStatusBar():
3107        Status = G2frame.dataFrame.CreateStatusBar()
3108    G2frame.Bind(wx.EVT_MENU, OnIndexPeaks, id=G2gd.wxID_INDEXPEAKS)
3109    G2frame.Bind(wx.EVT_MENU, CopyUnitCell, id=G2gd.wxID_COPYCELL)
3110    G2frame.Bind(wx.EVT_MENU, RefineCell, id=G2gd.wxID_REFINECELL)
3111    G2frame.Bind(wx.EVT_MENU, MakeNewPhase, id=G2gd.wxID_MAKENEWPHASE)
3112    G2frame.Bind(wx.EVT_MENU, OnExportCells, id=G2gd.wxID_EXPORTCELLS)
3113       
3114    controls,bravais,cells,dminx,ssopt = data
3115    if len(controls) < 13:              #add cell volume if missing
3116        controls.append(G2lat.calc_V(G2lat.cell2A(controls[6:12])))
3117    if len(controls) < 14:              #add space group used in indexing
3118        controls.append(spaceGroups[bravaisSymb.index(controls[5])])
3119    G2frame.PatternTree.SetItemPyData(UnitCellsId,data)            #update with volume
3120    bravaisNames = ['Cubic-F','Cubic-I','Cubic-P','Trigonal-R','Trigonal/Hexagonal-P',
3121        'Tetragonal-I','Tetragonal-P','Orthorhombic-F','Orthorhombic-I','Orthorhombic-C',
3122        'Orthorhombic-P','Monoclinic-C','Monoclinic-P','Triclinic']
3123    cellGUIlist = [[[0,1,2],4,zip([" Unit cell: a = "," Vol = "],["%.5f","%.3f"],[True,False],[0,0])],
3124    [[3,4,5,6],6,zip([" Unit cell: a = "," c = "," Vol = "],["%.5f","%.5f","%.3f"],[True,True,False],[0,2,0])],
3125    [[7,8,9,10],8,zip([" Unit cell: a = "," b = "," c = "," Vol = "],["%.5f","%.5f","%.5f","%.3f"],
3126        [True,True,True,False],[0,1,2,0])],
3127    [[11,12],10,zip([" Unit cell: a = "," b = "," c = "," beta = "," Vol = "],
3128        ["%.5f","%.5f","%.5f","%.3f","%.3f"],[True,True,True,True,False],[0,1,2,4,0])],
3129    [[13,],8,zip([" Unit cell: a = "," b = "," c = "," Vol = "," alpha = "," beta = "," gamma = "],
3130        ["%.5f","%.5f","%.5f","%.3f","%.3f","%.3f","%.3f"],
3131        [True,True,True,False,True,True,True],[0,1,2,0,3,4,5])]]
3132   
3133    G2frame.dataFrame.SetLabel('Unit Cells List')
3134    G2frame.dataFrame.IndexPeaks.Enable(False)
3135    peaks = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Index Peak List'))
3136    if peaks:
3137        G2frame.dataFrame.IndexPeaks.Enable(True)
3138    G2frame.dataFrame.RefineCell.Enable(False)
3139    if controls[12] > 1.0:                               #if a "real" volume (i.e. not default)
3140        G2frame.dataFrame.RefineCell.Enable(True)   
3141    G2frame.dataFrame.CopyCell.Enable(False)
3142    G2frame.dataFrame.MakeNewPhase.Enable(False)       
3143    G2frame.dataFrame.ExportCells.Enable(False)
3144    if cells:
3145        G2frame.dataFrame.CopyCell.Enable(True)
3146        G2frame.dataFrame.MakeNewPhase.Enable(True)
3147        G2frame.dataFrame.ExportCells.Enable(True)
3148    mainSizer = wx.BoxSizer(wx.VERTICAL)
3149    mainSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Indexing controls: '),0,WACV)
3150    mainSizer.Add((5,5),0)
3151    littleSizer = wx.FlexGridSizer(0,5,5,5)
3152    littleSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Max Nc/Nobs '),0,WACV)
3153    NcNo = wx.SpinCtrl(G2frame.dataDisplay)
3154    NcNo.SetRange(2,8)
3155    NcNo.SetValue(controls[2])
3156    NcNo.Bind(wx.EVT_SPINCTRL,OnNcNo)
3157    littleSizer.Add(NcNo,0,WACV)
3158    littleSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Start Volume '),0,WACV)
3159    startVol = wx.TextCtrl(G2frame.dataDisplay,value=str('%d'%(controls[3])),style=wx.TE_PROCESS_ENTER)
3160    startVol.Bind(wx.EVT_TEXT_ENTER,OnStartVol)
3161    startVol.Bind(wx.EVT_KILL_FOCUS,OnStartVol)
3162    littleSizer.Add(startVol,0,WACV)
3163    x20 = wx.CheckBox(G2frame.dataDisplay,label='Use M20/(X20+1)?')
3164    x20.SetValue(G2frame.ifX20)
3165    x20.Bind(wx.EVT_CHECKBOX,OnIfX20)
3166    littleSizer.Add(x20,0,WACV)
3167    mainSizer.Add(littleSizer,0)
3168    mainSizer.Add((5,5),0)
3169    mainSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Select Bravais Lattices for indexing: '),
3170        0,WACV)
3171    mainSizer.Add((5,5),0)
3172    littleSizer = wx.FlexGridSizer(0,7,5,5)
3173    bravList = []
3174    bravs = zip(bravais,bravaisNames)
3175    for brav,bravName in bravs:
3176        bravCk = wx.CheckBox(G2frame.dataDisplay,label=bravName)
3177        bravList.append(bravCk.GetId())
3178        bravCk.SetValue(brav)
3179        bravCk.Bind(wx.EVT_CHECKBOX,OnBravais)
3180        littleSizer.Add(bravCk,0,WACV)
3181    mainSizer.Add(littleSizer,0)
3182    mainSizer.Add((5,5),0)
3183   
3184    mainSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Cell Test & Refinement: '),0,WACV)
3185    mainSizer.Add((5,5),0)
3186    littleSizer = wx.BoxSizer(wx.HORIZONTAL)
3187    littleSizer.Add(wx.StaticText(G2frame.dataDisplay,label=" Bravais lattice "),0,WACV)
3188    bravSel = wx.Choice(G2frame.dataDisplay,choices=bravaisSymb)
3189    bravSel.SetSelection(bravaisSymb.index(controls[5]))
3190    bravSel.Bind(wx.EVT_CHOICE,OnBravSel)
3191    littleSizer.Add(bravSel,0,WACV)
3192    littleSizer.Add(wx.StaticText(G2frame.dataDisplay,label=" Space group "),0,WACV)
3193    spcSel = wx.Choice(G2frame.dataDisplay,choices=SPGlist[controls[5]])
3194    spcSel.SetSelection(SPGlist[controls[5]].index(controls[13]))
3195    spcSel.Bind(wx.EVT_CHOICE,OnSpcSel)
3196    littleSizer.Add(spcSel,0,WACV)
3197    if ssopt.get('Use',False):        #zero for super lattice doesn't work!
3198        controls[0] = False
3199    else:
3200        littleSizer.Add(wx.StaticText(G2frame.dataDisplay,label=" Zero offset"),0,WACV)
3201        zero = wx.TextCtrl(G2frame.dataDisplay,value="%.4f"%(controls[1]),style=wx.TE_PROCESS_ENTER)
3202        zero.Bind(wx.EVT_TEXT_ENTER,OnZero)
3203        zero.Bind(wx.EVT_KILL_FOCUS,OnZero)
3204        littleSizer.Add(zero,0,WACV)
3205        zeroVar = wx.CheckBox(G2frame.dataDisplay,label="Refine?")
3206        zeroVar.SetValue(controls[0])
3207        zeroVar.Bind(wx.EVT_CHECKBOX,OnZeroVar)
3208        littleSizer.Add(zeroVar,0,WACV)
3209    SSopt = wx.CheckBox(G2frame.dataDisplay,label="Super lattice?")
3210    SSopt.SetValue(ssopt.get('Use',False))
3211    SSopt.Bind(wx.EVT_CHECKBOX,OnSSopt)
3212    littleSizer.Add(SSopt,0,WACV)
3213    hklShow = wx.Button(G2frame.dataDisplay,label="Show hkl positions")
3214    hklShow.Bind(wx.EVT_BUTTON,OnHklShow)
3215    littleSizer.Add(hklShow,0,WACV)
3216    mainSizer.Add(littleSizer,0)
3217   
3218    mainSizer.Add((5,5),0)
3219    ibrav = SetLattice(controls)
3220    for cellGUI in cellGUIlist:
3221        if ibrav in cellGUI[0]:
3222            useGUI = cellGUI
3223    cellList = []
3224    valDict = {}
3225    littleSizer = wx.FlexGridSizer(0,useGUI[1],5,5)
3226    for txt,fmt,ifEdit,Id in useGUI[2]:
3227        littleSizer.Add(wx.StaticText(G2frame.dataDisplay,label=txt),0,WACV)
3228        if ifEdit:          #a,b,c,etc.
3229            cellVal = wx.TextCtrl(G2frame.dataDisplay,value=(fmt%(controls[6+Id])),style=wx.TE_PROCESS_ENTER)
3230            cellVal.Bind(wx.EVT_TEXT_ENTER,OnCellChange)       
3231            cellVal.Bind(wx.EVT_KILL_FOCUS,OnCellChange)
3232            valSizer = wx.BoxSizer(wx.HORIZONTAL)
3233            valSizer.Add(cellVal,0,WACV)
3234            cellSpin = wx.SpinButton(G2frame.dataDisplay,style=wx.SP_VERTICAL,size=wx.Size(20,20))
3235            cellSpin.SetValue(0)
3236            cellSpin.SetRange(-1,1)
3237            cellSpin.Bind(wx.EVT_SPIN, OnMoveCell)
3238            valSizer.Add(cellSpin,0,WACV)
3239            littleSizer.Add(valSizer,0,WACV)
3240            cellList.append(cellVal.GetId())
3241            cellList.append(cellSpin.GetId())
3242            valDict[cellSpin.GetId()] = cellVal
3243        else:               #volume
3244            volVal = wx.TextCtrl(G2frame.dataDisplay,value=(fmt%(controls[12])),style=wx.TE_READONLY)
3245            volVal.SetBackgroundColour(VERY_LIGHT_GREY)
3246            littleSizer.Add(volVal,0,WACV)
3247    mainSizer.Add(littleSizer,0)
3248    if ssopt.get('Use',False):        #super lattice display
3249        indChoice = ['1','2','3','4',]
3250        SpSg = controls[13]
3251        ssChoice = G2spc.ssdict[SpSg]
3252        if ssopt['ssSymb'] not in ssChoice:
3253            ssopt['ssSymb'] = ssChoice[0]
3254        ssSizer = wx.BoxSizer(wx.HORIZONTAL)
3255        ssSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Supersymmetry space group: '+SpSg+' '),0,WACV)
3256        selMG = wx.ComboBox(G2frame.dataDisplay,value=ssopt['ssSymb'],
3257                choices=ssChoice,style=wx.CB_READONLY|wx.CB_DROPDOWN)
3258        selMG.Bind(wx.EVT_COMBOBOX, OnSelMG)
3259        ssSizer.Add(selMG,0,WACV)
3260        ssSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Mod. vector: '),0,WACV)
3261        modS = G2spc.splitSSsym(ssopt['ssSymb'])[0]
3262        ssopt['ModVec'],ifShow = G2spc.SSGModCheck(ssopt['ModVec'],modS)
3263        Indx = {}
3264        for i,[val,show] in enumerate(zip(ssopt['ModVec'],ifShow)):
3265            if show:
3266                valSizer = wx.BoxSizer(wx.HORIZONTAL)
3267                modVal = wx.TextCtrl(G2frame.dataDisplay,value=('%.4f'%(val)),
3268                    size=wx.Size(50,20),style=wx.TE_PROCESS_ENTER)
3269                modVal.Bind(wx.EVT_TEXT_ENTER,OnModVal)       
3270                modVal.Bind(wx.EVT_KILL_FOCUS,OnModVal)
3271                valSizer.Add(modVal,0,WACV)
3272                modSpin = wx.SpinButton(G2frame.dataDisplay,style=wx.SP_VERTICAL,size=wx.Size(20,20))
3273                modSpin.SetValue(0)
3274                modSpin.SetRange(-1,1)
3275                modSpin.Bind(wx.EVT_SPIN, OnMoveMod)
3276                valSizer.Add(modSpin,0,WACV)
3277                ssSizer.Add(valSizer,0,WACV)
3278                Indx[modVal.GetId()] = i
3279                Indx[modSpin.GetId()] = [i,modVal]
3280            else:
3281                modVal = wx.TextCtrl(G2frame.dataDisplay,value=('%.3f'%(val)),
3282                    size=wx.Size(50,20),style=wx.TE_READONLY)
3283                modVal.SetBackgroundColour(VERY_LIGHT_GREY)
3284                ssSizer.Add(modVal,0,WACV)
3285        ssSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Max. M: '),0,WACV)
3286        maxMH = wx.ComboBox(G2frame.dataDisplay,value=str(ssopt['maxH']),
3287            choices=indChoice,style=wx.CB_READONLY|wx.CB_DROPDOWN)
3288        maxMH.Bind(wx.EVT_COMBOBOX, OnMaxMH)
3289        ssSizer.Add(maxMH,0,WACV)
3290        findMV = wx.Button(G2frame.dataDisplay,label="Find mod. vec.?")
3291        findMV.Bind(wx.EVT_BUTTON,OnFindMV)
3292        ssSizer.Add(findMV,0,WACV)
3293        mainSizer.Add(ssSizer,0)
3294
3295    if cells:
3296        mainSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label='\n Indexing Result:'),0,WACV)
3297        rowLabels = []
3298        colLabels = ['M20','X20','use','Bravais','a','b','c','alpha','beta','gamma','Volume','Keep']
3299        Types = [wg.GRID_VALUE_FLOAT+':10,2',wg.GRID_VALUE_NUMBER,wg.GRID_VALUE_BOOL,wg.GRID_VALUE_STRING,]+ \
3300            3*[wg.GRID_VALUE_FLOAT+':10,5',]+3*[wg.GRID_VALUE_FLOAT+':10,3',]+ \
3301            [wg.GRID_VALUE_FLOAT+':10,2',wg.GRID_VALUE_BOOL]
3302        table = []
3303        for cell in cells:
3304            rowLabels.append('')
3305            row = cell[0:2]+[cell[-2]]+[bravaisSymb[cell[2]]]+cell[3:10]+[cell[11],]
3306            if cell[-2]:
3307                A = G2lat.cell2A(cell[3:9])
3308                G2frame.HKL = G2lat.GenHBravais(dmin,cell[2],A)
3309                for hkl in G2frame.HKL:
3310                    hkl.insert(4,G2lat.Dsp2pos(Inst,hkl[3])+controls[1])
3311                G2frame.HKL = np.array(G2frame.HKL)
3312            table.append(row)
3313        UnitCellsTable = G2G.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
3314        gridDisplay = G2G.GSGrid(G2frame.dataDisplay)
3315        gridDisplay.SetTable(UnitCellsTable, True)
3316        G2frame.dataFrame.CopyCell.Enable(True)
3317        gridDisplay.Bind(wg.EVT_GRID_CELL_LEFT_CLICK,RefreshUnitCellsGrid)
3318        gridDisplay.Bind(wg.EVT_GRID_LABEL_LEFT_DCLICK,OnSortCells)
3319        gridDisplay.SetMargins(0,0)
3320        gridDisplay.SetRowLabelSize(0)
3321        gridDisplay.AutoSizeColumns(False)
3322        for r in range(gridDisplay.GetNumberRows()):
3323            for c in range(gridDisplay.GetNumberCols()):
3324                if c == 2:
3325                    gridDisplay.SetReadOnly(r,c,isReadOnly=False)
3326                else:
3327                    gridDisplay.SetReadOnly(r,c,isReadOnly=True)
3328        mainSizer.Add(gridDisplay,0,WACV)
3329    mainSizer.Layout()   
3330    G2frame.dataDisplay.SetSizer(mainSizer)
3331    G2frame.dataDisplay.SetAutoLayout(1)
3332    G2frame.dataDisplay.SetupScrolling()
3333    Size = mainSizer.Fit(G2frame.dataFrame)
3334    Size[0] += 25
3335    G2frame.dataDisplay.SetSize(Size)
3336    G2frame.dataFrame.setSizePosLeft(Size)   
3337   
3338################################################################################
3339#####  Reflection list
3340################################################################################           
3341       
3342def UpdateReflectionGrid(G2frame,data,HKLF=False,Name=''):
3343    '''respond to selection of PWDR Reflections data tree item by displaying
3344    a table of reflections in the data window.
3345    '''
3346    Controls = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.root, 'Controls'))
3347    dMin = 0.05
3348    if 'UsrReject' in Controls:
3349        dMin = Controls['UsrReject'].get('MinD',0.05)
3350    def OnPlotHKL(event):
3351        '''Plots a layer of reflections
3352        '''
3353        phaseName = G2frame.RefList
3354        if phaseName not in ['Unknown',]:
3355            pId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Phases')
3356            phaseId =  G2gd.GetPatternTreeItemId(G2frame,pId,phaseName)
3357            General = G2frame.PatternTree.GetItemPyData(phaseId)['General']
3358            Super = General.get('Super',0)
3359            SuperVec = General.get('SuperVec',[])
3360        else:
3361            Super = 0
3362            SuperVec = []       
3363        if 'list' in str(type(data)):   #single crystal data is 2 dict in list
3364            refList = data[1]['RefList']
3365        else:                           #powder data is a dict of dicts; each same structure as SC 2nd dict
3366            if 'RefList' in data[phaseName]:
3367                refList = np.array(data[phaseName]['RefList'])
3368            else:
3369                wx.MessageBox('No reflection list - do Refine first',caption='Reflection plotting')
3370                return
3371        FoMax = np.max(refList.T[8+Super])
3372        Hmin = np.array([int(np.min(refList.T[0])),int(np.min(refList.T[1])),int(np.min(refList.T[2]))])
3373        Hmax = np.array([int(np.max(refList.T[0])),int(np.max(refList.T[1])),int(np.max(refList.T[2]))])
3374        controls = {'Type' : 'Fo','ifFc' : True,'HKLmax' : Hmax,'HKLmin' : Hmin,
3375            'FoMax' : FoMax,'Zone' : '001','Layer' : 0,'Scale' : 1.0,'Super':Super,'SuperVec':SuperVec}
3376        G2plt.PlotSngl(G2frame,newPlot=True,Data=controls,hklRef=refList,Title=phaseName)
3377       
3378    def OnPlot3DHKL(event):
3379        '''Plots the reflections in 3D
3380        '''
3381        phaseName = G2frame.RefList
3382        if phaseName not in ['Unknown',]:
3383            pId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Phases')
3384            phaseId =  G2gd.GetPatternTreeItemId(G2frame,pId,phaseName)
3385            General = G2frame.PatternTree.GetItemPyData(phaseId)['General']
3386            Super = General.get('Super',0)
3387            SuperVec = General.get('SuperVec',[])
3388        else:
3389            Super = 0
3390            SuperVec = []       
3391        if 'list' in str(type(data)):   #single crystal data is 2 dict in list
3392            refList = data[1]['RefList']
3393        else:                           #powder data is a dict of dicts; each same structure as SC 2nd dict
3394            if 'RefList' in data[phaseName]:
3395                refList = np.array(data[phaseName]['RefList'])
3396            else:
3397                wx.MessageBox('No reflection list - do Refine first',caption='Reflection plotting')
3398                return
3399        refList.T[3+Super] = np.where(refList.T[4+Super]<dMin,-refList.T[3+Super],refList.T[3+Super])
3400        FoMax = np.max(refList.T[8+Super])
3401        Hmin = np.array([int(np.min(refList.T[0])),int(np.min(refList.T[1])),int(np.min(refList.T[2]))])
3402        Hmax = np.array([int(np.max(refList.T[0])),int(np.max(refList.T[1])),int(np.max(refList.T[2]))])
3403        Vpoint = np.array([int(np.mean(refList.T[0])),int(np.mean(refList.T[1])),int(np.mean(refList.T[2]))])
3404        controls = {'Type':'Fosq','Iscale':False,'HKLmax':Hmax,'HKLmin':Hmin,'Zone':False,'viewKey':'L',
3405            'FoMax' : FoMax,'Scale' : 1.0,'Drawing':{'viewPoint':[Vpoint,[]],'default':Vpoint[:],
3406            'backColor':[0,0,0],'depthFog':False,'Zclip':10.0,'cameraPos':10.,'Zstep':0.05,'viewUp':[0,1,0],
3407            'Scale':1.0,'oldxy':[],'viewDir':[0,0,1]},'Super':Super,'SuperVec':SuperVec}
3408        G2plt.Plot3DSngl(G2frame,newPlot=True,Data=controls,hklRef=refList,Title=phaseName)
3409       
3410    def MakeReflectionTable(phaseName):
3411        '''Returns a wx.grid table (G2G.Table) containing a list of all reflections
3412        for a phase.       
3413        '''
3414        if phaseName not in ['Unknown',]:
3415            pId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Phases')
3416            phaseId =  G2gd.GetPatternTreeItemId(G2frame,pId,phaseName)
3417            if not phaseId:         #phase deleted
3418                return None
3419            General = G2frame.PatternTree.GetItemPyData(phaseId)['General']
3420            Super = General.get('Super',0)
3421        else:
3422            Super = 0
3423        rowLabels = []
3424        if HKLF:
3425            refList = data[1]['RefList']
3426            refs = refList
3427        else:
3428            if len(data) > 1:
3429                G2frame.dataFrame.SelectPhase.Enable(True)
3430            try:            #patch for old reflection lists
3431                if not len(data[phaseName]):
3432                    return None
3433                refList = np.array(data[phaseName]['RefList'])
3434                I100 = refList.T[8+Super]*refList.T[11+Super]
3435            except TypeError:
3436                refList = np.array([refl[:11+Super] for refl in data[phaseName]])
3437                I100 = refList.T[8+Super]*np.array([refl[11+Super] for refl in data[phaseName]])
3438            Imax = np.max(I100)
3439            if Imax:
3440                I100 *= 100.0/Imax
3441            if 'C' in Inst['Type'][0]:
3442                refs = np.vstack((refList.T[:15+Super],I100)).T
3443            elif 'T' in Inst['Type'][0]:
3444                refs = np.vstack((refList.T[:18+Super],I100)).T
3445        rowLabels = [str(i) for i in range(len(refs))]
3446        Types = (4+Super)*[wg.GRID_VALUE_LONG,]+4*[wg.GRID_VALUE_FLOAT+':10,4',]+ \
3447            2*[wg.GRID_VALUE_FLOAT+':10,2',]+[wg.GRID_VALUE_FLOAT+':10,3',]+ \
3448            [wg.GRID_VALUE_FLOAT+':10,3',]
3449        if HKLF:
3450            colLabels = ['H','K','L','twin','d','Fosq','sig','Fcsq','FoTsq','FcTsq','phase','ExtC',]
3451            if 'T' in Inst['Type'][0]:
3452                colLabels = ['H','K','L','twin','d','Fosq','sig','Fcsq','FoTsq','FcTsq','phase','ExtC','wave','tbar']
3453                Types += 2*[wg.GRID_VALUE_FLOAT+':10,3',]
3454            if Super:
3455                colLabels.insert(3,'M')
3456        else:
3457            if 'C' in Inst['Type'][0]:
3458                colLabels = ['H','K','L','mul','d','pos','sig','gam','Fosq','Fcsq','phase','Icorr','Prfo','Trans','ExtP','I100']
3459                Types += 4*[wg.GRID_VALUE_FLOAT+':10,3',]
3460            elif 'T' in Inst['Type'][0]:
3461                colLabels = ['H','K','L','mul','d','pos','sig','gam','Fosq','Fcsq','phase','Icorr','alp','bet','wave','Prfo','Abs','Ext','I100']
3462                Types += 7*[wg.GRID_VALUE_FLOAT+':10,3',]
3463            if Super:
3464                colLabels.insert(3,'M')
3465        refs.T[3+Super] = np.where(refs.T[4+Super]<dMin,-refs.T[3+Super],refs.T[3+Super])
3466        return G2G.Table(refs,rowLabels=rowLabels,colLabels=colLabels,types=Types)
3467
3468    def ShowReflTable(phaseName):
3469        '''Posts a table of reflections for a phase, creating the table
3470        if needed using MakeReflectionTable
3471        '''
3472        def setBackgroundColors(im,it):
3473            for r in range(G2frame.refTable[phaseName].GetNumberRows()):
3474                if HKLF:
3475                    if float(G2frame.refTable[phaseName].GetCellValue(r,3+im)) <= 0.:
3476                        G2frame.refTable[phaseName].SetCellBackgroundColour(r,3+im,wx.RED)
3477                    Fosq = float(G2frame.refTable[phaseName].GetCellValue(r,5+im))
3478                    Fcsq = float(G2frame.refTable[phaseName].GetCellValue(r,7+im))
3479                    sig = float(G2frame.refTable[phaseName].GetCellValue(r,6+im))
3480                    rat = 11.
3481                    if sig:
3482                        rat = abs(Fosq-Fcsq)/sig
3483                    if  rat > 10.:
3484                        G2frame.refTable[phaseName].SetCellBackgroundColour(r,7+im,wx.RED)
3485                    elif rat > 3.0:
3486                        G2frame.refTable[phaseName].SetCellBackgroundColour(r,7+im,wx.Colour(255,255,0))
3487                else:   #PWDR
3488                    if float(G2frame.refTable[phaseName].GetCellValue(r,12+im+itof)) < 0.:
3489                        G2frame.refTable[phaseName].SetCellBackgroundColour(r,12+im+itof,wx.RED)
3490                    if float(G2frame.refTable[phaseName].GetCellValue(r,3+im)) < 0:
3491                        G2frame.refTable[phaseName].SetCellBackgroundColour(r,8+im,wx.RED)
3492                       
3493                                                 
3494        if not len(data[phaseName]):
3495            return          #deleted phase?
3496        G2frame.RefList = phaseName
3497        G2frame.dataFrame.SetLabel('Reflection List for '+phaseName)
3498        if HKLF:
3499            Status.SetStatusText('abs(DF)/sig > 10 red; > 3 yellow; twin < 0 (user rejected) red; twin=0 (sp. gp. absent) red')
3500        else:
3501            Status.SetStatusText('Prfo < 0. in red; if excluded Fosq in red & mul < 0')
3502        itof = 0
3503        if HKLF:
3504            im = data[1].get('Super',0)
3505        else:
3506            if 'T' in data[phaseName].get('Type',''):
3507                itof = 3
3508            im = data[phaseName].get('Super',0)
3509        # has this table already been displayed?
3510        if G2frame.refTable[phaseName].GetTable() is None:
3511            PeakTable = MakeReflectionTable(phaseName)
3512            G2frame.refTable[phaseName].SetTable(PeakTable, True)
3513            G2frame.refTable[phaseName].EnableEditing(False)
3514            G2frame.refTable[phaseName].SetMargins(0,0)
3515            G2frame.refTable[phaseName].AutoSizeColumns(False)
3516            setBackgroundColors(im,itof)
3517#        GSASIIpath.IPyBreak()
3518        refList = np.array([refl[:6+im] for refl in data[phaseName]['RefList']])
3519        G2frame.HKL = np.vstack((refList.T)).T    #build for plots
3520        # raise the tab (needed for 1st use and from OnSelectPhase)
3521        for PageNum in range(G2frame.dataDisplay.GetPageCount()):
3522            if phaseName == G2frame.dataDisplay.GetPageText(PageNum):
3523                G2frame.dataDisplay.SetSelection(PageNum)
3524                break
3525        else:
3526            print phaseName
3527            print phases
3528            raise Exception("how did we not find a phase name?")
3529       
3530    def OnPageChanged(event):
3531        '''Respond to a press on a phase tab by displaying the reflections. This
3532        routine is needed because the reflection table may not have been created yet.
3533        '''
3534        page = event.GetSelection()
3535        phaseName = G2frame.dataDisplay.GetPageText(page)
3536        ShowReflTable(phaseName)
3537
3538    def OnSelectPhase(event):
3539        '''For PWDR, selects a phase with a selection box. Called from menu.
3540        '''
3541        if len(phases) < 2: return
3542        dlg = wx.SingleChoiceDialog(G2frame,'Select','Phase',phases)
3543        try:
3544            if dlg.ShowModal() == wx.ID_OK:
3545                sel = dlg.GetSelection()
3546                ShowReflTable(phases[sel])
3547        finally:
3548            dlg.Destroy()
3549           
3550    if not data:
3551        print 'No phases, no reflections'
3552        return
3553    if HKLF:
3554        G2frame.RefList = 1
3555        phaseName = IsHistogramInAnyPhase(G2frame,Name)
3556        if not phaseName:
3557            phaseName = 'Unknown'
3558        phases = [phaseName]
3559    else:
3560        phaseName = G2frame.RefList
3561        phases = data.keys()
3562    if G2frame.dataDisplay:
3563        G2frame.dataFrame.Clear()
3564    Inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Instrument Parameters'))[0]
3565    if not G2frame.dataFrame.GetStatusBar():
3566        Status = G2frame.dataFrame.CreateStatusBar()   
3567    if HKLF:
3568        G2gd.SetDataMenuBar(G2frame)
3569        G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.ReflMenu)
3570        G2frame.Bind(wx.EVT_MENU, OnPlotHKL, id=G2gd.wxID_PWDHKLPLOT)
3571        G2frame.Bind(wx.EVT_MENU, OnPlot3DHKL, id=G2gd.wxID_PWD3DHKLPLOT)
3572        G2frame.dataFrame.SelectPhase.Enable(False)
3573    else:
3574        G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.ReflMenu)
3575        G2frame.Bind(wx.EVT_MENU, OnSelectPhase, id=G2gd.wxID_SELECTPHASE)
3576        G2frame.Bind(wx.EVT_MENU, OnPlotHKL, id=G2gd.wxID_PWDHKLPLOT)
3577        G2frame.Bind(wx.EVT_MENU, OnPlot3DHKL, id=G2gd.wxID_PWD3DHKLPLOT)
3578        G2frame.dataFrame.SelectPhase.Enable(False)
3579           
3580    G2frame.dataDisplay = G2G.GSNoteBook(parent=G2frame.dataFrame,size=G2frame.dataFrame.GetClientSize())
3581    G2frame.refTable = {}
3582    for tabnum,phase in enumerate(phases):
3583        if len(data[phase]):
3584            G2frame.refTable[phase] = G2G.GSGrid(parent=G2frame.dataDisplay)
3585            G2frame.dataDisplay.AddPage(G2frame.refTable[phase],phase)
3586        else:       #cleanup deleted phase reflection lists
3587            del data[phase]
3588            if len(data):
3589                G2frame.RefList = data.keys()[0]
3590                phaseName = G2frame.RefList
3591            else:
3592                G2frame.RefList = ''
3593                phaseName = ''
3594#    if phaseName not in G2frame.refTable:
3595#        print phaseName
3596#        print phases
3597#        raise Exception("how did we get a invalid phase name?")   
3598    if phaseName:
3599        ShowReflTable(phaseName)
3600#    G2frame.refTable[phaseName].Fit()   #slow!!
3601#    size = G2frame.refTable[phaseName].GetSize()
3602#    G2frame.dataFrame.setSizePosLeft([size[0]+32,350])
3603    G2frame.dataFrame.setSizePosLeft([550,350])
3604    G2frame.dataDisplay.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CHANGED, OnPageChanged)
3605   
3606################################################################################
3607#####  SASD Substances
3608################################################################################
3609           
3610def UpdateSubstanceGrid(G2frame,data):
3611    '''respond to selection of SASD Substance data tree item.
3612    '''
3613    import Substances as substFile
3614   
3615    def OnLoadSubstance(event):
3616        names = substFile.Substances.keys()
3617        names.sort()
3618        dlg = wx.SingleChoiceDialog(G2frame, 'Which substance?', 'Select substance', names, wx.CHOICEDLG_STYLE)
3619        try:
3620            if dlg.ShowModal() == wx.ID_OK:
3621                name = names[dlg.GetSelection()]
3622            else:
3623                return
3624        finally:
3625            dlg.Destroy()
3626        data['Substances'][name] = {'Elements':{},'Volume':1.0,'Density':1.0,
3627            'Scatt density':0.0,'XAnom density':0.0,'XAbsorption':0.0}
3628        subst = substFile.Substances[name]
3629        ElList = subst['Elements'].keys()
3630        for El in ElList:
3631            Info = G2elem.GetAtomInfo(El.strip().capitalize())
3632            Info.update(subst['Elements'][El])
3633            data['Substances'][name]['Elements'][El] = Info
3634            if 'Volume' in subst:
3635                data['Substances'][name]['Volume'] = subst['Volume']
3636                data['Substances'][name]['Density'] = \
3637                    G2mth.Vol2Den(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])
3638            elif 'Density' in subst:
3639                data['Substances'][name]['Density'] = subst['Density']
3640                data['Substances'][name]['Volume'] = \
3641                    G2mth.Den2Vol(data['Substances'][name]['Elements'],data['Substances'][name]['Density'])
3642            else:
3643                data['Substances'][name]['Volume'] = G2mth.El2EstVol(data['Substances'][name]['Elements'])
3644                data['Substances'][name]['Density'] = \
3645                    G2mth.Vol2Den(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])
3646            data['Substances'][name]['Scatt density'] = \
3647                G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])[0]
3648            contrst,absorb = G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'],wave)         
3649            data['Substances'][name]['XAnom density'] = contrst
3650            data['Substances'][name]['XAbsorption'] = absorb
3651                         
3652        UpdateSubstanceGrid(G2frame,data)
3653       
3654    def OnCopySubstance(event):
3655        hst = G2frame.PatternTree.GetItemText(G2frame.PatternId)
3656        histList = GetHistsLikeSelected(G2frame)
3657        if not histList:
3658            G2frame.ErrorDialog('No match','No histograms match '+hst,G2frame.dataFrame)
3659            return
3660        copyList = []
3661        dlg = G2G.G2MultiChoiceDialog(
3662            G2frame.dataFrame, 
3663            'Copy substances from\n'+hst[5:]+' to...',
3664            'Copy substances', histList)
3665        try:
3666            if dlg.ShowModal() == wx.ID_OK:
3667                for i in dlg.GetSelections(): 
3668                    copyList.append(histList[i])
3669        finally:
3670            dlg.Destroy()       
3671        for item in copyList:
3672            Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,item)
3673            Inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Instrument Parameters'))[0]
3674            wave = G2mth.getWave(Inst)
3675            ndata = copy.deepcopy(data)
3676            for name in ndata['Substances'].keys():
3677                contrst,absorb = G2mth.XScattDen(ndata['Substances'][name]['Elements'],ndata['Substances'][name]['Volume'],wave)         
3678                ndata['Substances'][name]['XAnom density'] = contrst
3679                ndata['Substances'][name]['XAbsorption'] = absorb
3680            G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Substances'),ndata)
3681   
3682    def OnAddSubstance(event):
3683        dlg = wx.TextEntryDialog(None,'Enter a name for this substance','Substance Name Entry','New substance',
3684            style=wx.OK)
3685        if dlg.ShowModal() == wx.ID_OK:
3686            Name = dlg.GetValue()
3687            data['Substances'][Name] = {'Elements':{},'Volume':1.0,'Density':1.0,
3688                'Scatt density':0.0,'XAnom density':0.,'XAbsorption':0.}
3689        dlg.Destroy()
3690        AddElement(Name)
3691        UpdateSubstanceGrid(G2frame,data)
3692       
3693    def OnDeleteSubstance(event):
3694        TextList = []
3695        for name in data['Substances']:
3696            if name != 'vacuum':
3697                TextList += [name,]
3698        if not TextList:
3699            return
3700        dlg = wx.SingleChoiceDialog(G2frame, 'Which substance?', 'Select substance to delete', TextList, wx.CHOICEDLG_STYLE)
3701        try:
3702            if dlg.ShowModal() == wx.ID_OK:
3703                name = TextList[dlg.GetSelection()]
3704            else:
3705                return
3706        finally:
3707            dlg.Destroy()
3708        del(data['Substances'][name])
3709        UpdateSubstanceGrid(G2frame,data)       
3710               
3711    def OnAddElement(event):       
3712        TextList = []
3713        for name in data['Substances']:
3714            if name != 'vacuum':
3715                TextList += [name,]
3716        if not TextList:
3717            return
3718        dlg = wx.SingleChoiceDialog(G2frame, 'Which substance?', 'Select substance', TextList, wx.CHOICEDLG_STYLE)
3719        try:
3720            if dlg.ShowModal() == wx.ID_OK:
3721                name = TextList[dlg.GetSelection()]
3722            else:
3723                return
3724        finally:
3725            dlg.Destroy()
3726        AddElement(name)
3727        UpdateSubstanceGrid(G2frame,data)
3728       
3729    def AddElement(name):
3730        ElList = data['Substances'][name]['Elements'].keys()
3731        dlg = G2elemGUI.PickElements(G2frame,ElList)
3732        if dlg.ShowModal() == wx.ID_OK:
3733            for El in dlg.Elem:
3734                El = El.strip().capitalize()
3735                Info = G2elem.GetAtomInfo(El)
3736                Info.update({'Num':1})
3737                data['Substances'][name]['Elements'][El] = Info
3738            data['Substances'][name]['Volume'] = G2mth.El2EstVol(data['Substances'][name]['Elements'])
3739            data['Substances'][name]['Density'] = \
3740                G2mth.Vol2Den(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])
3741            data['Substances'][name]['Scatt density'] = \
3742                G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])[0]
3743            contrst,absorb = G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'],wave)         
3744            data['Substances'][name]['XAnom density'] = contrst
3745            data['Substances'][name]['XAbsorption'] = absorb
3746        dlg.Destroy()
3747       
3748    def OnDeleteElement(event):
3749        TextList = []
3750        for name in data['Substances']:
3751            if name != 'vacuum':
3752                TextList += [name,]
3753        if not TextList:
3754            return
3755        dlg = wx.SingleChoiceDialog(G2frame, 'Which substance?', 'Select substance', TextList, wx.CHOICEDLG_STYLE)
3756        try:
3757            if dlg.ShowModal() == wx.ID_OK:
3758                name = TextList[dlg.GetSelection()]
3759            else:
3760                return
3761        finally:
3762            dlg.Destroy()
3763        ElList = data['Substances'][name]['Elements'].keys()
3764        if len(ElList):
3765            DE = G2elemGUI.DeleteElement(G2frame,ElList)
3766            if DE.ShowModal() == wx.ID_OK:
3767                El = DE.GetDeleteElement().strip().upper()
3768                del(data['Substances'][name]['Elements'][El])
3769                data['Substances'][name]['Volume'] = G2mth.El2EstVol(data['Substances'][name]['Elements'])
3770                data['Substances'][name]['Density'] = \
3771                    G2mth.Vol2Den(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])
3772                data['Substances'][name]['Scatt density'] = \
3773                    G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])[0]
3774                contrst,absorb = G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'],wave)         
3775                data['Substances'][name]['XAnom density'] = contrst
3776                data['Substances'][name]['XAbsorption'] = absorb
3777        UpdateSubstanceGrid(G2frame,data)
3778               
3779    def SubstSizer():
3780       
3781        def OnValueChange(event):
3782            event.Skip()
3783            Obj = event.GetEventObject()
3784            if len(Indx[Obj.GetId()]) == 3:
3785                name,El,keyId = Indx[Obj.GetId()]
3786                try:
3787                    value = max(0,float(Obj.GetValue()))
3788                except ValueError:
3789                    value = 0
3790                    Obj.SetValue('%.2f'%(value))
3791                data['Substances'][name]['Elements'][El][keyId] = value
3792                data['Substances'][name]['Volume'] = G2mth.El2EstVol(data['Substances'][name]['Elements'])
3793                data['Substances'][name]['Density'] = \
3794                    G2mth.Vol2Den(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])
3795            else:
3796                name,keyId = Indx[Obj.GetId()]
3797                try:
3798                    value = max(0,float(Obj.GetValue()))
3799                except ValueError:
3800                    value = 1.0
3801                data['Substances'][name][keyId] = value
3802                if keyId in 'Volume':
3803                    data['Substances'][name]['Density'] = \
3804                        G2mth.Vol2Den(data['Substances'][name]['Elements'],value)
3805                elif keyId in 'Density':
3806                    data['Substances'][name]['Volume'] = \
3807                        G2mth.Den2Vol(data['Substances'][name]['Elements'],value)
3808            data['Substances'][name]['Scatt density'] = \
3809                G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'])[0]
3810            contrst,absorb = G2mth.XScattDen(data['Substances'][name]['Elements'],data['Substances'][name]['Volume'],wave)         
3811            data['Substances'][name]['XAnom density'] = contrst
3812            data['Substances'][name]['XAbsorption'] = absorb
3813            wx.CallAfter(UpdateSubstanceGrid,G2frame,data)
3814       
3815        Indx = {}
3816        substSizer = wx.BoxSizer(wx.VERTICAL)
3817        substSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Substance list: wavelength: %.5fA'%(wave)),
3818            0,WACV)
3819        for name in data['Substances']:
3820            G2G.HorizontalLine(substSizer,G2frame.dataDisplay)   
3821            substSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Data for '+name+':'),
3822                0,WACV)
3823            if name == 'vacuum':
3824                substSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label='        Not applicable'),
3825                    0,WACV)
3826            else:   
3827                elSizer = wx.FlexGridSizer(0,6,5,5)
3828                Substance = data['Substances'][name]
3829                Elems = Substance['Elements']
3830                for El in Elems:    #do elements as pull downs for isotopes for neutrons
3831                    elSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' '+El+': '),
3832                        0,WACV)
3833                    num = wx.TextCtrl(G2frame.dataDisplay,value='%.2f'%(Elems[El]['Num']),style=wx.TE_PROCESS_ENTER)
3834                    Indx[num.GetId()] = [name,El,'Num']
3835                    num.Bind(wx.EVT_TEXT_ENTER,OnValueChange)       
3836                    num.Bind(wx.EVT_KILL_FOCUS,OnValueChange)
3837                    elSizer.Add(num,0,WACV)
3838                substSizer.Add(elSizer,0)
3839                vdsSizer = wx.FlexGridSizer(0,4,5,5)
3840                vdsSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Volume: '),
3841                    0,WACV)
3842                vol = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(Substance['Volume']),style=wx.TE_PROCESS_ENTER)
3843                Indx[vol.GetId()] = [name,'Volume']
3844                vol.Bind(wx.EVT_TEXT_ENTER,OnValueChange)       
3845                vol.Bind(wx.EVT_KILL_FOCUS,OnValueChange)
3846                vdsSizer.Add(vol,0,WACV)               
3847                vdsSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' Density: '),
3848                    0,WACV)
3849                den = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(Substance['Density']),style=wx.TE_PROCESS_ENTER)
3850                Indx[den.GetId()] = [name,'Density']
3851                den.Bind(wx.EVT_TEXT_ENTER,OnValueChange)       
3852                den.Bind(wx.EVT_KILL_FOCUS,OnValueChange)
3853                vdsSizer.Add(den,0,WACV)
3854                substSizer.Add(vdsSizer,0)
3855                substSizer.Add(wx.StaticText(G2frame.dataDisplay,
3856                    label=' Scattering density  : %.2f *10%scm%s'%(Substance['Scatt density'],Pwr10,Pwrm2)),
3857                    0,WACV)               
3858                substSizer.Add(wx.StaticText(G2frame.dataDisplay,       #allow neutrons here into NAnom density & NAbsorption
3859                    label=' Anomalous density : %.2f *10%scm%s'%(Substance['XAnom density'],Pwr10,Pwrm2)),
3860                    0,WACV)               
3861                substSizer.Add(wx.StaticText(G2frame.dataDisplay,
3862                    label=' X-ray absorption   : %.2f cm%s'%(Substance['XAbsorption'],Pwrm1)),
3863                    0,WACV)               
3864        return substSizer
3865           
3866    Inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Instrument Parameters'))[0]
3867    wave = G2mth.getWave(Inst)
3868    if G2frame.dataDisplay:
3869        G2frame.dataFrame.DestroyChildren()  # is this a ScrolledWindow? If so, bad!
3870    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.SubstanceMenu)
3871    if not G2frame.dataFrame.GetStatusBar():
3872        G2frame.dataFrame.CreateStatusBar()
3873    G2frame.dataDisplay = wxscroll.ScrolledPanel(G2frame.dataFrame)
3874    G2frame.dataFrame.SetLabel('Substances')
3875    G2frame.dataFrame.Bind(wx.EVT_MENU, OnLoadSubstance, id=G2gd.wxID_LOADSUBSTANCE)   
3876    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddSubstance, id=G2gd.wxID_ADDSUBSTANCE)
3877    G2frame.dataFrame.Bind(wx.EVT_MENU, OnCopySubstance, id=G2gd.wxID_COPYSUBSTANCE)
3878    G2frame.dataFrame.Bind(wx.EVT_MENU, OnDeleteSubstance, id=G2gd.wxID_DELETESUBSTANCE)   
3879    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddElement, id=G2gd.wxID_ELEMENTADD)
3880    G2frame.dataFrame.Bind(wx.EVT_MENU, OnDeleteElement, id=G2gd.wxID_ELEMENTDELETE)
3881    mainSizer = wx.BoxSizer(wx.VERTICAL)
3882    mainSizer.Add(SubstSizer(),0)
3883
3884    mainSizer.Layout()   
3885    G2frame.dataDisplay.SetSizer(mainSizer)
3886    G2frame.dataDisplay.SetAutoLayout(1)
3887    G2frame.dataDisplay.SetupScrolling()
3888    Size = mainSizer.Fit(G2frame.dataFrame)
3889    Size[0] += 25
3890    G2frame.dataDisplay.SetSize(Size)
3891    G2frame.dataFrame.setSizePosLeft(Size)   
3892       
3893################################################################################
3894#####  SASD Models
3895################################################################################           
3896       
3897def UpdateModelsGrid(G2frame,data):
3898    '''respond to selection of SASD Models data tree item.
3899    '''
3900    #patches
3901    if 'Current' not in data:
3902        data['Current'] = 'Size dist.'
3903    if 'logBins' not in data['Size']:
3904        data['Size']['logBins'] = True
3905    if 'MinMaxDiam' in data['Size']:
3906        data['Size']['MinDiam'] = 50.
3907        data['Size']['MaxDiam'] = 10000.
3908        del data['Size']['MinMaxDiam']
3909    if isinstance(data['Size']['MaxEnt']['Sky'],float):
3910        data['Size']['MaxEnt']['Sky'] = -3
3911    if 'Power' not in data['Size']['IPG']:
3912        data['Size']['IPG']['Power'] = -1
3913    if 'Matrix' not in data['Particle']:
3914        data['Particle']['Matrix'] = {'Name':'vacuum','VolFrac':[0.0,False]}
3915    if 'BackFile' not in data:
3916        data['BackFile'] = ''
3917    #end patches
3918   
3919    def RefreshPlots(newPlot=False):
3920        PlotText = G2frame.G2plotNB.nb.GetPageText(G2frame.G2plotNB.nb.GetSelection())
3921        if 'Powder' in PlotText:
3922            G2plt.PlotPatterns(G2frame,plotType='SASD',newPlot=newPlot)
3923        elif 'Size' in PlotText:
3924            G2plt.PlotSASDSizeDist(G2frame)
3925               
3926    def OnAddModel(event):
3927        if data['Current'] == 'Particle fit':
3928            material = 'vacuum'
3929            if len(data['Particle']['Levels']):
3930                material = data['Particle']['Levels'][-1]['Controls']['Material']
3931            data['Particle']['Levels'].append({
3932                'Controls':{'FormFact':'Sphere','DistType':'LogNormal','Material':material,
3933                    'FFargs':{},'SFargs':{},'NumPoints':50,'Cutoff':0.01,'Contrast':0.0,
3934                    'SlitSmear':[0.0,False],'StrFact':'Dilute'},    #last 2 not used - future?
3935                'LogNormal':{'Volume':[0.05,False],'Mean':[1000.,False],'StdDev':[0.5,False],'MinSize':[10.,False],},
3936                'Gaussian':{'Volume':[0.05,False],'Mean':[1000.,False],'StdDev':[300.,False],},
3937                'LSW':{'Volume':[0.05,False],'Mean':[1000.0,False],},
3938                'Schulz-Zimm':{'Volume':[0.05,False],'Mean':[1000.,False],'StdDev':[300.,False],},
3939                'Unified':{'G':[1.e3,False],'Rg':[100,False],'B':[1.e-5,False],'P':[4,False],'Cutoff':[1e-5,False],},
3940                'Porod':{'B':[1.e-4,False],'P':[4,False],'Cutoff':[1e-5,False],},
3941                'Monodisperse':{'Volume':[0.05,False],'Radius':[100,False],},   #OK for spheres
3942                'Bragg':{'PkInt':[100,False],'PkPos':[0.2,False],
3943                    'PkSig':[10,False],'PkGam':[10,False],},        #reasonable 31A peak
3944                })
3945            G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
3946            RefreshPlots(True)
3947                   
3948        wx.CallAfter(UpdateModelsGrid,G2frame,data)
3949       
3950    def OnCopyModel(event):
3951        hst = G2frame.PatternTree.GetItemText(G2frame.PatternId)
3952        histList = GetHistsLikeSelected(G2frame)
3953        if not histList:
3954            G2frame.ErrorDialog('No match','No histograms match '+hst,G2frame.dataFrame)
3955            return
3956        copyList = []
3957        dlg = G2G.G2MultiChoiceDialog(
3958            G2frame.dataFrame, 
3959            'Copy models from\n'+hst[5:]+' to...',
3960            'Copy models', histList)
3961        try:
3962            if dlg.ShowModal() == wx.ID_OK:
3963                for i in dlg.GetSelections(): 
3964                    copyList.append(histList[i])
3965        finally:
3966            dlg.Destroy()       
3967        for item in copyList:
3968            Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,item)
3969            newdata = copy.deepcopy(data)
3970            G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Models'),newdata)
3971            if newdata['BackFile']:
3972                Profile = G2frame.PatternTree.GetItemPyData(Id)[1]
3973                BackId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,newdata['BackFile'])
3974                BackSample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,BackId, 'Sample Parameters'))
3975                Profile[5] = BackSample['Scale'][0]*G2frame.PatternTree.GetItemPyData(BackId)[1][1]
3976        UpdateModelsGrid(G2frame,newdata) 
3977        wx.CallAfter(UpdateModelsGrid,G2frame,data)
3978        RefreshPlots(True)
3979               
3980    def OnCopyFlags(event):
3981        thisModel = copy.deepcopy(data)
3982        hst = G2frame.PatternTree.GetItemText(G2frame.PatternId)
3983        histList = GetHistsLikeSelected(G2frame)
3984        if not histList:
3985            G2frame.ErrorDialog('No match','No histograms match '+hst,G2frame.dataFrame)
3986            return
3987        dlg = G2G.G2MultiChoiceDialog(
3988            G2frame.dataFrame, 
3989            'Copy sample ref. flags from\n'+str(hst[5:])+' to...',
3990            'Copy sample flags', histList)
3991        distChoice = ['LogNormal','Gaussian','LSW','Schulz-Zimm','Bragg','Unified',
3992            'Porod','Monodisperse',]
3993        parmOrder = ['Volume','Radius','Mean','StdDev','G','Rg','B','P',
3994            'Cutoff','PkInt','PkPos','PkSig','PkGam','VolFr','Dist',]
3995        try:
3996            if dlg.ShowModal() == wx.ID_OK:
3997                result = dlg.GetSelections()
3998                for i in result: 
3999                    item = histList[i]
4000                    Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,item)
4001                    newModel = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Models'))
4002                    newModel['Back'][1] = copy.copy(thisModel['Back'][1])
4003                    for ilev,level in enumerate(newModel['Particle']['Levels']):
4004                        for form in level:
4005                            if form in distChoice:
4006                                thisForm = thisModel['Particle']['Levels'][ilev][form]                               
4007                                for item in parmOrder:
4008                                    if item in thisForm:
4009                                       level[form][item][1] = copy.copy(thisForm[item][1])
4010                            elif form == 'Controls':
4011                                thisForm = thisModel['Particle']['Levels'][ilev][form]['SFargs']
4012                                for item in parmOrder:
4013                                    if item in thisForm:
4014                                        level[form]['SFargs'][item][1] = copy.copy(thisForm[item][1])
4015        finally:
4016            dlg.Destroy()
4017               
4018    def OnFitModelAll(event):
4019        choices = G2gd.GetPatternTreeDataNames(G2frame,['SASD',])
4020        sel = []
4021        dlg = G2G.G2MultiChoiceDialog(G2frame.dataFrame, 'Sequential SASD refinement',
4022             'Select dataset to include',choices)
4023        dlg.SetSelections(sel)
4024        names = []
4025        if dlg.ShowModal() == wx.ID_OK:
4026            for sel in dlg.GetSelections():
4027                names.append(choices[sel])
4028        dlg.Destroy()
4029        SeqResult = {}
4030        Reverse = False
4031        CopyForward = False
4032        choice = ['Reverse sequence','Copy from prev.']
4033        dlg = wx.MultiChoiceDialog(G2frame.dataFrame,'Sequential controls','Select controls',choice)
4034        if dlg.ShowModal() == wx.ID_OK:
4035            for sel in dlg.GetSelections():
4036                if sel:
4037                    CopyForward = True
4038                else:
4039                    Reverse = True
4040        dlg.Destroy()
4041        dlg = wx.ProgressDialog('SASD Sequential fit','Data set name = '+names[0],len(names), 
4042            style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_REMAINING_TIME|wx.PD_CAN_ABORT)
4043        wx.BeginBusyCursor()
4044        if Reverse:
4045            names.reverse()
4046        JModel = None
4047        try:
4048            for i,name in enumerate(names):
4049                print ' Sequential fit for ',name
4050                GoOn = dlg.Update(i,newmsg='Data set name = '+name)[0]
4051                if not GoOn:
4052                    break
4053                Id =  G2gd.GetPatternTreeItemId(G2frame,G2frame.root,name)
4054                if i and CopyForward:
4055                    G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Models'),JModel)
4056                IProfDict,IProfile = G2frame.PatternTree.GetItemPyData(Id)[:2]
4057                IModel = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Models'))
4058                ISample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Sample Parameters'))
4059                ILimits = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Limits'))
4060                IfOK,result,varyList,sig,Rvals,covMatrix,parmDict,Msg = G2sasd.ModelFit(IProfile,IProfDict,ILimits,ISample,IModel)
4061                JModel = copy.deepcopy(IModel)
4062                if not IfOK:
4063                    G2frame.ErrorDialog('Failed sequential refinement for data '+name,
4064                        ' Msg: '+Msg+'\nYou need to rethink your selection of parameters\n'+    \
4065                        ' Model restored to previous version for'+name)
4066                    SeqResult['histNames'] = names[:i]
4067                    dlg.Destroy()
4068                    break
4069                else:
4070                    G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Models'),copy.deepcopy(IModel))
4071               
4072                G2sasd.ModelFxn(IProfile,IProfDict,ILimits,ISample,IModel)
4073                SeqResult[name] = {'variables':result[0],'varyList':varyList,'sig':sig,'Rvals':Rvals,
4074                    'covMatrix':covMatrix,'title':name,'parmDict':parmDict}
4075            else:
4076                dlg.Destroy()
4077                print ' ***** Small angle sequential refinement successful *****'
4078        finally:
4079            wx.EndBusyCursor()   
4080        if Reverse:
4081            names.reverse()
4082        SeqResult['histNames'] = names
4083        Id =  G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Sequential SASD results')
4084        if Id:
4085            G2frame.PatternTree.SetItemPyData(Id,SeqResult)
4086        else:
4087            Id = G2frame.PatternTree.AppendItem(parent=G2frame.root,text='Sequential SASD results')
4088            G2frame.PatternTree.SetItemPyData(Id,SeqResult)
4089        G2frame.PatternTree.SelectItem(Id)
4090       
4091    def OnFitModel(event):
4092        if data['Current'] == 'Size dist.':
4093            if not any(Sample['Contrast']):
4094                G2frame.ErrorDialog('No contrast; your sample is a vacuum!',
4095                    'You need to define a scattering substance!\n'+    \
4096                    ' Do Substances and then Sample parameters')
4097                return
4098            G2sasd.SizeDistribution(Profile,ProfDict,Limits,Sample,data)
4099            G2plt.PlotSASDSizeDist(G2frame)
4100            RefreshPlots(True)
4101           
4102        elif data['Current'] == 'Particle fit':
4103            SaveState()
4104            Results = G2sasd.ModelFit(Profile,ProfDict,Limits,Sample,data)
4105            if not Results[0]:
4106                    G2frame.ErrorDialog('Failed refinement',
4107                        ' Msg: '+Results[-1]+'\nYou need to rethink your selection of parameters\n'+    \
4108                        ' Model restored to previous version')
4109            G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
4110            RefreshPlots(True)
4111            wx.CallAfter(UpdateModelsGrid,G2frame,data)
4112           
4113    def OnUnDo(event):
4114        DoUnDo()
4115        data = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,
4116            G2frame.PatternId,'Models'))
4117        G2frame.dataFrame.SasdUndo.Enable(False)
4118        UpdateModelsGrid(G2frame,data)
4119        G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
4120        RefreshPlots(True)
4121
4122    def DoUnDo():
4123        print 'Undo last refinement'
4124        file = open(G2frame.undosasd,'rb')
4125        PatternId = G2frame.PatternId
4126        G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Models'),cPickle.load(file))
4127        print ' Models recovered'
4128        file.close()
4129       
4130    def SaveState():
4131        G2frame.undosasd = os.path.join(G2frame.dirname,'GSASIIsasd.save')
4132        file = open(G2frame.undosasd,'wb')
4133        PatternId = G2frame.PatternId
4134        for item in ['Models']:
4135            cPickle.dump(G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,item)),file,1)
4136        file.close()
4137        G2frame.dataFrame.SasdUndo.Enable(True)
4138       
4139    def OnSelectFit(event):
4140        data['Current'] = fitSel.GetValue()
4141        wx.CallAfter(UpdateModelsGrid,G2frame,data)
4142       
4143    def OnCheckBox(event):
4144        Obj = event.GetEventObject()
4145        item,ind = Indx[Obj.GetId()]
4146        item[ind] = Obj.GetValue()
4147       
4148    def OnIntVal(event):
4149        event.Skip()
4150        Obj = event.GetEventObject()
4151        item,ind,minVal = Indx[Obj.GetId()]
4152        try:
4153            value = int(Obj.GetValue())
4154            if value <= minVal:
4155                raise ValueError
4156        except ValueError:
4157            value = item[ind]
4158        Obj.SetValue(str(value))
4159        item[ind] = value
4160
4161    def SizeSizer():
4162       
4163        def OnShape(event):
4164            data['Size']['Shape'][0] = partsh.GetValue()
4165            wx.CallAfter(UpdateModelsGrid,G2frame,data)
4166           
4167        def OnMethod(event):
4168            data['Size']['Method'] = method.GetValue()
4169            wx.CallAfter(UpdateModelsGrid,G2frame,data)
4170           
4171        def OnPartVal(event):
4172            event.Skip()
4173            try:
4174                val = max(0.0,float(partprm.GetValue()))
4175            except ValueError:
4176                val = 1
4177            data['Size']['Shape'][1] = val
4178            partprm.SetValue('%.3f'%(val))
4179           
4180        sizeSizer = wx.BoxSizer(wx.VERTICAL)
4181        sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Size distribution parameters: '),0,WACV)
4182        binSizer = wx.FlexGridSizer(0,7,5,5)
4183        binSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' No. size bins: '),0,WACV)
4184        bins = ['50','100','150','200']
4185        nbins = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['Nbins']),choices=bins,
4186            style=wx.CB_READONLY|wx.CB_DROPDOWN)
4187        Indx[nbins.GetId()] = [data['Size'],'Nbins',0]
4188        nbins.Bind(wx.EVT_COMBOBOX,OnIntVal)       
4189        binSizer.Add(nbins,0,WACV)