source: trunk/GSASIIpwdGUI.py @ 2525

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

fix to plotting after limit change problem

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