source: trunk/GSASIIpwdGUI.py @ 1391

Last change on this file since 1391 was 1391, checked in by vondreele, 8 years ago

remove stray prints
Breit-Wigner & Lynn & Seeger neutron anomalous form factors for CW data
Add 'Ext' to HKLF reflection lists
make sure wave & tbar are in TOF HKLF reflection lists
add '_refln_f_sigma' & '_refln_f_squared_sigma' to possible cif reflection columns

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