source: trunk/GSASIIpwdGUI.py @ 1327

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

Better error trapping for SASD fitting LS.

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