source: trunk/GSASIIpwdGUI.py @ 1337

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

add parmDict to SASD seq output dictionary to match that from PWDR

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 180.9 KB
Line 
1# -*- coding: utf-8 -*-
2#GSASIIpwdGUI - powder data display routines
3########### SVN repository information ###################
4# $Date: 2014-05-07 20:30:22 +0000 (Wed, 07 May 2014) $
5# $Author: vondreele $
6# $Revision: 1337 $
7# $URL: trunk/GSASIIpwdGUI.py $
8# $Id: GSASIIpwdGUI.py 1337 2014-05-07 20:30:22Z 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: 1337 $")
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','VolFr','Dist',]
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                            elif form == 'Controls':
2765                                thisForm = thisModel['Particle']['Levels'][ilev][form]['SFargs']
2766                                for item in parmOrder:
2767                                    if item in thisForm:
2768                                        level[form]['SFargs'][item][1] = copy.copy(thisForm[item][1])
2769        finally:
2770            dlg.Destroy()
2771               
2772    def OnFitModelAll(event):
2773        choices = G2gd.GetPatternTreeDataNames(G2frame,['SASD',])
2774        sel = []
2775        dlg = G2gd.G2MultiChoiceDialog(G2frame.dataFrame, 'Sequential SASD refinement',
2776             'Select dataset to include',choices)
2777        dlg.SetSelections(sel)
2778        names = []
2779        if dlg.ShowModal() == wx.ID_OK:
2780            for sel in dlg.GetSelections():
2781                names.append(choices[sel])
2782        dlg.Destroy()
2783        SeqResult = {'histNames':names}
2784        Reverse = False
2785        CopyForward = False
2786        choice = ['Reverse sequence','Copy from prev.']
2787        dlg = wx.MultiChoiceDialog(G2frame.dataFrame,'Sequential controls','Select controls',choice)
2788        if dlg.ShowModal() == wx.ID_OK:
2789            for sel in dlg.GetSelections():
2790                if sel:
2791                    CopyForward = True
2792                else:
2793                    G2frame.seqReverse = True
2794        dlg.Destroy()
2795        dlg = wx.ProgressDialog('SASD Sequential fit','Data set name = '+names[0],len(names), 
2796            style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_REMAINING_TIME|wx.PD_CAN_ABORT)
2797        wx.BeginBusyCursor()
2798        if G2frame.seqReverse:
2799            names.reverse()
2800        try:
2801            for i,name in enumerate(names):
2802                print ' Sequential fit for ',name
2803                GoOn = dlg.Update(i,newmsg='Data set name = '+name)[0]
2804                if not GoOn:
2805                    break
2806                Id =  G2gd.GetPatternTreeItemId(G2frame,G2frame.root,name)
2807                if i and CopyForward:
2808                    G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Models'),JModel)
2809                IProfDict,IProfile = G2frame.PatternTree.GetItemPyData(Id)[:2]
2810                IModel = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Models'))
2811                ISample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Sample Parameters'))
2812                ILimits = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Limits'))
2813                IInst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Instrument Parameters'))
2814                IfOK,result,varyList,sig,Rvals,covMatrix,parmDict,Msg = G2sasd.ModelFit(IProfile,IProfDict,ILimits,ISample,IModel)
2815                JModel = copy.copy(IModel)
2816                if not IfOK:
2817                    G2frame.ErrorDialog('Failed sequential refinement for data '+name,
2818                        ' Msg: '+Msg+'\nYou need to rethink your selection of parameters\n'+    \
2819                        ' Model restored to previous version for'+name)
2820                    SeqResult['histNames'] = names[:i]
2821                    dlg.Destroy()
2822                    break
2823               
2824                G2sasd.ModelFxn(IProfile,IProfDict,ILimits,ISample,IModel)
2825                SeqResult[name] = {'variables':result[0],'varyList':varyList,'sig':sig,'Rvals':Rvals,
2826                    'covMatrix':covMatrix,'title':name,'parmDict':parmDict}
2827            else:
2828                dlg.Destroy()
2829                print ' ***** Small angle sequential refinement successful *****'
2830        finally:
2831            wx.EndBusyCursor()   
2832        Id =  G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Sequential results')
2833        if Id:
2834            G2frame.PatternTree.SetItemPyData(Id,SeqResult)
2835        else:
2836            Id = G2frame.PatternTree.AppendItem(parent=G2frame.root,text='Sequential results')
2837            G2frame.PatternTree.SetItemPyData(Id,SeqResult)
2838        G2frame.PatternTree.SelectItem(Id)
2839       
2840    def OnFitModel(event):
2841        if data['Current'] == 'Size dist.':
2842            if not any(Sample['Contrast']):
2843                G2frame.ErrorDialog('No contrast; your sample is a vacuum!',
2844                    'You need to define a scattering substance!\n'+    \
2845                    ' Do Substances and then Sample parameters')
2846                return
2847            G2sasd.SizeDistribution(Profile,ProfDict,Limits,Sample,data)
2848            G2plt.PlotSASDSizeDist(G2frame)
2849            RefreshPlots(True)
2850           
2851        elif data['Current'] == 'Particle fit':
2852            SaveState()
2853            Results = G2sasd.ModelFit(Profile,ProfDict,Limits,Sample,data)
2854            if not Results[0]:
2855                    G2frame.ErrorDialog('Failed refinement',
2856                        ' Msg: '+Results[-1]+'\nYou need to rethink your selection of parameters\n'+    \
2857                        ' Model restored to previous version')
2858            G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
2859            RefreshPlots(True)
2860            wx.CallAfter(UpdateModelsGrid,G2frame,data)
2861           
2862    def OnUnDo(event):
2863        DoUnDo()
2864        data = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,
2865            G2frame.PatternId,'Models'))
2866        G2frame.dataFrame.SasdUndo.Enable(False)
2867        UpdateModelsGrid(G2frame,data)
2868        G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
2869        RefreshPlots(True)
2870
2871    def DoUnDo():
2872        print 'Undo last refinement'
2873        file = open(G2frame.undosasd,'rb')
2874        PatternId = G2frame.PatternId
2875        G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Models'),cPickle.load(file))
2876        print ' Models recovered'
2877        file.close()
2878       
2879    def SaveState():
2880        G2frame.undosasd = os.path.join(G2frame.dirname,'GSASIIsasd.save')
2881        file = open(G2frame.undosasd,'wb')
2882        PatternId = G2frame.PatternId
2883        for item in ['Models']:
2884            cPickle.dump(G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,item)),file,1)
2885        file.close()
2886        G2frame.dataFrame.SasdUndo.Enable(True)
2887       
2888    def OnSelectFit(event):
2889        data['Current'] = fitSel.GetValue()
2890        wx.CallAfter(UpdateModelsGrid,G2frame,data)
2891       
2892    def OnCheckBox(event):
2893        Obj = event.GetEventObject()
2894        item,ind = Indx[Obj.GetId()]
2895        item[ind] = Obj.GetValue()
2896       
2897    def OnIntVal(event):
2898        Obj = event.GetEventObject()
2899        item,ind,minVal = Indx[Obj.GetId()]
2900        try:
2901            value = int(Obj.GetValue())
2902            if value <= minVal:
2903                raise ValueError
2904        except ValueError:
2905            value = item[ind]
2906        Obj.SetValue(str(value))
2907        item[ind] = value
2908
2909    def SizeSizer():
2910       
2911        def OnShape(event):
2912            data['Size']['Shape'][0] = partsh.GetValue()
2913            wx.CallAfter(UpdateModelsGrid,G2frame,data)
2914           
2915        def OnMethod(event):
2916            data['Size']['Method'] = method.GetValue()
2917            wx.CallAfter(UpdateModelsGrid,G2frame,data)
2918           
2919        def OnPartVal(event):
2920            try:
2921                val = max(0.0,float(partprm.GetValue()))
2922            except ValueError:
2923                val = 1
2924            data['Size']['Shape'][1] = val
2925            partprm.SetValue('%.3f'%(val))
2926           
2927        sizeSizer = wx.BoxSizer(wx.VERTICAL)
2928        sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Size distribution parameters: '),0,WACV)
2929        binSizer = wx.FlexGridSizer(1,7,5,5)
2930        binSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' No. size bins: '),0,WACV)
2931        bins = ['50','100','150','200']
2932        nbins = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['Nbins']),choices=bins,
2933            style=wx.CB_READONLY|wx.CB_DROPDOWN)
2934        Indx[nbins.GetId()] = [data['Size'],'Nbins',0]
2935        nbins.Bind(wx.EVT_COMBOBOX,OnIntVal)       
2936        binSizer.Add(nbins,0,WACV)
2937        binSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Min diam.: '),0,WACV)
2938        minDias = ['10','25','50','100','150','200']
2939        mindiam = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['MinDiam']),choices=minDias,
2940            style=wx.CB_DROPDOWN)
2941        mindiam.Bind(wx.EVT_LEAVE_WINDOW,OnIntVal)
2942        mindiam.Bind(wx.EVT_TEXT_ENTER,OnIntVal)       
2943        mindiam.Bind(wx.EVT_KILL_FOCUS,OnIntVal)
2944        Indx[mindiam.GetId()] = [data['Size'],'MinDiam',0]
2945        binSizer.Add(mindiam,0,WACV)
2946        binSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Max diam.: '),0,WACV)
2947        maxDias = [str(1000*(i+1)) for i in range(10)]
2948        maxdiam = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['MaxDiam']),choices=maxDias,
2949            style=wx.CB_DROPDOWN)
2950        maxdiam.Bind(wx.EVT_LEAVE_WINDOW,OnIntVal)
2951        maxdiam.Bind(wx.EVT_TEXT_ENTER,OnIntVal)       
2952        maxdiam.Bind(wx.EVT_KILL_FOCUS,OnIntVal)
2953        Indx[maxdiam.GetId()] = [data['Size'],'MaxDiam',0]
2954        binSizer.Add(maxdiam,0,WACV)
2955        logbins = wx.CheckBox(G2frame.dataDisplay,label='Log bins?')
2956        Indx[logbins.GetId()] = [data['Size'],'logBins']
2957        logbins.SetValue(data['Size']['logBins'])
2958        logbins.Bind(wx.EVT_CHECKBOX, OnCheckBox)
2959        binSizer.Add(logbins,0,WACV)
2960        sizeSizer.Add(binSizer,0)
2961        sizeSizer.Add((5,5),0)
2962        partSizer = wx.BoxSizer(wx.HORIZONTAL)
2963        partSizer.Add(wx.StaticText(G2frame.dataDisplay,label='Particle description: '),0,WACV)
2964        shapes = {'Spheroid':' Aspect ratio: ','Cylinder':' Diameter ','Cylinder AR':' Aspect ratio: ',
2965            'Unified sphere':'','Unified rod':' Diameter: ','Unified rod AR':' Aspect ratio: ',
2966            'Unified disk':' Thickness: '}
2967        partsh = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['Shape'][0]),choices=shapes.keys(),
2968            style=wx.CB_READONLY|wx.CB_DROPDOWN)
2969        partsh.Bind(wx.EVT_COMBOBOX,OnShape)       
2970        partSizer.Add(partsh,0,WACV)
2971        if data['Size']['Shape'][0] not in ['Unified sphere',]:
2972            partSizer.Add(wx.StaticText(G2frame.dataDisplay,label=shapes[data['Size']['Shape'][0]]),0,WACV)
2973            partprm = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(data['Size']['Shape'][1]),
2974                style=wx.TE_PROCESS_ENTER)
2975            partprm.Bind(wx.EVT_TEXT_ENTER,OnPartVal)       
2976            partprm.Bind(wx.EVT_KILL_FOCUS,OnPartVal)
2977            partSizer.Add(partprm,0,WACV)
2978        sizeSizer.Add(partSizer,0)
2979        sizeSizer.Add((5,5),0)
2980        fitSizer = wx.BoxSizer(wx.HORIZONTAL)
2981        methods = ['MaxEnt','IPG',]
2982        fitSizer.Add(wx.StaticText(G2frame.dataDisplay,label='Fitting method: '),0,WACV)
2983        method = wx.ComboBox(G2frame.dataDisplay,value=data['Size']['Method'],choices=methods,
2984            style=wx.CB_READONLY|wx.CB_DROPDOWN)
2985        method.Bind(wx.EVT_COMBOBOX,OnMethod)
2986        fitSizer.Add(method,0,WACV)
2987        iters = ['10','25','50','100','150','200']       
2988        fitSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' No. iterations: '),0,WACV)
2989        Method = data['Size']['Method']
2990        iter = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size'][Method]['Niter']),choices=iters,
2991            style=wx.CB_READONLY|wx.CB_DROPDOWN)
2992        Indx[iter.GetId()] = [data['Size'][Method],'Niter',0]
2993        iter.Bind(wx.EVT_COMBOBOX,OnIntVal)
2994        fitSizer.Add(iter,0,WACV)
2995        if 'MaxEnt' in data['Size']['Method']:
2996            fitSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Log floor factor: '),0,WACV)
2997            floors = [str(-i) for i in range(9)]
2998            floor = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['MaxEnt']['Sky']),choices=floors,
2999                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3000            Indx[floor.GetId()] = [data['Size']['MaxEnt'],'Sky',-10]
3001            floor.Bind(wx.EVT_COMBOBOX,OnIntVal)
3002            fitSizer.Add(floor,0,WACV)
3003        elif 'IPG' in data['Size']['Method']:
3004            fitSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Q power weight (-1 for sigma): '),0,WACV)
3005            choices = ['-1','0','1','2','3','4']
3006            power = wx.ComboBox(G2frame.dataDisplay,value=str(data['Size']['IPG']['Power']),choices=choices,
3007                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3008            Indx[power.GetId()] = [data['Size']['IPG'],'Power',-2]
3009            power.Bind(wx.EVT_COMBOBOX,OnIntVal)
3010            fitSizer.Add(power,0,WACV)
3011        sizeSizer.Add(fitSizer,0)
3012
3013        return sizeSizer
3014       
3015    def PartSizer():
3016       
3017        FormFactors = {'Sphere':{},'Spheroid':{'Aspect ratio':[1.0,False]},
3018            'Cylinder':{'Length':[100.,False]},'Cylinder diam':{'Diameter':[100.,False]},
3019            'Cylinder AR':{'Aspect ratio':[1.0,False]},'Unified sphere':{},
3020            'Unified rod':{'Length':[100.,False]},'Unified rod AR':{'Aspect ratio':[1.0,False]},
3021            'Unified disk':{'Thickness':[100.,False]},
3022            'Unified tube':{'Length':[100.,False],'Thickness':[10.,False]},}
3023               
3024        StructureFactors = {'Dilute':{},'Hard sphere':{'VolFr':[0.1,False],'Dist':[100.,False]},
3025            'Sticky hard sphere':{'VolFr':[0.1,False],'Dist':[100.,False],'epis':[0.05,False],'Sticky':[0.2,False]},
3026            'Square well':{'VolFr':[0.1,False],'Dist':[100.,False],'Depth':[0.1,False],'Width':[1.,False]},
3027            'InterPrecipitate':{'VolFr':[0.1,False],'Dist':[100.,False]},}
3028               
3029        ffDistChoices =  ['Sphere','Spheroid','Cylinder','Cylinder diam',
3030            'Cylinder AR','Unified sphere','Unified rod','Unified rod AR',
3031            'Unified disk','Unified tube',]
3032               
3033        ffMonoChoices = ['Sphere','Spheroid','Cylinder','Cylinder AR',]
3034       
3035        sfChoices = ['Dilute','Hard sphere','Sticky hard sphere','Square well','InterPrecipitate',]
3036           
3037        slMult = 1000.
3038                 
3039        def OnValue(event):
3040            Obj = event.GetEventObject()
3041            item,key,sldrObj = Indx[Obj.GetId()]
3042            try:
3043                value = float(Obj.GetValue())
3044                if value <= 0.:
3045                    raise ValueError
3046            except ValueError:
3047                value = item[key][0]
3048            item[key][0] = value
3049            Obj.SetValue('%.3g'%(value))
3050            if key in ['P','epis','Sticky','Depth','Width','VolFr','Dist']:
3051                sldrObj.SetValue(slMult*value)
3052            else:
3053                logv = np.log10(value)
3054                valMinMax = [logv-1,logv+1]
3055                sldrObj.SetRange(slMult*valMinMax[0],slMult*valMinMax[1])
3056                sldrObj.SetValue(slMult*logv)
3057            G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
3058            RefreshPlots()
3059           
3060        def OnSelect(event):
3061            Obj = event.GetEventObject()
3062            item,key = Indx[Obj.GetId()]
3063            item[key] = Obj.GetValue()
3064            if 'Refine' not in Obj.GetLabel():
3065                if 'FormFact' in key :
3066                    item['FFargs'] = FormFactors[Obj.GetValue()]
3067                elif 'StrFact' in key:
3068                    item['SFargs'] = StructureFactors[Obj.GetValue()]
3069                wx.CallAfter(UpdateModelsGrid,G2frame,data)
3070                G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
3071                RefreshPlots()
3072               
3073        def OnDelLevel(event):
3074            Obj = event.GetEventObject()
3075            item = Indx[Obj.GetId()]
3076            del data['Particle']['Levels'][item]
3077            wx.CallAfter(UpdateModelsGrid,G2frame,data)
3078            G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
3079            RefreshPlots()
3080           
3081        def OnParmSlider(event):
3082            Obj = event.GetEventObject()
3083            item,key,pvObj = Indx[Obj.GetId()]
3084            slide = Obj.GetValue()
3085            if key in ['P','epis','Sticky','Depth','Width','VolFr','Dist']:
3086                value = float(slide/slMult)
3087            else:
3088                value = 10.**float(slide/slMult)
3089            item[key][0] = value
3090            pvObj.SetValue('%.3g'%(item[key][0]))
3091            G2sasd.ModelFxn(Profile,ProfDict,Limits,Sample,data)
3092            RefreshPlots()
3093           
3094        def SizeSizer():
3095            sizeSizer = wx.FlexGridSizer(0,4,5,5)
3096            sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Distribution: '),0,WACV)
3097            Distchoice = ['LogNormal','Gaussian','LSW','Schulz-Zimm','Bragg','Unified','Porod','Monodisperse',]
3098            distChoice = wx.ComboBox(G2frame.dataDisplay,value=level['Controls']['DistType'],choices=Distchoice,
3099                style=wx.CB_READONLY|wx.CB_DROPDOWN)
3100            Indx[distChoice.GetId()] = [level['Controls'],'DistType']
3101            distChoice.Bind(wx.EVT_COMBOBOX,OnSelect)
3102            sizeSizer.Add(distChoice,0,WACV)    #put structure factor choices here
3103            if level['Controls']['DistType'] not in ['Bragg','Unified','Porod',]:
3104                sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Form Factor: '),0,WACV)
3105                if 'Mono' in level['Controls']['DistType']:
3106                    ffChoice = wx.ComboBox(G2frame.dataDisplay,value=level['Controls']['FormFact'],choices=ffMonoChoices,
3107                        style=wx.CB_READONLY|wx.CB_DROPDOWN)
3108                else:
3109                    ffChoice = wx.ComboBox(G2frame.dataDisplay,value=level['Controls']['FormFact'],choices=ffDistChoices,
3110                        style=wx.CB_READONLY|wx.CB_DROPDOWN)
3111                Indx[ffChoice.GetId()] = [level['Controls'],'FormFact']
3112                ffChoice.Bind(wx.EVT_COMBOBOX,OnSelect)
3113                sizeSizer.Add(ffChoice,0,WACV)
3114               
3115                sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Material: '),0,WACV)
3116                matSel = wx.ComboBox(G2frame.dataDisplay,value=level['Controls']['Material'],
3117                    choices=Substances['Substances'].keys(),style=wx.CB_READONLY|wx.CB_DROPDOWN)
3118                Indx[matSel.GetId()] = [level['Controls'],'Material']
3119                matSel.Bind(wx.EVT_COMBOBOX,OnSelect)       
3120                sizeSizer.Add(matSel,0,WACV) #do neutron test here?
3121                rho = Substances['Substances'][level['Controls']['Material']].get('XAnom density',0.0)
3122                level['Controls']['Contrast'] = contrast = (rho-rhoMat)**2                 
3123                sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Resonant X-ray contrast: '),0,WACV)
3124                sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=%.2f 10%scm%s'%(contrast,Pwr20,Pwrm4)),0,WACV)
3125                if 'Mono' not in level['Controls']['DistType']:
3126                    sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Num. radii: '),0,WACV)
3127                    radii = ['25','50','75','100','200']
3128                    nRadii = wx.ComboBox(G2frame.dataDisplay,value=str(level['Controls']['NumPoints']),choices=radii,
3129                        style=wx.CB_READONLY|wx.CB_DROPDOWN)
3130                    Indx[nRadii.GetId()] = [level['Controls'],'NumPoints']
3131                    nRadii.Bind(wx.EVT_COMBOBOX,OnSelect)
3132                    sizeSizer.Add(nRadii,0,WACV)
3133                    sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' R dist. cutoff: '),0,WACV)
3134                    rCutoff = G2gd.ValidatedTxtCtrl(G2frame.dataDisplay,level['Controls'],'Cutoff',
3135                        min=0.001,max=0.1,typeHint=float)
3136                    sizeSizer.Add(rCutoff,0,WACV)
3137            elif level['Controls']['DistType']  in ['Unified',]:
3138                Parms = level['Unified']
3139                Best = G2sasd.Bestimate(Parms['G'][0],Parms['Rg'][0],Parms['P'][0])
3140                sizeSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Estimated Dist B: %12.4g'%(Best)),0,WACV)
3141            return sizeSizer
3142           
3143        def ParmSizer():
3144            parmSizer = wx.FlexGridSizer(1,3,5,5)
3145            parmSizer.AddGrowableCol(2,1)
3146            parmSizer.SetFlexibleDirection(wx.HORIZONTAL)
3147            Parms = level[level['Controls']['DistType']]
3148            FFargs = level['Controls']['FFargs']
3149            SFargs = level['Controls'].get('SFargs',{})
3150            parmOrder = ['Volume','Radius','Mean','StdDev','MinSize','G','Rg','B','P','Cutoff',
3151                'PkInt','PkPos','PkSig','PkGam',]
3152            for parm in parmOrder:
3153                if parm in Parms:
3154                    if parm == 'MinSize':
3155                        parmSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Dist '+parm),0,wx.ALIGN_CENTER)
3156                    else:
3157                        parmVar = wx.CheckBox(G2frame.dataDisplay,label='Refine? Dist '+parm) 
3158                        parmVar.SetValue(Parms[parm][1])
3159                        parmVar.Bind(wx.EVT_CHECKBOX, OnSelect)
3160                        parmSizer.Add(parmVar,0,WACV)
3161                        Indx[parmVar.GetId()] = [Parms[parm],1]
3162                    parmValue = wx.TextCtrl(G2frame.dataDisplay,value='%.3g'%(Parms[parm][0]),
3163                        style=wx.TE_PROCESS_ENTER)
3164                    parmValue.Bind(wx.EVT_TEXT_ENTER,OnValue)       
3165                    parmValue.Bind(wx.EVT_KILL_FOCUS,OnValue)
3166                    parmSizer.Add(parmValue,0,WACV)
3167                    if parm == 'P':
3168                        value = Parms[parm][0]
3169                        valMinMax = [0.1,4.2]
3170                    else:
3171                        value = np.log10(Parms[parm][0])
3172                        valMinMax = [value-1,value+1]
3173                    parmSldr = wx.Slider(G2frame.dataDisplay,minValue=slMult*valMinMax[0],
3174                        maxValue=slMult*valMinMax[1],value=slMult*value)
3175                    Indx[parmValue.GetId()] = [Parms,parm,parmSldr]
3176                    Indx[parmSldr.GetId()] = [Parms,parm,parmValue]
3177                    parmSldr.Bind(wx.EVT_SLIDER,OnParmSlider)
3178                    parmSizer.Add(parmSldr,1,wx.EXPAND)
3179            if level['Controls']['DistType'] not in ['Bragg']:
3180                parmOrder = ['Aspect ratio','Length','Diameter','Thickness','VolFr','Dist','epis','Sticky','Depth','Width']
3181                fTypes = ['FF ','SF ']
3182                for iarg,Args in enumerate([FFargs,SFargs]):
3183                    for parm in parmOrder:
3184                        if parm in Args:
3185                            parmVar = wx.CheckBox(G2frame.dataDisplay,label='Refine? '+fTypes[iarg]+parm) 
3186                            parmVar.SetValue(Args[parm][1])
3187                            Indx[parmVar.GetId()] = [Args[parm],1]
3188                            parmVar.Bind(wx.EVT_CHECKBOX, OnSelect)
3189                            parmSizer.Add(parmVar,0,WACV)
3190                            parmValue = wx.TextCtrl(G2frame.dataDisplay,value='%.3g'%(Args[parm][0]),
3191                                style=wx.TE_PROCESS_ENTER)
3192                            parmValue.Bind(wx.EVT_TEXT_ENTER,OnValue)       
3193                            parmValue.Bind(wx.EVT_KILL_FOCUS,OnValue)
3194                            parmSizer.Add(parmValue,0,WACV)
3195                            value = Args[parm][0]
3196                            if parm == 'epis':
3197                                valMinMax = [0,.1]
3198                            elif parm in ['Sticky','Width',]:
3199                                valMinMax = [0,1.]
3200                            elif parm == 'Depth':
3201                                valMinMax = [-2.,2.]
3202                            elif parm == 'Dist':
3203                                valMinMax = [100.,1000.]
3204                            elif parm == 'VolFr':
3205                                valMinMax = [1.e-4,1.]
3206                            else:
3207                                value = np.log10(Args[parm][0])
3208                                valMinMax = [value-1,value+1]
3209                            parmSldr = wx.Slider(G2frame.dataDisplay,minValue=slMult*valMinMax[0],
3210                                maxValue=slMult*valMinMax[1],value=slMult*value)
3211                            Indx[parmVar.GetId()] = [Args[parm],1]
3212                            Indx[parmValue.GetId()] = [Args,parm,parmSldr]
3213                            Indx[parmSldr.GetId()] = [Args,parm,parmValue]
3214                            parmSldr.Bind(wx.EVT_SLIDER,OnParmSlider)
3215                            parmSizer.Add(parmSldr,1,wx.EXPAND)
3216            return parmSizer               
3217           
3218        Indx = {}
3219        partSizer = wx.BoxSizer(wx.VERTICAL)
3220        topSizer = wx.BoxSizer(wx.HORIZONTAL)
3221        topSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Particle fit parameters: '),0,WACV)
3222        topSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Matrix: '),0,WACV)
3223        matsel = wx.ComboBox(G2frame.dataDisplay,value=data['Particle']['Matrix']['Name'],
3224            choices=Substances['Substances'].keys(),style=wx.CB_READONLY|wx.CB_DROPDOWN)
3225        Indx[matsel.GetId()] = [data['Particle']['Matrix'],'Name'] 
3226        matsel.Bind(wx.EVT_COMBOBOX,OnSelect) #Do neutron test here?
3227        rhoMat = Substances['Substances'][data['Particle']['Matrix']['Name']].get('XAnom density',0.0)       
3228        topSizer.Add(matsel,0,WACV)
3229        topSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Volume fraction: '),0,WACV)
3230        volfrac = G2gd.ValidatedTxtCtrl(G2frame.dataDisplay,data['Particle']['Matrix']['VolFrac'],0,
3231                typeHint=float)
3232        topSizer.Add(volfrac,0,WACV)
3233        volVar = wx.CheckBox(G2frame.dataDisplay,label=' Refine?')
3234        volVar.SetValue(data['Particle']['Matrix']['VolFrac'][1])
3235        Indx[volVar.GetId()] = [data['Particle']['Matrix']['VolFrac'],1]
3236        volVar.Bind(wx.EVT_CHECKBOX, OnSelect)
3237        topSizer.Add(volVar,0,WACV)
3238        partSizer.Add(topSizer,0,)
3239        for ilev,level in enumerate(data['Particle']['Levels']):
3240            G2gd.HorizontalLine(partSizer,G2frame.dataDisplay)
3241            topLevel = wx.BoxSizer(wx.HORIZONTAL)
3242            topLevel.Add(wx.StaticText(G2frame.dataDisplay,label=' Model component %d: '%(ilev)),0,WACV)
3243            delBtn = wx.Button(G2frame.dataDisplay,label=' Delete?')
3244            Indx[delBtn.GetId()] = ilev
3245            delBtn.Bind(wx.EVT_BUTTON,OnDelLevel)
3246            topLevel.Add(delBtn,0,WACV)
3247            partSizer.Add(topLevel,0)
3248            partSizer.Add(SizeSizer())
3249            if level['Controls']['DistType'] not in ['Bragg','Unified','Porod',]:
3250                topLevel.Add(wx.StaticText(G2frame.dataDisplay,label=' Structure factor: '),0,WACV)
3251                strfctr = wx.ComboBox(G2frame.dataDisplay,value=level['Controls']['StrFact'],
3252                    choices=sfChoices,style=wx.CB_READONLY|wx.CB_DROPDOWN)
3253                Indx[strfctr.GetId()] = [level['Controls'],'StrFact']
3254                strfctr.Bind(wx.EVT_COMBOBOX,OnSelect)
3255                topLevel.Add(strfctr,0,WACV)
3256            partSizer.Add(ParmSizer(),0,wx.EXPAND)
3257        return partSizer
3258       
3259    def OnEsdScale(event):
3260        try:
3261            value = float(esdScale.GetValue())
3262            if value <= 0.:
3263                raise ValueError
3264        except ValueError:
3265            value = 1./np.sqrt(ProfDict['wtFactor'])
3266        ProfDict['wtFactor'] = 1./value**2
3267        esdScale.SetValue('%.3f'%(value))
3268        RefreshPlots(True)
3269       
3270    def OnBackChange(event):
3271        try:
3272            value = float(backVal.GetValue())
3273        except ValueError:
3274            value = 0.0
3275        backVal.SetValue('%.3g'%(value))
3276        data['Back'][0] = value
3277        Profile[4][:] = value
3278        RefreshPlots()
3279       
3280    def OnBackFile(event):
3281        data['BackFile'] = backFile.GetValue()
3282        if data['BackFile']:
3283            fixBack =  data['Back'][0]
3284            BackId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,data['BackFile'])
3285            BackSample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,BackId, 'Sample Parameters'))
3286            Profile[5] = BackSample['Scale'][0]*G2frame.PatternTree.GetItemPyData(BackId)[1][1]
3287            RefreshPlots(True)
3288           
3289    Sample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Sample Parameters'))
3290    Limits = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Limits'))
3291    Inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Instrument Parameters'))
3292    Substances = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Substances'))
3293    ProfDict,Profile = G2frame.PatternTree.GetItemPyData(G2frame.PatternId)[:2]
3294    if data['BackFile']:
3295        BackId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,data['BackFile'])
3296        BackSample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,BackId, 'Sample Parameters'))
3297        Profile[5] = BackSample['Scale'][0]*G2frame.PatternTree.GetItemPyData(BackId)[1][1]
3298    if G2frame.dataDisplay:
3299        G2frame.dataFrame.DestroyChildren()
3300    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.ModelMenu)
3301    if not G2frame.dataFrame.GetStatusBar():
3302        Status = G2frame.dataFrame.CreateStatusBar()
3303    G2frame.dataFrame.SetLabel('Modelling')
3304    G2frame.dataDisplay = wxscroll.ScrolledPanel(G2frame.dataFrame)
3305    G2frame.dataFrame.Bind(wx.EVT_MENU, OnCopyModel, id=G2gd.wxID_MODELCOPY)
3306    G2frame.dataFrame.Bind(wx.EVT_MENU, OnCopyFlags, id=G2gd.wxID_MODELCOPYFLAGS)
3307    G2frame.dataFrame.Bind(wx.EVT_MENU, OnFitModel, id=G2gd.wxID_MODELFIT)
3308    G2frame.dataFrame.Bind(wx.EVT_MENU, OnFitModelAll, id=G2gd.wxID_MODELFITALL)
3309    G2frame.dataFrame.Bind(wx.EVT_MENU, OnUnDo, id=G2gd.wxID_MODELUNDO)
3310    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddModel, id=G2gd.wxID_MODELADD)
3311    Indx = {}
3312    mainSizer = wx.BoxSizer(wx.VERTICAL)
3313    topSizer = wx.BoxSizer(wx.HORIZONTAL)
3314    models = ['Size dist.','Particle fit']
3315    topSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Modeling by: '),0,WACV)
3316    fitSel = wx.ComboBox(G2frame.dataDisplay,value=data['Current'],choices=models,
3317        style=wx.CB_READONLY|wx.CB_DROPDOWN)
3318    fitSel.Bind(wx.EVT_COMBOBOX,OnSelectFit)       
3319    topSizer.Add(fitSel,0,WACV)
3320    topSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Error multiplier: '),0,WACV)
3321    esdScale = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(1./np.sqrt(ProfDict['wtFactor'])),style=wx.TE_PROCESS_ENTER)
3322    esdScale.Bind(wx.EVT_TEXT_ENTER,OnEsdScale)       
3323    esdScale.Bind(wx.EVT_KILL_FOCUS,OnEsdScale)
3324    topSizer.Add(esdScale,0,WACV)
3325    mainSizer.Add(topSizer)
3326    G2gd.HorizontalLine(mainSizer,G2frame.dataDisplay)
3327    if 'Size' in data['Current']:
3328        if 'MaxEnt' in data['Size']['Method']:
3329            Status.SetStatusText('Size distribution by Maximum entropy')
3330        elif 'IPG' in data['Size']['Method']:
3331            Status.SetStatusText('Size distribution by Interior-Point Gradient')
3332        mainSizer.Add(SizeSizer())       
3333    elif 'Particle' in data['Current']:
3334        mainSizer.Add(PartSizer(),1,wx.ALIGN_LEFT|wx.EXPAND)
3335    G2gd.HorizontalLine(mainSizer,G2frame.dataDisplay)   
3336    backSizer = wx.BoxSizer(wx.HORIZONTAL)
3337    backSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Background:'),0,WACV)
3338    backVal = wx.TextCtrl(G2frame.dataDisplay,value='%.3g'%(data['Back'][0]),style=wx.TE_PROCESS_ENTER)
3339    Indx[backVal.GetId()] = ['Back',0,'%.3g']
3340    backVal.Bind(wx.EVT_TEXT_ENTER,OnBackChange)       
3341    backVal.Bind(wx.EVT_KILL_FOCUS,OnBackChange)
3342    backSizer.Add(backVal,0,WACV)
3343    backVar = wx.CheckBox(G2frame.dataDisplay,label='Refine?')
3344    Indx[backVar.GetId()] = [data['Back'],1]
3345    backVar.SetValue(data['Back'][1])
3346    backVar.Bind(wx.EVT_CHECKBOX, OnCheckBox)
3347    backSizer.Add(backVar,0,WACV)   
3348    backSizer.Add(wx.StaticText(G2frame.dataDisplay,-1,' Background file: '),0,WACV)
3349    Choices = ['',]+G2gd.GetPatternTreeDataNames(G2frame,['SASD',])
3350    backFile = wx.ComboBox(parent=G2frame.dataDisplay,value=data['BackFile'],choices=Choices,
3351        style=wx.CB_READONLY|wx.CB_DROPDOWN)
3352    backFile.Bind(wx.EVT_COMBOBOX,OnBackFile)
3353    backSizer.Add(backFile)   
3354    mainSizer.Add(backSizer)
3355
3356    mainSizer.Layout()   
3357    G2frame.dataDisplay.SetSizer(mainSizer)
3358    G2frame.dataDisplay.SetAutoLayout(1)
3359    G2frame.dataDisplay.SetupScrolling()
3360    Size = mainSizer.Fit(G2frame.dataFrame)
3361    Size[0] += 25
3362    G2frame.dataDisplay.SetSize(Size)
3363    G2frame.dataFrame.setSizePosLeft(Size)   
3364   
3365################################################################################
3366#####  PDF controls
3367################################################################################           
3368       
3369def UpdatePDFGrid(G2frame,data):
3370    '''respond to selection of PWDR PDF data tree item.
3371    '''
3372    global inst
3373    tth2q = lambda t,w:4.0*math.pi*sind(t/2.0)/w
3374    dataFile = G2frame.PatternTree.GetItemText(G2frame.PatternId)
3375    powName = 'PWDR'+dataFile[4:]
3376    powId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, powName)
3377    fullLimits,limits = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,powId, 'Limits'))[:2]
3378    inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,powId, 'Instrument Parameters'))[0]
3379    if 'Lam' in inst:
3380        keV = 12.397639/inst['Lam'][1]
3381    else:
3382        keV = 12.397639/inst['Lam1'][0]
3383    wave = 12.397639/keV
3384    qLimits = [tth2q(fullLimits[0],wave),tth2q(fullLimits[1],wave)]
3385    data['QScaleLim'][1] = min(qLimits[1],data['QScaleLim'][1])
3386    if data['QScaleLim'][0]:
3387        data['QScaleLim'][0] = max(qLimits[0],data['QScaleLim'][0])
3388    else:                                #initial setting at 90% of max Q
3389        data['QScaleLim'][0] = 0.90*data['QScaleLim'][1]
3390    polariz = inst['Polariz.'][1]
3391    azimuth = inst['Azimuth'][1]
3392    itemDict = {}
3393   
3394    def FillFileSizer(fileSizer,key):
3395        #fileSizer is a FlexGridSizer(3,6)
3396       
3397        def OnSelectFile(event):
3398            Obj = event.GetEventObject()
3399            fileKey,itemKey,fmt = itemDict[Obj.GetId()]
3400            if itemKey == 'Name':
3401                value = Obj.GetValue()
3402            Obj.SetValue(fmt%(value))
3403            data[fileKey][itemKey] = value
3404            UpdatePDFGrid(G2frame,data)
3405       
3406        def OnValueChange(event):
3407            Obj = event.GetEventObject()
3408            fileKey,itemKey,fmt = itemDict[Obj.GetId()]
3409            try:
3410                value = float(Obj.GetValue())
3411            except ValueError:
3412                value = -1.0
3413            Obj.SetValue(fmt%(value))
3414            data[fileKey][itemKey] = value
3415            auxPlot = ComputePDF(data)
3416            G2plt.PlotISFG(G2frame,newPlot=True)
3417                       
3418        item = data[key]
3419        fileList = np.array(GetFileList('PWDR')).T[1]
3420        fileSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' '+key+' file:'),0,WACV)
3421        fileName = wx.ComboBox(G2frame.dataDisplay,value=item['Name'],choices=fileList,
3422            style=wx.CB_READONLY|wx.CB_DROPDOWN)
3423        itemDict[fileName.GetId()] = [key,'Name','%s']
3424        fileName.Bind(wx.EVT_COMBOBOX,OnSelectFile)       
3425        fileSizer.Add(fileName,0,)
3426        fileSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label='Multiplier:'),0,WACV)
3427        mult = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(item['Mult']),style=wx.TE_PROCESS_ENTER)
3428        itemDict[mult.GetId()] = [key,'Mult','%.3f']
3429        mult.Bind(wx.EVT_TEXT_ENTER,OnValueChange)       
3430        mult.Bind(wx.EVT_KILL_FOCUS,OnValueChange)
3431        fileSizer.Add(mult,0,)
3432        fileSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label='Add:'),0,WACV)
3433        add = wx.TextCtrl(G2frame.dataDisplay,value='%.0f'%(item['Add']),style=wx.TE_PROCESS_ENTER)
3434        itemDict[add.GetId()] = [key,'Add','%.0f']
3435        add.Bind(wx.EVT_TEXT_ENTER,OnValueChange)       
3436        add.Bind(wx.EVT_KILL_FOCUS,OnValueChange)
3437        fileSizer.Add(add,0,)
3438       
3439    def SumElementVolumes():
3440        sumVol = 0.
3441        ElList = data['ElList']
3442        for El in ElList:
3443            Avol = (4.*math.pi/3.)*ElList[El]['Drad']**3
3444            sumVol += Avol*ElList[El]['FormulaNo']
3445        return sumVol
3446        auxPlot = ComputePDF(data)
3447        G2plt.PlotISFG(G2frame,newPlot=True)       
3448       
3449    def FillElemSizer(elemSizer,ElData):
3450       
3451        def OnFractionChange(event):
3452            try:
3453                value = max(0.0,float(num.GetValue()))
3454            except ValueError:
3455                value = 0.0
3456            num.SetValue('%.3f'%(value))
3457            ElData['FormulaNo'] = value
3458            data['Form Vol'] = max(10.0,SumElementVolumes())
3459            formVol.SetValue('%.2f'%(data['Form Vol']))
3460            wx.CallAfter(UpdatePDFGrid,G2frame,data)
3461            auxPlot = ComputePDF(data)
3462            G2plt.PlotISFG(G2frame,newPlot=True)       
3463       
3464        elemSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,
3465            label=' Element: '+'%2s'%(ElData['Symbol'])+' * '),0,WACV)
3466        num = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(ElData['FormulaNo']),style=wx.TE_PROCESS_ENTER)
3467        num.Bind(wx.EVT_TEXT_ENTER,OnFractionChange)       
3468        num.Bind(wx.EVT_KILL_FOCUS,OnFractionChange)
3469        elemSizer.Add(num,0,WACV)
3470        elemSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,
3471            label="f': %.3f"%(ElData['fp'])+' f": %.3f'%(ElData['fpp'])+' mu: %.2f barns'%(ElData['mu']) ),
3472            0,WACV)
3473           
3474    def OnGeometry(event):
3475        data['Geometry'] = geometry.GetValue()
3476        UpdatePDFGrid(G2frame,data)
3477        auxPlot = ComputePDF(data)
3478        G2plt.PlotISFG(G2frame,newPlot=True)       
3479       
3480    def OnDetType(event):
3481        data['DetType'] = detType.GetValue()
3482        UpdatePDFGrid(G2frame,data)
3483        auxPlot = ComputePDF(data)
3484        G2plt.PlotISFG(G2frame,newPlot=True)       
3485       
3486    def OnFormVol(event):
3487        try:
3488            value = float(formVol.GetValue())
3489            if value <= 0.0:
3490                raise ValueError
3491        except ValueError:
3492            value = data['Form Vol']
3493        data['Form Vol'] = value
3494        UpdatePDFGrid(G2frame,data)
3495        auxPlot = ComputePDF(data)
3496        G2plt.PlotISFG(G2frame,newPlot=False)       
3497       
3498    def OnDiameter(event):
3499        try:
3500            value = float(diam.GetValue())
3501            if value <= 0.0:
3502                raise ValueError
3503        except ValueError:
3504            value = data['Diam']
3505        data['Diam'] = value
3506        UpdatePDFGrid(G2frame,data)
3507        auxPlot = ComputePDF(data)
3508        G2plt.PlotISFG(G2frame,newPlot=False)
3509       
3510    def OnPolaVal(event):
3511        try:
3512            value = float(polaVal.GetValue())
3513            if not (0.0 <= value <= 1.0):
3514                raise ValueError
3515        except ValueError:
3516            value = inst['Polariz.'][1]
3517        inst['Polariz.'][1] = value
3518        polaVal.SetValue('%.2f'%(inst['Polariz.'][1]))
3519        UpdatePDFGrid(G2frame,data)
3520        auxPlot = ComputePDF(data)
3521        G2plt.PlotISFG(G2frame,newPlot=False)
3522               
3523    def OnAzimVal(event):
3524        try:
3525            value = float(azimVal.GetValue())
3526            if not (0. <= value <= 360.):
3527                raise ValueError
3528        except ValueError:
3529            value = inst['Azimuth'][1]
3530        inst['Azimuth'][1] = value
3531        azimVal.SetValue('%.1f'%(inst['Azimuth'][1]))
3532        UpdatePDFGrid(G2frame,data)
3533        auxPlot = ComputePDF(data)
3534        G2plt.PlotISFG(G2frame,newPlot=False)
3535                       
3536    def OnObliqCoeff(event):
3537        try:
3538            value = float(obliqCoeff.GetValue())
3539            if value < 0.0:
3540                raise ValueError
3541            elif value > 1.0:
3542                value = 1.0
3543        except ValueError:
3544            value = data['ObliqCoeff']
3545        data['ObliqCoeff'] = value
3546        obliqCoeff.SetValue('%.3f'%(value))
3547        auxPlot = ComputePDF(data)
3548        G2plt.PlotISFG(G2frame,newPlot=False)
3549       
3550    def OnRulandWdt(event):
3551        try:
3552            value = float(rulandWdt.GetValue())
3553            if value <= 0.001:
3554                raise ValueError
3555            elif value > 1.0:
3556                value = 1.0
3557        except ValueError:
3558            value = data['Ruland']
3559        data['Ruland'] = value
3560        rulandWdt.SetValue('%.3f'%(value))
3561        auxPlot = ComputePDF(data)
3562        G2plt.PlotISFG(G2frame,newPlot=False)
3563       
3564    def OnRulSlider(event):
3565        value = int(rulandSldr.GetValue())/1000.
3566        data['Ruland'] = max(0.001,value)
3567        rulandWdt.SetValue('%.3f'%(data['Ruland']))
3568        auxPlot = ComputePDF(data)
3569        G2plt.PlotISFG(G2frame,newPlot=False)
3570       
3571    def OnLorch(event):
3572        data['Lorch'] = lorch.GetValue()
3573        auxPlot = ComputePDF(data)
3574        G2plt.PlotISFG(G2frame,newPlot=False)       
3575                       
3576    def OnPacking(event):
3577        try:
3578            value = float(pack.GetValue())
3579            if value <= 0.0:
3580                raise ValueError
3581        except ValueError:
3582            value = data['Pack']
3583        data['Pack'] = value
3584        UpdatePDFGrid(G2frame,data)
3585        auxPlot = ComputePDF(data)
3586        G2plt.PlotISFG(G2frame,newPlot=False)       
3587               
3588    def OnSQmin(event):
3589        try:
3590            value = float(SQmin.GetValue())
3591            if value < qLimits[0]:
3592                raise ValueError
3593        except ValueError:
3594            value = max(qLimits[0],data['QScaleLim'][0])
3595        data['QScaleLim'][0] = value
3596        SQmin.SetValue('%.1f'%(value))
3597        auxPlot = ComputePDF(data)
3598        G2plt.PlotISFG(G2frame,newPlot=True)       
3599       
3600    def OnSQmax(event):
3601        try:
3602            value = float(SQmax.GetValue())
3603            if value > qLimits[1]:
3604                raise ValueError
3605        except ValueError:
3606            value = min(qLimits[1],data['QScaleLim'][1])
3607        data['QScaleLim'][1] = value
3608        if value < data['QScaleLim'][0]:
3609            data['QScaleLim'][0] = 0.90*value
3610            SQmin.SetValue('%.1f'%(data['QScaleLim'][0]))
3611        SQmax.SetValue('%.1f'%(value))
3612        auxPlot = ComputePDF(data)
3613        G2plt.PlotISFG(G2frame,newPlot=True)
3614       
3615    def OnResetQ(event):
3616        resetQ.SetValue(False)
3617        data['QScaleLim'][1] = qLimits[1]
3618        SQmax.SetValue('%.1f'%(data['QScaleLim'][1]))
3619        data['QScaleLim'][0] = 0.9*qLimits[1]
3620        SQmin.SetValue('%.1f'%(data['QScaleLim'][0]))
3621        auxPlot = ComputePDF(data)
3622        G2plt.PlotISFG(G2frame,newPlot=True)       
3623
3624    def GetFileList(fileType,skip=None):
3625        fileList = [[False,'',0]]
3626        Source = ''
3627        id, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
3628        while id:
3629            name = G2frame.PatternTree.GetItemText(id)
3630            if fileType in name:
3631                if id == skip:
3632                    Source = name
3633                else:
3634                    fileList.append([False,name,id])
3635            id, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
3636        if skip:
3637            return fileList,Source
3638        else:
3639            return fileList
3640       
3641    def OnCopyPDFControls(event):
3642        import copy
3643        TextList,Source = GetFileList('PDF',skip=G2frame.PatternId)
3644        TextList[0] = [False,'All PDF',0]
3645        if len(TextList) == 1:
3646            G2frame.ErrorDialog('Nothing to copy controls to','There must be more than one "PDF" pattern')
3647            return
3648        dlg = G2frame.CopyDialog(G2frame,'Copy PDF controls','Copy controls from '+Source+' to:',TextList)
3649        try:
3650            if dlg.ShowModal() == wx.ID_OK:
3651                result = dlg.GetData()
3652                if result[0][0]:
3653                    result = TextList[1:]
3654                    for item in result: item[0] = True
3655                for i,item in enumerate(result):
3656                    ifcopy,name,id = item
3657                    if ifcopy:
3658                        olddata = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,id, 'PDF Controls'))
3659                        sample = olddata['Sample']
3660                        olddata.update(copy.deepcopy(data))
3661                        olddata['Sample'] = sample
3662                        G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,id, 'PDF Controls'),olddata)
3663                Status.SetStatusText('PDF controls copied')
3664        finally:
3665            dlg.Destroy()
3666               
3667    def OnSavePDFControls(event):
3668        print 'save PDF controls?'
3669       
3670    def OnLoadPDFControls(event):
3671        print 'Load PDF controls?'
3672       
3673    def OnAddElement(event):
3674        ElList = data['ElList']
3675        PE = G2elemGUI.PickElement(G2frame,oneOnly=True)
3676        if PE.ShowModal() == wx.ID_OK:
3677            El = PE.Elem
3678            if El not in ElList and El != 'None':
3679                ElemSym = El.strip().upper()               
3680                FpMu = G2elem.FPcalc(G2elem.GetXsectionCoeff(ElemSym), keV)
3681                ElData = G2elem.GetFormFactorCoeff(ElemSym)[0]
3682                ElData['FormulaNo'] = 0.0
3683                ElData.update(G2elem.GetAtomInfo(ElemSym))
3684                ElData.update(dict(zip(['fp','fpp','mu'],FpMu)))
3685                ElData.update(G2elem.GetFFC5(El))
3686                data['ElList'][El] = ElData
3687            data['Form Vol'] = max(10.0,SumElementVolumes())
3688        PE.Destroy()
3689        UpdatePDFGrid(G2frame,data)
3690       
3691    def OnDeleteElement(event):
3692        ElList = data['ElList']
3693        choice = ElList.keys()
3694        dlg = G2elemGUI.DeleteElement(G2frame,choice=choice)
3695        if dlg.ShowModal() == wx.ID_OK:
3696            del ElList[dlg.GetDeleteElement()]
3697        dlg.Destroy()
3698        UpdatePDFGrid(G2frame,data)
3699               
3700    def ComputePDF(Data):
3701        xydata = {}
3702        for key in ['Sample','Sample Bkg.','Container','Container Bkg.']:
3703            name = Data[key]['Name']
3704            if name:
3705                xydata[key] = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.root,name))
3706                PDFname = name
3707        powName = xydata['Sample'][2]
3708        powId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,powName)
3709        inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,powId,'Instrument Parameters'))[0]
3710        auxPlot = G2pwd.CalcPDF(Data,inst,xydata)
3711        PDFId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'PDF '+powName[4:])
3712        G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PDFId,'I(Q)'+powName[4:]),xydata['IofQ'])
3713        G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PDFId,'S(Q)'+powName[4:]),xydata['SofQ'])
3714        G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PDFId,'F(Q)'+powName[4:]),xydata['FofQ'])
3715        G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PDFId,'G(R)'+powName[4:]),xydata['GofR'])
3716        return auxPlot
3717       
3718    def OnComputePDF(event):
3719        print 'Calculating PDF:'
3720        auxPlot = ComputePDF(data)
3721        print 'Done calculating PDF:'
3722        Status.SetStatusText('PDF computed')
3723        for plot in auxPlot:
3724            G2plt.PlotXY(G2frame,plot[:2],type=plot[2])
3725       
3726        G2plt.PlotISFG(G2frame,newPlot=True,type='I(Q)')
3727        G2plt.PlotISFG(G2frame,newPlot=True,type='S(Q)')
3728        G2plt.PlotISFG(G2frame,newPlot=True,type='F(Q)')
3729        G2plt.PlotISFG(G2frame,newPlot=True,type='G(R)')
3730       
3731    def OnComputeAllPDF(event):
3732        print 'Calculating PDFs:'
3733        if G2frame.PatternTree.GetCount():
3734            id, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
3735            while id:
3736                Name = G2frame.PatternTree.GetItemText(id)
3737                if 'PDF' in Name:
3738                    Data = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,id,'PDF Controls'))
3739                    auxPlot = ComputePDF(Data)                   
3740                id, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
3741            Status.SetStatusText('All PDFs computed')
3742            G2plt.PlotISFG(G2frame,newPlot=True,type='G(R)')
3743            print ' Done calculating PDFs:'
3744       
3745    def OnShowTip(G2frame,tip):
3746        print tip   
3747               
3748    if G2frame.dataDisplay:
3749        G2frame.dataFrame.Clear()
3750    G2gd.SetDataMenuBar(G2frame,G2frame.dataFrame.PDFMenu)
3751    if not G2frame.dataFrame.GetStatusBar():
3752        Status = G2frame.dataFrame.CreateStatusBar()   
3753    G2frame.dataDisplay = wx.Panel(G2frame.dataFrame)
3754    G2frame.dataFrame.Bind(wx.EVT_MENU, OnCopyPDFControls, id=G2gd.wxID_PDFCOPYCONTROLS)
3755    G2frame.dataFrame.Bind(wx.EVT_MENU, OnSavePDFControls, id=G2gd.wxID_PDFSAVECONTROLS)
3756    G2frame.dataFrame.Bind(wx.EVT_MENU, OnLoadPDFControls, id=G2gd.wxID_PDFLOADCONTROLS)
3757    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAddElement, id=G2gd.wxID_PDFADDELEMENT)
3758    G2frame.dataFrame.Bind(wx.EVT_MENU, OnDeleteElement, id=G2gd.wxID_PDFDELELEMENT)
3759    G2frame.dataFrame.Bind(wx.EVT_MENU, OnComputePDF, id=G2gd.wxID_PDFCOMPUTE)
3760    G2frame.dataFrame.Bind(wx.EVT_MENU, OnComputeAllPDF, id=G2gd.wxID_PDFCOMPUTEALL)
3761    mainSizer = wx.BoxSizer(wx.VERTICAL)
3762    mainSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' PDF data files: '),0,WACV)
3763    mainSizer.Add((5,5),0)
3764    str = ' Sample file: PWDR %s   Wavelength, A: %.5f  Energy, keV: %.3f  Polariz.: %.2f '%(dataFile[3:],wave,keV,polariz)
3765    mainSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=str),0,WACV)
3766#    dataSizer = wx.BoxSizer(wx.HORIZONTAL)
3767#    dataSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label='Azimuth'),0,WACV)
3768#    azimVal = wx.TextCtrl(G2frame.dataDisplay,value='%.2f'%(inst['Azimuth']))
3769#    azimVal.Bind(wx.EVT_TEXT_ENTER,OnAzimVal)       
3770#    azimVal.Bind(wx.EVT_KILL_FOCUS,OnAzimVal)
3771#    dataSizer.Add(azimVal,0)   
3772#    dataSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label='Polarization'),0,WACV)
3773#    polaVal = wx.TextCtrl(G2frame.dataDisplay,value='%.2f'%(inst['Polariz.']))
3774#    polaVal.Bind(wx.EVT_TEXT_ENTER,OnPolaVal)       
3775#    polaVal.Bind(wx.EVT_KILL_FOCUS,OnPolaVal)
3776#    dataSizer.Add(polaVal,0)   
3777#    mainSizer.Add(dataSizer,0)
3778    mainSizer.Add((5,5),0)
3779    fileSizer = wx.FlexGridSizer(3,6,5,1)
3780    select = ['Sample Bkg.','Container']
3781    if data['Container']['Name']:
3782        select.append('Container Bkg.')
3783    for key in select:
3784        FillFileSizer(fileSizer,key)
3785    mainSizer.Add(fileSizer,0)
3786    mainSizer.Add((5,5),0)
3787    mainSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Sample information: '),0,WACV)
3788    mainSizer.Add((5,5),0)   
3789
3790    ElList = data['ElList']
3791    Abs = G2lat.CellAbsorption(ElList,data['Form Vol'])
3792    Trans = G2pwd.Transmission(data['Geometry'],Abs*data['Pack'],data['Diam'])
3793    elemSizer = wx.FlexGridSizer(3,3,5,1)
3794    for El in ElList:
3795        FillElemSizer(elemSizer,ElList[El])
3796    mainSizer.Add(elemSizer,0)
3797    mainSizer.Add((5,5),0)   
3798    midSizer = wx.BoxSizer(wx.HORIZONTAL)
3799    midSizer.Add(wx.StaticText(G2frame.dataDisplay,label=' Formula volume: '),0,WACV)
3800    formVol = wx.TextCtrl(G2frame.dataDisplay,value='%.2f'%(data['Form Vol']))
3801    formVol.Bind(wx.EVT_TEXT_ENTER,OnFormVol)       
3802    formVol.Bind(wx.EVT_KILL_FOCUS,OnFormVol)
3803    midSizer.Add(formVol,0)
3804    midSizer.Add(wx.StaticText(G2frame.dataDisplay,
3805        label=' Theoretical absorption: %.4f cm-1 Sample absorption: %.4f cm-1'%(Abs,Abs*data['Pack'])),
3806        0,WACV)
3807    mainSizer.Add(midSizer,0)
3808    mainSizer.Add((5,5),0)   
3809
3810    geoBox = wx.BoxSizer(wx.HORIZONTAL)
3811    geoBox.Add(wx.StaticText(G2frame.dataDisplay,label=' Sample geometry: '),0,WACV)
3812    choice = ['Cylinder','Bragg-Brentano','Tilting flat plate in transmission','Fixed flat plate']
3813    geometry = wx.ComboBox(G2frame.dataDisplay,value=data['Geometry'],choices=choice,
3814            style=wx.CB_READONLY|wx.CB_DROPDOWN)
3815    geometry.Bind(wx.EVT_COMBOBOX, OnGeometry)
3816    geoBox.Add(geometry,0)
3817    geoBox.Add(wx.StaticText(G2frame.dataDisplay,label=' Sample diameter/thickness, mm: '),0,WACV)
3818    diam = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(data['Diam']))
3819    diam.Bind(wx.EVT_TEXT_ENTER,OnDiameter)       
3820    diam.Bind(wx.EVT_KILL_FOCUS,OnDiameter)
3821#    diam.Bind(wx.EVT_SET_FOCUS,OnShowTip(G2frame,'tip')) #this doesn't work - what would????
3822    geoBox.Add(diam,0)
3823    mainSizer.Add(geoBox,0)
3824    mainSizer.Add((5,5),0)   
3825    geoBox = wx.BoxSizer(wx.HORIZONTAL)
3826    geoBox.Add(wx.StaticText(G2frame.dataDisplay,label=' Packing: '),0,WACV)
3827    pack = wx.TextCtrl(G2frame.dataDisplay,value='%.2f'%(data['Pack']))
3828    pack.Bind(wx.EVT_TEXT_ENTER,OnPacking)       
3829    pack.Bind(wx.EVT_KILL_FOCUS,OnPacking)
3830    geoBox.Add(pack,0)
3831    geoBox.Add(wx.StaticText(G2frame.dataDisplay,label=' Sample transmission: %.3f %%'%(Trans)),0,WACV)   
3832    mainSizer.Add(geoBox,0)
3833    mainSizer.Add((5,5),0)   
3834       
3835    mainSizer.Add(wx.StaticText(parent=G2frame.dataDisplay,label=' S(Q)->F(Q)->G(R) controls: '),0,WACV)
3836    mainSizer.Add((5,5),0)
3837    sqBox = wx.BoxSizer(wx.HORIZONTAL)
3838    sqBox.Add(wx.StaticText(G2frame.dataDisplay,label=' Detector type: '),0,WACV)
3839    choice = ['Image plate','Point detector']
3840    detType = wx.ComboBox(G2frame.dataDisplay,value=data['DetType'],choices=choice,
3841            style=wx.CB_READONLY|wx.CB_DROPDOWN)
3842    detType.Bind(wx.EVT_COMBOBOX, OnDetType)
3843    sqBox.Add(detType,0)
3844    if data['DetType'] == 'Image plate':
3845        sqBox.Add(wx.StaticText(G2frame.dataDisplay,label=' IP transmission coeff.: '),0,WACV)
3846        obliqCoeff = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(data['ObliqCoeff']))
3847        obliqCoeff.Bind(wx.EVT_TEXT_ENTER,OnObliqCoeff)       
3848        obliqCoeff.Bind(wx.EVT_KILL_FOCUS,OnObliqCoeff)
3849        sqBox.Add(obliqCoeff,0)
3850    mainSizer.Add(sqBox,0)
3851       
3852    sqBox = wx.BoxSizer(wx.HORIZONTAL)
3853    sqBox.Add(wx.StaticText(G2frame.dataDisplay,label=' Ruland width: '),0,WACV)   
3854    rulandSldr = wx.Slider(parent=G2frame.dataDisplay,style=wx.SL_HORIZONTAL,
3855        value=int(1000*data['Ruland']))
3856    sqBox.Add(rulandSldr,1,wx.EXPAND)
3857    rulandSldr.Bind(wx.EVT_SLIDER, OnRulSlider)
3858    rulandWdt = wx.TextCtrl(G2frame.dataDisplay,value='%.3f'%(data['Ruland']))
3859    rulandWdt.Bind(wx.EVT_TEXT_ENTER,OnRulandWdt)       
3860    rulandWdt.Bind(wx.EVT_KILL_FOCUS,OnRulandWdt)
3861    sqBox.Add(rulandWdt,0,WACV)   
3862    mainSizer.Add(sqBox,0,wx.ALIGN_LEFT|wx.EXPAND)
3863   
3864    sqBox = wx.BoxSizer(wx.HORIZONTAL)
3865    lorch = wx.CheckBox(parent=G2frame.dataDisplay,label='Lorch damping?')
3866    lorch.SetValue(data['Lorch'])
3867    lorch.Bind(wx.EVT_CHECKBOX, OnLorch)
3868    sqBox.Add(lorch,0,WACV)
3869    sqBox.Add(wx.StaticText(G2frame.dataDisplay,label=' Scaling q-range: '),0,WACV)
3870    SQmin = wx.TextCtrl(G2frame.dataDisplay,value='%.1f'%(data['QScaleLim'][0]))
3871    SQmin.Bind(wx.EVT_TEXT_ENTER,OnSQmin)       
3872    SQmin.Bind(wx.EVT_KILL_FOCUS,OnSQmin)   
3873    sqBox.Add(SQmin,0)
3874    sqBox.Add(wx.StaticText(G2frame.dataDisplay,label=' to '),0,WACV)
3875    SQmax = wx.TextCtrl(G2frame.dataDisplay,value='%.1f'%(data['QScaleLim'][1]))
3876    SQmax.Bind(wx.EVT_TEXT_ENTER,OnSQmax)       
3877    SQmax.Bind(wx.EVT_KILL_FOCUS,OnSQmax)
3878    sqBox.Add(SQmax,0)
3879    resetQ = wx.CheckBox(parent=G2frame.dataDisplay,label='Reset?')
3880    sqBox.Add(resetQ,0)
3881    resetQ.Bind(wx.EVT_CHECKBOX, OnResetQ)
3882   
3883    mainSizer.Add(sqBox,0)
3884
3885    mainSizer.Layout()   
3886    G2frame.dataDisplay.SetSizer(mainSizer)
3887    Size = mainSizer.Fit(G2frame.dataFrame)
3888    G2frame.dataDisplay.SetSize(Size)
3889    G2frame.dataFrame.setSizePosLeft(Size)
3890   
Note: See TracBrowser for help on using the repository browser.