source: trunk/GSASIIpwdGUI.py @ 1515

Last change on this file since 1515 was 1515, checked in by vondreele, 9 years ago

allow '#' comments in GSAS iparm files.
add class G2ColumnIDDialog for loading sample data for all histograms from a text file. This file has optional '#' comments followed by columns of data items each line begins with a file name that matches the file names for the histograms.
This class allows simple arithmetic modification of a column of data.
G2MultiChoiceDialog now allows selection of a block of items
Add 'Time' to Sample parameters - typically clock time
Further work on modulated structures
change default .gsa GSAS powder data extension to .gda - a lot more common.

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